Skip to content

Instantly share code, notes, and snippets.

@back2dos
Last active August 29, 2015 14:02
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save back2dos/ad1703c631abbd451b75 to your computer and use it in GitHub Desktop.
Save back2dos/ad1703c631abbd451b75 to your computer and use it in GitHub Desktop.
Generate es5 style properties. Use with --macro Gen.use().
package ;
import haxe.macro.*;
import haxe.macro.Type;
using haxe.macro.Tools;
private typedef Accessor = {
name: String,
read: Bool,
field: ClassField,
}
class Gen extends ExampleJSGenerator {
var accessors:Map<String, Accessor>;
override function getType(t:Type) //just a workaround until this is merged: https://github.com/HaxeFoundation/haxe/pull/3106
return
switch Context.follow(t) {
case TAbstract(a, _): getPath(a.get());
default: super.getType(t);
}
override function genClass(c: ClassType) {
accessors = new Map();
for(f in c.fields.get())
switch f.kind {
case FVar(get, set):
if (get == AccCall)
accessors['get_' + f.name] = { read: true, name: f.name, field: null };
if (set == AccCall)
accessors['set_' + f.name] = { read: false, name: f.name, field: null };
default:
}
for (f in c.fields.get())
if (accessors.exists(f.name))
accessors[f.name].field = f;
super.genClass(c);
}
override function genClassField( c : ClassType, p : String, f : ClassField ) {
switch f.kind {
case FVar(get, set) if (get == AccCall || set == AccCall):
var name = f.name;
function makePhysical() {
var any = false;
for (kind in 'get,set'.split(','))
switch accessors['${kind}_$name'] {
case null:
case a:
a = Reflect.copy(a);
function fixField(t:TypedExpr)
return switch t.expr {
case TField(owner, FInstance(cl, f)) if (f.get().name == name && owner.expr.equals(TConst(TThis))):
t.expr = TField(owner, FDynamic('_' + name));
any = true;
t;
default: t.map(fixField);
}
var expr = fixField(a.field.expr());
untyped a.field.expr = function () return expr;
accessors['${kind}_$name'] = a;
}
if (any) {
var f = Reflect.copy(f);
f.name = '_'+name;
f.kind = FVar(AccNormal, AccNormal);
genClassField(c, p, f);
}
}
function makeAccessors() {
var first = true;
print('Object.defineProperty($p.prototype, "$name", {');
for (kind in 'get,set'.split(','))
switch accessors['${kind}_$name'] {
case null:
case { field: accessor }:
if (first)
first = false;
else
print(',');
print(' $kind : ');
genExpr(accessor.expr());
}
print('})');
newline();
}
switch [get, set] {
case [AccCall | AccNever, AccCall | AccNever]:
if (f.meta.has(':isVar'))
makePhysical();
makeAccessors();
case [AccCall | AccNormal | AccNo, AccCall | AccNormal | AccNo]:
makePhysical();
makeAccessors();
default:
throw 'assert';
}
case FMethod(_) if (accessors.exists(f.name)):
var accessor = accessors[f.name],
func = field(f.name);
var field = field(accessor.name);
print('$p.prototype$func = ');
if (accessor.read)
print('function () { return this$field; }');
else
print('function (param) { return this$field = param; }');
newline();
default:
super.genClassField(c, p, f);
}
}
static function use()
Compiler.setCustomJSGenerator(function(api) new Gen(api).generate());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment