Casting structs (or how to handle generic functions)
Opened this issue · 1 comments
I have a language ( https://github.com/johnynek/bosatsu ) that I am considering compiling to wax to take advantage of the many backends.
My language supports generics. When I compile to python, this isn't a problem since I leave the code untyped. I had imagined compiling to java by making generic values Object
and casting results from calls to generic functions (since the compile can see the resulting type).
For C, I had imagined casting to void*
doing a similar approach.
I don't want to have to monomorphize the code (that brings a lot of issues, and it is not clear all recursions result in statically known types inside of recursions, but maybe they do).
Do you have any suggestions of how I would represent generics in my language in wax? There does not seem to be a way to cast pointers or have any equivalent of a void*
.
Am I getting that right?
Hi @johnynek ,
Thanks for the interest in using wax as a backend! :) Currently wax does not support generics, and I think monomorphizing might be the best solution.
I think casting from struct to struct is a pretty different notion in different languages. In C struct fields are accessed by offsets, in dynamic languages fields are accessed by names, in Java as far as I know one can't cast unrelated classes without first serializing them to bytes and reinterpret (which is then the same as C notion of casting).
Say you have A and B whose fields of same names are declared in different order, a reinterpret cast has a different effect than duck typing:
typedef struct{ int x; int y; } A;
typedef struct{ int y; int x; } B;
A a = {1,2};
B b = *(B*)&a; // reinterpret cast
printf("%d\n", b.x); // oops, prints a.y
However, if you have a well-defined definition of "casting" for all target languages, wax supports embedding target language code directly ((asm "...")
), so theoretically you can generate the required code for each cast for each language, e.g.
(func castAtoB (param (struct A) a) (result (struct B))
(@if TARGET_C
(asm "return *(B*)&a;\n")
)
(@if TARGET_PY
(asm "return a\n")
)
(@if TARGET_JAVA
...
...
)
BTW nice language you're making. Hope this is helpful to your question!