Created
March 23, 2011 03:22
-
-
Save zoon/882558 to your computer and use it in GitHub Desktop.
Recursive alpha-renamer for 'this'
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.Context; | |
import haxe.macro.Expr; | |
using Lambda; | |
class Macros | |
{ | |
public static var fresh(getFresh, null):String; | |
private static var _fresh:Int = 0; | |
private static function getFresh() | |
{ | |
return "_u" + (_fresh++); | |
} | |
private static var _wasThis:Bool; | |
/** | |
* Makes thunk (nulary function) from expression. Permits 'this' in expression. | |
* TODO: add arguments? | |
* NOTE: practically untested | |
* @param expression : T | |
* @return Void -> T | |
*/ | |
@:macro public static function fn(body:Expr):Expr | |
{ | |
_wasThis = false; | |
var fnargs = []; | |
var pos = Context.currentPos(); | |
var self = fresh; | |
var thisId = { pos:pos, expr:EConst(CIdent("this")) }; | |
var local = { pos:pos, expr:EVars([ { name:self, type:null, expr:thisId } ]) }; | |
var enew = substExpr(body, self); | |
var fn = { pos:pos, expr:EFunction( { args:fnargs, ret:null, name:null, expr:enew } ) }; | |
if (_wasThis) | |
return { pos:pos, expr:EBlock([local, fn]) }; | |
else | |
return fn; | |
} | |
private static function substExpr(?e:Expr, to:String) | |
{ | |
if (e == null) | |
return e; | |
return { expr:substExprDef(e.expr, to), pos:e.pos }; | |
} | |
private static function substExpArray(es:Array<Expr>, to:String) | |
{ | |
var result:Array<Expr> = []; | |
for (e in es) | |
result.push(substExpr(e, to)); | |
return result; | |
} | |
private static function substExprDef(expr:ExprDef, to:String):ExprDef | |
{ | |
switch (expr) | |
{ | |
case EConst(c): return expr; | |
case EArray(e1, e2): return EArray(substExpr(e1,to), substExpr(e2,to)); | |
case EBinop(op , e1, e2): return EBinop(op, substExpr(e1, to), substExpr(e2, to)); | |
case EField(e, field): | |
switch(e.expr) | |
{ | |
case EConst(c): | |
{ | |
if (Type.enumEq(c, CIdent("this"))) | |
{ | |
_wasThis = true; | |
return EField( { expr:EConst(CIdent(to)), pos:e.pos }, field); | |
} | |
else | |
return EField(substExpr(e, to), field); | |
} | |
default: | |
return EField(substExpr(e, to), field); | |
} | |
case EType(e, field): return expr; | |
case EParenthesis(e): return EParenthesis(substExpr(e,to)); | |
case EObjectDecl(fields): return expr; | |
case EArrayDecl(values): return EArrayDecl(substExpArray(values, to)); | |
case ECall(e, params): return ECall(substExpr(e, to), substExpArray(params, to)); | |
case ENew( t, params): return ENew(t, substExpArray(params, to)); | |
case EUnop( op, postFix, e): return EUnop(op,postFix,substExpr(e,to)); | |
case EVars(vars): return EVars(Lambda.map(vars, function(v) return | |
{ | |
name:v.name, type:v.type, expr:substExpr(v.expr, to) | |
}).array()); | |
case EFunction(f): | |
return EFunction( { ret:f.ret, name:f.name, args:f.args, expr:substExpr(f.expr, to) } ); | |
case EBlock( exprs): return EBlock(substExpArray(exprs, to)); | |
case EFor(v, it, expr): | |
return EFor(v, substExpr(it, to), substExpr(expr, to)); | |
case EIf( econd, eif, eelse): | |
return EIf(substExpr(econd, to), substExpr(eif, to), substExpr(eelse, to)); | |
case EWhile( econd, e, normalWhile): | |
return EWhile(substExpr(econd, to), substExpr(e, to), normalWhile); | |
case ESwitch(e, cases, edef): | |
return ESwitch(substExpr(e, to), Lambda.map(cases , function(v) return | |
{ | |
values:substExpArray(v.values, to), | |
expr:substExpr(v.expr, to) | |
}).array(), substExpr(edef, to)); | |
case ETry(e, catches): | |
return ETry(substExpr(e, to), Lambda.map(catches, function(v) return | |
{ | |
name:v.name,type:v.type, expr:substExpr(v.expr, to) | |
}).array()); | |
case EReturn(e): return EReturn(substExpr(e,to)); | |
case EBreak: return expr; | |
case EContinue: return expr; | |
case EUntyped(e): return EUntyped(substExpr(e, to)); | |
case EThrow(e): return EThrow(substExpr(e, to)); | |
case ECast(e, t): return ECast(substExpr(e, to), t); | |
case EDisplay(e, isCall): return EDisplay(substExpr(e, to), isCall); | |
case EDisplayNew(t): return expr; | |
case ETernary(econd, eif, eelse): | |
return ETernary(substExpr(econd, to), substExpr(eif, to), substExpr(eelse, to)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment