Last active
May 2, 2019 21:02
-
-
Save endel/30ef12fd88d6684cb4d7c15be55b5088 to your computer and use it in GitHub Desktop.
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
-main Sandbox.hx | |
-js Sandbox.js |
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; | |
#if macro | |
import haxe.macro.Context; | |
import haxe.macro.Expr; | |
typedef DecoratedField = { | |
field: Field, | |
meta: MetadataEntry | |
}; | |
#end | |
class Decorator { | |
#if macro | |
static public inline var TYPE = ':type'; | |
static public function build() { | |
var localClass = haxe.macro.Context.getLocalClass().get(); | |
var fields = haxe.macro.Context.getBuildFields(); | |
var constructor: haxe.macro.Field = null; | |
var exprs: Array<Expr> = []; | |
fields = fields.filter(function(f) { | |
if (f.name != "new") { | |
return true; | |
} else { | |
constructor = f; | |
return false; | |
} | |
}); | |
var index = 0; | |
var hasSuperClass = localClass.superClass; | |
if (hasSuperClass != null) { | |
var superClass = hasSuperClass.t.get(); | |
// add super() call on constructor. | |
if (constructor == null) { | |
exprs.push(macro super()); | |
} else { | |
switch (constructor.kind) { | |
case FFun(f): exprs.unshift(f.expr); | |
default: | |
} | |
} | |
var parentFields = superClass.fields.get(); | |
for (f in parentFields) { | |
// FIXME: check for annotated types instead of starting with "_". | |
if (f.name.indexOf("_") != 0) { | |
index++; | |
} | |
} | |
} | |
var decoratedFields = getDecoratedFields(fields); | |
for (f in decoratedFields) { | |
exprs.push(macro $p{["this", "_indexes"]}.set($v{index}, $v{f.field.name})); | |
exprs.push(macro $p{["this", "_types"]}.set($v{index}, $e{f.meta.params[0]})); | |
if (f.meta.params.length > 1) { | |
switch f.meta.params[1].expr { | |
case EConst(CIdent(exp)): | |
exprs.push(macro $p{["this", "_childSchemaTypes"]}.set($v{index}, $i{exp})); | |
case EConst(CString(exp)): | |
exprs.push(macro $p{["this", "_childPrimitiveTypes"]}.set($v{index}, $v{exp})); | |
default: | |
} | |
} | |
index++; | |
} | |
// add constructor to fields | |
fields.push({ | |
name: "new", | |
pos: Context.currentPos(), | |
access: [APublic], | |
kind: FFun({ | |
args: [], | |
expr: macro $b{exprs}, | |
params: [], | |
ret: null | |
}) | |
}); | |
return fields; | |
} | |
static function getDecoratedFields(fields:Array<Field>) | |
return fields.map(getDecoration).filter(notNull); | |
static function getDecoration(field:Field):DecoratedField { | |
for (meta in field.meta) { | |
if (meta.name == TYPE) | |
return { | |
field: field, | |
meta: meta | |
}; | |
} | |
return null; | |
} | |
static function notNull(v:Dynamic) | |
return v != null; | |
#end | |
} | |
#if !macro @:autoBuild(Decorator.build()) #end | |
class Schema { | |
public var _indexes: Map<Int, String> = []; | |
public var _types: Map<Int, String> = []; | |
public var _childSchemaTypes: Map<Int, Class<Schema>> = []; | |
public var _childPrimitiveTypes: Map<Int, String> = []; | |
public function new(){} | |
} | |
class Entity extends Schema { | |
@:type("number") | |
public var x: Dynamic = 0; | |
@:type("number") | |
public var y: Dynamic = 0; | |
} | |
class Player extends Entity { | |
@:type("string") | |
public var name: String = ""; | |
} | |
class State extends Schema { | |
@:type("string") | |
public var myString: String = ""; | |
@:type("number") | |
public var myNumber: Dynamic = 0; | |
@:type("ref", Player) | |
public var player: Player = new Player(); | |
public function new () { | |
super(); | |
trace("HELLO!"); | |
} | |
} | |
class Sandbox { | |
static function main() { | |
var state = new State(); | |
trace("INITIALIZED"); | |
trace(State); | |
trace("_indexes => ", state._indexes); | |
trace("_types => ", state._types); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment