Rudy Ges 2 lat temu
rodzic
commit
c8f24b20b0

+ 1 - 1
src/codegen/gencommon/initFunction.ml

@@ -145,7 +145,7 @@ let handle_class gen cl =
 				in
 
 				let ret = binop Ast.OpAssign var (change_expr e) (fn cf.cf_type) cf.cf_pos in
-				cf.cf_expr <- None;
+				(* cf.cf_expr <- None; *)
 				let is_override = has_class_field_flag cf CfOverride in
 
 				if is_override then begin

+ 709 - 252
src/compiler/hxb/hxbReader.ml

@@ -16,10 +16,18 @@ class hxb_reader
 
 	val mutable classes = Array.make 0 null_class
 	val mutable abstracts = Array.make 0 null_abstract
+	(* val mutable enums = Array.make 0 null_enum *)
+	val mutable typedefs = Array.make 0 null_tdef
+	(* val mutable class_fields = Array.make 0 null_class_field *)
+	(* val mutable abstract_fields = Array.make 0 null_abstract_field *)
+	(* val mutable enum_fields = Array.make 0 null_enum_field *)
 
 	val mutable type_type_parameters = Array.make 0 (mk_type_param "" t_dynamic None)
 	val mutable field_type_parameters = Array.make 0 (mk_type_param "" t_dynamic None)
 
+	method set_input file_ch =
+		ch <- file_ch
+
 	(* Primitives *)
 
 	method read_u8 =
@@ -28,6 +36,9 @@ class hxb_reader
 	method read_u32 =
 		IO.read_real_i32 ch
 
+	method read_i16 =
+		IO.read_i16 ch
+
 	method read_f64 =
 		IO.read_double ch
 
@@ -57,17 +68,33 @@ class hxb_reader
 	method read_bool =
 		self#read_u8 <> 0
 
-	method read_string =
+	method read_from_string_pool pool =
+		(* TODO fix module vs global string pool handling *)
 		let l = self#read_uleb128 in
-		string_pool.(l)
+		(* Printf.eprintf "  Get string #%d\n" l; *)
+		try pool.(l) with e -> begin
+			Printf.eprintf "  Failed getting string #%d\n" l;
+			(* "" *)
+			raise e
+		end
+
+	method read_string =
+		self#read_from_string_pool string_pool
 
 	method read_raw_string =
 		let l = self#read_uleb128 in
-		Bytes.unsafe_to_string (IO.nread ch l)
+		let s = Bytes.unsafe_to_string (IO.nread ch l) in
+		(* Printf.eprintf "  Read raw string %s\n" s; *)
+		s
 
 	(* Basic compounds *)
 
-	method read_list : 'a . (unit -> 'a) -> 'a list = fun f ->
+	method read_list8 : 'a . (unit -> 'a) -> 'a list = fun f ->
+		let l = self#read_leb128 in
+		let a = Array.init l (fun _ -> f ()) in
+		Array.to_list a
+
+	method read_list16 : 'a . (unit -> 'a) -> 'a list = fun f ->
 		let l = self#read_uleb128 in
 		let a = Array.init l (fun _ -> f ()) in
 		Array.to_list a
@@ -80,23 +107,35 @@ class hxb_reader
 			Some (f())
 
 	method read_path =
-		let pack = self#read_list (fun () -> self#read_string) in
+		let pack = self#read_list8 (fun () -> self#read_string) in
 		let name = self#read_string in
 		(pack,name)
 
 	method read_full_path =
-		let pack = self#read_list (fun () -> self#read_string) in
+		let pack = self#read_list8 (fun () -> self#read_string) in
 		let mname = self#read_string in
 		let tname = self#read_string in
 		(pack,mname,tname)
 
 	method read_documentation =
 		let doc_own = self#read_option (fun () ->
