|
package ; |
|
|
|
import haxe.macro.Type; |
|
import haxe.macro.Expr; |
|
import haxe.macro.Context; |
|
|
|
using haxe.macro.Tools; |
|
|
|
class MacroHijacked { |
|
|
|
#if macro |
|
private static var counter:Int = 0; |
|
|
|
public static function build() { |
|
var type = Context.getLocalType(); |
|
|
|
switch (type) { |
|
case TInst(_, params): |
|
type = params[0]; |
|
|
|
switch (type) { |
|
case TInst(rcls, params): |
|
var cls = rcls.get(); |
|
var ifields = cls.fields.get(); |
|
var sfields = cls.statics.get(); |
|
|
|
var ctype = Context.toComplexType( type ); |
|
var others:Array<Array<Field>->Void> = []; |
|
var fields:Array<Field> = [for (field in ifields) if (field.isPublic) { |
|
var _type = field.type.applyTypeParameters(cls.params, params); |
|
{ |
|
name: field.name, |
|
access: [APublic, switch(field.kind) { case FMethod(_):AInline; case _:APublic; } ], |
|
kind: switch (field.kind) { |
|
case FVar(_, _): |
|
others.push( function(f) { |
|
f.push( { |
|
name: 'get_${field.name}', |
|
access: [APrivate,AInline], |
|
kind: FFun( { args:[], ret:_type.toComplexType(), expr:Context.parse( 'return this.${field.name}', field.pos ) } ), |
|
pos: field.pos, |
|
} ); |
|
} ); |
|
FProp('get', 'never', _type.toComplexType(), null); |
|
|
|
case FMethod(k): |
|
var typed = field.expr(); |
|
var fargs:Array<FunctionArg> = []; |
|
var nargs:Array<String> = []; |
|
var ret:Type = null; |
|
|
|
if (typed != null) switch (typed.expr) { |
|
case TFunction(f): |
|
fargs = [for (arg in f.args) { |
|
var _t = try arg.v.t.applyTypeParameters(cls.params, params) catch (_e:Dynamic) arg.v.t; |
|
{ name:arg.v.name, type:_t.toComplexType() }; |
|
} ]; |
|
nargs = [for (arg in f.args) arg.v.name]; |
|
ret = f.t; |
|
|
|
case _: |
|
} else switch (field.type) { |
|
case TFun(a, r): |
|
fargs = [for (aa in a) { name:aa.name, type:aa.t.applyTypeParameters(cls.params, params).toComplexType() } ]; |
|
nargs = [for (aa in a) aa.name]; |
|
ret = r; |
|
|
|
case _: |
|
} |
|
|
|
var args = nargs.join(","); |
|
ret = ret.applyTypeParameters(cls.params, params); |
|
|
|
FFun( { |
|
args: fargs, |
|
ret: ret.toComplexType(), |
|
expr: macro { |
|
return $e { Context.parse( 'this.${field.name}($args)', field.pos ) }; |
|
}, |
|
params: [for (param in field.params) { |
|
{ name: param.name, params: [{name:param.t.getClass().name, params:[]}] } |
|
}], |
|
} ); |
|
}, |
|
pos: field.pos, |
|
} |
|
}]; |
|
|
|
for (other in others) other(fields); |
|
|
|
var td = { |
|
name: 'Hijacked${cls.name}_$counter', |
|
pack: [], |
|
pos: cls.pos, |
|
params: [], |
|
kind: TDAbstract( ctype, [ctype], [ctype] ), |
|
fields: fields, |
|
} |
|
|
|
Context.defineType( td ); |
|
type = Context.getType( td.name ); |
|
|
|
counter++; |
|
|
|
case _: |
|
} |
|
|
|
case _: |
|
} |
|
|
|
return type; |
|
} |
|
#end |
|
|
|
} |