Skip to content

Instantly share code, notes, and snippets.

@endel
Last active May 2, 2019 21:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save endel/30ef12fd88d6684cb4d7c15be55b5088 to your computer and use it in GitHub Desktop.
Save endel/30ef12fd88d6684cb4d7c15be55b5088 to your computer and use it in GitHub Desktop.
-main Sandbox.hx
-js Sandbox.js
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