-			doc_pool.(self#read_uleb128)
-		) in
-		let doc_inherited = self#read_list (fun () ->
-			doc_pool.(self#read_uleb128)
+			(* TODO fix that *)
+			(* let _ = self#read_uleb128 in *)
+			(* doc_pool.(self#read_uleb128) *)
+			self#read_from_string_pool doc_pool
+			(* "" *)
 		) in
+		let doc_inherited = [] in
+		(* let doc_inherited = self#read_list8 (fun () -> *)
+		(* 	(1* TODO fix that *1) *)
+		(* 	(1* let i = self#read_uleb128 in *1) *)
+		(* 	(1* let _ = self#read_uleb128 in *1) *)
+		(* 	(1* Printf.eprintf "    Read doc string %d\n" i; *1) *)
+		(* 	(1* doc_pool.(i) *1) *)
+		(* 	(1* doc_pool.(self#read_uleb128) *1) *)
+		(* 	self#read_from_string_pool doc_pool *)
+		(* 	(1* "" *1) *)
+		(* ) in *)
 		{doc_own;doc_inherited}
 
 	method read_pos =
@@ -116,24 +155,49 @@ class hxb_reader
 		(Meta.from_string name,[],p)
 
 	method read_metadata =
-		self#read_list (fun () -> self#read_metadata_entry)
+		self#read_list16 (fun () -> self#read_metadata_entry)
 
 	(* References *)
 
 	method read_class_ref =
-		classes.(self#read_uleb128)
+		let i = self#read_uleb128 in
+		Printf.eprintf "  Reading class ref %d...\n" i;
+		try
+			classes.(i)
+		with e ->
+			Printf.eprintf "  Failed to read class ref %d\n" i;
+			raise e
 
 	method read_abstract_ref =
-		abstracts.(self#read_uleb128)
+		let i = self#read_uleb128 in
+		Printf.eprintf "  Reading class ref %d...\n" i;
+		try
+			abstracts.(i)
+		with e ->
+			Printf.eprintf "  Failed to read abstract ref %d\n" i;
+			raise e
+
+	method read_enum_ref =
+		assert false (* TODO *)
+
+	method read_typedef_ref =
+		typedefs.(self#read_uleb128)
 
 	method read_field_ref =
 		null_field (* TODO *)
 
+	method read_enum_field_ref =
+		assert false (* TODO *)
+
+	method read_anon_field_ref =
+		assert false (* TODO *)
+
 	(* Type instances *)
 
 	method read_type_instance =
 		match self#read_u8 with
 		| 0 ->
+			Printf.eprintf "  TODO identity\n";
 			mk_mono() (* TODO: identity *)
 		| 1 ->
 			self#read_type_instance
@@ -148,6 +212,7 @@ class hxb_reader
 		| 11
 		| 12 ->
 			ignore(self#read_uleb128);
+			Printf.eprintf "  TODO TType\n";
 			t_dynamic (* TODO *)
 		| 14 ->
 			let c = self#read_class_ref in
@@ -158,6 +223,7 @@ class hxb_reader
 		| 17 ->
 			ignore(self#read_uleb128);
 			let _ = self#read_types in
+			Printf.eprintf "  TODO TAbstract\n";
 			t_dynamic (* TODO *)
 		| 32 ->
 			let f () =
@@ -166,7 +232,8 @@ class hxb_reader
 				let t = self#read_type_instance in
 				(name,opt,t)
 			in
-			let args = self#read_list f in
+			(* TODO check list 8 vs 16 *)
+			let args = self#read_list16 f in
 			let ret = self#read_type_instance in
 			TFun(args,ret)
 		| 40 ->
@@ -177,12 +244,15 @@ class hxb_reader
 			mk_anon (ref Closed)
 		| 51 ->
 			ignore(self#read_uleb128);
+			Printf.eprintf "  TODO TAnon\n";
 			t_dynamic (* TODO *)
 		| i ->
 			error (Printf.sprintf "Bad type instance id: %i" i)
 
 	method read_types =
-		self#read_list (fun () -> self#read_type_instance)
+			(* TODO check list 8 vs 16 *)
+		self#read_list8 (fun () -> self#read_type_instance)
+		(* self#read_list16 (fun () -> self#read_type_instance) *)
 
 	(* Fields *)
 
@@ -244,272 +314,659 @@ class hxb_reader
 		| i ->
 			error (Printf.sprintf "Bad field kind: %i" i)
 
-	method read_class_field (m : module_def) : tclass_field =
+	(* method read_type_parameter = *)
+	(* 	let name = self#read_string in *)
+	(* 	let c = self#read_class true in *)
+	(* 	(name,TInst(c,[])) *)
+
+	method read_binop =
+		match IO.read_byte ch with
+			| 0 -> OpAdd
+			| 1 -> OpMult
+			| 2 -> OpDiv
+			| 3 -> OpSub
+			| 4 -> OpAssign
+			| 5 -> OpEq
+			| 6 -> OpNotEq
+			| 7 -> OpGt
+			| 8 -> OpGte
+			| 9 -> OpLt
+			| 10 -> OpLte
+			| 11 -> OpAnd
+			| 12 -> OpOr
+			| 13 -> OpXor
+			| 14 -> OpBoolAnd
+			| 15 -> OpBoolOr
+			| 16 -> OpShl
+			| 17 -> OpShr
+			| 18 -> OpUShr
+			| 19 -> OpMod
+			| 20 -> OpAssignOp(self#read_binop)
+			| 21 -> OpInterval
+			| 22 -> OpArrow
+			| 23 -> OpIn
+			| _ -> assert false
+
+	method read_unop =
+		match IO.read_byte ch with
+		| 0 -> Increment
+		| 1 -> Decrement
+		| 2 -> Not
+		| 3 -> Neg
+		| 4 -> NegBits
+		| _ -> assert false
+
+	method read_quote_status =
+		match IO.read_byte ch with
+		| 0 -> NoQuotes
+		| 1 -> DoubleQuotes
+		| _ -> assert false
+
+	method read_tconstant =
+		match IO.read_byte ch with
+		| 0 -> TBool(false)
+		| 1 -> TBool(true)
+		| 2 -> TNull
+		| 3 -> TThis
+		| 4 -> TSuper
+		| 5 -> TInt(IO.read_real_i32 ch)
+		| 6 -> TFloat(self#read_string)
+		| 7 -> TString(self#read_string)
+		| _ -> assert false
+
+	method read_tvar_def =
+		let read_tvar_extra =
+			(* TODO type parameters *)
+			(* list_8 *)
+			(* let params = self#read_list8 (fun () -> self#read_type_parameter) in *)
+			let params = [] in
+			let e = self#read_option (fun () -> self#read_texpr) in
+			{
+				v_params = params;
+				v_expr = e;
+			}
+		in
+		(* let i = self#read_lut in *)
+		let id = IO.read_i32 ch in
 		let name = self#read_string in
-		self#read_type_parameters m ([],name) (fun a ->
-			field_type_parameters <- a
-		);
-		let params = Array.to_list field_type_parameters in
 		let t = self#read_type_instance in
-		let flags = Int32.to_int self#read_u32 in
-		let pos = self#read_pos in
-		let name_pos = self#read_pos in
-		let doc = self#read_option (fun () -> self#read_documentation) in
+		(* let capture = self#read_bool in *)
+		let _ = self#read_bool in
+		let extra = self#read_option (fun () -> read_tvar_extra) in
+		(* list 8 *)
 		let meta = self#read_metadata in
-		let kind = self#read_field_kind in
-		let overloads = self#read_list (fun () -> self#read_class_field m) in
+		let p = self#read_pos in
+		let v = {
+			v_id = id;
+			v_name = name;
+			v_type = t;
+			(* TODO *)
+			(* v_capture = capture; *)
+			v_kind = VGenerated; (* TODO *)
+			v_extra = extra;
+			(* TODO *)
+			v_flags = 0;
+			v_meta = meta;
+			v_pos = p;
+		} in
+		(* vars.(i) <- v; *)
+		v
+
+	method read_object_field_key =
+		let name = self#read_string in
+		let p = self#read_pos in
+		let quotes = self#read_quote_status in
+		(name,p,quotes)
+
+	method read_object_field =
+		let k = self#read_object_field_key in
+		let e = self#read_texpr in
+		(k,e)
+
+	method read_tfunction_arg =
+		let v = self#read_tvar_def in
+		let cto = self#read_option (fun () -> self#read_texpr) in
+		(* let cto = self#read_option (fun () -> self#read_tconstant) in *)
+		(v,cto)
+
+	method read_tfunction =
+		(* list_8 *)
+		let args = self#read_list8 (fun () -> self#read_tfunction_arg) in
+		let r = self#read_type_instance in
+		let e = self#read_texpr in
 		{
-			cf_name = name;
-			cf_type = t;
-			cf_pos = pos;
-			cf_name_pos = name_pos;
-			cf_doc = doc;
-			cf_meta = meta;
-			cf_kind = kind;
-			cf_expr = None;
-			cf_expr_unoptimized = None;
-			cf_params = params;
-			cf_overloads = overloads;
-			cf_flags = flags;
+			tf_args = args;
+			tf_type = r;
+			tf_expr = e;
 		}
 
-	method read_class_fields (m : module_def) (c : tclass) =
-		let f () = self#read_class_field m in
-		begin match c.cl_kind with
-		| KAbstractImpl a ->
-			type_type_parameters <- Array.of_list a.a_params
-		| _ ->
-			type_type_parameters <- Array.of_list c.cl_params
-		end;
-		c.cl_constructor <- self#read_option f;
-		c.cl_ordered_fields <- self#read_list f;
-		c.cl_ordered_statics <- self#read_list f;
-		List.iter (fun cf -> c.cl_statics <- PMap.add cf.cf_name cf c.cl_statics) c.cl_ordered_statics;
-
-	(* Module types *)
-
-	method read_common_module_type (m : module_def) (infos : tinfos) =
-		infos.mt_private <- self#read_bool;
-		infos.mt_doc <- self#read_option (fun () -> self#read_documentation);
-		infos.mt_meta <- self#read_metadata;
-		self#read_type_parameters m infos.mt_path (fun a ->
-			type_type_parameters <- a
-		);
-		infos.mt_params <- Array.to_list type_type_parameters;
-		infos.mt_using <- self#read_list (fun () ->
-			let c = self#read_class_ref in
-			let p = self#read_pos in
-			(c,p)
-		)
+	method read_switch_case =
+		(* list_8 *)
+		let el = self#read_list8 (fun () -> self#read_texpr) in
+		let e = self#read_texpr in
+		{
+			case_patterns = el;
+			case_expr = e;
+		}
+
+	method read_catch =
+		let v = self#read_tvar_def in
+		let e = self#read_texpr in
+		(v,e)
 
-	method read_class_kind = match self#read_u8 with
+	method read_tfield_access =
+		match IO.read_byte ch with
 		| 0 ->
-			KNormal
-		| 1 ->
-			KTypeParameter self#read_types
-		| 2 ->
-			KExpr ((EBlock []),null_pos) (* TODO *)
-		| 3 ->
-			KGeneric
-		| 4 ->
 			let c = self#read_class_ref in
 			let tl = self#read_types in
-			KGenericInstance(c,tl)
+			let cf = self#read_field_ref in
+			FInstance(c,tl,cf)
+		| 1 ->
+			let c = self#read_class_ref in
+			let cf = self#read_field_ref in
+			FStatic(c,cf)
+		| 2 -> FAnon(self#read_anon_field_ref)
+		| 3 -> FDynamic(self#read_string)
+		| 4 -> FClosure(None,self#read_field_ref)
 		| 5 ->
-			KMacroType
-		| 6 ->
-			KGenericBuild [] (* TODO *)
-		| 7 ->
-			KAbstractImpl self#read_abstract_ref
-		| 8 ->
-			(* TODO *)
-			KNormal
-		| i ->
-			error (Printf.sprintf "Invalid class kind id: %i" i)
-
-	method read_class (m : module_def) (c : tclass) =
-		self#read_common_module_type m (Obj.magic c);
-		c.cl_kind <- self#read_class_kind;
-		c.cl_flags <- (Int32.to_int self#read_u32);
-		let read_relation () =
 			let c = self#read_class_ref in
 			let tl = self#read_types in
-			(c,tl)
-		in
-		c.cl_super <- self#read_option read_relation;
-		c.cl_implements <- self#read_list read_relation;
-		c.cl_dynamic <- self#read_option (fun () -> self#read_type_instance);
-		c.cl_array_access <- self#read_option (fun () -> self#read_type_instance);
-
-	method read_abstract (m : module_def) (a : tabstract) =
-		self#read_common_module_type m (Obj.magic a);
-		a.a_impl <- self#read_option (fun () -> self#read_class_ref);
-		a.a_this <- self#read_type_instance;
-		a.a_from <- self#read_list (fun () -> self#read_type_instance);
-		a.a_from_field <- self#read_list (fun () ->
-			let t = self#read_type_instance in
-			let cf = self#read_field_ref in
-			(t,cf)
-		);
-		a.a_to <- self#read_list (fun () -> self#read_type_instance);
-		a.a_to_field <- self#read_list (fun () ->
-			let t = self#read_type_instance in
 			let cf = self#read_field_ref in
-			(t,cf)
-		);
-		a.a_array <- self#read_list (fun () -> self#read_field_ref);
-		a.a_read <- self#read_option (fun () -> self#read_field_ref);
-		a.a_write <- self#read_option (fun () -> self#read_field_ref);
-		a.a_call <- self#read_option (fun () -> self#read_field_ref);
-		a.a_enum <- self#read_bool
+			FClosure(Some(c,tl),cf)
+		| 6 ->
+			let en = self#read_enum_ref in
+			let ef = self#read_enum_field_ref in
+			FEnum(en,ef)
+		| _ -> assert false
 
-	(* Chunks *)
+	method read_texpr =
+		let pos = self#read_pos in
 
-	method read_string_pool =
-		let l = self#read_uleb128 in
-		Array.init l (fun i ->
-			self#read_raw_string;
-		);
-
-	method read_chunk =
-		let size = Int32.to_int self#read_u32 in
-		let name = Bytes.unsafe_to_string (IO.nread ch 4) in
-		let data = IO.nread ch size in
-		let crc = self#read_u32 in
-		ignore(crc); (* TODO *)
-		let kind = chunk_kind_of_string name in
-		(kind,data)
-
-	method read_cfld (m : module_def) =
-		let l = self#read_uleb128 in
-		for i = 0 to l - 1 do
-			let c = classes.(i) in
-			self#read_class_fields m c;
-		done
+		let update_pos =
+			let dmin = self#read_i16 in
+			let dmax = self#read_i16 in
 
-	method read_clsd (m : module_def) =
-		let l = self#read_uleb128 in
-		for i = 0 to l - 1 do
-			let c = classes.(i) in
-			self#read_class m c;
-		done
+			(* TODO return updated pos *)
+			ignore(dmin);
+			ignore(dmax);
+			pos
+		in
 
-	method read_absd (m : module_def) =
-		let l = self#read_uleb128 in
-		for i = 0 to l - 1 do
-			let a = abstracts.(i) in
-			self#read_abstract m a;
-		done
+		let loop () =
+		(* let rec loop () = *)
+			let t = self#read_type_instance in
+			let pos = update_pos in
+
+			let e = match IO.read_byte ch with
+				(* values 0-19 *)
+				| 0 -> TConst TNull
+				| 1 -> TConst TThis
+				| 2 -> TConst TSuper
+				| 3 -> TConst (TBool false)
+				| 4 -> TConst (TBool true)
+				| 5 -> TConst (TInt (IO.read_real_i32 ch))
+				| 6 -> TConst (TFloat self#read_string)
+				| 7 -> TConst (TString self#read_string)
+
+				(* vars 20-29 *)
+				(* TODO retrieve local by v_vid *)
+				(* | 20 -> TLocal (vars.self#read_lut)) *)
+				(* TODO read_var *)
+				(* | 21 -> TVar (self#read_var,None) *)
+				(* | 22 -> TVar (self#read_var, Some (loop ())) *)
+
+				(* blocks 30-49 *)
 
-	method read_clsr =
-		let l = self#read_uleb128 in
-		classes <- Array.init l (fun _ ->
-			let (pack,mname,tname) = self#read_full_path in
-			match resolve_type pack mname tname with
-			| TClassDecl c ->
-				c
-			| _ ->
-				error ("Unexpected type where class was expected: " ^ (s_type_path (pack,tname)))
-		)
+				| i ->
+					Printf.eprintf "  [ERROR] Unhandled texpr %d\n" i;
+					assert false
+			in
 
-	method read_absr =
-		let l = self#read_uleb128 in
-		abstracts <- Array.init l (fun _ ->
-			let (pack,mname,tname) = self#read_full_path in
-			match resolve_type pack mname tname with
-			| TAbstractDecl a ->
-				a
-			| _ ->
-				error ("Unexpected type where class was expected: " ^ (s_type_path (pack,tname)))
-		)
+			{
+				eexpr = e;
+				etype = t;
+				epos = pos;
+			}
+		in
 
-	method read_typf (m : module_def) =
-		self#read_list (fun () ->
-			let kind = self#read_u8 in
-			let path = self#read_path in
+		loop ();
+
+			(* let e = match IO.read_byte ch with *)
+			(* 	| 0 -> TConst(self#read_tconstant) *)
+			(* 	| 1 -> assert false *)
+			(* 	(1* | 1 -> TLocal (vars.(self#read_lut)) (2* TODO *2) *1) *)
+			(* 	| 2 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let e2 = self#read_texpr in *)
+			(* 		TArray(e1,e2) *)
+			(* 	| 3 -> *)
+			(* 		let op = self#read_binop in *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let e2 = self#read_texpr in *)
+			(* 		TBinop(op,e1,e2) *)
+			(* 	| 4 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let fa = self#read_tfield_access in *)
+			(* 		TField(e1,fa) *)
+			(* 	| 5 -> TTypeExpr (TClassDecl (self#read_class_ref)) *)
+			(* 	| 6 -> TTypeExpr (TEnumDecl (self#read_enum_ref)) *)
+			(* 	| 7 -> TTypeExpr (TTypeDecl (self#read_typedef_ref)) *)
+			(* 	| 8 -> TTypeExpr (TAbstractDecl (self#read_abstract_ref)) *)
+			(* 	| 9 -> TParenthesis(self#read_texpr) *)
+			(* 	| 10 -> TObjectDecl(self#read_list8 (fun () -> self#read_object_field)) *)
+			(* 	| 11 -> TArrayDecl(self#read_list8 (fun () -> self#read_texpr)) *)
+			(* 	| 12 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let el = self#read_list8 (fun () -> self#read_texpr) in *)
+			(* 		TCall(e1,el) *)
+			(* 	| 13 -> *)
+			(* 		let c = self#read_class_ref in *)
+			(* 		let tl = self#read_types in *)
+			(* 		let el = self#read_list8 (fun () -> self#read_texpr) in *)
+			(* 		TNew(c,tl,el) *)
+			(* 	| 14 -> *)
+			(* 		let op = self#read_unop in *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		TUnop(op,Prefix,e1) *)
+			(* 	| 15 -> *)
+			(* 		let op = self#read_unop in *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		TUnop(op,Postfix,e1) *)
+			(* 	| 16 -> TFunction(self#read_tfunction) *)
+			(* 	| 17 -> *)
+			(* 		let v = self#read_tvar_def in *)
+			(* 		let eo = self#read_option (fun () -> self#read_texpr) in *)
+			(* 		TVar(v,eo) *)
+			(* 	(1* TODO check list 8 vs 16 *1) *)
+			(* 	| 18 -> TBlock(self#read_list16 (fun () -> self#read_texpr)) *)
+			(* 	| 19 -> *)
+			(* 		let v = self#read_tvar_def in *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let e2 = self#read_texpr in *)
+			(* 		TFor(v,e1,e2) *)
+			(* 	| 20 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let e2 = self#read_texpr in *)
+			(* 		TIf(e1,e2,None) *)
+			(* 	| 21 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let e2 = self#read_texpr in *)
+			(* 		let e3 = self#read_texpr in *)
+			(* 		TIf(e1,e2,Some e3) *)
+			(* 	| 22 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let e2 = self#read_texpr in *)
+			(* 		TWhile(e1,e2,NormalWhile) *)
+			(* 	| 23 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let e2 = self#read_texpr in *)
+			(* 		TWhile(e1,e2,DoWhile) *)
+			(* 	| 24 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 	(1* TODO check list 8 vs 16 *1) *)
+			(* 		let cases = self#read_list16 (fun () -> self#read_switch_case) in *)
+			(* 		let eo = self#read_option (fun () -> self#read_texpr) in *)
+
+			(* 		TSwitch { *)
+			(* 			switch_subject = e1; *)
+			(* 			switch_cases = cases; *)
+			(* 			switch_default = eo; *)
+			(* 			switch_exhaustive = true; (1* I guess, if this was saved? *1) *)
+			(* 		} *)
+			(* 	| 25 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let catches = self#read_list8 (fun () -> self#read_catch) in *)
+			(* 		TTry(e1,catches) *)
+			(* 	| 26 -> TReturn None *)
+			(* 	| 27 -> TReturn (Some (self#read_texpr)) *)
+			(* 	| 28 -> TBreak *)
+			(* 	| 29 -> TContinue *)
+			(* 	| 30 -> TThrow (self#read_texpr) *)
+			(* 	| 31 -> TCast(self#read_texpr,None) *)
+			(* 	| 32 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let c = self#read_class_ref in *)
+			(* 		TCast(e1,Some (TClassDecl c)) *)
+			(* 	| 33 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let en = self#read_enum_ref in *)
+			(* 		TCast(e1,Some (TEnumDecl en)) *)
+			(* 	| 34 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let td = self#read_typedef_ref in *)
+			(* 		TCast(e1,Some (TTypeDecl td)) *)
+			(* 	| 35 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let a = self#read_abstract_ref in *)
+			(* 		TCast(e1,Some (TAbstractDecl a)) *)
+			(* 	| 36 -> *)
+			(* 		let m = self#read_metadata_entry in *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		TMeta(m,e1) *)
+			(* 	| 37 -> *)
+			(* 		let e1 = self#read_texpr in *)
+			(* 		let ef = self#read_enum_field_ref in *)
+			(* 		let i = IO.read_i32 ch in *)
+			(* 		TEnumParameter(e1,ef,i) *)
+			(* 	| 38 -> TEnumIndex(self#read_texpr) *)
+			(* 	| 39 -> TIdent(self#read_string) *)
+			(* 	| _ -> assert false *)
+			(* in *)
+
+		method read_class_field (m : module_def) : tclass_field =
+			let name = self#read_string in
+			Printf.eprintf "  Read class field %s\n" name;
+			(* TODO read_list? *)
+			(* self#read_type_parameters m ([],name) (fun a -> *)
+			(* 	field_type_parameters <- a *)
+			(* ); *)
+
+			(* TODO fix flags *)
+			(* let flags = Int32.to_int self#read_u32 in *)
+			(* let flags = Int32.to_int (IO.read_real_i32 ch) in *)
+			(* let flags = IO.read_i32 ch in *)
+			let flags = 0 in
+
+			let t = self#read_type_instance in
 			let pos = self#read_pos in
 			let name_pos = self#read_pos in
-			let mt = match kind with
+			let doc = self#read_option (fun () -> self#read_documentation) in
+			let meta = self#read_metadata in
+			self#read_type_parameters m ([],name) (fun a ->
+				field_type_parameters <- a
+			);
+			let params = Array.to_list field_type_parameters in
+			let kind = self#read_field_kind in
+			let expr = self#read_option (fun () -> self#read_texpr) in
+			let expr_unoptimized = self#read_option (fun () -> self#read_texpr) in
+			let overloads = self#read_list16 (fun () -> self#read_class_field m) in
+			{
+				cf_name = name;
+				cf_type = t;
+				cf_pos = pos;
+				cf_name_pos = name_pos;
+				cf_doc = doc;
+				cf_meta = meta;
+				cf_kind = kind;
+				(* cf_expr = None; *)
+				(* cf_expr_unoptimized = None; *)
+				cf_expr = expr;
+				cf_expr_unoptimized = expr_unoptimized;
+				cf_params = params;
+				cf_overloads = overloads;
+				cf_flags = flags;
+			}
+
+		method read_class_fields (m : module_def) (c : tclass) =
+			Printf.eprintf "  Read class fields for %s\n" (snd m.m_path);
+			let f () = self#read_class_field m in
+			begin match c.cl_kind with
+			| KAbstractImpl a ->
+				type_type_parameters <- Array.of_list a.a_params
+			| _ ->
+				type_type_parameters <- Array.of_list c.cl_params
+			end;
+			c.cl_constructor <- self#read_option f;
+				(* TODO check list 8 vs 16 *)
+			c.cl_ordered_fields <- self#read_list8 f;
+				(* TODO check list 8 vs 16 *)
+			c.cl_ordered_statics <- self#read_list8 f;
+			List.iter (fun cf -> c.cl_statics <- PMap.add cf.cf_name cf c.cl_statics) c.cl_ordered_statics;
+
+		(* Module types *)
+
+		method read_common_module_type (m : module_def) (infos : tinfos) =
+			infos.mt_private <- self#read_bool;
+			(* TODO: fix that *)
+			(* infos.mt_doc <- self#read_option (fun () -> self#read_documentation); *)
+			infos.mt_meta <- self#read_metadata;
+			(* TODO update to new type param format? *)
+			self#read_type_parameters m infos.mt_path (fun a ->
+				type_type_parameters <- a
+			);
+			infos.mt_params <- Array.to_list type_type_parameters;
+				(* TODO check list 8 vs 16 *)
+			infos.mt_using <- self#read_list16 (fun () ->
+				let c = self#read_class_ref in
+				let p = self#read_pos in
+				(c,p)
+			)
+
+		method read_class_kind = match self#read_u8 with
 			| 0 ->
-				let c = mk_class m path pos name_pos in
-				TClassDecl c
+				KNormal
 			| 1 ->
-				let en = mk_enum m path pos name_pos in
-				TEnumDecl en
+				KTypeParameter self#read_types
 			| 2 ->
-				let td = mk_typedef m path pos name_pos (mk_mono()) in
-				TTypeDecl td
+				KExpr ((EBlock []),null_pos) (* TODO *)
 			| 3 ->
-				let a = mk_abstract m path pos name_pos in
-				TAbstractDecl a
-			| _ ->
-				error ("Invalid type kind: " ^ (string_of_int kind));
+				KGeneric
+			| 4 ->
+				let c = self#read_class_ref in
+				let tl = self#read_types in
+				KGenericInstance(c,tl)
+			| 5 ->
+				KMacroType
+			| 6 ->
+				KGenericBuild [] (* TODO *)
+			| 7 ->
+				KAbstractImpl self#read_abstract_ref
+			| 8 ->
+				(* TODO *)
+				KNormal
+			| i ->
+				error (Printf.sprintf "Invalid class kind id: %i" i)
+
+		method read_class (m : module_def) (c : tclass) =
+			self#read_common_module_type m (Obj.magic c);
+			c.cl_kind <- self#read_class_kind;
+			c.cl_flags <- (Int32.to_int self#read_u32);
+			let read_relation () =
+				let c = self#read_class_ref in
+				let tl = self#read_types in
+				(c,tl)
 			in
-			mt
-		)
+			c.cl_super <- self#read_option read_relation;
+				(* TODO check list 8 vs 16 *)
+			c.cl_implements <- self#read_list16 read_relation;
+			c.cl_dynamic <- self#read_option (fun () -> self#read_type_instance);
+			c.cl_array_access <- self#read_option (fun () -> self#read_type_instance);
+
+		method read_abstract (m : module_def) (a : tabstract) =
+			self#read_common_module_type m (Obj.magic a);
+			a.a_impl <- self#read_option (fun () -> self#read_class_ref);
+			a.a_this <- self#read_type_instance;
+				(* TODO check list 8 vs 16 *)
+			a.a_from <- self#read_list16 (fun () -> self#read_type_instance);
+				(* TODO check list 8 vs 16 *)
+			a.a_from_field <- self#read_list16 (fun () ->
+				let t = self#read_type_instance in
+				let cf = self#read_field_ref in
+				(t,cf)
+			);
+				(* TODO check list 8 vs 16 *)
+			a.a_to <- self#read_list16 (fun () -> self#read_type_instance);
+				(* TODO check list 8 vs 16 *)
+			a.a_to_field <- self#read_list16 (fun () ->
+				let t = self#read_type_instance in
+				let cf = self#read_field_ref in
+				(t,cf)
+			);
+				(* TODO check list 8 vs 16 *)
+			a.a_array <- self#read_list16 (fun () -> self#read_field_ref);
+			a.a_read <- self#read_option (fun () -> self#read_field_ref);
+			a.a_write <- self#read_option (fun () -> self#read_field_ref);
+			a.a_call <- self#read_option (fun () -> self#read_field_ref);
+			a.a_enum <- self#read_bool
+
+		(* Chunks *)
+
+		method read_string_pool =
+			let l = self#read_uleb128 in
+			(* Printf.eprintf "  Read string pool of size %d\n" l; *)
+			Array.init l (fun i ->
+				self#read_raw_string;
+			);
+
+		method read_chunk =
+			let size = Int32.to_int self#read_u32 in
+			let name = Bytes.unsafe_to_string (IO.nread ch 4) in
+			let data = IO.nread ch size in
+			let crc = self#read_u32 in
+			ignore(crc); (* TODO *)
+			let kind = chunk_kind_of_string name in
+			(kind,data)
+
+		method read_cfld (m : module_def) =
+			let l = self#read_uleb128 in
+			for i = 0 to l - 1 do
+				let c = classes.(i) in
+				self#read_class_fields m c;
+			done
+
+		method read_clsd (m : module_def) =
+			let l = self#read_uleb128 in
+			for i = 0 to l - 1 do
+				let c = classes.(i) in
+				self#read_class m c;
+			done
+
+		method read_absd (m : module_def) =
+			let l = self#read_uleb128 in
+			for i = 0 to l - 1 do
+				let a = abstracts.(i) in
+				self#read_abstract m a;
+			done
+
+		method read_clsr =
+			let l = self#read_uleb128 in
+			classes <- Array.append classes (Array.init l (fun i ->
+				let (pack,mname,tname) = self#read_full_path in
+				Printf.eprintf "  Read clsr %d of %d for class %s\n" i (l-1) tname;
+				match resolve_type pack mname tname with
+				| TClassDecl c ->
+					c
+				| _ ->
+					error ("Unexpected type where class was expected: " ^ (s_type_path (pack,tname)))
+			))
+			(* classes <- self#read_list16 (fun () -> *)
+			(* 	let (pack,mname,tname) = self#read_full_path in *)
+			(* 	match resolve_type pack mname tname with *)
+			(* 	| TClassDecl c -> *)
+			(* 		c *)
+			(* 	| _ -> *)
+			(* 		error ("Unexpected type where class was expected: " ^ (s_type_path (pack,tname))) *)
+			(* ); *)
+
+		method read_absr =
+			let l = self#read_uleb128 in
+			abstracts <- Array.append abstracts (Array.init l (fun i ->
+				let (pack,mname,tname) = self#read_full_path in
+				Printf.eprintf "  Read absr %d of %d for abstract %s\n" i l tname;
+				match resolve_type pack mname tname with
+				| TAbstractDecl a ->
+					a
+				| _ ->
+					error ("Unexpected type where class was expected: " ^ (s_type_path (pack,tname)))
+			))
+
+		method read_typf (m : module_def) =
+				(* TODO check list 8 vs 16 *)
+			self#read_list16 (fun () ->
+				let kind = self#read_u8 in
+				let path = self#read_path in
+				let pos = self#read_pos in
+				let name_pos = self#read_pos in
+				let mt = match kind with
+				| 0 ->
+					let c = mk_class m path pos name_pos in
+					TClassDecl c
+				| 1 ->
+					let en = mk_enum m path pos name_pos in
+					TEnumDecl en
+				| 2 ->
+					let td = mk_typedef m path pos name_pos (mk_mono()) in
+					TTypeDecl td
+				| 3 ->
+					let a = mk_abstract m path pos name_pos in
+					TAbstractDecl a
+				| _ ->
+					error ("Invalid type kind: " ^ (string_of_int kind));
+				in
+				mt
+			)
 
-	method read_hhdr =
-		let path = self#read_path in
-		let file = self#read_string in
-		let m = make_module path file in
-		m
-
-	method read (debug : bool) (p : pos) =
-		(* TODO: add it to writer! *)
-		(* if (Bytes.to_string (IO.nread ch 3)) <> "hxb" then *)
-		(* 	raise (HxbFailure "magic"); *)
-		(* let version = self#read_u8 in *)
-		(* ignore(version); *)
-		let rec loop acc =
-			ch <- file_ch;
-			let chunk = self#read_chunk in
-			match fst chunk with
-			| HEND ->
-				List.rev acc
-			| _ ->
-				loop (chunk :: acc)
-		in
-		let chunks = loop [] in
-		let chunks = List.sort (fun (kind1,_) (kind2,_) ->
-			(Obj.magic kind1) - (Obj.magic kind2)
-		) chunks in
-		let rec pass_0 chunks = match chunks with
-			| [] ->
-				raise (HxbFailure "Missing HHDR chunk")
-			| (kind,data) :: chunks ->
+		method read_hhdr =
+			let path = self#read_path in
+			let file = self#read_string in
+			let m = make_module path file in
+			m
+
+		method read (debug : bool) (p : pos) =
+			(* TODO: add it to writer! *)
+			(* if (Bytes.to_string (IO.nread ch 3)) <> "hxb" then *)
+			(* 	raise (HxbFailure "magic"); *)
+			(* let version = self#read_u8 in *)
+			(* ignore(version); *)
+			let rec loop acc =
+				(* ch <- file_ch; *)
+				let chunk = self#read_chunk in
+				match fst chunk with
+				| HEND ->
+					List.rev acc
+				| _ ->
+					loop (chunk :: acc)
+			in
+			let chunks = loop [] in
+			let chunks = List.sort (fun (kind1,_) (kind2,_) ->
+				(Obj.magic kind1) - (Obj.magic kind2)
+			) chunks in
+			let rec pass_0 chunks = match chunks with
+				| [] ->
+					raise (HxbFailure "Missing HHDR chunk")
+				| (kind,data) :: chunks ->
+					ch <- IO.input_bytes data;
+					match kind with
+					| HHDR ->
+						let m = self#read_hhdr in
+						m,chunks
+					| STRI ->
+						string_pool <- Array.concat [string_pool; self#read_string_pool];
+						(* string_pool <- self#read_string_pool; *)
+						(* Array.iteri (fun i s -> *)
+						(* 	Printf.eprintf "  [Pool] string #%d %s\n" i s; *)
+						(* ) string_pool; *)
+						pass_0 chunks
+					| DOCS ->
+						doc_pool <- Array.concat [doc_pool; self#read_string_pool];
+						(* doc_pool <- self#read_string_pool; *)
+						(* Array.iteri (fun i s -> *)
+						(* 	Printf.eprintf "  [Pool] doc string #%d %s\n" i s; *)
+						(* ) doc_pool; *)
+						pass_0 chunks
+					| _ ->
+						raise (HxbFailure ("Unexpected early chunk: " ^ (string_of_chunk_kind kind)))
+			in
+			let m,chunks = pass_0 chunks in
+			List.iter (fun (kind,data) ->
 				ch <- IO.input_bytes data;
 				match kind with
-				| HHDR ->
-					let m = self#read_hhdr in
-					m,chunks
-				| STRI ->
-					string_pool <- self#read_string_pool;
-					pass_0 chunks
-				| DOCS ->
-					doc_pool <- self#read_string_pool;
-					pass_0 chunks
+				| TYPF ->
+					m.m_types <- self#read_typf m;
+					add_module m;
+				| CLSR ->
+					self#read_clsr;
+				| ABSR ->
+					self#read_absr;
+				| CLSD ->
+					self#read_clsd m;
+				| CFLD ->
+					Printf.eprintf "  Read class fields\n";
+					self#read_cfld m;
+				| ABSD ->
+					self#read_absd m;
 				| _ ->
-					raise (HxbFailure ("Unexpected early chunk: " ^ (string_of_chunk_kind kind)))
-		in
-		let m,chunks = pass_0 chunks in
-		List.iter (fun (kind,data) ->
-			ch <- IO.input_bytes data;
-			match kind with
-			| TYPF ->
-				m.m_types <- self#read_typf m;
-				add_module m;
-			| CLSR ->
-				self#read_clsr;
-			| ABSR ->
-				self#read_absr;
-			| CLSD ->
-				self#read_clsd m;
-			| CFLD ->
-				self#read_cfld m;
-			| ABSD ->
-				self#read_absd m;
-			| _ ->
-				raise (HxbFailure ("Unexpected late chunk: " ^ (string_of_chunk_kind kind)))
-		) chunks;
-		m
-end
+					raise (HxbFailure ("Unexpected late chunk: " ^ (string_of_chunk_kind kind)))
+			) chunks;
+			m
+	end

+ 325 - 706
src/compiler/hxb/hxbWriter.ml

@@ -9,6 +9,47 @@ type field_source =
 	| ClassMember of tclass
 	| CLassConstructor of tclass
 
+let rec binop_index op = match op with
+	| OpAdd -> 0
+	| OpMult -> 1
+	| OpDiv -> 2
+	| OpSub -> 3
+	| OpAssign -> 4
+	| OpEq -> 5
+	| OpNotEq -> 6
+	| OpGt -> 7
+	| OpGte -> 8
+	| OpLt -> 9
+	| OpLte -> 10
+	| OpAnd -> 11
+	| OpOr -> 12
+	| OpXor -> 13
+	| OpBoolAnd -> 14
+	| OpBoolOr -> 15
+	| OpShl -> 16
+	| OpShr -> 17
+	| OpUShr -> 18
+	| OpMod -> 19
+	| OpInterval -> 20
+	| OpArrow -> 21
+	| OpIn -> 22
+	| OpNullCoal -> 23
+	| OpAssignOp op -> 30 + binop_index op
+
+let unop_index op flag = match op,flag with
+	| Increment,Prefix -> 0
+	| Decrement,Prefix -> 1
+	| Not,Prefix -> 2
+	| Neg,Prefix -> 3
+	| NegBits,Prefix -> 4
+	| Spread,Prefix -> 5
+	| Increment,Postfix -> 6
+	| Decrement,Postfix -> 7
+	| Not,Postfix -> 8
+	| Neg,Postfix -> 9
+	| NegBits,Postfix -> 10
+	| Spread,Postfix -> 11
+
 class ['key,'value] pool = object(self)
 	val lut = Hashtbl.create 0
 	val items = DynArray.create ()
@@ -118,7 +159,7 @@ class string_pool (kind : chunk_kind) = object(self)
 	method is_empty =
 		pool#is_empty
 
-	method export : 'a . 'a IO.output -> unit = fun chex ->
+	method !export : 'a . 'a IO.output -> unit = fun chex ->
 		self#write_uleb128 (DynArray.length pool#items);
 		DynArray.iter (fun s ->
 			let b = Bytes.unsafe_of_string s in
@@ -206,528 +247,7 @@ class ['a] hxb_writer
 	method write_pos (p : pos) =
 		chunk#write_string p.pfile;
 		chunk#write_leb128 p.pmin;
-		chunk#write_leb128 p.pmax;
-
-	method write_metadata_entry ((meta,el,p) : metadata_entry) =
-		chunk#write_string (Meta.to_string meta);
-		(* TODO: el -_- *)
-		self#write_pos p
-
-	method write_metadata ml =
-		chunk#write_list ml self#write_metadata_entry
-
-	(* References *)
-
-	method write_class_ref (c : tclass) =
-		chunk#write_uleb128 (classes#get_or_add c.cl_path c)
-
-	method write_enum_ref (en : tenum) =
-		chunk#write_uleb128 (enums#get_or_add en.e_path en)
-
-	method write_typedef_ref (td : tdef) =
-		chunk#write_uleb128 (typedefs#get_or_add td.t_path td)
-
-	method write_abstract_ref (a : tabstract) =
-		chunk#write_uleb128 (abstracts#get_or_add a.a_path a)
-
-	method write_field_ref (source : field_source) (cf : tclass_field) =
-		chunk#write_string cf.cf_name
-
-	(* Type instances *)
-
-	method write_type_instance t =
-		let write_function_arg (n,o,t) =
-			chunk#write_string n;
-			chunk#write_bool o;
-			self#write_type_instance t;
-		in
-		match t with
-		| TMono r ->
-			begin match r.tm_type with
-			| None ->
-				chunk#write_byte 0
-			| Some t ->
-				chunk#write_byte 1;
-				self#write_type_instance t
-			end
-		| TInst({cl_kind = KTypeParameter _} as c,[]) ->
-			begin try
-				let i = field_type_parameters#get (snd c.cl_path) in
-				chunk#write_byte 5;
-				chunk#write_uleb128 i
-			with Not_found -> try
-				let i = type_type_parameters#get (snd c.cl_path) in
-				chunk#write_byte 6;
-				chunk#write_uleb128 i
-			with Not_found ->
-				error ("Unbound type parameter " ^ (s_type_path c.cl_path))
-			end
-		| TInst(c,[]) ->
-			chunk#write_byte 10;
-			self#write_class_ref c;
-		| TEnum(en,[]) ->
-			chunk#write_byte 11;
-			self#write_enum_ref en;
-		| TType(td,[]) ->
-			chunk#write_byte 12;
-			self#write_typedef_ref td;
-		| TAbstract(a,[]) ->
-			chunk#write_byte 13;
-			self#write_abstract_ref a;
-		| TInst(c,tl) ->
-			chunk#write_byte 14;
-			self#write_class_ref c;
-			self#write_types tl
-		| TEnum(en,tl) ->
-			chunk#write_byte 15;
-			self#write_enum_ref en;
-			self#write_types tl
-		| TType(td,tl) ->
-			chunk#write_byte 16;
-			self#write_typedef_ref td;
-			self#write_types tl
-		| TAbstract(a,tl) ->
-			chunk#write_byte 17;
-			self#write_abstract_ref a;
-			self#write_types tl
-		(* | TFun([],t) when ExtType.is_void (follow t) ->
-			chunk#write_byte 30;
-		| TFun(args,t) when ExtType.is_void (follow t) ->
-			chunk#write_byte 31;
-			chunk#write_list args write_function_arg; *)
-		| TFun(args,t) ->
-			chunk#write_byte 32;
-			chunk#write_list args write_function_arg;
-			self#write_type_instance t;
-		| TLazy r ->
-			self#write_type_instance (lazy_type r);
-		| TDynamic None ->
-			chunk#write_byte 40
-		| TDynamic (Some t) ->
-			chunk#write_byte 41;
-			self#write_type_instance t;
-		| TAnon an when PMap.is_empty an.a_fields ->
-			chunk#write_byte 50;
-		| TAnon an ->
-			let pfm = Option.get (anon_id#identify true t) in
-			chunk#write_byte 51;
-			chunk#write_uleb128 (anons#get_or_add pfm.pfm_path an)
-			(* begin match !(an.a_status) with
-			| Closed -> chunk#write_byte 50
-			| Const -> chunk#write_byte 51
-			| Extend _ -> chunk#write_byte 52
-			| Statics _ -> chunk#write_byte 53
-			| EnumStatics _ -> chunk#write_byte 54
-			| AbstractStatics _ -> chunk#write_byte 55
-			end; *)
-			(* let l = pmap_to_list an.a_fields in
-			(* chunk#write_list l (fun (_,cf) -> self#write_class_field cf); *)
-			begin match !(an.a_status) with
-			| Extend tl -> self#write_types tl
-			| Statics c -> self#write_class_ref c
-			| EnumStatics en -> self#write_enum_ref en
-			| AbstractStatics a -> self#write_abstract_ref a
-			| Closed
-			| Const ->
-				()
-			end; *)
-
-	method write_types tl =
-		chunk#write_list tl self#write_type_instance
-
-	(* Fields *)
-
-	method set_field_type_parameters (params : typed_type_param list) =
-		field_type_parameters <- new pool;
-		List.iter (fun ttp ->
-			ignore(field_type_parameters#add ttp.ttp_name ttp);
-		) params
-
-	method write_type_parameter_forward ttp = match follow ttp.ttp_type with
-		| TInst({cl_kind = KTypeParameter _} as c,_) ->
-			chunk#write_string ttp.ttp_name;
-			self#write_pos c.cl_name_pos
-		| _ ->
-			die "" __LOC__
-
-	method write_type_parameter_data ttp = match follow ttp.ttp_type with
-		| TInst({cl_kind = KTypeParameter tl1},tl2) ->
-			self#write_types tl1;
-			self#write_types tl2;
-		| _ ->
-			die "" __LOC__
-
-	method write_field_kind = function
-		| Method MethNormal -> chunk#write_byte 0;
-		| Method MethInline -> chunk#write_byte 1;
-		| Method MethDynamic -> chunk#write_byte 2;
-		| Method MethMacro -> chunk#write_byte 3;
-		(* normal read *)
-		| Var {v_read = AccNormal; v_write = AccNormal } -> chunk#write_byte 10
-		| Var {v_read = AccNormal; v_write = AccNo } -> chunk#write_byte 11
-		| Var {v_read = AccNormal; v_write = AccNever } -> chunk#write_byte 12
-		| Var {v_read = AccNormal; v_write = AccCtor } -> chunk#write_byte 13
-		| Var {v_read = AccNormal; v_write = AccCall } -> chunk#write_byte 14
-		(* inline read *)
-		| Var {v_read = AccInline; v_write = AccNever } -> chunk#write_byte 20
-		(* getter read *)
-		| Var {v_read = AccCall; v_write = AccNormal } -> chunk#write_byte 30
-		| Var {v_read = AccCall; v_write = AccNo } -> chunk#write_byte 31
-		| Var {v_read = AccCall; v_write = AccNever } -> chunk#write_byte 32
-		| Var {v_read = AccCall; v_write = AccCtor } -> chunk#write_byte 33
-		| Var {v_read = AccCall; v_write = AccCall } -> chunk#write_byte 34
-		(* weird/overlooked combinations *)
-		| Var {v_read = r;v_write = w } ->
-			chunk#write_byte 100;
-			let f = function
-				| AccNormal -> chunk#write_byte 0
-				| AccNo -> chunk#write_byte 1
-				| AccNever -> chunk#write_byte 2
-				| AccCtor -> chunk#write_byte 3
-				| AccCall -> chunk#write_byte 4
-				| AccInline -> chunk#write_byte 5
-				| AccRequire(s,so) ->
-					chunk#write_byte 6;
-					chunk#write_string s;
-					chunk#write_option so chunk#write_string
-			in
-			f r;
-			f w;
-
-	method write_class_field cf =
-		self#set_field_type_parameters cf.cf_params;
-		chunk#write_string cf.cf_name;
-		chunk#write_list cf.cf_params self#write_type_parameter_forward;
-		chunk#write_list cf.cf_params self#write_type_parameter_data;
-		self#write_type_instance cf.cf_type;
-		chunk#write_i32 cf.cf_flags;
-		self#write_pos cf.cf_pos;
-		self#write_pos cf.cf_name_pos;
-		chunk#write_option cf.cf_doc self#write_documentation;
-		self#write_metadata cf.cf_meta;
-		self#write_field_kind cf.cf_kind;
-		chunk#write_list cf.cf_overloads self#write_class_field;
-
-	(* Module types *)
-
-	method select_type (path : path) =
-		type_type_parameters <- type_param_lut#extract path
-
-	method write_common_module_type (infos : tinfos) : unit =
-		chunk#write_bool infos.mt_private;
-		chunk#write_option infos.mt_doc self#write_documentation;
-		self#write_metadata infos.mt_meta;
-		chunk#write_list infos.mt_params self#write_type_parameter_forward;
-		chunk#write_list infos.mt_params self#write_type_parameter_data;
-		chunk#write_list infos.mt_using (fun (c,p) ->
-			self#write_class_ref c;
-			self#write_pos p;
-		);
-
-	method write_class_kind = function
-		| KNormal ->
-			chunk#write_byte 0
-		| KTypeParameter tl ->
-			chunk#write_byte 1;
-			self#write_types tl;
-		| KExpr e ->
-			chunk#write_byte 2;
-			(* TODO *)
-		| KGeneric ->
-			chunk#write_byte 3;
-		| KGenericInstance(c,tl) ->
-			chunk#write_byte 4;
-			self#write_class_ref c;
-			self#write_types tl
-		| KMacroType ->
-			chunk#write_byte 5;
-		| KGenericBuild l ->
-			chunk#write_byte 6;
-			(* TODO *)
-		| KAbstractImpl a ->
-			chunk#write_byte 7;
-			self#write_abstract_ref a;
-		| KModuleFields md ->
-			chunk#write_byte 8;
-			(* TODO *)
-
-	method write_class (c : tclass) =
-		begin match c.cl_kind with
-		| KAbstractImpl a ->
-			self#select_type a.a_path
-		| _ ->
-			self#select_type c.cl_path;
-		end;
-		self#write_common_module_type (Obj.magic c);
-		self#write_class_kind c.cl_kind;
-		chunk#write_u32 (Int32.of_int c.cl_flags);
-		chunk#write_option c.cl_super (fun (c,tl) ->
-			self#write_class_ref c;
-			self#write_types tl
-		);
-		chunk#write_list c.cl_implements (fun (c,tl) ->
-			self#write_class_ref c;
-			self#write_types tl
-		);
-		chunk#write_option c.cl_dynamic self#write_type_instance;
-		chunk#write_option c.cl_array_access self#write_type_instance;
-
-	method write_abstract (a : tabstract) =
-		begin try
-			self#select_type a.a_path
-		with Not_found ->
-			print_endline ("Could not select abstract " ^ (s_type_path a.a_path));
-		end;
-		self#write_common_module_type (Obj.magic a);
-		(* ops *)
-		(* unops *)
-		chunk#write_option a.a_impl self#write_class_ref;
-		let c = match a.a_impl with
-			| None ->
-				null_class
-			| Some c ->
-				c
-		in
-		self#write_type_instance a.a_this;
-		chunk#write_list a.a_from self#write_type_instance;
-		chunk#write_list a.a_from_field (fun (t,cf) ->
-			self#set_field_type_parameters cf.cf_params;
-			self#write_type_instance t;
-			self#write_field_ref (ClassStatic c) cf;
-		);
-		chunk#write_list a.a_to self#write_type_instance;
-		chunk#write_list a.a_to_field (fun (t,cf) ->
-			self#set_field_type_parameters cf.cf_params;
-			self#write_type_instance t;
-			self#write_field_ref (ClassStatic c) cf;
-		);
-		chunk#write_list a.a_array (self#write_field_ref (ClassStatic c));
-		chunk#write_option a.a_read (self#write_field_ref (ClassStatic c));
-		chunk#write_option a.a_write (self#write_field_ref (ClassStatic c));
-		chunk#write_option a.a_call (self#write_field_ref (ClassStatic c));
-		chunk#write_bool a.a_enum
-
-	(* Module *)
-
-	method forward_declare_type (mt : module_type) =
-		let i = match mt with
-		| TClassDecl c ->
-			ignore(classes#add c.cl_path c);
-			ignore(own_classes#add c.cl_path c);
-			0
-		| TEnumDecl _ ->
-			1
-		| TTypeDecl _ ->
-			2
-		| TAbstractDecl a ->
-			ignore(abstracts#add a.a_path a);
-			ignore(own_abstracts#add a.a_path a);
-			3
-		in
-		let infos = t_infos mt in
-		chunk#write_byte i;
-		self#write_path infos.mt_path;
-		self#write_pos infos.mt_pos;
-		self#write_pos infos.mt_name_pos;
-		let params = new pool in
-		type_type_parameters <- params;
-		ignore(type_param_lut#add infos.mt_path params);
-		List.iter (fun ttp ->
-			ignore(type_type_parameters#add ttp.ttp_name ttp);
-		) infos.mt_params;
-
-	method write_module (m : module_def) =
-		self#start_chunk HHDR;
-		self#write_path m.m_path;
-		chunk#write_string (Path.UniqueKey.lazy_path m.m_extra.m_file);
-
-		self#start_chunk TYPF;
-		chunk#write_list m.m_types self#forward_declare_type;
-
-		begin match own_classes#to_list with
-		| [] ->
-			()
-		| own_classes ->
-			self#start_chunk CLSD;
-			chunk#write_list own_classes self#write_class;
-			self#start_chunk CFLD;
-			chunk#write_list own_classes (fun c ->
-				begin match c.cl_kind with
-				| KAbstractImpl a ->
-					self#select_type a.a_path
-				| _ ->
-					self#select_type c.cl_path;
-				end;
-				chunk#write_option c.cl_constructor self#write_class_field;
-				chunk#write_list c.cl_ordered_fields self#write_class_field;
-				chunk#write_list c.cl_ordered_statics self#write_class_field;
-			)
-		end;
-		begin match own_abstracts#to_list with
-		| [] ->
-			()
-		| own_abstracts ->
-			self#start_chunk ABSD;
-			chunk#write_list own_abstracts self#write_abstract;
-		end;
-		begin match classes#to_list with
-		| [] ->
-			()
-		| l ->
-			self#start_chunk CLSR;
-			chunk#write_list l (fun c ->
-				let m = c.cl_module in
-				self#write_full_path (fst m.m_path) (snd m.m_path) (snd c.cl_path)
-			)
-		end;
-		begin match abstracts#to_list with
-		| [] ->
-			()
-		| l ->
-			self#start_chunk ABSR;
-			chunk#write_list l (fun a ->
-				let m = a.a_module in
-				self#write_full_path (fst m.m_path) (snd m.m_path) (snd a.a_path)
-			)
-		end;
-		self#start_chunk HEND;
-
-	(* Export *)
-
-	method export : 'a . 'a IO.output -> unit = fun ch ->
-		cp#export ch;
-		if not docs#is_empty then
-			docs#export ch;
-		let l = DynArray.to_list chunks in
-		let l = List.sort (fun chunk1 chunk2 ->
-			(Obj.magic chunk1#kind) - (Obj.magic chunk2#kind)
-		) l in
-		List.iter (fun (chunk : chunk) ->
-			chunk#export ch
-		) l
-end
-
-(*
-class hxb_constant_pool_writer = object(self)
-	val lut = Hashtbl.create 0
-	val pool = DynArray.create ()
-
-	method get_index (s : string) =
-		try
-			Hashtbl.find lut s
-		with Not_found ->
-			let index = DynArray.length pool in
-			Hashtbl.add lut s index;
-			DynArray.add pool s;
-			index
-
-	method export : 'a . 'a IO.output -> unit = fun ch ->
-		IO.write_real_i32 ch (Int32.of_int (DynArray.length pool));
-		DynArray.iter (fun s ->
-			let b = Bytes.of_string s in
-			IO.write_real_i32 ch (Int32.of_int (Bytes.length b));
-			IO.nwrite ch b;
-		) pool;
-end
-
-let pmap_to_list map = PMap.foldi (fun k x l -> (k,x) :: l) map []
-let hashtbl_to_list h = Hashtbl.fold (fun k x l -> (k,x) :: l) h []
-
-let rec binop_index op = match op with
-	| OpAdd -> 0
-	| OpMult -> 1
-	| OpDiv -> 2
-	| OpSub -> 3
-	| OpAssign -> 4
-	| OpEq -> 5
-	| OpNotEq -> 6
-	| OpGt -> 7
-	| OpGte -> 8
-	| OpLt -> 9
-	| OpLte -> 10
-	| OpAnd -> 11
-	| OpOr -> 12
-	| OpXor -> 13
-	| OpBoolAnd -> 14
-	| OpBoolOr -> 15
-	| OpShl -> 16
-	| OpShr -> 17
-	| OpUShr -> 18
-	| OpMod -> 19
-	| OpInterval -> 20
-	| OpArrow -> 21
-	| OpIn -> 22
-	| OpAssignOp op -> 30 + binop_index op
-
-let unop_index op flag = match op,flag with
-	| Increment,Prefix -> 0
-	| Decrement,Prefix -> 1
-	| Not,Prefix -> 2
-	| Neg,Prefix -> 3
-	| NegBits,Prefix -> 4
-	| Increment,Postfix -> 5
-	| Decrement,Postfix -> 6
-	| Not,Postfix -> 7
-	| Neg,Postfix -> 8
-	| NegBits,Postfix -> 9
-
-class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = object(self)
-
-	(* basic *)
-
-	method write_byte b =
-		IO.write_byte ch b;
-
-	method write_bool b =
-		chunk#write_byte (if b then 1 else 0)
-
-	method write_ui16 i =
-		IO.write_ui16 ch i;
-
-	method write_i16 i =
-		IO.write_i16 ch i;
-
-	method write_i32 i =
-		IO.write_real_i32 ch (Int32.of_int i);
-
-	method write_float f =
-		IO.write_double ch f
-
-	method write_string s =
-		self#write_i32 (cp#get_index s);
-
-	method write_bytes b =
-		self#write_i32 (Bytes.length b);
-		IO.nwrite ch b;
-
-	method write_list8 : 'b . 'b list -> ('b -> unit) -> unit = fun l f ->
-		chunk#write_byte (List.length l);
-		List.iter f l;
-
-	method write_list16 : 'b . 'b list -> ('b -> unit) -> unit = fun l f ->
-		self#write_ui16 (List.length l);
-		List.iter f l;
-
-	method write_option : 'b . 'b option -> ('b -> unit) -> unit = fun v f -> match v with
-		| None -> chunk#write_byte 0
-		| Some v ->
-			chunk#write_byte 1;
-			f v
-
-	method write_path (path : path) =
-		self#write_list8 (fst path) chunk#write_string;
-		chunk#write_string (snd path);
-
-	method write_documentation (doc : doc_block) =
-		chunk#write_option doc.doc_own chunk#write_string;
-		self#write_list8 doc.doc_inherited chunk#write_string
-
-	(* basic compounds *)
-
-	method write_pos p =
-		chunk#write_string p.pfile;
-		self#write_i32 p.pmin;
-		self#write_i32 p.pmax;
+		chunk#write_leb128 p.pmax;
 
 	method write_metadata_entry ((meta,el,p) : metadata_entry) =
 		chunk#write_string (Meta.to_string meta);
@@ -735,39 +255,41 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 		self#write_pos p
 
 	method write_metadata ml =
-		self#write_list16 ml self#write_metadata_entry
-
-	method write_type_params params =
-		self#write_list16 params (fun (s,t) ->
-			chunk#write_string s;
-			match follow t with
-			| TInst({cl_kind = KTypeParameter tl},_) ->
-				self#write_types tl;
-			| _ ->
-				assert false
-		)
+		chunk#write_list ml self#write_metadata_entry
 
-	(* refs *)
+	(* References *)
 
-	method write_class_ref c =
-		self#write_path c.cl_path
+	method write_class_ref (c : tclass) =
+		(* chunk#write_uleb128 (classes#get_or_add c.cl_path c) *)
+		let i = classes#get_or_add c.cl_path c in
+		Printf.eprintf "  Write class ref %d for %s\n" i (snd c.cl_path);
+		chunk#write_uleb128 i
 
-	method write_enum_ref en =
-		self#write_path en.e_path
+	method write_enum_ref (en : tenum) =
+		(* chunk#write_uleb128 (enums#get_or_add en.e_path en) *)
+		let i = enums#get_or_add en.e_path en in
+		Printf.eprintf "  Write enum ref %d for %s\n" i (snd en.e_path);
+		chunk#write_uleb128 i
 
-	method write_typedef_ref td =
-		self#write_path td.t_path
+	method write_typedef_ref (td : tdef) =
+		(* chunk#write_uleb128 (typedefs#get_or_add td.t_path td) *)
+		let i = typedefs#get_or_add td.t_path td in
+		Printf.eprintf "  Write typedef ref %d for %s\n" i (snd td.t_path);
+		chunk#write_uleb128 i
 
-	method write_abstract_ref a =
-		self#write_path a.a_path
+	method write_abstract_ref (a : tabstract) =
+		(* chunk#write_uleb128 (abstracts#get_or_add a.a_path a) *)
+		let i = abstracts#get_or_add a.a_path a in
+		Printf.eprintf "  Write abstract ref %d for %s\n" i (snd a.a_path);
+		chunk#write_uleb128 i
 
-	method write_field_ref cf =
+	method write_field_ref (source : field_source) (cf : tclass_field) =
 		chunk#write_string cf.cf_name
 
 	method write_enum_field_ref ef =
 		chunk#write_string ef.ef_name
 
-	(* type instance *)
+	(* Type instances *)
 
 	method write_type_instance t =
 		let write_function_arg (n,o,t) =
@@ -778,11 +300,24 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 		match t with
 		| TMono r ->
 			begin match r.tm_type with
-			| None -> chunk#write_byte 0
+			| None ->
+				chunk#write_byte 0
 			| Some t ->
 				chunk#write_byte 1;
 				self#write_type_instance t
 			end
+		| TInst({cl_kind = KTypeParameter _} as c,[]) ->
+			begin try
+				let i = field_type_parameters#get (snd c.cl_path) in
+				chunk#write_byte 5;
+				chunk#write_uleb128 i
+			with Not_found -> try
+				let i = type_type_parameters#get (snd c.cl_path) in
+				chunk#write_byte 6;
+				chunk#write_uleb128 i
+			with Not_found ->
+				error ("Unbound type parameter " ^ (s_type_path c.cl_path))
+			end
 		| TInst(c,[]) ->
 			chunk#write_byte 10;
 			self#write_class_ref c;
@@ -811,33 +346,38 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 			chunk#write_byte 17;
 			self#write_abstract_ref a;
 			self#write_types tl
-		| TFun([],t) when ExtType.is_void (follow t) ->
+		(* | TFun([],t) when ExtType.is_void (follow t) ->
 			chunk#write_byte 30;
 		| TFun(args,t) when ExtType.is_void (follow t) ->
 			chunk#write_byte 31;
-			self#write_list16 args write_function_arg;
+			chunk#write_list args write_function_arg; *)
 		| TFun(args,t) ->
 			chunk#write_byte 32;
-			self#write_list16 args write_function_arg;
+			chunk#write_list args write_function_arg;
+			self#write_type_instance t;
 		| TLazy r ->
 			self#write_type_instance (lazy_type r);
-		| TDynamic t ->
-			if t == t_dynamic then chunk#write_byte 40
-			else begin
-				chunk#write_byte 41;
-				self#write_type_instance t;
-			end
+		| TDynamic None ->
+			chunk#write_byte 40
+		| TDynamic (Some t) ->
+			chunk#write_byte 41;
+			self#write_type_instance t;
+		| TAnon an when PMap.is_empty an.a_fields ->
+			chunk#write_byte 50;
 		| TAnon an ->
-			begin match !(an.a_status) with
+			let pfm = Option.get (anon_id#identify true t) in
+			chunk#write_byte 51;
+			chunk#write_uleb128 (anons#get_or_add pfm.pfm_path an)
+			(* begin match !(an.a_status) with
 			| Closed -> chunk#write_byte 50
 			| Const -> chunk#write_byte 51
 			| Extend _ -> chunk#write_byte 52
 			| Statics _ -> chunk#write_byte 53
 			| EnumStatics _ -> chunk#write_byte 54
 			| AbstractStatics _ -> chunk#write_byte 55
-			end;
-			let l = pmap_to_list an.a_fields in
-			self#write_list16 l (fun (_,cf) -> self#write_class_field cf);
+			end; *)
+			(* let l = pmap_to_list an.a_fields in
+			(* chunk#write_list l (fun (_,cf) -> self#write_class_field cf); *)
 			begin match !(an.a_status) with
 			| Extend tl -> self#write_types tl
 			| Statics c -> self#write_class_ref c
@@ -846,10 +386,10 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 			| Closed
 			| Const ->
 				()
-			end;
+			end; *)
 
 	method write_types tl =
-		self#write_list16 tl self#write_type_instance
+		chunk#write_list tl self#write_type_instance
 
 	(* texpr *)
 
@@ -865,11 +405,12 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 			| VInlined -> 7
 			| VInlinedConstructorVariable -> 8
 			| VExtractorVariable -> 9
+			| VAbstractThis -> 10
 		in
 		chunk#write_byte b
 
 	method write_var v =
-		self#write_i32 v.v_id;
+		chunk#write_i32 v.v_id;
 		chunk#write_string v.v_name;
 		self#write_type_instance v.v_type;
 		self#write_var_kind v.v_kind;
@@ -883,14 +424,15 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 		self#write_pos v.v_pos;
 
 	method write_texpr (e : texpr) =
+		Printf.eprintf "  Print texpr\n";
 		self#write_pos e.epos;
 		let curmin = ref e.epos.pmin in
 		let curmax = ref e.epos.pmax in
 		let check_diff p =
 			let dmin = p.pmin - !curmin in
 			let dmax = p.pmax - !curmax in
-			self#write_i16 dmin;
-			self#write_i16 dmax;
+			chunk#write_i16 dmin;
+			chunk#write_i16 dmax;
 			curmin := p.pmin;
 			curmax := p.pmax;
 		in
@@ -913,7 +455,7 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 					chunk#write_byte 4;
 				| TInt i32 ->
 					chunk#write_byte 5;
-					IO.write_real_i32 ch i32;
+					chunk#write_u32 i32;
 				| TFloat f ->
 					chunk#write_byte 6;
 					chunk#write_string f;
@@ -924,7 +466,7 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 			(* vars 20-29 *)
 			| TLocal v ->
 				chunk#write_byte 20;
-				self#write_i32 v.v_id;
+				chunk#write_i32 v.v_id;
 			| TVar(v,None) ->
 				chunk#write_byte 21;
 				self#write_var v;
@@ -949,17 +491,18 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 						chunk#write_byte l;
 					end else if l < 0xFFFF then begin
 						chunk#write_byte 37;
-						self#write_ui16 l;
+						chunk#write_ui16 l;
 					end else begin
 						chunk#write_byte 38;
-						self#write_i32 l;
+						chunk#write_i32 l;
 					end;
 				end;
 				List.iter loop el
 			(* function 50-59 *)
 			| TFunction tf ->
 				chunk#write_byte 50;
-				self#write_list16 tf.tf_args (fun (v,eo) ->
+				(* list16 *)
+				chunk#write_list tf.tf_args (fun (v,eo) ->
 					self#write_var v;
 					chunk#write_option eo loop
 				);
@@ -978,7 +521,8 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 				loop_el el;
 			| TObjectDecl fl ->
 				chunk#write_byte 63;
-				self#write_list16 fl (fun ((name,p,qs),e) ->
+				(* list16 *)
+				chunk#write_list fl (fun ((name,p,qs),e) ->
 					chunk#write_string name;
 					self#write_pos p;
 					begin match qs with
@@ -1005,18 +549,20 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 				loop e1;
 				loop e2;
 				loop e3;
-			| TSwitch(e1,cases,def) ->
+			| TSwitch s ->
 				chunk#write_byte 82;
-				loop e1;
-				self#write_list16 cases (fun (el,e) ->
-					loop_el el;
-					loop e;
+				loop s.switch_subject;
+				(* list16 *)
+				chunk#write_list s.switch_cases (fun c ->
+					loop_el c.case_patterns;
+					loop c.case_expr;
 				);
-				chunk#write_option def loop;
+				chunk#write_option s.switch_default loop;
 			| TTry(e1,catches) ->
 				chunk#write_byte 83;
 				loop e1;
-				self#write_list16 catches  (fun (v,e) ->
+				(* list16 *)
+				chunk#write_list catches  (fun (v,e) ->
 					self#write_var v;
 					loop e
 				);
@@ -1050,32 +596,34 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 				chunk#write_byte 101;
 				loop e1;
 				self#write_enum_field_ref ef;
-				self#write_i32 i;
+				chunk#write_i32 i;
 			| TField(e1,FInstance(c,tl,cf)) ->
 				chunk#write_byte 102;
 				loop e1;
 				self#write_class_ref c;
 				self#write_types tl;
-				self#write_field_ref cf;
+				self#write_field_ref (ClassMember c) cf; (* TODO check source *)
 			| TField(e1,FStatic(c,cf)) ->
 				chunk#write_byte 103;
 				loop e1;
 				self#write_class_ref c;
-				self#write_field_ref cf;
+				self#write_field_ref (ClassMember c) cf; (* TODO check source *)
 			| TField(e1,FAnon cf) ->
 				chunk#write_byte 104;
 				loop e1;
-				self#write_field_ref cf;
+				(* TODO *)
+				(* self#write_field_ref (ClassMember c) cf; (1* TODO check source *1) *)
 			| TField(e1,FClosure(Some(c,tl),cf)) ->
 				chunk#write_byte 105;
 				loop e1;
 				self#write_class_ref c;
 				self#write_types tl;
-				self#write_field_ref cf;
+				self#write_field_ref (ClassMember c) cf; (* TODO check source *)
 			| TField(e1,FClosure(None,cf)) ->
 				chunk#write_byte 106;
 				loop e1;
-				self#write_field_ref cf;
+				(* TODO *)
+				(* self#write_field_ref (ClassMember c) cf; (1* TODO check source *1) *)
 			| TField(e1,FEnum(en,ef)) ->
 				chunk#write_byte 107;
 				loop e1;
@@ -1124,12 +672,32 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 				chunk#write_byte 250;
 				chunk#write_string s;
 		and loop_el el =
-			self#write_ui16 (List.length el);
+			chunk#write_ui16 (List.length el);
 			List.iter loop el
 		in
 		loop e
 
-	(* field *)
+	(* Fields *)
+
+	method set_field_type_parameters (params : typed_type_param list) =
+		field_type_parameters <- new pool;
+		List.iter (fun ttp ->
+			ignore(field_type_parameters#add ttp.ttp_name ttp);
+		) params
+
+	method write_type_parameter_forward ttp = match follow ttp.ttp_type with
+		| TInst({cl_kind = KTypeParameter _} as c,_) ->
+			chunk#write_string ttp.ttp_name;
+			self#write_pos c.cl_name_pos
+		| _ ->
+			die "" __LOC__
+
+	method write_type_parameter_data ttp = match follow ttp.ttp_type with
+		| TInst({cl_kind = KTypeParameter tl1},tl2) ->
+			self#write_types tl1;
+			self#write_types tl2;
+		| _ ->
+			die "" __LOC__
 
 	method write_field_kind = function
 		| Method MethNormal -> chunk#write_byte 0;
@@ -1169,30 +737,38 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 			f w;
 
 	method write_class_field cf =
-		self#write_field_ref cf;
-		self#write_i32 cf.cf_flags;
+		Printf.eprintf " Write class field %s\n" cf.cf_name;
+		self#set_field_type_parameters cf.cf_params;
+		chunk#write_string cf.cf_name;
+		(* chunk#write_list cf.cf_params self#write_type_parameter_forward; *)
+		(* chunk#write_list cf.cf_params self#write_type_parameter_data; *)
 		self#write_type_instance cf.cf_type;
+		chunk#write_i32 cf.cf_flags;
 		self#write_pos cf.cf_pos;
 		self#write_pos cf.cf_name_pos;
 		chunk#write_option cf.cf_doc self#write_documentation;
 		self#write_metadata cf.cf_meta;
-		self#write_type_params cf.cf_params;
 		self#write_field_kind cf.cf_kind;
 		chunk#write_option cf.cf_expr self#write_texpr;
-		(* TODO: expr_unoptimized *)
-		self#write_list16 cf.cf_overloads self#write_class_field;
+		chunk#write_option cf.cf_expr_unoptimized self#write_texpr;
+		chunk#write_list cf.cf_overloads self#write_class_field;
+
+	(* Module types *)
 
-	method write_enum_field ef =
-		self#write_enum_field_ref ef;
-		self#write_type_instance ef.ef_type;
-		self#write_pos ef.ef_pos;
-		self#write_pos ef.ef_name_pos;
-		chunk#write_option ef.ef_doc self#write_documentation;
-		self#write_i32 ef.ef_index;
-		self#write_type_params ef.ef_params;
-		self#write_metadata ef.ef_meta;
+	method select_type (path : path) =
+		type_type_parameters <- type_param_lut#extract path
 
-	(* module *)
+	method write_common_module_type (infos : tinfos) : unit =
+		chunk#write_bool infos.mt_private;
+		(* TODO: fix that *)
+		(* chunk#write_option infos.mt_doc self#write_documentation; *)
+		self#write_metadata infos.mt_meta;
+		chunk#write_list infos.mt_params self#write_type_parameter_forward;
+		chunk#write_list infos.mt_params self#write_type_parameter_data;
+		chunk#write_list infos.mt_using (fun (c,p) ->
+			self#write_class_ref c;
+			self#write_pos p;
+		);
 
 	method write_class_kind = function
 		| KNormal ->
@@ -1221,115 +797,158 @@ class ['a] hxb_writer (ch : 'a IO.output) (cp : hxb_constant_pool_writer) = obje
 			chunk#write_byte 8;
 			(* TODO *)
 
-	method write_module_type mt =
-		let infos = t_infos mt in
-		self#write_path infos.mt_path;
-		self#write_pos infos.mt_pos;
-		self#write_pos infos.mt_name_pos;
-		chunk#write_bool infos.mt_private;
-		chunk#write_option infos.mt_doc self#write_documentation;
-		self#write_metadata infos.mt_meta;
-		self#write_type_params infos.mt_params;
-		self#write_list8 infos.mt_using (fun (c,p) ->
+	method write_class (c : tclass) =
+		begin match c.cl_kind with
+		| KAbstractImpl a ->
+			self#select_type a.a_path
+		| _ ->
+			self#select_type c.cl_path;
+		end;
+		self#write_common_module_type (Obj.magic c);
+		self#write_class_kind c.cl_kind;
+		chunk#write_u32 (Int32.of_int c.cl_flags);
+		chunk#write_option c.cl_super (fun (c,tl) ->
 			self#write_class_ref c;
-			self#write_pos p;
+			self#write_types tl
 		);
-		match mt with
-		| TClassDecl c ->
-			chunk#write_byte 0;
-			self#write_class_kind c.cl_kind;
-			(* TODO *)
-			(* chunk#write_bool c.cl_extern;
-			chunk#write_bool c.cl_final;
-			chunk#write_bool c.cl_interface; *)
-			let write_relation (cr,tl) =
-				self#write_class_ref cr;
-				self#write_types tl;
-			in
-			chunk#write_option c.cl_super write_relation;
-			self#write_list16 c.cl_implements write_relation;
-			self#write_list16 c.cl_ordered_statics self#write_class_field;
-			self#write_list16 c.cl_ordered_fields self#write_class_field;
-			chunk#write_option c.cl_dynamic self#write_type_instance;
-			chunk#write_option c.cl_array_access self#write_type_instance;
-			chunk#write_option c.cl_constructor self#write_class_field;
-			chunk#write_option c.cl_init self#write_texpr;
-		| TEnumDecl en ->
-			chunk#write_byte 1;
-			self#write_module_type (TTypeDecl en.e_type);
-			chunk#write_bool en.e_extern;
-			self#write_list16 en.e_names (fun s ->
-				let ef = PMap.find s en.e_constrs in
-				self#write_enum_field ef;
-			);
-		| TTypeDecl td ->
-			chunk#write_byte 2;
-			self#write_type_instance td.t_type;
-		| TAbstractDecl a ->
-			chunk#write_byte 3;
-			self#write_list16 a.a_ops (fun (op,cf) ->
-				chunk#write_byte (binop_index op);
-				self#write_field_ref cf
-			);
-			self#write_list16 a.a_unops (fun (op,flag,cf) ->
-				chunk#write_byte (unop_index op flag);
-				self#write_field_ref cf;
-			);
-			chunk#write_option a.a_impl self#write_class_ref;
-			self#write_type_instance a.a_this;
-			self#write_types a.a_from;
-			self#write_list16 a.a_from_field (fun (t,cf) ->
-				self#write_type_instance t;
-				self#write_field_ref cf
-			);
-			self#write_types a.a_to;
-			self#write_list16 a.a_to_field (fun (t,cf) ->
-				self#write_type_instance t;
-				self#write_field_ref cf
-			);
-			self#write_list16 a.a_array self#write_field_ref;
-			chunk#write_option a.a_read self#write_field_ref;
-			chunk#write_option a.a_write self#write_field_ref;
-
-	method write_module m =
-		self#write_i32 m.m_id;
-		self#write_path m.m_path;
-		self#write_list16 m.m_types self#write_module_type;
-		let extra = m.m_extra in
-		chunk#write_string (Path.UniqueKey.lazy_path extra.m_file);
-		chunk#write_string (Digest.to_hex extra.m_sign);
-		self#write_list16 extra.m_display.m_inline_calls (fun (p1,p2) ->
-			self#write_pos p1;
-			self#write_pos p2;
+		chunk#write_list c.cl_implements (fun (c,tl) ->
+			self#write_class_ref c;
+			self#write_types tl
 		);
-		(* TODO *)
-		(* self#write_list16 extra.m_display.m_type_hints (fun (p,t) ->
-			self#write_pos p;
+		chunk#write_option c.cl_dynamic self#write_type_instance;
+		chunk#write_option c.cl_array_access self#write_type_instance;
+
+	method write_abstract (a : tabstract) =
+		begin try
+			self#select_type a.a_path
+		with Not_found ->
+			print_endline ("Could not select abstract " ^ (s_type_path a.a_path));
+		end;
+		self#write_common_module_type (Obj.magic a);
+		(* ops *)
+		(* unops *)
+		chunk#write_option a.a_impl self#write_class_ref;
+		let c = match a.a_impl with
+			| None ->
+				null_class
+			| Some c ->
+				c
+		in
+		self#write_type_instance a.a_this;
+		chunk#write_list a.a_from self#write_type_instance;
+		chunk#write_list a.a_from_field (fun (t,cf) ->
+			self#set_field_type_parameters cf.cf_params;
 			self#write_type_instance t;
-		); *)
-		self#write_list8 extra.m_check_policy (fun pol -> chunk#write_byte (Obj.magic pol)); (* TODO: don't be lazy *)
-		self#write_float extra.m_time;
-		(* chunk#write_option extra.m_dirty (fun m -> self#write_path m.m_path); *) (* TODO *)
-		self#write_i32 extra.m_added;
-		self#write_i32 extra.m_mark;
-		self#write_list16 (pmap_to_list extra.m_deps) (fun (i,m) ->
-			self#write_i32 i;
-			self#write_path m.m_path;
-		);
-		self#write_i32 extra.m_processed;
-		chunk#write_byte (Obj.magic extra.m_kind); (* TODO: don't be lazy *)
-		self#write_list16 (pmap_to_list extra.m_binded_res) (fun (s1,s2) ->
-			chunk#write_string s1;
-			chunk#write_bytes (Bytes.unsafe_of_string s2);
-		);
-		self#write_list16 extra.m_if_feature (fun (s,(c,cf,b)) ->
-			chunk#write_string s;
-			self#write_class_ref c;
-			self#write_field_ref cf;
-			chunk#write_bool b;
+			self#write_field_ref (ClassStatic c) cf;
 		);
-		self#write_list16 (hashtbl_to_list extra.m_features) (fun (s,b) ->
-			chunk#write_string s;
-			chunk#write_bool b;
+		chunk#write_list a.a_to self#write_type_instance;
+		chunk#write_list a.a_to_field (fun (t,cf) ->
+			self#set_field_type_parameters cf.cf_params;
+			self#write_type_instance t;
+			self#write_field_ref (ClassStatic c) cf;
 		);
-end *)
+		chunk#write_list a.a_array (self#write_field_ref (ClassStatic c));
+		chunk#write_option a.a_read (self#write_field_ref (ClassStatic c));
+		chunk#write_option a.a_write (self#write_field_ref (ClassStatic c));
+		chunk#write_option a.a_call (self#write_field_ref (ClassStatic c));
+		chunk#write_bool a.a_enum
+
+	(* Module *)
+
+	method forward_declare_type (mt : module_type) =
+		let i = match mt with
+		| TClassDecl c ->
+			ignore(classes#add c.cl_path c);
+			ignore(own_classes#add c.cl_path c);
+			0
+		| TEnumDecl _ ->
+			1
+		| TTypeDecl _ ->
+			2
+		| TAbstractDecl a ->
+			ignore(abstracts#add a.a_path a);
+			ignore(own_abstracts#add a.a_path a);
+			3
+		in
+		let infos = t_infos mt in
+		chunk#write_byte i;
+		self#write_path infos.mt_path;
+		self#write_pos infos.mt_pos;
+		self#write_pos infos.mt_name_pos;
+		let params = new pool in
+		type_type_parameters <- params;
+		ignore(type_param_lut#add infos.mt_path params);
+		List.iter (fun ttp ->
+			ignore(type_type_parameters#add ttp.ttp_name ttp);
+		) infos.mt_params;
+
+	method write_module (m : module_def) =
+		self#start_chunk HHDR;
+		self#write_path m.m_path;
+		chunk#write_string (Path.UniqueKey.lazy_path m.m_extra.m_file);
+
+		self#start_chunk TYPF;
+		chunk#write_list m.m_types self#forward_declare_type;
+
+		begin match own_classes#to_list with
+		| [] ->
+			()
+		| own_classes ->
+			self#start_chunk CLSD;
+			chunk#write_list own_classes self#write_class;
+			self#start_chunk CFLD;
+			chunk#write_list own_classes (fun c ->
+				begin match c.cl_kind with
+				| KAbstractImpl a ->
+					self#select_type a.a_path
+				| _ ->
+					self#select_type c.cl_path;
+				end;
+				chunk#write_option c.cl_constructor self#write_class_field;
+				chunk#write_list c.cl_ordered_fields self#write_class_field;
+				chunk#write_list c.cl_ordered_statics self#write_class_field;
+			)
+		end;
+		begin match own_abstracts#to_list with
+		| [] ->
+			()
+		| own_abstracts ->
+			self#start_chunk ABSD;
+			chunk#write_list own_abstracts self#write_abstract;
+		end;
+		begin match classes#to_list with
+		| [] ->
+			()
+		| l ->
+			self#start_chunk CLSR;
+			chunk#write_list l (fun c ->
+				let m = c.cl_module in
+				self#write_full_path (fst m.m_path) (snd m.m_path) (snd c.cl_path)
+			)
+		end;
+		begin match abstracts#to_list with
+		| [] ->
+			()
+		| l ->
+			self#start_chunk ABSR;
+			chunk#write_list l (fun a ->
+				let m = a.a_module in
+				self#write_full_path (fst m.m_path) (snd m.m_path) (snd a.a_path)
+			)
+		end;
+		self#start_chunk HEND;
+
+	(* Export *)
+
+	method export : 'a . 'a IO.output -> unit = fun ch ->
+		cp#export ch;
+		if not docs#is_empty then
+			docs#export ch;
+		let l = DynArray.to_list chunks in
+		let l = List.sort (fun chunk1 chunk2 ->
+			(Obj.magic chunk1#kind) - (Obj.magic chunk2#kind)
+		) l in
+		List.iter (fun (chunk : chunk) ->
+			chunk#export ch
+		) l
+end

+ 2 - 2
src/compiler/tasks.ml

@@ -37,7 +37,7 @@ class class_maintenance_task (cs : CompilationCache.t) (c : tclass) = object(sel
 		let rec field cf =
 			(* Unset cf_expr. This holds the optimized version for generators, which we don't need to persist. If
 				we compile again, the semi-optimized expression will be restored by calling cl_restore(). *)
-			cf.cf_expr <- None;
+			(* cf.cf_expr <- None; *)
 			List.iter field cf.cf_overloads
 		in
 		(* What we're doing here at the moment is free, so we can just do it in one task. If this ever gets more expensive,
@@ -64,4 +64,4 @@ class server_exploration_task (cs : CompilationCache.t) = object(self)
 
 	method private execute =
 		cs#iter_modules (fun m -> cs#add_task (new module_maintenance_task cs m))
-end
+end

+ 15 - 6
src/core/tFunctions.ml

@@ -199,19 +199,24 @@ let mk_field name ?(public = true) ?(static = false) t p name_pos = {
 }
 
 let null_module = {
-		m_id = alloc_mid();
-		m_path = [] , "";
-		m_types = [];
-		m_statics = None;
-		m_extra = module_extra "" "" 0. MFake [];
-	}
+	m_id = alloc_mid();
+	m_path = [] , "";
+	m_types = [];
+	m_statics = None;
+	m_extra = module_extra "" "" 0. MFake [];
+}
 
 let null_class =
 	let c = mk_class null_module ([],"") null_pos null_pos in
 	c.cl_private <- true;
 	c
 
+(* TODO null_enum *)
+
 let null_field = mk_field "" t_dynamic null_pos null_pos
+(* TODO null_class_field *)
+(* TODO null_abstract_field *)
+(* TODO null_enum_field *)
 
 let null_abstract = {
 	a_path = ([],"");
@@ -239,6 +244,10 @@ let null_abstract = {
 	a_enum = false;
 }
 
+let null_tdef =
+	(* TODO better null type? *)
+	mk_typedef null_module ([],"") null_pos null_pos (TDynamic None)
+
 let add_dependency ?(skip_postprocess=false) m mdep =
 	if m != null_module && (m.m_path != mdep.m_path || m.m_extra.m_sign != mdep.m_extra.m_sign) then begin
 		m.m_extra.m_deps <- PMap.add mdep.m_id (mdep.m_extra.m_sign, mdep.m_path) m.m_extra.m_deps;

+ 1 - 1
src/filters/filters.ml

@@ -494,7 +494,7 @@ let add_field_inits cl_path locals com t =
 				| None -> die "" __LOC__
 				| Some e ->
 					let lhs = mk (TField({ ethis with epos = cf.cf_pos },FInstance (c,extract_param_types c.cl_params,cf))) cf.cf_type cf.cf_pos in
-					cf.cf_expr <- None;
+					(* cf.cf_expr <- None; *)
 					mk (TBinop(OpAssign,lhs,e)) cf.cf_type e.epos
 			) inits in
 			let el = if !need_this then (mk (TVar((v, Some ethis))) ethis.etype ethis.epos) :: el else el in

+ 1 - 1
src/typing/typeloadCheck.ml

@@ -409,7 +409,7 @@ module Inheritance = struct
 					add_class_field_flag cf CfAbstract;
 				end else if has_class_field_flag f CfDefault then begin
 					let cf = make_implicit_field () in
-					cf.cf_expr <- None;
+					(* cf.cf_expr <- None; *)
 					add_class_field_flag cf CfExtern;
 					add_class_field_flag cf CfOverride;
 				end else if not (has_class_flag c CInterface) then begin

+ 28 - 18
src/typing/typeloadModule.ml

@@ -797,32 +797,42 @@ let type_module ctx mpath file ?(dont_check_path=false) ?(is_extern=false) tdecl
 
 let type_module_hook = ref (fun _ _ _ -> None)
 
-let rec load_hxb_module ctx path p =
+let reader : HxbReader.hxb_reader option ref = ref None
+let rec get_reader ctx input p = match !reader with
+	| Some r ->
+		r#set_input input;
+		r
+	| None ->
+		let make_module path file = ModuleLevel.make_module ctx path file p in
+		let add_module m = ctx.com.module_lut#add m.m_path m in
+
+		let resolve_type pack mname tname =
+			let m = try ctx.com.module_lut#find (pack,mname) with Not_found -> load_module' ctx ctx.g (pack,mname) p in
+			List.find (fun t -> snd (t_path t) = tname) m.m_types;
+		in
+
+		let r = new HxbReader.hxb_reader input make_module add_module resolve_type in
+		reader := Some r;
+		r
+
+and load_hxb_module ctx path p =
 	(* Modules failing to load so far *)
-	match snd path with
-	(* | "ArrayIterattnameor" *)
-	(* | "ArrayKeyValueIterator" *)
-	(* | "StdTypes" *)
-	| "Any"
-		-> raise Not_found
-	| _ -> ();
+	(* match snd path with *)
+	(* (1* | "ArrayIterator" *1) *)
+	(* (1* | "ArrayKeyValueIterator" *1) *)
+	(* (1* | "StdTypes" *1) *)
+	(* | "Any" *)
+	(* 	-> raise Not_found *)
+	(* | _ -> (); *)
 
 	let l = ((Common.dump_path ctx.com) :: "hxb" :: (Common.platform_name_macro ctx.com) :: fst path @ [snd path]) in
 	let filepath = (List.fold_left (fun acc s -> acc ^ "/" ^ s) "." l) ^ ".hxb" in
 	let ch = try open_in_bin filepath with Sys_error _ -> raise Not_found in
 	let input = IO.input_channel ch in
 
-	let make_module path file = ModuleLevel.make_module ctx path file p in
-	let add_module m = ctx.com.module_lut#add m.m_path m in
-
-	let resolve_type pack mname tname =
-		let m = try ctx.com.module_lut#find (pack,mname) with Not_found -> load_module' ctx ctx.g (pack,mname) p in
-		List.find (fun t -> snd (t_path t) = tname) m.m_types;
-	in
-
 	(* TODO store reader somewhere *)
-	let reader = new HxbReader.hxb_reader input make_module add_module resolve_type in
-	let m = reader#read true p in
+	Printf.eprintf "Loading %s from %s...\n" (snd path) filepath;
+	let m = (get_reader ctx input p)#read true p in
 	close_in ch;
 	Printf.eprintf "Loaded %s from %s\n" (snd m.m_path) filepath;
 	m