Last active
August 29, 2015 14:02
-
-
Save back2dos/ad1703c631abbd451b75 to your computer and use it in GitHub Desktop.
Generate es5 style properties. Use with --macro Gen.use().
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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