Skip to content

Instantly share code, notes, and snippets.

@zoon
Created March 18, 2011 13:01
Show Gist options
  • Save zoon/876025 to your computer and use it in GitHub Desktop.
Save zoon/876025 to your computer and use it in GitHub Desktop.
Property extraction macro
package ;
import haxe.macro.Expr;
import haxe.macro.Context;
class Test
{
public static var staticField:String = "hello";
public var intField:Int;
public var floatProp(getB, setB):Float;
private var _floatProp:Float;
private function getB() { return _floatProp;}
private function setB(v:Float) { return _floatProp = v; }
public function new()
{
intField = 1;
floatProp = 3.14;
}
}
class Main
{
public static var fresh(getFresh, null):String;
private static var _fresh:Int = 0;
private static function getFresh()
{
return "_u" + (_fresh++);
}
/**
* Object's field/property extraction macro
* @param field
* @return { set : T -> T, get : Void -> T }
*/
@:macro public static function prop(field:Expr)
{
var pos = Context.currentPos();
switch (field.expr)
{
case EField(_, __):
// getter
var getBody:Expr = { expr:EReturn( { expr:field.expr, pos:pos } ), pos:pos };
var getFn = EFunction( { ret:null, name:null, expr:getBody, args:[] } );
// setter
var fresh = fresh;
var rval:Expr = { expr:EConst(CIdent(fresh)), pos:pos };
var assign:ExprDef = EBinop(Binop.OpAssign, field, rval);
var setBody:Expr = { expr:EReturn( { expr:assign, pos:pos } ), pos:pos };
var arg:FunctionArg = { value:null, type:null, opt:false, name:fresh };
var setFn = EFunction( { ret:null, name:null, expr:setBody, args:[arg] } );
// record
var get = { field:"get", expr: { expr:getFn, pos:pos }};
var set = { field:"set", expr: { expr:setFn, pos:pos }};
return { expr:EObjectDecl([get, set]), pos:pos };
default:
return Context.error("prop macro: argument must be a field", pos);
}
}
// DEMO:
static function main()
{
var staticFieldEx = type(prop(Test.staticField));
var t = new Test();
var intFieldEx = type(prop(t.intField));
var floatPropEx = type(prop(t.floatProp));
// TEST:
trace(staticFieldEx.get());
trace(staticFieldEx.set("world!"));
trace(staticFieldEx.get());
trace(intFieldEx.get());
trace(intFieldEx.set(42));
trace(intFieldEx.get());
trace(floatPropEx.get());
trace(floatPropEx.set(2.71828));
trace(floatPropEx.get());
// trace(prop(t)); // <-- expected compile-time error
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment