I intend to write a toy OS kernel in Crystal. Now I need to replace the prelude with a simple one of my own making. The first thing I tried to implement is the comparison operator. It is awesome how Crystal allows you to replace/extend such core constructs.
I know that writing a kernel is a complicated thing and there will be problems with stuff like the GC but others have solved that before.
Now my problem, when I write it as:
struct UInt64
def ==( other : UInt64 )
self == other
end
end
The function of course calls itself in an infinite loop. I tried to skim through the crystal source code and that of other mini OS kernels on GitHub but couldn’t find the solution.
Lilith declares this as @[Primitive(:binary)] but I get this error msg when trying that: Error: BUG: unhandled primitive in MainVisitor: binary
Many thanks in advance!
I think you can convert to another type for comparison, compare the memory, perform an XOR operation, or inherit the method from the parent class to avoid infinite recursion.
struct UInt64
def ==(other : UInt64)
self.unsafe_as(StaticArray(UInt8, 8)) == other.unsafe_as(StaticArray(UInt8, 8))
end
end
struct UInt64
def ==(other : UInt64)
x = self
pointerof(x).memcmp(pointerof(other), 1).zero?
end
end
struct UInt64
def ==(other : UInt64)
(self ^ other).zero?
end
end
struct UInt64
def ==(other : UInt64)
super
end
end
2 Likes
You forgot to declare Bool
as the return type, that’s why MainVisitor
complains
2 Likes
You can take the code in primitives.cr
for reference:
Unfortunately, it’s a bit more complicated than necessary due to macro deduplication. It should be fairly easy to understand.
And as HertzDevil mentioned, the primitive binding requires a full method signature, including the return type restriction.
2 Likes
This is trickier than it looks. All the snippets @Sunrise posted rely on some other prelude functions which at some point need to be implemented without the help of other yet to defined functions. But yeah the solution @HertzDevil posted works once I added the return type.
For a custom prelude, you must either require or reimplement most of:
require "lib_c"
require "primitives"
require "c/stddef"
require "intrinsics"
You’ll also have to implement or stub the __crystal_*
funs expected by codegen, as well as the raise
def and some exception types (TypeCastError
, IndexError
).
You might be interested by nano that takes care of all of that.
1 Like