Nicolas Cannasse 9 rokov pred
rodič
commit
c70645ba4f
1 zmenil súbory, kde vykonal 76 pridanie a 52 odobranie
  1. 76 52
      genhl.ml

+ 76 - 52
genhl.ml

@@ -1182,8 +1182,8 @@ and eval_expr ctx e =
 		op ctx (ORet r);
 		r
 	| TReturn (Some e) ->
-		before_return ctx;
 		let r = eval_to ctx e ctx.m.mret in
+		before_return ctx;
 		op ctx (ORet r);
 		alloc_tmp ctx HVoid
 	| TParenthesis e ->
@@ -1527,7 +1527,7 @@ and eval_expr ctx e =
 			let v = eval_to ctx v (to_type ctx ft) in
 			op ctx (ODynSet (r,alloc_string ctx s,v));
 		) o;
-		r
+		cast_to ctx r (to_type ctx e.etype) e.epos
 	| TNew (c,pl,el) ->
 		let c = resolve_class ctx c pl in
 		let r = alloc_tmp ctx (class_type ctx c pl false) in
@@ -2038,10 +2038,10 @@ and eval_expr ctx e =
 			let switch_pos = current_pos ctx in
 			(match def with
 			| None ->
-				op ctx (ONull r);
+				if rt <> HVoid then op ctx (ONull r);
 			| Some e ->
 				let re = eval_to ctx e rt in
-				op ctx (OMov (r,re)));
+				if rt <> HVoid then op ctx (OMov (r,re)));
 			let jends = ref [jump ctx (fun i -> OJAlways i)] in
 			List.iter (fun (values,ecase) ->
 				List.iter (fun v ->
@@ -2287,6 +2287,7 @@ and make_fun ?gen_content ctx fidx f cthis cparent =
 	ignore(eval_expr ctx f.tf_expr);
 	let tret = to_type ctx f.tf_type in
 	let rec has_final_jump e =
+		(* prevents a jump outside function bounds error *)
 		match e.eexpr with
 		| TBlock el -> (match List.rev el with e :: _ -> has_final_jump e | [] -> false)
 		| TParenthesis e -> has_final_jump e
@@ -2300,6 +2301,7 @@ and make_fun ?gen_content ctx fidx f cthis cparent =
 		(match tret with
 		| HI32 | HI8 | HI16 -> op ctx (OInt (r,alloc_i32 ctx 0l))
 		| HF32 | HF64 -> op ctx (OFloat (r,alloc_float ctx 0.))
+		| HBool -> op ctx (OBool (r,false))
 		| _ -> op ctx (ONull r));
 		op ctx (ORet r)
 	end;
@@ -2850,8 +2852,8 @@ and vproto = {
 
 and vvirtual = {
 	vtype : virtual_proto;
-	vindexes : vfield array;
-	vtable : value array;
+	mutable vindexes : vfield array;
+	mutable vtable : value array;
 	vvalue : value;
 }
 
@@ -3070,7 +3072,14 @@ let interp code =
 		match obj with
 		| VDynObj d ->
 			let rebuild_virtuals() =
-				if d.dvirtuals <> [] then assert false (* TODO : update virtuals table *)
+				let old = d.dvirtuals in
+				d.dvirtuals <- [];
+				List.iter (fun v ->
+					let v2 = (match to_virtual obj v.vtype with VVirtual v -> v | _ -> assert false) in
+					v.vindexes <- v2.vindexes;
+					v.vtable <- d.dvalues;
+				) old;
+				d.dvirtuals <- old;
 			in
 			(try
 				let idx = Hashtbl.find d.dfields field in
@@ -3232,6 +3241,52 @@ let interp code =
 		| _ ->
 			error ("Can't compare " ^ vstr_d a ^ " and " ^ vstr_d b)
 
+	and to_virtual v vp =
+		let vt = (match get_type v with None -> HVoid | Some t -> t) in
+		match v with
+		| VNull ->
+			VNull
+		| VObj o ->
+			let indexes = Array.mapi (fun i (n,_,t) ->
+				try
+					let idx, ft = get_index n o.oproto.pclass in
+					if not (tsame t ft) then error ("Can't cast " ^ tstr vt ^ " to " ^ tstr (HVirtual vp) ^ "(" ^ n ^ " type differ)");
+					VFIndex idx
+				with Not_found ->
+					VFNone (* most likely a method *)
+			) vp.vfields in
+			let v = {
+				vtype = vp;
+				vindexes = indexes;
+				vtable = o.ofields;
+				vvalue = v;
+			} in
+			VVirtual v
+		| VDynObj d ->
+			(try
+				VVirtual (List.find (fun v -> v.vtype == vp) d.dvirtuals)
+			with Not_found ->
+				let indexes = Array.mapi (fun i (n,_,t) ->
+					try
+						let idx = Hashtbl.find d.dfields n in
+						if not (tsame t d.dtypes.(idx)) then error ("Can't cast " ^ tstr vt ^ " to " ^ tstr (HVirtual vp) ^ "(" ^ n ^ " type differ)");
+						VFIndex idx
+					with Not_found ->
+						VFNone
+				) vp.vfields in
+				let v = {
+					vtype = vp;
+					vindexes = indexes;
+					vtable = d.dvalues;
+					vvalue = v;
+				} in
+				d.dvirtuals <- v :: d.dvirtuals;
+				VVirtual v
+			)
+		| VVirtual v ->
+			to_virtual v.vvalue vp
+		| _ ->
+			error ("Invalid ToVirtual " ^ vstr_d v ^ " : " ^ tstr (HVirtual vp))
 
 	and call f args =
 		let regs = Array.create (Array.length f.regs) VUndef in
@@ -3565,48 +3620,7 @@ let interp code =
 					Array.unsafe_set regs i v
 				| _ -> assert false)
 			| OToVirtual (r,rv) ->
-				let v = get rv in
-				set r (match v, rtype r with
-				| VNull, _ -> VNull
-				| VObj o, HVirtual vp ->
-					let indexes = Array.mapi (fun i (n,_,t) ->
-						try
-							let idx, ft = get_index n o.oproto.pclass in
-							if not (tsame t ft) then error ("Can't cast " ^ tstr (rtype rv) ^ " to " ^ tstr (rtype r) ^ "(" ^ n ^ " type differ)");
-							VFIndex idx
-						with Not_found ->
-							VFNone (* most likely a method *)
-					) vp.vfields in
-					let v = {
-						vtype = vp;
-						vindexes = indexes;
-						vtable = o.ofields;
-						vvalue = v;
-					} in
-					VVirtual v
-				| VDynObj d, HVirtual vp ->
-					(try
-						VVirtual (List.find (fun v -> v.vtype == vp) d.dvirtuals)
-					with Not_found ->
-						let indexes = Array.mapi (fun i (n,_,t) ->
-							try
-								let idx = Hashtbl.find d.dfields n in
-								if not (tsame t d.dtypes.(idx)) then error ("Can't cast " ^ tstr (rtype rv) ^ " to " ^ tstr (rtype r) ^ "(" ^ n ^ " type differ)");
-								VFIndex idx
-							with Not_found ->
-								VFNone
-						) vp.vfields in
-						let v = {
-							vtype = vp;
-							vindexes = indexes;
-							vtable = d.dvalues;
-							vvalue = v;
-						} in
-						d.dvirtuals <- v :: d.dvirtuals;
-						VVirtual v
-					)
-				| v, t ->
-					error ("Invalid ToVirtual " ^ vstr_d v ^ " : " ^ tstr t))
+				set r (to_virtual (get rv) (match rtype r with HVirtual vp -> vp | _ -> assert false))
 			| OUnVirtual (r,v) ->
 				set r (match get v with VNull -> VNull | VVirtual v -> v.vvalue | _ -> assert false)
 			| ODynGet (r,o,f) ->
@@ -3914,9 +3928,19 @@ let interp code =
 				(function
 				| [o;VInt hash] ->
 					let f = (try Hashtbl.find hash_cache hash with Not_found -> assert false) in
-					VBool (match o with
-					| VDynObj d -> Hashtbl.mem d.dfields f
-					| _ -> false)
+					let rec loop o =
+						match o with
+						| VDynObj d -> Hashtbl.mem d.dfields f
+						| VObj o ->
+							let rec loop p =
+								let f = PMap.mem f p.pindex in
+								if f then true else match p.psuper with None -> false | Some p -> loop p
+							in
+							loop o.oproto.pclass
+						| VVirtual v -> loop v.vvalue
+						| _ -> false
+					in
+					VBool (loop o)
 				| _ -> assert false)
 			| "call_method" ->
 				(function