Browse Source

delay generic expression mapping until after all field types are updated

Simon Krajewski 12 years ago
parent
commit
4c4802eb49
3 changed files with 14 additions and 9 deletions
  1. 10 5
      codegen.ml
  2. 4 0
      type.ml
  3. 0 4
      typer.ml

+ 10 - 5
codegen.ml

@@ -265,9 +265,8 @@ let generic_substitute_expr gctx e =
 	in
 	let rec build_expr e =
 		match e.eexpr with
-		| TField({eexpr = TConst TThis} as e1, FInstance({cl_kind = KGeneric},cf)) ->
-			let cg = match follow (generic_substitute_type gctx (e1.etype)) with TInst(c,_) -> c | _ -> assert false in
-			build_expr {e with eexpr = TField(e1,FInstance(cg,cf))}
+		| TField(e1, FInstance({cl_kind = KGeneric},cf)) ->
+			build_expr {e with eexpr = TField(e1,quick_field_dynamic (generic_substitute_type gctx (e1.etype)) cf.cf_name)}
 		| _ -> map_expr_type build_expr (generic_substitute_type gctx) build_var e
 	in
 	build_expr e
@@ -359,10 +358,15 @@ let rec build_generic ctx c p tl =
 			List.iter loop tl
 		in
 		List.iter loop tl;
+		let delays = ref [] in
 		let build_field f =
 			let t = generic_substitute_type gctx f.cf_type in
-			try { f with cf_type = t; cf_expr = (match f.cf_expr with None -> None | Some e -> Some (generic_substitute_expr gctx e)) }
-			with Unify_error l -> error (error_msg (Unify l)) f.cf_pos
+			let f = { f with cf_type = t} in
+			(* delay the expression mapping to make sure all cf_type fields are set correctly first *)
+			(delays := (fun () ->
+				try (match f.cf_expr with None -> () | Some e -> f.cf_expr <- Some (generic_substitute_expr gctx e))
+				with Unify_error l -> error (error_msg (Unify l)) f.cf_pos) :: !delays);
+			f
 		in
 		if c.cl_init <> None || c.cl_dynamic <> None then error "This class can't be generic" p;
 		if c.cl_ordered_statics <> [] then error "A generic class can't have static fields" p;
@@ -394,6 +398,7 @@ let rec build_generic ctx c p tl =
 			cg.cl_fields <- PMap.add f.cf_name f cg.cl_fields;
 			f
 		) c.cl_ordered_fields;
+		List.iter (fun f -> f()) !delays;
 		TInst (cg,[])
 
 (* -------------------------------------------------------------------------- *)

+ 4 - 0
type.ml

@@ -963,6 +963,10 @@ let quick_field t n =
 	| TLazy _ | TType _ ->
 		assert false
 
+let quick_field_dynamic t s =
+	try quick_field t s
+	with Not_found -> FDynamic s
+
 let rec get_constructor build_type c =
 	match c.cl_constructor, c.cl_super with
 	| Some c, _ -> build_type c, c

+ 0 - 4
typer.ml

@@ -93,10 +93,6 @@ let rec classify t =
 	| TDynamic _ -> KDyn
 	| _ -> KOther
 
-let quick_field_dynamic t s =
-	try quick_field t s
-	with Not_found -> FDynamic s
-
 let object_field f =
 	let pf = Parser.quoted_ident_prefix in
 	let pflen = String.length pf in