Skip to content

Instantly share code, notes, and snippets.

@Dvergar
Last active December 12, 2016 22:46
Show Gist options
  • Select an option

  • Save Dvergar/e2faa5f006c0482a5343232760f50721 to your computer and use it in GitHub Desktop.

Select an option

Save Dvergar/e2faa5f006c0482a5343232760f50721 to your computer and use it in GitHub Desktop.
Variable listener
import lemino.Listener;
using lemino.Lemino;
class HpView
{
public function new() {}
public function onHpUpdate(value:Int, player:Player)
trace("hpupdate " + value);
}
class Player implements Listener
{
@listen public var hp:Int = 20;
public function new() {}
}
class Main
{
public function new()
{
trace("DUMMY");
var player = new Player();
player.makeView(player.hp, new HpView());
player.hp += 4;
}
static public function main() new Main();
}
package lemino;
import haxe.macro.Context;
import haxe.macro.Expr;
class Lemino {
static function capitalize(str:String) : String {
var firstChar:String = str.substr(0, 1);
var restOfString:String = str.substr(1, str.length);
return firstChar.toUpperCase()+restOfString.toLowerCase();
}
macro static public function makeView(bindInst, attr, viewInst)
{
// CATCH LISTENED VAR NAME FROM ARGUMENT
var varListened = "";
switch(attr.expr)
{
case EField(ex, v):
varListened = v;
case _:
}
// GENERATE EVENT FUNCTION NAME (used as name in source(model) & target(view))
var funcName = "on"+capitalize(varListened)+"Update";
// BUILD EVENT FUNCTION
var exp = macro ${bindInst}.$funcName = ${viewInst}.$funcName;
var exp2 = macro ${viewInst}.$funcName($attr, $bindInst);
var exps:Array<Expr> = new Array();
exps.push(exp);
exps.push(exp2);
trace(new haxe.macro.Printer().printExprs(exps, " | "));
return macro $b{exps};
}
macro static public function build():Array<Field>
{
var fields = Context.getBuildFields();
var listenVarNames = new Array<String>();
var listenVarTypes = new Array<ComplexType>();
for(f in fields)
{
if(f.meta.length != 0)
{
for(m in f.meta)
{
// CATCHING LISTEN METADATA
if(m.name == "listen")
{
trace(f);
listenVarNames.push(f.name);
// ATTACH A LISTENER TO THE VAR
switch(f.kind)
{
case FVar(tpath, val):
f.kind = FieldType.FProp("default", "set", tpath, val);
switch(tpath)
{
case TPath(type):
listenVarTypes.push(tpath);
case _:
}
case _:
}
}
}
}
}
// BUILD SETTER
var i = 0;
for(listenVarName in listenVarNames)
{
// SETTER NAME
var setterName = "set_" + listenVarName;
// TODO RENAME listenvarname and above other name
var binderName = "on"+capitalize(listenVarName)+"Update";
var tpath = listenVarTypes[i];
var type = macro : $tpath;
var tooptmp = Context.getLocalType();
var tooptmp = Context.toComplexType(tooptmp);
var toop = macro : $tooptmp;
trace(toop);
// SETTER FUNCTION
var setter = macro class
{
// public var test:$toop;
public var $binderName:$type->$toop->Void;
public function $setterName(value)
{
if($i{binderName} != null) $i{binderName}(value, this);
return this.$listenVarName = value;
}
};
// PUSH SETTER
fields = fields.concat(setter.fields);
i++;
}
// DEBUG
trace("---- DEBUG VIEW ----");
for(f in fields)
{
#if debug trace(new haxe.macro.Printer().printField(f) ); #end
}
trace("---- END DEBUG VIEW ----");
return fields;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment