Browse Source

removed (moved to hxbit a long time ago)

ncannasse 6 years ago
parent
commit
62c5edf011
1 changed files with 0 additions and 1409 deletions
  1. 0 1409
      hxd/net/Macros.hx

+ 0 - 1409
hxd/net/Macros.hx

@@ -1,1409 +0,0 @@
-package hxd.net;
-import haxe.macro.Expr;
-import haxe.macro.Type;
-import haxe.macro.Context;
-using haxe.macro.TypeTools;
-using haxe.macro.ComplexTypeTools;
-
-enum RpcMode {
-	/*
-		When called on the client: will forward the call on the server, but not execute locally.
-		When called on the server: will forward the call to the clients (and force its execution), then execute.
-		This is the default behavior.
-	*/
-	All;
-	/*
-		When called on the server: will forward the call to the clients, but not execute locally.
-		When called on the client: will execute locally.
-	*/
-	Client;
-	/*
-		When called on the client: will forward the call the server, but not execute locally.
-		When called on the server: will execute locally.
-	*/
-	Server;
-	/*
-		When called on the client: will forward the call to the server if not the owner, or else execute locally.
-		When called on the server: will forward the call to the owner.
-		Will fail if there is no owner.
-	*/
-	Owner;
-}
-
-enum PropTypeDesc<PropType> {
-	PInt;
-	PFloat;
-	PBool;
-	PString;
-	PBytes;
-	PSerializable( name : String );
-	PEnum( name : String );
-	PMap( k : PropType, v : PropType );
-	PArray( k : PropType );
-	PObj( fields : Array<{ name : String, type : PropType, opt : Bool }> );
-	PAlias( k : PropType );
-	PVector( k : PropType );
-	PNull( t : PropType );
-	PUnknown;
-}
-
-typedef PropType = {
-	var d : PropTypeDesc<PropType>;
-	var t : ComplexType;
-	@:optional var isProxy : Bool;
-	@:optional var increment : Float;
-	@:optional var condSend : Expr;
-	@:optional var notMutable : Bool;
-}
-
-class Macros {
-
-	static var IN_ENUM_SER = false;
-
-	public static macro function serializeValue( ctx : Expr, v : Expr ) : Expr {
-		var t = Context.typeof(v);
-		var pt = getPropType(t);
-		if( pt == null ) {
-			Context.error("Unsupported serializable type " + t.toString(), v.pos);
-			return macro { };
-		}
-		IN_ENUM_SER = StringTools.startsWith(Context.getLocalClass().toString(), "hxd.net.enumSer.");
-		return serializeExpr(ctx, v, pt);
-	}
-
-	public static macro function unserializeValue( ctx : Expr, v : Expr ) : Expr {
-		var t = Context.typeof(v);
-		var pt = getPropType(t);
-		if( pt == null ) {
-			return macro { };
-		}
-		IN_ENUM_SER = StringTools.startsWith(Context.getLocalClass().toString(), "hxd.net.enumSer.");
-		return unserializeExpr(ctx, v, pt);
-	}
-
-	public static macro function getFieldType( v : Expr ) {
-		var t = Context.typeof(v);
-		var pt = getPropType(t);
-		if( pt == null )
-			return macro null;
-		var v = toFieldType(pt);
-		return macro $v{v};
-	}
-
-	#if macro
-
-	static function toFieldType( t : PropType ) : Schema.FieldType {
-		return switch( t.d ) {
-		case PInt: PInt;
-		case PFloat: PFloat;
-		case PBool: PBool;
-		case PString: PString;
-		case PBytes: PBytes;
-		case PSerializable(name): PSerializable(name);
-		case PEnum(name): PEnum(name);
-		case PMap(k, v): PMap(toFieldType(k), toFieldType(v));
-		case PArray(v): PArray(toFieldType(v));
-		case PObj(fields): PObj([for( f in fields ) { name : f.name, type : toFieldType(f.type), opt : f.opt }]);
-		case PAlias(t): return toFieldType(t);
-		case PVector(k): PVector(toFieldType(k));
-		case PNull(t): PNull(toFieldType(t));
-		case PUnknown: PUnknown;
-		};
-	}
-
-	static function isSerializable( c : Ref<ClassType> ) {
-		while( true ) {
-			var cg = c.get();
-			for( i in cg.interfaces )
-				switch( i.t.toString() ) {
-				case "hxd.net.Serializable", "hxd.net.NetworkSerializable":
-					return true;
-				default:
-				}
-			var sup = cg.superClass;
-			if( sup == null )
-				break;
-			c = sup.t;
-		}
-		return false;
-	}
-
-	static function getPropField( ft : Type, meta : Metadata ) {
-		var t = getPropType(ft);
-		if( t == null )
-			return null;
-		for( m in meta) {
-			switch( m.name ) {
-			case ":s", ":optional":
-				//
-			case ":increment":
-				var inc : Null<Float> = null;
-				if( m.params.length == 1 )
-					switch( m.params[0].expr ) {
-					case EConst(CInt(i)): inc = Std.parseInt(i);
-					case EConst(CFloat(f)): inc = Std.parseFloat(f);
-					default:
-					}
-				if( inc == null )
-					Context.error("Increment requires value parameter", m.pos);
-				switch( t.d ) {
-				case PFloat, PNull({ d : PFloat }):
-					t.increment = inc;
-				default:
-					Context.error("Increment not allowed on " + t.t.toString(), m.pos);
-				}
-			case ":condSend" if( m.params.length == 1 ):
-				t.condSend = m.params[0];
-			case ":notMutable":
-				t.notMutable = true;
-			default:
-				Context.error("Unsupported network metadata", m.pos);
-			}
-		}
-		return t;
-	}
-
-	static function getPropType( t : haxe.macro.Type ) : PropType {
-		var isProxy = false;
-		var desc = switch( t ) {
-		case TAbstract(a, pl):
-			switch( a.toString() ) {
-			case "Float":
-				PFloat;
-			case "Int","UInt":
-				PInt;
-			case "Bool":
-				PBool;
-			case "Map":
-				var tk = getPropType(pl[0]);
-				var tv = getPropType(pl[1]);
-				if( tk == null || tv == null )
-					return null;
-				PMap(tk, tv);
-			case "haxe.ds.Vector":
-				var tk = getPropType(pl[0]);
-				if( tk == null )
-					return null;
-				PVector(tk);
-			case "hxd.net.VectorProxy":
-				var t = getPropType(pl[0]);
-				if( t == null )
-					return null;
-				isProxy = true;
-				PVector(t);
-			case "hxd.net.ArrayProxy", "hxd.net.ArrayProxy2":
-				var t = getPropType(pl[0]);
-				if( t == null )
-					return null;
-				isProxy = true;
-				PArray(t);
-			case "hxd.net.MapProxy", "hxd.net.MapProxy2":
-				var k = getPropType(pl[0]);
-				var v = getPropType(pl[1]);
-				if( k == null || v == null ) return null;
-				isProxy = true;
-				PMap(k,v);
-			case name:
-				var t2 = Context.followWithAbstracts(t, true);
-				switch( t2 ) {
-				case TAbstract(a2, _) if( a2.toString() == name ):
-					return null;
-				default:
-				}
-				var pt = getPropType(t2);
-				if( pt == null ) return null;
-				PAlias(pt);
-			}
-		case TEnum(e,_):
-			PEnum(e.toString());
-		case TAnonymous(a):
-			var a = a.get();
-			var fields = [];
-			for( f in a.fields ) {
-				if( f.meta.has(":noSerialize") )
-					continue;
-				var ft = getPropField(f.type, f.meta.get());
-				if( ft == null ) return null;
-				fields.push( { name : f.name, type : ft, opt : f.meta.has(":optional") } );
-			}
-			PObj(fields);
-		case TInst(c, pl):
-			switch( c.toString() ) {
-			case "String":
-				PString;
-			case "Array":
-				var at = getPropType(pl[0]);
-				if( at == null ) return null;
-				PArray(at);
-			case "haxe.io.Bytes":
-				PBytes;
-			case name if( StringTools.startsWith(name, "hxd.net.ObjProxy_") ):
-				var fields = c.get().fields.get();
-				for( f in fields )
-					if( f.name == "__value" ) {
-						var t = getPropType(f.type);
-						t.isProxy = true;
-						return t;
-					}
-				throw "assert";
-			default:
-				if( isSerializable(c) )
-					PSerializable(c.toString());
-				else
-					return null;
-			}
-		case TType(td, pl):
-			switch( td.toString() ) {
-			case "Null":
-				var p = getPropType(pl[0]);
-				if( p != null && !isNullable(p) )
-					p = { d : PNull(p), t : TPath( { pack : [], name : "Null", params : [TPType(p.t)] } ) };
-				return p;
-			default:
-				var p = getPropType(Context.follow(t, true));
-				if( p != null )
-					p.t = t.toComplexType(); // more general, still identical
-				return p;
-			}
-		default:
-			return null;
-		}
-		var p : PropType = {
-			d : desc,
-			t : t.toComplexType(),
-		};
-		if( isProxy ) p.isProxy = isProxy;
-		return p;
-	}
-
-	static function isNullable( t : PropType ) {
-		switch( t.d ) {
-		case PInt, PFloat, PBool:
-			return false;
-		default:
-			return true;
-		}
-	}
-
-	static function toType( t : ComplexType ) : Type {
-		return Context.typeof(macro (null:$t));
-	}
-
-	static function serializeExpr( ctx : Expr, v : Expr, t : PropType, skipCheck = false ) {
-
-		if( t.isProxy && !skipCheck )
-			return serializeExpr(ctx, { expr : EField(v, "__value"), pos : v.pos }, t, true);
-
-		switch( t.d ) {
-		case PFloat:
-			return macro $ctx.addFloat($v);
-		case PInt:
-			return macro $ctx.addInt($v);
-		case PBool:
-			return macro $ctx.addBool($v);
-		case PBytes:
-			return macro $ctx.addBytes($v);
-		case PMap(kt, vt):
-			var kt = kt.t;
-			var vt = vt.t;
-			var vk = { expr : EConst(CIdent("k")), pos : v.pos };
-			var vv = { expr : EConst(CIdent("v")), pos : v.pos };
-			return macro $ctx.addMap($v, function(k:$kt) return hxd.net.Macros.serializeValue($ctx, $vk), function(v:$vt) return hxd.net.Macros.serializeValue($ctx, $vv));
-		case PEnum(_):
-			var et = t.t;
-			var ser = "serialize";
-			if( IN_ENUM_SER )
-				ser += "2";
-			return macro (null : hxd.net.Serializable.SerializableEnum<$et>).$ser($ctx,$v);
-		case PObj(fields):
-			var nullables = [for( f in fields ) if( isNullable(f.type) ) f];
-			var ct = t.t;
-			if( nullables.length >= 32 )
-				Context.error("Too many nullable fields", v.pos);
-			return macro {
-				var v : $ct = $v;
-				if( v == null )
-					$ctx.addByte(0);
-				else {
-					var fbits = 0;
-					$b{[
-						for( i in 0...nullables.length ) {
-							var name = nullables[i].name;
-							macro if( v.$name != null ) fbits |= $v{ 1 << i };
-						}
-					]};
-					$ctx.addInt(fbits + 1);
-					$b{[
-						for( f in fields ) {
-							var nidx = nullables.indexOf(f);
-							var name = f.name;
-							if( nidx < 0 )
-								macro hxd.net.Macros.serializeValue($ctx, v.$name);
-							else
-								macro if( fbits & $v{1<<nidx} != 0 ) hxd.net.Macros.serializeValue($ctx, v.$name);
-						}
-					]};
-				}
-			};
-		case PString:
-			return macro $ctx.addString($v);
-		case PArray(t):
-			var at = toProxy(t);
-			var ve = { expr : EConst(CIdent("e")), pos : v.pos };
-			return macro $ctx.addArray($v, function(e:$at) return hxd.net.Macros.serializeValue($ctx, $ve));
-		case PVector(t):
-			var at = toProxy(t);
-			var ve = { expr : EConst(CIdent("e")), pos : v.pos };
-			return macro $ctx.addVector($v, function(e:$at) return hxd.net.Macros.serializeValue($ctx, $ve));
-		case PSerializable(_):
-			return macro $ctx.addKnownRef($v);
-		case PAlias(t):
-			return serializeExpr(ctx, { expr : ECast(v, null), pos : v.pos }, t);
-		case PNull(t):
-			var e = serializeExpr(ctx, v, t);
-			return macro if( $v == null ) $ctx.addByte(0) else { $ctx.addByte(1); $e; };
-		case PUnknown:
-			throw "assert";
-		}
-	}
-
-	static function unserializeExpr( ctx : Expr, v : Expr, t : PropType ) {
-		switch( t.d ) {
-		case PFloat:
-			return macro $v = $ctx.getFloat();
-		case PInt:
-			return macro $v = $ctx.getInt();
-		case PBool:
-			return macro $v = $ctx.getBool();
-		case PBytes:
-			return macro $v = $ctx.getBytes();
-		case PMap(k,t):
-			var kt = k.t;
-			var vt = t.t;
-			var vk = { expr : EConst(CIdent("k")), pos : v.pos };
-			var vv = { expr : EConst(CIdent("v")), pos : v.pos };
-			return macro {
-				var k : $kt;
-				var v : $vt;
-				$v = $ctx.getMap(function() { hxd.net.Macros.unserializeValue($ctx, $vk); return $vk; }, function() { hxd.net.Macros.unserializeValue($ctx, $vv); return $vv; });
-			};
-		case PEnum(_):
-			var et = t.t;
-			var unser = "unserialize";
-			if( IN_ENUM_SER )
-				unser += "2";
-			return macro { var __e : $et; __e = (null : hxd.net.Serializable.SerializableEnum<$et>).$unser($ctx); $v = __e; }
-		case PObj(fields):
-			var nullables = [for( f in fields ) if( isNullable(f.type) ) f];
-			if( nullables.length >= 32 )
-				Context.error("Too many nullable fields", v.pos);
-			var ct = t.t;
-			return macro {
-				var fbits = $ctx.getInt();
-				if( fbits == 0 )
-					$v = null;
-				else {
-					fbits--;
-					$b{{
-						var exprs = [];
-						var vars = [];
-						for( f in fields ) {
-							var nidx = nullables.indexOf(f);
-							var name = f.name;
-							var ct = f.type.t;
-							vars.push( { field : name, expr : { expr : EConst(CIdent(name)), pos:v.pos } } );
-							if( nidx < 0 ) {
-								exprs.unshift(macro var $name : $ct);
-								exprs.push(macro hxd.net.Macros.unserializeValue($ctx, $i { name } ));
-							} else {
-								exprs.unshift(macro var $name : $ct = null);
-								exprs.push(macro if( fbits & $v { 1 << nidx } != 0 ) hxd.net.Macros.unserializeValue($ctx, $i { name } ));
-							}
-						}
-						exprs.push( { expr : EBinop(OpAssign,v, { expr : EObjectDecl(vars), pos:v.pos } ), pos:v.pos } );
-						exprs;
-					}};
-				}
-			};
-		case PString:
-			return macro $v = $ctx.getString();
-		case PArray(at):
-			var at = toProxy(at);
-			var ve = { expr : EConst(CIdent("e")), pos : v.pos };
-			return macro {
-				var e : $at;
-				$v = $ctx.getArray(function() { hxd.net.Macros.unserializeValue($ctx, e); return e; });
-			};
-		case PVector(at):
-			var at = toProxy(at);
-			var ve = { expr : EConst(CIdent("e")), pos : v.pos };
-			return macro {
-				var e : $at;
-				$v = $ctx.getVector(function() { hxd.net.Macros.unserializeValue($ctx, e); return e; });
-			};
-		case PSerializable(_):
-			function loop(t:ComplexType) {
-				switch( t ) {
-				case TPath( { name : "Null", params:[TPType(t)] } ):
-					return loop(t);
-				case TPath( p = { params:a } ) if( a.length > 0 ):
-					return TPath( { pack : p.pack, name:p.name, sub:p.sub } );
-				default:
-					return t;
-				}
-			}
-			var cexpr = Context.parse(loop(t.t).toString(), v.pos);
-			return macro $v = $ctx.getRef($cexpr,@:privateAccess $cexpr.__clid);
-		case PAlias(at):
-			var cvt = at.t;
-			return macro {
-				var v : $cvt;
-				${unserializeExpr(ctx,macro v,at)};
-				$v = cast v;
-			};
-		case PNull(t):
-			var e = unserializeExpr(ctx, v, t);
-			return macro if( $ctx.getByte() == 0 ) $v = null else $e;
-		case PUnknown:
-			throw "assert";
-		}
-	}
-
-	static function withPos( e : Expr, p : Position ) {
-		e.pos = p;
-		haxe.macro.ExprTools.iter(e, function(e) withPos(e, p));
-		return e;
-	}
-
-	public static function buildSerializable() {
-		var cl = Context.getLocalClass().get();
-		if( cl.isInterface )
-			return null;
-		var fields = Context.getBuildFields();
-		var toSerialize = [];
-
-		if( !Context.defined("display") )
-		for( f in fields ) {
-			if( f.meta == null ) continue;
-			for( meta in f.meta )
-				if( meta.name == ":s" ) {
-					toSerialize.push({ f : f, m : meta });
-					break;
-				}
-		}
-
-		var fieldsInits = [];
-		for( f in fields ) {
-			if( f.access.indexOf(AStatic) >= 0 ) continue;
-			switch( f.kind ) {
-			case FVar(_, e), FProp(_, _, _, e) if( e != null ):
-				// before unserializing
-				fieldsInits.push({ expr : EBinop(OpAssign,{ expr : EConst(CIdent(f.name)), pos : e.pos },e), pos : e.pos });
-			default:
-			}
-		}
-
-		var sup = cl.superClass;
-		var isSubSer = sup != null && isSerializable(sup.t);
-
-		var pos = Context.currentPos();
-		var el = [], ul = [];
-		for( f in toSerialize ) {
-			var fname = f.f.name;
-			el.push(withPos(macro hxd.net.Macros.serializeValue(__ctx, this.$fname),f.f.pos));
-			ul.push(withPos(macro hxd.net.Macros.unserializeValue(__ctx, this.$fname),f.f.pos));
-		}
-
-		var noCompletion = [{ name : ":noCompletion", pos : pos }];
-		var access = [APublic];
-		if( isSubSer )
-			access.push(AOverride);
-		else
-			fields.push({
-				name : "__uid",
-				pos : pos,
-				access : [APublic],
-				meta : noCompletion,
-				kind : FVar(macro : Int, macro @:privateAccess hxd.net.Serializer.allocUID()),
-			});
-
-		var clName = StringTools.endsWith(cl.module,"."+cl.name) ? cl.module.split(".") : [cl.name];
-		fields.push({
-			name : "__clid",
-			pos : pos,
-			access : [AStatic],
-			meta : noCompletion,
-			kind : FVar(macro : Int, macro @:privateAccess hxd.net.Serializer.registerClass($p{clName})),
-		});
-		fields.push({
-			name : "getCLID",
-			pos : pos,
-			access : access,
-			meta : noCompletion,
-			kind : FFun({ args : [], ret : macro : Int, expr : macro return __clid }),
-		});
-
-		var needSerialize = toSerialize.length != 0 || !isSubSer;
-		var needUnserialize = needSerialize || fieldsInits.length != 0;
-
-		if( needSerialize ) {
-			fields.push({
-				name : "serialize",
-				pos : pos,
-				access : access,
-				kind : FFun({
-					args : [ { name : "__ctx", type : macro : hxd.net.Serializer } ],
-					ret : null,
-					expr : macro @:privateAccess { ${ if( isSubSer ) macro super.serialize(__ctx) else macro { } }; $b{el} }
-				}),
-			});
-			var schema = [for( s in toSerialize ) {
-				var name = s.f.name;
-				macro { schema.fieldsNames.push($v{name}); schema.fieldsTypes.push(hxd.net.Macros.getFieldType(this.$name)); }
-			}];
-			fields.push({
-				name : "getSerializeSchema",
-				pos : pos,
-				access : access,
-				meta : noCompletion,
-				kind : FFun({
-					args : [],
-					ret : null,
-					expr : macro { var schema = ${if( isSubSer ) macro super.getSerializeSchema() else macro new hxd.net.Schema()}; $b{schema}; return schema; }
-				})
-			});
-		}
-
-		if( fieldsInits.length > 0 || !isSubSer )
-			fields.push({
-				name : "unserializeInit",
-				pos : pos,
-				meta : noCompletion,
-				access : access,
-				kind : FFun({
-					args : [],
-					ret : null,
-					expr : isSubSer ? macro { super.unserializeInit(); $b{fieldsInits}; } : { expr : EBlock(fieldsInits), pos : pos },
-				})
-			});
-
-		if( needUnserialize ) {
-			var unserExpr = macro @:privateAccess { ${ if( isSubSer ) macro super.unserialize(__ctx) else macro { } }; $b{ul} };
-
-			for( f in fields )
-				if( f.name == "unserialize" ) {
-					var found = false;
-					function repl(e:Expr) {
-						switch( e.expr ) {
-						case ECall( { expr : EField( { expr : EConst(CIdent("super")) }, "unserialize") }, [ctx]):
-							found = true;
-							return macro { var __ctx : hxd.net.Serializer = $ctx; $unserExpr; }
-						default:
-							return haxe.macro.ExprTools.map(e, repl);
-						}
-					}
-					switch( f.kind ) {
-					case FFun(f):
-						f.expr = repl(f.expr);
-					default:
-					}
-					if( !found ) Context.error("Override of unserialize() with no super.unserialize(ctx) found", f.pos);
-					return fields;
-				}
-
-			fields.push({
-				name : "unserialize",
-				pos : pos,
-				access : access,
-				kind : FFun({
-					args : [ { name : "__ctx", type : macro : hxd.net.Serializer } ],
-					ret : null,
-					expr : unserExpr,
-				}),
-			});
-		}
-
-		return fields;
-	}
-
-	public static function buildSerializableEnum() {
-		var pt = switch( Context.getLocalType() ) {
-		case TInst(_, [pt]): pt;
-		default: null;
-		}
-		if( pt != null )
-			pt = Context.follow(pt);
-		if( pt != null )
-		switch( pt ) {
-		case TEnum(e, tparams):
-			var e = e.get();
-			var name = e.pack.length == 0 ? e.name : e.pack.join("_") + "_" + e.name;
-			try {
-				return Context.getType("hxd.net.enumSer." + name);
-			} catch( _ : Dynamic ) {
-				var pos = Context.currentPos();
-				var cases = [], ucases = [];
-				if( e.names.length >= 256 )
-					Context.error("Too many constructors", pos);
-				for( f in e.names ) {
-					var c = e.constructs.get(f);
-					switch( Context.follow(c.type) ) {
-					case TFun(args, _):
-						var eargs = [for( a in args ) macro hxd.net.Macros.serializeValue(ctx,$i{a.name})];
-						cases.push({
-							values : [{ expr : ECall({ expr : EConst(CIdent(c.name)), pos : pos },[for( a in args ) { expr : EConst(CIdent(a.name)), pos : pos }]), pos : pos }],
-							expr : macro {
-								ctx.addByte($v{c.index+1});
-								$b{eargs};
-							}
-						});
-
-						var evals = [];
-						for( a in args ) {
-							var aname = "_" + a.name;
-							var at = haxe.macro.TypeTools.applyTypeParameters(a.t,e.params,tparams).toComplexType();
-							evals.push(macro var $aname : $at);
-							evals.push(macro hxd.net.Macros.unserializeValue(ctx,$i{aname}));
-						}
-						evals.push({ expr : ECall({ expr : EConst(CIdent(c.name)), pos : pos },[for( a in args ) { expr : EConst(CIdent("_"+a.name)), pos : pos }]), pos : pos });
-						ucases.push({
-							values : [macro $v{c.index+1}],
-							expr : { expr : EBlock(evals), pos : pos },
-						});
-
-					default:
-						cases.push({
-							values : [ { expr : EConst(CIdent(c.name)), pos : pos } ],
-							expr : macro ctx.addByte($v{c.index+1}),
-						});
-						ucases.push({
-							values : [macro $v{c.index+1}],
-							expr : { expr : EConst(CIdent(c.name)), pos : pos },
-						});
-					}
-				}
-				var t : TypeDefinition = {
-					name : name,
-					pack : ["hxd","net","enumSer"],
-					kind : TDClass(),
-					fields : [
-					{
-						name : "doSerialize",
-						access : [AStatic],
-						pos : pos,
-						kind : FFun( {
-							args : [{ name : "ctx", type : macro : hxd.net.Serializer },{ name : "v", type : pt.toComplexType() }],
-							expr : macro @:privateAccess if( v == null ) ctx.addByte(0) else ${{ expr : ESwitch(macro v,cases,null), pos : pos }},
-							ret : macro : Void,
-						}),
-					},{
-						name : "doUnserialize",
-						access : [AStatic],
-						pos : pos,
-						kind : FFun( {
-							args : [{ name : "ctx", type : macro : hxd.net.Serializer }],
-							expr : macro @:privateAccess {
-								var b = ctx.getByte();
-								if( b == 0 )
-									return null;
-								return ${{ expr : ESwitch(macro b,ucases,macro throw "Invalid enum index "+b), pos : pos }}
-							},
-							ret : pt.toComplexType(),
-						}),
-
-					},{
-						name : "serialize",
-						access : [AInline, APublic],
-						meta : [{name:":extern",pos:pos}],
-						pos : pos,
-						kind : FFun( {
-							args : [{ name : "ctx", type : macro : hxd.net.Serializer },{ name : "v", type : pt.toComplexType() }],
-							expr : macro doSerialize(ctx,v),
-							ret : null,
-						}),
-					},{
-						name : "unserialize",
-						access : [AInline, APublic],
-						meta : [{name:":extern",pos:pos}],
-						pos : pos,
-						kind : FFun( {
-							args : [{ name : "ctx", type : macro : hxd.net.Serializer }],
-							expr : macro return doUnserialize(ctx),
-							ret : null,
-						}),
-					}],
-					pos : pos,
-				};
-
-				// hack to allow recursion (duplicate serialize/unserialize for recursive usage)
-				var tf = Reflect.copy(t.fields[t.fields.length - 2]);
-				tf.name += "2";
-				t.fields.push(tf);
-				var tf = Reflect.copy(t.fields[t.fields.length - 2]);
-				tf.name += "2";
-				t.fields.push(tf);
-
-				Context.defineType(t);
-				return Context.getType("hxd.net.enumSer." + name);
-			}
-		default:
-		}
-		Context.error("Enum expected", Context.currentPos());
-		return null;
-	}
-
-	static function quickInferType( e : Expr ) {
-		if( e == null )
-			return null;
-		switch( e.expr ) {
-		case EConst(CInt(_)):
-			return macro : Int;
-		case EConst(CFloat(_)):
-			return macro : Float;
-		case EConst(CString(_)):
-			return macro : String;
-		case EConst(CIdent("true" | "false")):
-			return macro : Bool;
-		default:
-		}
-		return null;
-	}
-
-	static function needProxy( t : PropType ) {
-		if( t == null || t.isProxy )
-			return false;
-		switch( t.d ) {
-		case PMap(_), PArray(_), PObj(_), PVector(_):
-			return !t.notMutable;
-		default:
-			return false;
-		}
-	}
-
-	static function checkProxy( p : PropType ) {
-		if( needProxy(p) ) {
-			p.isProxy = true;
-			p.t = toProxy(p);
-		}
-	}
-
-	static function toProxy( p : PropType ) {
-		if( !p.isProxy )
-			return p.t;
-		var pt = p.t;
-		return macro : hxd.net.NetworkSerializable.Proxy<$pt>;
-	}
-
-
-	static var hasRetVal : Bool;
-	static function hasReturnVal( e : Expr ) {
-		hasRetVal = false;
-		checkRetVal(e);
-		return hasRetVal;
-	}
-
-	static function checkRetVal( e : Expr ) {
-		if( hasRetVal )
-			return;
-		switch( e.expr ) {
-		case EReturn(e):
-			if( e != null )
-				hasRetVal = true;
-		case EFunction(_):
-			return;
-		default:
-			haxe.macro.ExprTools.iter(e, checkRetVal);
-		}
-	}
-
-	static function superImpl( name : String, e : Expr ) {
-		switch( e.expr ) {
-		case EField( esup = { expr : EConst(CIdent("super")) }, fname) if( fname == name ):
-			e.expr = EField(esup, name+"__impl");
-		default:
-		}
-		return haxe.macro.ExprTools.map(e, superImpl.bind(name));
-	}
-
-	static function replaceSetter( fname : String, setExpr : Expr -> Expr, e : Expr ) {
-		switch( e.expr ) {
-		case EBinop(OpAssign, e1 = { expr : (EConst(CIdent(name)) | EField( { expr : EConst(CIdent("this")) }, name)) }, e2) if( name == fname ):
-			e.expr = EBinop(OpAssign,e1,setExpr(e2));
-		case EBinop(OpAssignOp(_), { expr : (EConst(CIdent(name)) | EField( { expr : EConst(CIdent("this")) }, name)) }, _) if( name == fname ):
-			throw "TODO";
-		default:
-			haxe.macro.ExprTools.iter(e, function(e) replaceSetter(fname,setExpr,e));
-		}
-	}
-
-	public static function buildNetworkSerializable() {
-		var cl = Context.getLocalClass().get();
-		if( cl.isInterface )
-			return null;
-		var fields = Context.getBuildFields();
-		var toSerialize = [];
-		var rpc = [];
-		var superRPC = new Map();
-		var superFields = new Map();
-		var startFID = 0, rpcID = 0;
-		{
-			var sup = cl.superClass;
-			while( sup != null ) {
-				var c = sup.t.get();
-				for( m in c.meta.get() )
-					switch( m.name)  {
-					case ":rpcCalls":
-						for( a in m.params )
-							switch( a.expr ) {
-							case EConst(CIdent(id)):
-								rpcID++;
-								superRPC.set(id, true);
-							default:
-								throw "assert";
-							}
-					case ":sFields":
-						for( a in m.params )
-							switch( a.expr ) {
-							case EConst(CIdent(id)):
-								superFields.set(id, true);
-								startFID++;
-							default:
-								throw "assert";
-							}
-					}
-				sup = c.superClass;
-			}
-		}
-
-		if( !Context.defined("display") )
-		for( f in fields ) {
-
-			if( superRPC.exists(f.name) ) {
-				switch( f.kind ) {
-				case FFun(ff):
-					ff.expr = superImpl(f.name, ff.expr);
-				default:
-				}
-				f.name += "__impl";
-				continue;
-			}
-
-			if( f.access.indexOf(AOverride) >= 0 && StringTools.startsWith(f.name, "set_") && superFields.exists(f.name.substr(4)) ) {
-				// overridden setter of network property
-				var fname = f.name.substr(4);
-				switch( f.kind ) {
-				case FFun(ff):
-					replaceSetter(fname, function(e) return macro $i{"__net_mark_"+fname}($e), ff.expr);
-				default:
-				}
-				continue;
-			}
-
-			if( f.meta == null ) continue;
-
-			for( meta in f.meta ) {
-				if( meta.name == ":s" ) {
-					toSerialize.push({ f : f, m : meta });
-					break;
-				}
-				if( meta.name == ":rpc" ) {
-					var mode : RpcMode = All;
-					if( meta.params.length != 0 )
-						switch( meta.params[0].expr ) {
-						case EConst(CIdent("all")):
-						case EConst(CIdent("client")): mode = Client;
-						case EConst(CIdent("server")): mode = Server;
-						case EConst(CIdent("owner")): mode = Owner;
-						default:
-							Context.error("Unexpected Rpc mode : should be all|client|server|owner", meta.params[0].pos);
-						}
-					rpc.push( { f : f, mode:mode } );
-					superRPC.set(f.name, true);
-					break;
-				}
-			}
-		}
-
-		var sup = cl.superClass;
-		var isSubSer = sup != null && isSerializable(sup.t);
-		var pos = Context.currentPos();
-		if( !isSubSer ) {
-			fields = fields.concat((macro class {
-				@:noCompletion public var __host : hxd.net.NetworkHost;
-				@:noCompletion public var __bits : Int = 0;
-				@:noCompletion public var __next : hxd.net.NetworkSerializable;
-				@:noCompletion public inline function networkSetBit( b : Int ) {
-					if( __host != null && (__next != null || @:privateAccess __host.mark(this)) )
-						__bits |= 1 << b;
-				}
-				public var enableReplication(get, set) : Bool;
-				inline function get_enableReplication() return __host != null;
-				function set_enableReplication(b) {
-					@:privateAccess hxd.net.NetworkHost.enableReplication(this, b);
-					return b;
-				}
-				public inline function networkCancelProperty( props : hxd.net.NetworkSerializable.NetworkProperty ) {
-					__bits &= ~props.toInt();
-				}
-				public inline function networkLocalChange( f : Void -> Void ) {
-					var old = __host;
-					__host = null;
-					f();
-					__host = old;
-				}
-			}).fields);
-
-			if( !Lambda.exists(fields, function(f) return f.name == "networkGetOwner") )
-				fields = fields.concat((macro class {
-					public function networkGetOwner() : hxd.net.NetworkSerializable { return null; }
-				}).fields);
-		}
-
-		var firstFID = startFID;
-		var flushExpr = [];
-		var syncExpr = [];
-		var noComplete : Metadata = [ { name : ":noCompletion", pos : pos } ];
-		for( f in toSerialize ) {
-			var pos = f.f.pos;
-			var fname = f.f.name;
-			var bitID = startFID++;
-			var ftype : PropType;
-			switch( f.f.kind ) {
-			case FVar(t, e):
-				if( t == null ) t = quickInferType(e);
-				if( t == null ) Context.error("Type required", pos);
-				var tt = Context.resolveType(t, pos);
-				ftype = getPropField(tt, f.f.meta);
-				if( ftype == null ) ftype = { t : t, d : PUnknown };
-				checkProxy(ftype);
-				f.f.kind = FProp("default", "set", ftype.t, e);
-			case FProp(get, set, t, e):
-				if( t == null ) t = quickInferType(e);
-				if( t == null ) Context.error("Type required", pos);
-				var tt = Context.resolveType(t, pos);
-				ftype = getPropField(tt, f.f.meta);
-				if( ftype == null ) ftype = { t : t, d : PUnknown };
-				checkProxy(ftype);
-				if( set == "null" )
-					Context.warning("Null setter is not respected when using NetworkSerializable", pos);
-				else if( set != "default" && set != "set" )
-					Context.error("Invalid setter", pos);
-				f.f.kind = FProp(get,"set", ftype.t, e);
-			default:
-				throw "assert";
-			}
-
-			var markExpr = macro networkSetBit($v{ bitID });
-			markExpr = makeMarkExpr(fields, fname, ftype, markExpr);
-
-			var markFun = "__net_mark_" + f.f.name;
-			fields.push( {
-				name : markFun,
-				access : [AInline],
-				meta : noComplete,
-				pos : pos,
-				kind : FFun({
-					args : [{ name : "v", type : ftype.t }],
-					ret : ftype.t,
-					expr : macro {
-						if( this.$fname != v ) {
-							$markExpr;
-							${if( ftype.isProxy ) macro (if( v != null ) v.bindHost(this,$v{bitID})) else macro {}};
-						}
-						return v;
-					}
-				}),
-			});
-
-			var found = false;
-			for( set in fields )
-				if( set.name == "set_" + f.f.name )
-					switch( set.kind ) {
-					case FFun(fun):
-						replaceSetter(f.f.name, function(e) return macro $i{markFun}($e),fun.expr);
-						found = true;
-						break;
-					default:
-					}
-			if( !found )
-				fields.push({
-					name : "set_" + fname,
-					pos : pos,
-					kind : FFun({
-						args : [ { name : "v", type : ftype.t } ],
-						expr : macro return this.$fname = $i{markFun}(v),
-						ret : ftype.t,
-					}),
-				});
-			var fexpr = { expr : EField({ expr : EConst(CIdent("this")), pos : pos }, fname), pos : pos };
-			flushExpr.push(macro if( b & (1 << $v{ bitID } ) != 0 ) hxd.net.Macros.serializeValue(ctx, $fexpr));
-			syncExpr.push(macro if( __bits & (1 << $v { bitID } ) != 0 ) hxd.net.Macros.unserializeValue(ctx, $fexpr));
-
-			var prop = "networkProp" + fname.charAt(0).toUpperCase() + fname.substr(1);
-			fields.push({
-				name : prop,
-				pos : pos,
-				kind : FProp("get", "never", macro : hxd.net.NetworkSerializable.NetworkProperty),
-				access : [APublic],
-			});
-			fields.push({
-				name : "get_"+prop,
-				pos : pos,
-				kind : FFun( {
-					args : [],
-					expr : macro return new hxd.net.NetworkSerializable.NetworkProperty(1 << $v{bitID}),
-					ret : null,
-				}),
-				access : [AInline],
-			});
-		}
-
-		// BUILD RPC
-		var firstRPCID = rpcID;
-		var rpcCases = [];
-		for( r in rpc ) {
-			switch( r.f.kind ) {
-			case FFun(f):
-				var id = rpcID++;
-				var hasReturnVal = hasReturnVal(f.expr);
-				var name = r.f.name;
-				var p = r.f.pos;
-				r.f.name += "__impl";
-
-				var cargs = [for( a in f.args ) { expr : EConst(CIdent(a.name)), pos : p } ];
-				var fcall = { expr : ECall( { expr : EField( { expr : EConst(CIdent("this")), pos:p }, r.f.name), pos : p }, cargs), pos : p };
-
-				var doCall = fcall;
-				var rpcArgs = f.args;
-				var resultCall = macro null;
-
-				if( hasReturnVal ) {
-					doCall = macro onResult($fcall);
-					resultCall = macro function(__ctx) {
-						var v = cast null;
-						if( false ) v = $fcall;
-						hxd.net.Macros.unserializeValue(__ctx, v);
-						onResult(v);
-					};
-					rpcArgs = rpcArgs.copy();
-					rpcArgs.push( { name : "onResult", type: f.ret == null ? null : TFunction([f.ret], macro:Void) } );
-				}
-
-				var forwardRPC = macro {
-					var __ctx = @:privateAccess __host.beginRPC(this,$v{id},$resultCall);
-					$b{[
-						for( a in f.args )
-							withPos(macro hxd.net.Macros.serializeValue(__ctx, $i{a.name}), f.expr.pos)
-					] };
-					@:privateAccess __host.endRPC();
-				};
-
-				var rpcExpr = switch( r.mode ) {
-				case All:
-					macro {
-						if( __host != null ) {
-							$forwardRPC;
-							if( !__host.isAuth ) return;
-						}
-						$doCall;
-					}
-				case Client:
-					macro {
-						if( __host != null && __host.isAuth ) {
-							$forwardRPC;
-							return;
-						}
-						$doCall;
-					}
-				case Server:
-					macro {
-						if( __host != null && !__host.isAuth ) {
-							$forwardRPC;
-							return;
-						}
-						$doCall;
-					}
-				case Owner:
-					macro {
-						if( __host == null ) return;
-						var owner = networkGetOwner();
-						if( owner == null ) throw "Calling RPC(owner) function on a not owned object";
-						if( owner != __host.self.ownerObject ) @:privateAccess {
-							var old = __host.targetClient;
-							if( __host.setTargetOwner(owner) ) {
-								$forwardRPC;
-								__host.setTargetOwner(null);
-							}
-							__host.targetClient = old;
-							return;
-						}
-						$doCall;
-					}
-				};
-
-				var rpc : Field = {
-					name : name,
-					access : r.f.access.copy(),
-					kind : FFun({
-						args : rpcArgs,
-						ret : macro : Void,
-						expr : rpcExpr,
-					}),
-					pos : p,
-					meta : [{ name : ":final", pos : p }],
-				};
-				fields.push(rpc);
-
-				r.f.access.remove(APublic);
-				r.f.meta.push( { name : ":noCompletion", pos : p } );
-
-				var exprs = [ { expr : EVars([for( a in f.args ) { name : a.name, type : a.type, expr : macro cast null } ]), pos : p } ];
-				exprs.push(macro if( false ) $fcall); // force typing
-				for( a in f.args )
-					exprs.push(macro hxd.net.Macros.unserializeValue(__ctx, $i { a.name } ));
-
-				if( hasReturnVal ) {
-					exprs.push({ expr : EVars([ { name : "result", type : f.ret, expr : fcall } ]), pos : p } );
-					exprs.push(macro {
-						@:privateAccess __clientResult.beginRPCResult();
-						hxd.net.Macros.serializeValue(__ctx, result);
-					});
-				} else
-					exprs.push(fcall);
-
-				rpcCases.push({ values : [{ expr : EConst(CInt(""+id)), pos : p }], guard : null, expr : { expr : EBlock(exprs), pos : p } });
-
-			default:
-				Context.error("Cannot use @:rpc on non function", r.f.pos);
-			}
-		}
-
-		// Add network methods
-		var access = [APublic];
-		if( isSubSer ) access.push(AOverride);
-
-		if( fields.length != 0 || !isSubSer ) {
-			if( isSubSer ) {
-				flushExpr.unshift(macro super.networkFlush(ctx));
-				syncExpr.unshift(macro super.networkSync(ctx));
-			} else {
-				flushExpr.unshift(macro ctx.addInt(__bits));
-				flushExpr.push(macro __bits = 0);
-				syncExpr.unshift(macro __bits = ctx.getInt());
-			}
-			flushExpr.unshift(macro var b = __bits);
-			fields.push({
-				name : "networkFlush",
-				pos : pos,
-				access : access,
-				meta : noComplete,
-				kind : FFun({
-					args : [ { name : "ctx", type : macro : hxd.net.Serializer } ],
-					ret : null,
-					expr : { expr : EBlock(flushExpr), pos : pos },
-				}),
-			});
-
-			fields.push({
-				name : "networkSync",
-				pos : pos,
-				access : access,
-				meta : noComplete,
-				kind : FFun({
-					args : [ { name : "ctx", type : macro : hxd.net.Serializer } ],
-					ret : null,
-					expr : macro @:privateAccess $b{syncExpr},
-				}),
-			});
-		}
-
-		if( rpc.length != 0 || !isSubSer ) {
-			var swExpr = { expr : ESwitch( { expr : EConst(CIdent("__id")), pos : pos }, rpcCases, macro throw "Unknown RPC identifier " + __id), pos : pos };
-			fields.push({
-				name : "networkRPC",
-				pos : pos,
-				access : access,
-				meta : noComplete,
-				kind : FFun({
-					args : [ { name : "__ctx", type : macro : hxd.net.Serializer }, { name : "__id", type : macro : Int }, { name : "__clientResult", type : macro : hxd.net.NetworkHost.NetworkClient } ],
-					ret : null,
-					expr : if( isSubSer && firstRPCID > 0 ) macro { if( __id < $v { firstRPCID } ) { super.networkRPC(__ctx, __id, __clientResult); return; } $swExpr; } else swExpr,
-				}),
-			});
-		}
-
-
-		if( toSerialize.length != 0 || rpc.length != 0 || !isSubSer ) {
-			var cases = [];
-			for( i in 0...toSerialize.length )
-				cases.push( { id : i + firstFID, name : toSerialize[i].f.name } );
-			for( i in 0...rpc.length )
-				cases.push( { id : i + startFID + firstRPCID, name : rpc[i].f.name.substr(0,-6) } );
-			var ecases = [for( c in cases ) { values : [ { expr : EConst(CInt("" + c.id)), pos : pos } ], expr : { expr : EConst(CString(c.name)), pos : pos }, guard : null } ];
-			var swExpr = { expr : EReturn( { expr : ESwitch(macro isRPC ? id + $v { startFID } : id, ecases, macro null), pos : pos } ), pos : pos };
-			fields.push( {
-				name : "networkGetName",
-				pos : pos,
-				access : access,
-				meta : noComplete,
-				kind : FFun({
-					args : [ { name : "id", type : macro : Int }, { name : "isRPC", type : macro : Bool, value:macro false } ],
-					ret : macro : String,
-					expr : if( isSubSer ) macro { if( id < (isRPC ? $v{ firstRPCID } : $v{ firstFID }) ) return super.networkGetName(id, isRPC); $swExpr; } else swExpr,
-				}),
-			});
-		}
-
-
-		// add metadata
-
-		if( startFID > 32 ) Context.error("Too many serializable fields", pos);
-		if( rpcID > 255 ) Context.error("Too many rpc calls", pos);
-
-		if( rpc.length > 0 )
-			cl.meta.add(":rpcCalls", [for( r in rpc ) { expr : EConst(CIdent(r.f.name.substr(0, -6))), pos : pos } ], pos);
-		if( toSerialize.length > 0 )
-			cl.meta.add(":sFields", [for( r in toSerialize ) { expr : EConst(CIdent(r.f.name)), pos : pos }], pos);
-
-		return fields;
-	}
-
-	static function makeMarkExpr( fields : Array<Field>, fname : String, t : PropType, mark : Expr ) {
-		var rname = "__ref_" + fname;
-		var needRef = false;
-		if( t.increment != null ) {
-			needRef = true;
-			mark = macro if( Math.floor(this.$fname / $v{t.increment}) != this.$rname ) { this.$rname = Math.floor(this.$fname / $v{t.increment}); $mark; };
-		}
-		if( t.condSend != null ) {
-			function loop(e:Expr) {
-				switch( e.expr ) {
-				case EConst(CIdent("current")):
-					return { expr : EConst(CIdent(rname)), pos : e.pos };
-				default:
-					return haxe.macro.ExprTools.map(e, loop);
-				}
-			}
-			if( t.condSend.expr.match(EConst(CIdent("false"))) )
-				return macro {}; // no marking
-			var condSend = loop(t.condSend);
-			needRef = true;
-			mark = macro if( $condSend ) { this.$rname = this.$fname; $mark; };
-		}
-		if( needRef && fields != null )
-			fields.push({
-				name : rname,
-				pos : mark.pos,
-				meta : [{ name : ":noCompletion", pos : mark.pos }],
-				kind : FVar(t.t,macro 0),
-			});
-		return mark;
-	}
-
-	static function buildProxyType( p : PropType ) : ComplexType {
-		if( !needProxy(p) )
-			return p.t;
-		switch( p.d ) {
-		case PArray(k):
-			checkProxy(k);
-			var subName = k.isProxy ? "ArrayProxy2" : "ArrayProxy";
-			return TPath( { pack : ["hxd", "net"], name : "ArrayProxy", sub : subName, params : [TPType(k.t)] } );
-		case PVector(k):
-			checkProxy(k);
-			var subName = k.isProxy ? "VectorProxy2" : "VectorProxy";
-			return TPath( { pack : ["hxd", "net"], name : "VectorProxy", sub : subName, params : [TPType(k.t)] } );
-		case PMap(k, v):
-			checkProxy(v);
-			var subName = k.isProxy ? "MapProxy2" : "MapProxy";
-			return TPath( { pack : ["hxd", "net"], name : "MapProxy", sub : subName, params : [TPType(k.t),TPType(v.t)] } );
-		case PObj(fields):
-			// define type
-			var name = "ObjProxy_";
-			fields.sort(function(f1, f2) return Reflect.compare(f1.name, f2.name));
-			name += [for( f in fields ) f.name+"_" + ~/[<>.]/g.replace(f.type.t.toString(),"_")].join("_");
-			try {
-				return Context.getType("hxd.net." + name).toComplexType();
-			} catch( e : Dynamic ) {
-				var pos = Context.currentPos();
-				var pt = p.t;
-				var myT = TPath( { pack : ["hxd", "net"], name : name } );
-				var tfields = (macro class {
-					var obj : hxd.net.NetworkSerializable.ProxyHost;
-					var bit : Int;
-					@:noCompletion public var __value(get, never) : $pt;
-					inline function get___value() : $pt return cast this;
-					inline function mark() if( obj != null ) obj.networkSetBit(bit);
-					@:noCompletion public function networkSetBit(_) mark();
-					@:noCompletion public function bindHost(obj, bit) { this.obj = obj; this.bit = bit; }
-					@:noCompletion public function unbindHost() this.obj = null;
-				}).fields;
-				for( f in fields ) {
-					var ft = f.type.t;
-					var fname = f.name;
-					tfields.push({
-						name : f.name,
-						pos : pos,
-						access : [APublic],
-						kind : FProp("default","set",ft),
-					});
-
-					var markExpr = makeMarkExpr(tfields, fname, f.type, macro mark());
-
-					tfields.push( {
-						name : "set_" + f.name,
-						pos : pos,
-						access : [AInline],
-						kind : FFun({
-							ret : ft,
-							args : [ { name : "v", type : ft } ],
-							expr : macro { this.$fname = v; $markExpr; return v; }
-						}),
-					});
-				}
-				tfields.push({
-					name : "new",
-					pos : pos,
-					access : [APublic],
-					kind : FFun({
-						ret : null,
-						args : [for( f in fields ) { name : f.name, type : f.type.t, opt : f.opt } ],
-						expr : { expr : EBlock([for( f in fields ) { var fname = f.name; macro this.$fname = $i{fname}; }]), pos : pos },
-					})
-				});
-				var t : TypeDefinition = {
-					pos : pos,
-					pack : ["hxd", "net"],
-					meta : [{ name : ":structInit", pos : pos }],
-					name : name,
-					kind : TDClass([
-						{ pack : ["hxd", "net"], name : "NetworkSerializable", sub : "ProxyHost" },
-						{ pack : ["hxd", "net"], name : "NetworkSerializable", sub : "ProxyChild" },
-					]),
-					fields : tfields,
-				};
-				Context.defineType(t);
-				return TPath({ pack : ["hxd","net"], name : name });
-			}
-		default:
-		}
-		return null;
-	}
-
-	public static function buildSerializableProxy() {
-		var t = Context.getLocalType();
-		switch( t ) {
-		case TInst(_, [pt]):
-			var p = getPropType(pt);
-			if( p != null ) {
-				var t = buildProxyType(p);
-				if( t != null ) return toType(t);
-			}
-			throw "TODO "+pt+" ("+p+")";
-		default:
-			throw "assert";
-		}
-	}
-
-	#end
-
-}