Closed Simn closed 11 years ago
I think the best way is to make a simple enum be just an int, and detect when it's boxed so we can box it in a strongly typed manner. Enums with parameters are a little harder to make it right. We could use unions, but it may be hard to get the arguments out correctly when having grouped cases.
"grouped cases"?
Like:
enum Test
{
A(d:Float, s:String, b:Int);
B(i:Int, s:String);
C;
}
switch(t)
{
case A(_,s,_), B(_,s): //grouped case
default:
}
Oh don't worry about that, TMatch doesn't exist anymore so we either get nested TSwitch nodes that have some TVars using TEnumParameter, or (once we activate it) TPatMatch which allows us to go goto-crazy.
I have committed something and would appreciate a review. Given this enum:
enum MyEnum {
A;
B(s:String);
}
It generates this header file MyEnum.h:
// constructor structure;
typedef void* MyEnum_A;
typedef struct {
char* s;
} MyEnum_B;
// enum structure;
typedef struct {
int index;
union {
MyEnum_A A;
MyEnum_B B;
} args;
} MyEnum;
// constructor functions;
MyEnum* new_MyEnum_A() {
MyEnum* this = (MyEnum*) GC_MALLOC(sizeof(MyEnum));
this->index = 0;
return this;
}
MyEnum* new_MyEnum_B(char* s) {
MyEnum* this = (MyEnum*) GC_MALLOC(sizeof(MyEnum));
this->index = 1;
this->args.B.s = s;
return this;
}
A pattern matching then looks like this:
x = new_MyEnum_B("foo");
switch((x)->index){
case 0:
haxe_Log_trace("A",0);
break;
case 1:
s = x->args.B.s;
haxe_Log_trace(s,0);
break;
}
It's looking great, Simon! We just need to make sure that our ultimate GC host will accept union declarations (I wouldn't like to keep with boehm). Otherwise we may need to only use unions for basic types.
Also when I was writing the Java/C# targets, I decided to go with the usual Array
fromArray sounds good. We don't want to make the basic structures slower/less type safe just to support reflection if we can avoid it. That's like a general rule of this project. ;)
Okay, you're right! :) Though the amount of code may be a little big (fromArray and toArray for each construct... Imagine for something like Expr) We may figure out another way to deal with that though... Maybe something intelligent using offsetof() for each enum type / argument number would work nicely!
We could, in general, split up all types into a file for the static/typed definitions and one for the dynamic/reflection definitions. This way we can have a concise MyEnum.h
, and if need be also a MyEnum__dyn.h
file with all the reflection information in some lut or whatever one uses in C for that.
This would make it easy to allow omitting these dynamic portions via a combination of a compiler flag (to disable them) and a type metadata (to enable them individually).
That's a great idea. Though by omitting the dynamic portions, we won't be able to neither box the enum, nor get a string representation of it. I think it's a fair trade.
For the statically typed part, it's very simple to feed whatever type to a corresponding function, to print or do whatever else with them.
I suppose this can be considered done. We can still tweak the representation and optimize it, but it's basically working.
Figure out the best way to represent enums. If it makes sense, we can distinguish "flat" enums (those that have no constructors expecting arguments).