Răsfoiți Sursa

indexed enums

Nicolas Cannasse 18 ani în urmă
părinte
comite
eb468d8785
13 a modificat fișierele cu 178 adăugiri și 122 ștergeri
  1. 3 0
      doc/CHANGES.txt
  2. 7 5
      genas3.ml
  3. 8 7
      genjs.ml
  4. 7 6
      genneko.ml
  5. 14 7
      genswf8.ml
  6. 31 13
      genswf9.ml
  7. 16 7
      std/Type.hx
  8. 3 3
      std/flash/Boot.hx
  9. 26 17
      std/haxe/Serializer.hx
  10. 32 44
      std/haxe/Unserializer.hx
  11. 3 3
      std/js/Boot.hx
  12. 3 1
      type.ml
  13. 25 9
      typer.ml

+ 3 - 0
doc/CHANGES.txt

@@ -20,6 +20,9 @@
 	removed haxe.Proxy
 	added flash.XMLRequest
 	fixed Type.enumParameters for Neko
+	guaranteed order of Type.getEnumConstructs same as code
+	used index-based dispatch for enums
+	added Type.enumIndex
 
 2007-08-29: 1.15
 	fixed bug with Enum.construct when Enum have type parameters

+ 7 - 5
genas3.ml

@@ -517,11 +517,11 @@ and gen_expr ctx e =
 		print ctx "var %s : enum = " tmp;
 		gen_value ctx e;
 		newline ctx;
-		print ctx "switch( %s.tag ) {" tmp;
+		print ctx "switch( %s.index ) {" tmp;
 		newline ctx;
 		List.iter (fun (cl,params,e) ->
 			List.iter (fun c ->
-				print ctx "case \"%s\":" c;
+				print ctx "case %d:" c;
 				newline ctx;
 			) cl;
 			let b = save_locals ctx in
@@ -840,7 +840,7 @@ let generate_enum ctx e =
 	newline ctx;
 	print ctx "public static const __isenum : Boolean = true";
 	newline ctx;
-	print ctx "public function %s( t : String, p : Array = null ) : void { this.tag = t; this.params = p; }" ename;
+	print ctx "public function %s( t : String, index : int, p : Array = null ) : void { this.tag = t; this.index = index; this.params = p; }" ename;
 	PMap.iter (fun _ c ->
 		newline ctx;
 		match c.ef_type with
@@ -851,11 +851,11 @@ let generate_enum ctx e =
 				if o then spr ctx " = null";
 			) args;
 			print ctx ") : %s {" ename;
-			print ctx " return new %s(\"%s\",[" ename c.ef_name;
+			print ctx " return new %s(\"%s\",%d,[" ename c.ef_name c.ef_index;
 			concat ctx "," (fun (a,_,_) -> spr ctx a) args;
 			print ctx "]); }";
 		| _ ->
-			print ctx "public static var %s : %s = new %s(\"%s\")" c.ef_name ename ename c.ef_name;
+			print ctx "public static var %s : %s = new %s(\"%s\",%d)" c.ef_name ename ename c.ef_name c.ef_index;
 	) e.e_constrs;
 	cl();
 	newline ctx;
@@ -872,6 +872,8 @@ let generate_base_enum ctx =
 	newline ctx;
 	spr ctx "public var tag : String";
 	newline ctx;
+	spr ctx "public var index : int";
+	newline ctx;
 	spr ctx "public var params : Array";
 	cl();
 	newline ctx;

+ 8 - 7
genjs.ml

@@ -382,21 +382,21 @@ and gen_expr ctx e =
 		bend();
 		newline ctx;
 		spr ctx "}";
-	| TMatch (e,_,cases,def) ->
+	| TMatch (e,(estruct,_),cases,def) ->
 		spr ctx "var $e = ";
 		gen_value ctx e;
 		newline ctx;
