Skip to content

Instantly share code, notes, and snippets.

@nadako
Created April 23, 2015 12:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nadako/97c51fb829202cd33103 to your computer and use it in GitHub Desktop.
Save nadako/97c51fb829202cd33103 to your computer and use it in GitHub Desktop.
Poor man's enum
#if macro
import haxe.macro.Context;
import haxe.macro.Expr;
import haxe.macro.Type;
using haxe.macro.Tools;
#end
abstract Choice<T>(T) from T {
public macro function match(self, match) {
switch (match.expr) {
case ESwitch(_, origCases, def):
var ctors = new Map();
var ctorsOrder = [];
for (c in origCases) {
switch (c.values) {
case [macro $i{ctor}($a{args})]:
var ctorCases = ctors[ctor];
if (ctorCases == null)
{
ctorCases = ctors[ctor] = [];
ctorsOrder.push(ctor);
}
ctorCases.push({
arg: args[0],
guard: c.guard,
expr: c.expr
});
default:
throw false;
}
}
var switchElems = [macro Reflect.fields(v)[0]];
var cases:Array<Case> = [];
for (i in 0...ctorsOrder.length) {
var ctor = ctorsOrder[i];
switchElems.push(macro v.$ctor);
for (c in ctors[ctor]) {
var values = [macro $v{ctor}];
for (j in 0...ctorsOrder.length) {
if (j == i)
values.push(c.arg);
else
values.push(macro _);
}
cases.push({
values: [macro $a{values}],
expr: c.expr,
guard: c.guard
});
}
}
var switchExpr = {
pos: match.pos,
expr: ESwitch(macro $a{switchElems}, cases, def)
};
var ct = switch (Context.typeof(self).follow()) {
case TAbstract(_, [t]): t.toComplexType();
default: throw false;
}
trace(switchExpr.toString());
return macro {
var v:$ct = cast $self;
$switchExpr;
};
default:
throw false;
}
}
}
typedef MyEnum = Choice<{
?a:Int,
?b:Array<String>,
}>;
class Main {
static function main () {
var a:MyEnum = {a: 10};
a.match(switch _ {
case a(v):
trace(v);
case b(v):
trace(v);
default:
trace("hello");
});
}
}
@nadako
Copy link
Author

nadako commented Apr 23, 2015

generated js:

Main.main = function() {
    var a = { a : 10};
    var v = a;
    {
        var _g = Reflect.fields(v)[0];
        var _g1 = v.a;
        var _g2 = v.b;
        switch(_g) {
        case "a":
            console.log(_g1);
            break;
        case "b":
            console.log(_g2);
            break;
        default:
            console.log("hello");
        }
    }
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment