Created
March 18, 2011 13:01
-
-
Save zoon/876025 to your computer and use it in GitHub Desktop.
Property extraction macro
This file contains hidden or 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.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