-		spr ctx "switch( $e[0] ) {";
+		spr ctx "switch( $e[1] ) {";
 		newline ctx;
 		List.iter (fun (cl,params,e) ->
 			List.iter (fun c ->
-				print ctx "case \"%s\":" c;
+				print ctx "case %d:" c;
 				newline ctx;
 			) cl;
 			(match params with
 			| None | Some [] -> ()
 			| Some l ->
-				let n = ref 0 in
+				let n = ref 1 in
 				let l = List.fold_left (fun acc (v,_) -> incr n; match v with None -> acc | Some v -> (v,!n) :: acc) [] l in
 				match l with
 				| [] -> ()
@@ -637,16 +637,17 @@ let generate_class ctx c =
 let generate_enum ctx e =
 	let p = s_path e.e_path in
 	generate_package_create ctx e.e_path;
-	print ctx "%s = { __ename__ : [%s] }" p (String.concat "," (List.map (fun s -> Printf.sprintf "\"%s\"" (Ast.s_escape s)) (fst e.e_path @ [snd e.e_path])));
+	let ename = List.map (fun s -> Printf.sprintf "\"%s\"" (Ast.s_escape s)) (fst e.e_path @ [snd e.e_path]) in
+	print ctx "%s = { __ename__ : [%s], __constructs__ : [%s] }" p (String.concat "," ename) (String.concat "," (List.map (Printf.sprintf "\"%s\"") e.e_names));
 	newline ctx;
 	PMap.iter (fun _ f ->
 		print ctx "%s%s = " p (field f.ef_name);
 		(match f.ef_type with
 		| TFun (args,_) ->
 			let sargs = String.concat "," (List.map arg_name args) in
-			print ctx "function(%s) { var $x = [\"%s\",%s]; $x.__enum__ = %s; return $x; }" sargs f.ef_name sargs p;
+			print ctx "function(%s) { var $x = [\"%s\",%d,%s]; $x.__enum__ = %s; return $x; }" sargs f.ef_name f.ef_index sargs p;
 		| _ ->
-			print ctx "[\"%s\"]" f.ef_name;
+			print ctx "[\"%s\",%d]" f.ef_name f.ef_index;
 			newline ctx;
 			print ctx "%s%s.__enum__ = %s" p (field f.ef_name) p;
 		);

+ 7 - 6
genneko.ml

@@ -402,7 +402,7 @@ and gen_expr ctx e =
 		call p (builtin p "throw") [gen_expr ctx e]
 	| TMatch (e,_,cases,eo) ->
 		let etmp = (EVars ["@tmp",Some (gen_expr ctx e)],p) in
-		let etag = field p (ident p "@tmp") "tag" in
+		let eindex = field p (ident p "@tmp") "index" in
 		let gen_params params e =
 			match params with
 			| None ->
@@ -433,10 +433,10 @@ and gen_expr ctx e =
 		  (EBlock [
 			etmp;
 			(ESwitch (
-				etag,
+				eindex,
 				List.map (fun (cl,params,e2) ->
 					let cond = match cl with
-						| [s] -> str p s
+						| [s] -> int p s
 						| _ -> raise Exit
 					in					
 					cond , gen_params params e2
@@ -448,12 +448,12 @@ and gen_expr ctx e =
 			Exit ->
 				(EBlock [
 					etmp;
-					(EVars ["@tag",Some etag],p);
+					(EVars ["@index",Some eindex],p);
 					List.fold_left (fun acc (cl,params,e2) ->
 						let cond = (match cl with
 							| [] -> assert false
 							| c :: l ->
-								let eq c = (EBinop ("==",ident p "@tag",str p c),p) in
+								let eq c = (EBinop ("==",ident p "@index",int p c),p) in
 								List.fold_left (fun acc c -> (EBinop ("||",acc,eq c),p)) (eq c) l
 						) in
 						EIf (cond,gen_params params e2,Some acc),p
@@ -572,6 +572,7 @@ let gen_enum_constr ctx path c =
 				(EBlock [
 					(EVars ["@tmp",Some (EObject [
 						"tag" , str p c.ef_name;
+						"index" , int p c.ef_index;
 						"args" , array p (List.map (ident p) params);
 					],p)],p);
 					call p (builtin p "objsetproto") [ident p "@tmp"; field p path "prototype"];
@@ -580,7 +581,7 @@ let gen_enum_constr ctx path c =
 			),p)
 		| _ ->
 			(EBlock [
-				(EVars ["@tmp",Some (EObject ["tag" , str p c.ef_name; "__serialize" , ident p "@tag_serialize"],p)],p);
+				(EVars ["@tmp",Some (EObject ["tag" , str p c.ef_name; "index", int p c.ef_index; "__serialize" , ident p "@tag_serialize"],p)],p);
 				call p (builtin p "objsetproto") [ident p "@tmp"; field p path "prototype"];				
 				ident p "@tmp";
 			],p)

+ 14 - 7
genswf8.ml

@@ -657,7 +657,7 @@ and gen_match ctx retval e cases def =
 	gen_expr ctx true e;
 	let renum = alloc_tmp ctx in
 	set_tmp ctx renum;
-	push ctx [VInt 0];
+	push ctx [VInt 1];
 	write ctx AObjGet;
 	let rtag = alloc_tmp ctx in
 	set_tmp ctx rtag;
@@ -665,7 +665,7 @@ and gen_match ctx retval e cases def =
 	let dispatch = List.map (fun (cl,params,e) ->
 		List.map (fun c ->
 			if !first then first := false else get_tmp ctx rtag;
-			push ctx [VStr (c,false)];
+			push ctx [VInt c];
 			write ctx APhysEqual;
 			cjmp ctx
 		) cl, params, e
@@ -680,7 +680,7 @@ and gen_match ctx retval e cases def =
 		let regs = ctx.regs in
 		let nregs = ctx.reg_count in
 		List.iter (fun j -> j()) jl;
-		let n = ref 0 in
+		let n = ref 1 in
 		List.iter (fun (a,t) ->
 			incr n;
 			match a with
@@ -1117,7 +1117,7 @@ let gen_enum_field ctx e f =
 		ctx.reg_count <- 1;
 		let no_reg = ctx.version = 6 in
 		let rargs = List.map (fun (n,_,_) -> if no_reg then 0, n else alloc_reg ctx , "") args in
-		let nregs = List.length rargs + 1 in
+		let nregs = List.length rargs + 2 in
 		let tf = func ctx false false rargs in
 		List.iter (fun (r,name) -> 
 			if no_reg then begin
@@ -1126,7 +1126,7 @@ let gen_enum_field ctx e f =
 			end else
 				push ctx [VReg r]
 		) (List.rev rargs);
-		push ctx [VStr (f.ef_name,false); VInt nregs];
+		push ctx [VInt f.ef_index; VStr (f.ef_name,false); VInt nregs];
 		write ctx AInitArray;
 		write ctx ADup;
 		push ctx [VStr ("__enum__",false); VThis];
@@ -1135,9 +1135,9 @@ let gen_enum_field ctx e f =
 		write ctx AReturn;
 		tf();
 	| t ->
-		push ctx [VStr (f.ef_name,false); VInt 1];
+		push ctx [VInt f.ef_index; VStr (f.ef_name,false); VInt 2];
 		write ctx AInitArray;
-		ctx.stack_size <- ctx.stack_size - 1;
+		ctx.stack_size <- ctx.stack_size - 2;
 		write ctx ADup;
 		push ctx [VStr ("__enum__",false); VReg 0];
 		write ctx AObjSet;
@@ -1294,6 +1294,13 @@ let gen_type_def ctx t =
 		write ctx (ASetReg 0);
 		setvar ctx acc;
 		init_name ctx e.e_path true;
+		let nitems = List.length e.e_names in
+		push ctx [VReg 0; VStr ("__constructs__",true)];
+		List.iter (fun s -> push ctx [VStr (s,true)]) (List.rev e.e_names);
+		push ctx [VInt nitems];
+		write ctx AInitArray;
+		write ctx AObjSet;
+		ctx.stack_size <- ctx.stack_size - nitems;
 		PMap.iter (fun _ f -> gen_enum_field ctx e f) e.e_constrs
 	| TTypeDecl _ ->
 		()

+ 31 - 13
genswf9.ml

@@ -130,9 +130,11 @@ let t_void = TEnum ({
 		e_extern = false;
 		e_types = [];
 		e_constrs = PMap.empty;
+		e_names = [];
 	},[])
 
 let t_string = TInst (mk_class ([],"String") null_pos None false,[])
+let t_int = TInst (mk_class ([],"Int") null_pos None false,[])
 
 let lookup i w =
 	try
@@ -916,11 +918,11 @@ let rec gen_expr_content ctx retval e =
 	| TMatch (e0,_,cases,def) ->
 		let t = classify ctx e.etype in
 		let rparams = alloc_reg ctx KDynamic in
-		let rtag = alloc_reg ctx KDynamic in
+		let rindex = alloc_reg ctx KInt in
 		gen_expr ctx true e0;
 		write ctx A3Dup;
-		write ctx (A3GetProp (ident ctx "tag"));
-		set_reg ctx rtag;
+		write ctx (A3GetProp (ident ctx "index"));
+		set_reg ctx rindex;
 		write ctx (A3GetProp (ident ctx "params"));
 		set_reg ctx rparams;
 		let branch = begin_branch ctx in
@@ -931,12 +933,12 @@ let rec gen_expr_content ctx retval e =
 				| [] ->
 					assert false
 				| [tag] ->
-					write ctx (A3Reg rtag.rid);
-					write ctx (A3String (lookup tag ctx.strings));
+					write ctx (A3Reg rindex.rid);
+					write ctx (A3Int tag);
 					prev := jump ctx J3Neq;
 				| tag :: l ->
-					write ctx (A3Reg rtag.rid);
-					write ctx (A3String (lookup tag ctx.strings));
+					write ctx (A3Reg rindex.rid);
+					write ctx (A3Int tag);
 					let j = jump ctx J3Eq in
 					loop l;
 					j()
@@ -981,7 +983,7 @@ let rec gen_expr_content ctx retval e =
 		);
 		List.iter (fun j -> j()) jend;
 		branch();
-		free_reg ctx rtag;
+		free_reg ctx rindex;
 		free_reg ctx rparams
 
 and gen_call ctx e el =
@@ -1320,10 +1322,15 @@ let generate_enum_init ctx e slot =
 			write ctx (A3Reg r.rid);
 			write ctx (A3FindPropStrict name_id);
 			write ctx (A3String (lookup f.ef_name ctx.strings));
+			write ctx (A3Int f.ef_index);
 			write ctx A3Null;
-			write ctx (A3ConstructProperty (name_id,2));
+			write ctx (A3ConstructProperty (name_id,3));
 			write ctx (A3SetSlot !nslot);
 	) e.e_constrs;
+	write ctx (A3Reg r.rid);
+	List.iter (fun n -> write ctx (A3String (lookup n ctx.strings))) e.e_names;
+	write ctx (A3Array (List.length e.e_names));
+	write ctx (A3SetSlot (!nslot + 1));
 	free_reg ctx r
 
 let generate_field_kind ctx f c stat =
@@ -1441,14 +1448,18 @@ let generate_class ctx c =
 let generate_enum ctx e =
 	let name_id = type_path ctx e.e_path in
 	let st_id = empty_method ctx in
-	let f = begin_fun ctx [("tag",false,t_string);("params",false,mk_mono())] t_void [] false in
+	let f = begin_fun ctx [("tag",false,t_string);("index",false,t_int);("params",false,mk_mono())] t_void [] false in
 	let tag_id = ident ctx "tag" in
+	let index_id = ident ctx "index" in
 	let params_id = ident ctx "params" in
 	write ctx (A3FindProp tag_id);
 	write ctx (A3Reg 1);
 	write ctx (A3InitProp tag_id);
-	write ctx (A3FindProp params_id);
+	write ctx (A3FindProp index_id);
 	write ctx (A3Reg 2);
+	write ctx (A3InitProp index_id);
+	write ctx (A3FindProp params_id);
+	write ctx (A3Reg 3);
 	write ctx (A3InitProp params_id);
 	write ctx A3RetVoid;
 	let construct = f() in
@@ -1469,6 +1480,7 @@ let generate_enum ctx e =
 		cl3_construct = construct;
 		cl3_fields = [|
 			{ f3_name = tag_id; f3_slot = 0; f3_kind = A3FVar { v3_type = None; v3_value = A3VNone; v3_const = false; }; f3_metas = None };
+			{ f3_name = index_id; f3_slot = 0; f3_kind = A3FVar { v3_type = None; v3_value = A3VNone; v3_const = false; }; f3_metas = None };
 			{ f3_name = params_id; f3_slot = 0; f3_kind = A3FVar { v3_type = None; v3_value = A3VNone; v3_const = false; }; f3_metas = None };
 			{ f3_name = ident ctx "__enum__"; f3_slot = 0; f3_kind = A3FVar { v3_type = None; v3_value = A3VBool true; v3_const = true }; f3_metas = None };
 			{
@@ -1495,10 +1507,11 @@ let generate_enum ctx e =
 					let fdata = begin_fun ctx args (TEnum (e,[])) [] true in
 					write ctx (A3FindPropStrict name_id);
 					write ctx (A3String (lookup f.ef_name ctx.strings));
+					write ctx (A3Int f.ef_index);
 					let n = ref 0 in
 					List.iter (fun _ -> incr n; write ctx (A3Reg !n)) args;
 					write ctx (A3Array (!n));
-					write ctx (A3ConstructProperty (name_id,2));
+					write ctx (A3ConstructProperty (name_id,3));
 					write ctx A3Ret;
 					let fid = fdata() in
 					A3FMethod {
@@ -1517,9 +1530,14 @@ let generate_enum ctx e =
 		st3_method = st_id;
 		st3_fields = Array.of_list ({
 			f3_name = ident ctx "__isenum";
-			f3_slot = !st_count + 1;
+			f3_slot = !st_count + 2;
 			f3_kind = A3FVar { v3_type = None; v3_value = A3VBool true; v3_const = true; };
 			f3_metas = None;
+		} :: {
+			f3_name = ident ctx "__constructs__";
+			f3_slot = !st_count + 1;
+			f3_kind = A3FVar { v3_type = None; v3_value = A3VNone; v3_const = false; };
+			f3_metas = None;
 		} :: constrs)
 	} in
 	ctx.classes <- sc :: ctx.classes;

+ 16 - 7
std/Type.hx

@@ -380,15 +380,13 @@ class Type {
 		Returns all the available constructor names for an enum.
 	**/
 	public static function getEnumConstructs( e : Enum ) : Array<String> {
-		#if flash9
-			return describe(e,false);
-		#else true
+		#if neko
 			var a = Reflect.fields(e);
 			a.remove(__unprotect__("__ename__"));
-			#if neko
 			a.remove("prototype");
-			#end
 			return a;
+		#else true
+			return untyped e.__constructs__;
 		#end
 	}
 
@@ -508,7 +506,7 @@ class Type {
 		#else true
 		if( a[0] != b[0] )
 			return false;
-		for( i in 1...a.length )
+		for( i in 2...a.length )
 			if( !enumEq(a[i],b[i]) )
 				return false;
 		var e = a.__enum__;
@@ -540,7 +538,18 @@ class Type {
 	#else flash9
 		return if( e.params == null ) [] else e.params;
 	#else true
-		return e.slice(1);
+		return e.slice(2);
+	#end
+	}
+
+	/**
+		Returns the index of the constructor of an enum
+	**/
+	public static function enumIndex( e : Dynamic ) : Int {
+	#if (neko || flash9)
+		return e.index;
+	#else true
+		return e[1];
 	#end
 	}
 

+ 3 - 3
std/flash/Boot.hx

@@ -41,12 +41,12 @@ class Boot {
 			case "object":
 				if( __instanceof__(o,Array) ) {
 					if( o.__enum__ != null ) {
-						if( o["length"] == 1 )
+						if( o["length"] == 2 )
 							return o[0];
 						var str = o[0]+"(";
 						s += "    ";
-						for( i in 1...o["length"] ) {
-							if( i != 1 )
+						for( i in 2...o["length"] ) {
+							if( i != 2 )
 								str += "," + __string_rec(o[i],s);
 							else
 								str += __string_rec(o[i],s);

+ 26 - 17
std/haxe/Serializer.hx

@@ -33,16 +33,24 @@ class Serializer {
 	**/
 	public static var USE_CACHE = false;
 
+	/**
+		Use constructor indexes for enums instead of names.
+		This is less reliable but more compact.
+	**/
+	public static var USE_ENUM_INDEX = false;
+
 	var buf : StringBuf;
 	var cache : Array<Dynamic>;
 	var shash : Hash<Int>;
 	var scount : Int;
 	var useCache : Bool;
+	var useEnumIndex : Bool;
 
 	public function new() {
 		buf = new StringBuf();
 		cache = new Array();
 		useCache = USE_CACHE;
+		useEnumIndex = USE_ENUM_INDEX;
 		shash = new Hash();
 		scount = 0;
 	}
@@ -61,7 +69,7 @@ class Serializer {
 		g : object end
 		h : array/list/hash end
 		i : Int
-		j :
+		j : enum (by index)
 		k : NaN
 		l : list
 		m : -Inf
@@ -89,16 +97,8 @@ class Serializer {
 		}
 		shash.set(s,scount++);
 		#if old_serialize
-			if( s.indexOf("\n") != -1 || s.indexOf("\r") != -1 ) {
-				buf.add("j");
-				s = s.split("\\").join("\\\\").split("\n").join("\\n").split("\r").join("\\r");
-			} else
-				buf.add("s");
-			#if neko
-			buf.add(neko.Utf8.length(s));
-			#else true
-			buf.add(s.length);
-			#end
+			// no more support for -D old_serialize due to 'j' reuse
+			#if error #end
 		#else true
 		buf.add("y");
 		s = StringTools.urlEncode(s);
@@ -277,10 +277,13 @@ class Serializer {
 			if( useCache && serializeRef(v) )
 				return;
 			cache.pop();
-			buf.add("w");
+			buf.add(useEnumIndex?"j":"w");
 			serialize(Type.getEnumName(e));
 			#if neko
-			serializeString(new String(v.tag));
+			if( useEnumIndex )
+				buf.add(v.index);
+			else
+				serializeString(new String(v.tag));
 			buf.add(":");
 			if( v.args == null )
 				buf.add(0);
@@ -291,7 +294,10 @@ class Serializer {
 					serialize(v.args[i]);
 			}
 			#else flash9
-			serializeString(v.tag);
+			if( useEnumIndex )
+				buf.add(v.index);
+			else
+				serializeString(v.tag);
 			buf.add(":");
 			if( v.params == null )
 				buf.add(0);
@@ -302,11 +308,14 @@ class Serializer {
 					serialize(v.params[i]);
 			}
 			#else true
-			serializeString(v[0]);
+			if( useEnumIndex )
+				buf.add(v[1]);
+			else
+				serializeString(v[0]);
 			buf.add(":");
 			var l = v[untyped "length"];
-			buf.add(l - 1);
-			for( i in 1...l )
+			buf.add(l - 2);
+			for( i in 2...l )
 				serialize(v[i]);
 			#end
 			cache.push(v);

+ 32 - 44
std/haxe/Unserializer.hx

@@ -107,6 +107,27 @@ class Unserializer {
  		pos++;
 	}
 
+	function unserializeEnum( edecl, tag ) {
+		var constr = Reflect.field(edecl,tag);
+		if( constr == null )
+			throw "Unknown enum tag "+Type.getEnumName(edecl)+"."+tag;
+		if( buf.charCodeAt(pos++) != 58 ) // ':'
+			throw "Invalid enum format";
+		var nargs = readDigits();
+		if( nargs == 0 ) {
+			cache.push(constr);
+			return constr;
+		}
+		var args = new Array();
+		while( nargs > 0 ) {
+			args.push(unserialize());
+			nargs -= 1;
+		}
+		var e = Reflect.callMethod(edecl,constr,args);
+		cache.push(e);
+		return e;
+	}
+
  	public function unserialize() : Dynamic {
  		switch( buf.charCodeAt(pos++) ) {
  		case 110: // n
@@ -193,27 +214,17 @@ class Unserializer {
 			var edecl = resolver.resolveEnum(name);
 			if( edecl == null )
 				throw "Enum not found " + name;
-			var tag : String = unserialize();
-			if( !Std.is(tag,String) )
-				throw "Invalid enum tag";
-			var constr = Reflect.field(edecl,tag);
-			if( constr == null )
-				throw "Unknown enum tag "+name+"."+tag;
-			if( buf.charCodeAt(pos++) != 58 ) // ':'
-				throw "Invalid enum format";
-			var nargs = readDigits();
-			if( nargs == 0 ) {
-				cache.push(constr);
-				return constr;
-			}
-			var args = new Array();
-			while( nargs > 0 ) {
-				args.push(unserialize());
-				nargs -= 1;
-			}
-			var e = Reflect.callMethod(edecl,constr,args);
-			cache.push(e);
-			return e;
+			return unserializeEnum(edecl,unserialize());
+ 		case 106: // j
+			var name = unserialize();
+			var edecl = resolver.resolveEnum(name);
+			if( edecl == null )
+				throw "Enum not found " + name;
+			var index = readDigits();
+			var tag = Type.getEnumConstructs(edecl)[index];
+			if( tag == null )
+				throw "Unknown enum index "+name+"@"+index;
+			return unserializeEnum(edecl,tag);
 		case 108: // l
 			var l = new List();
 			while( buf.charCodeAt(pos) != 104 /*h*/ )
@@ -258,29 +269,6 @@ class Unserializer {
  			#end
 			scache.push(s);
 			return s;
- 		case 106: // j
- 			var len = readDigits();
- 			if( buf.charAt(pos++) != ":" )
- 				throw "Invalid string length";
- 			#if neko
-			if( length - pos < len )
-				throw "Invalid string length";
- 			var s = neko.Utf8.sub(buf,pos-upos,len);
- 			pos += s.length;
- 			upos += s.length - len;
- 			#else true
- 			var s = buf.substr(pos,len);
- 			pos += len;
- 			#end
-			var delim = "##__delim__##";
-			#if flash9
-			var a = ~/\\\\/g.split(s);
-			#else true
-			var a = s.split("\\\\");
-			#end
- 			s = a.join(delim).split("\\r").join("\r").split("\\n").join("\n").split(delim).join("\\");
- 			scache.push(s);
- 			return s;
  		default:
  		}
  		pos--;

+ 3 - 3
std/js/Boot.hx

@@ -76,12 +76,12 @@ class Boot {
 			case "object":
 				if( __js__("o instanceof Array") ) {
 					if( o.__enum__ != null ) {
-						if( o.length == 1 )
+						if( o.length == 2 )
 							return o[0];
 						var str = o[0]+"(";
 						s += "\t";
-						for( i in 1...o.length ) {
-							if( i != 1 )
+						for( i in 2...o.length ) {
+							if( i != 2 )
 								str += "," + __string_rec(o[i],s);
 							else
 								str += __string_rec(o[i],s);

+ 3 - 1
type.ml

@@ -87,7 +87,7 @@ and texpr_expr =
 	| TIf of texpr * texpr * texpr option
 	| TWhile of texpr * texpr * Ast.while_flag
 	| TSwitch of texpr * (texpr list * texpr) list * texpr option
-	| TMatch of texpr * (tenum * tparams) * (string list * (string option * t) list option * texpr) list * texpr option
+	| TMatch of texpr * (tenum * tparams) * (int list * (string option * t) list option * texpr) list * texpr option
 	| TTry of texpr * (string * t * texpr) list
 	| TReturn of texpr option
 	| TBreak
@@ -137,6 +137,7 @@ and tenum_field = {
 	ef_type : t;
 	ef_pos : Ast.pos;
 	ef_doc : Ast.documentation;
+	ef_index : int;
 }
 
 and tenum = {
@@ -147,6 +148,7 @@ and tenum = {
 	e_extern : bool;
 	mutable e_types : (string * t) list;
 	mutable e_constrs : (string , tenum_field) PMap.t;
+	mutable e_names : string list;
 }
 
 and tdef = {

+ 25 - 9
typer.ml

@@ -71,7 +71,7 @@ type access_kind =
 	| AccSetField of texpr * string * t
 
 type switch_mode =
-	| CMatch of (string * (string option * t) list option)
+	| CMatch of (tenum_field * (string option * t) list option)
 	| CExpr of texpr
 
 exception Error of error_msg * pos
@@ -330,7 +330,7 @@ let rec load_normal_type ctx t p allow_no_params =
 						| Float f -> "F" ^ f
 						| _ -> assert false
 					) in
-					TEnum ({ e_path = ([],name); e_pos = p; e_doc = None; e_private = false; e_extern = true; e_types = []; e_constrs = PMap.empty },[]), true
+					TEnum ({ e_path = ([],name); e_pos = p; e_doc = None; e_private = false; e_extern = true; e_types = []; e_constrs = PMap.empty; e_names = [] },[]), true
 				| TPType t -> load_type ctx p t, false
 			) t.tparams in
 			let bparams = List.map fst tparams in
@@ -594,6 +594,7 @@ let type_type_params ctx path p (n,flags) =
 			e_types = [];
 			e_constrs = PMap.empty;
 			e_doc = None;
+			e_names = [];
 		} in
 		TEnum (e,[])
 	| l ->
@@ -1042,7 +1043,7 @@ let type_matching ctx (enum,params) (e,p) ecases first_case =
 			| TEnum _ -> ()
 			| _ -> assert false
 		);
-		(name,None)
+		(c,None)
 	| ECall ((EConst (Ident name),_),el)
 	| ECall ((EConst (Type name),_),el) ->
 		let c = constr name in
@@ -1062,7 +1063,7 @@ let type_matching ctx (enum,params) (e,p) ecases first_case =
 				Some name , t
 			| _ -> invalid()
 		) el args in
-		(name,Some idents)
+		(c,Some idents)
 	| _ ->
 		invalid()
 
@@ -1516,12 +1517,15 @@ and type_switch ctx e cases def need_val p =
 				assert false
 		in
 		let constructs (el,_,e) =
-			let cl = List.map (fun c -> mk (TField (mk (TTypeExpr (TEnumDecl en)) t_dynamic p , c)) (TEnum (en,enparams)) p) el in
+			let cl = List.map (fun c -> mk (TField (mk (TTypeExpr (TEnumDecl en)) t_dynamic p , c.ef_name)) (TEnum (en,enparams)) p) el in
 			(cl,e)
 		in
+		let indexes (el,vars,e) =
+			List.map (fun c -> c.ef_index) el, vars, e
+		in
 		let cases = List.map matchs cases in
 		match !has_params with
-		| true -> mk (TMatch (e,(en,enparams),cases,def)) t p
+		| true -> mk (TMatch (e,(en,enparams),List.map indexes cases,def)) t p
 		| false -> mk (TSwitch (e,List.map constructs cases,def)) t p
 
 and type_access ctx e p get =
@@ -2453,6 +2457,7 @@ let type_module ctx m tdecls loadp =
 				e_private = priv;
 				e_extern = List.mem EExtern d.d_flags || d.d_data = [];
 				e_constrs = PMap.empty;
+				e_names = [];
 			} in
 			decls := TEnumDecl e :: !decls
 		| ETypedef d ->
@@ -2554,15 +2559,26 @@ let type_module ctx m tdecls loadp =
 			let e = get_enum d.d_name in
 			ctx.type_params <- e.e_types;
 			let et = TEnum (e,List.map snd e.e_types) in
+			let names = ref [] in
+			let index = ref 0 in
 			List.iter (fun (c,doc,t,p) ->
 				if c = "name" && Plugin.defined "js" then error "This identifier cannot be used in Javascript" p;
 				let t = (match t with
 					| [] -> et
 					| l -> TFun (List.map (fun (s,opt,t) -> s, opt, load_type_opt ~param:opt ctx p (Some t)) l, et)
 				) in
-				if PMap.mem c e.e_constrs then error ("Duplicate constructor " ^ c) p;
-				e.e_constrs <- PMap.add c { ef_name = c; ef_type = t; ef_pos = p; ef_doc = doc } e.e_constrs
-			) d.d_data
+				if PMap.mem c e.e_constrs then error ("Duplicate constructor " ^ c) p;				
+				e.e_constrs <- PMap.add c {
+					ef_name = c;
+					ef_type = t;
+					ef_pos = p;
+					ef_doc = doc;
+					ef_index = !index;
+				} e.e_constrs;
+				incr index;
+				names := c :: !names;
+			) d.d_data;
+			e.e_names <- List.rev !names;
 		| ETypedef d ->
 			let t = get_tdef d.d_name in
 			ctx.type_params <- t.t_types;