|
@@ -1340,12 +1340,12 @@ and eval_expr ctx e =
|
|
);
|
|
);
|
|
alloc_tmp ctx HVoid
|
|
alloc_tmp ctx HVoid
|
|
| TLocal v ->
|
|
| TLocal v ->
|
|
- (match captured_index ctx v with
|
|
|
|
|
|
+ cast_to ctx (match captured_index ctx v with
|
|
| None -> alloc_reg ctx v
|
|
| None -> alloc_reg ctx v
|
|
| Some idx ->
|
|
| Some idx ->
|
|
let r = alloc_tmp ctx (to_type ctx v.v_type) in
|
|
let r = alloc_tmp ctx (to_type ctx v.v_type) in
|
|
op ctx (OEnumField (r, ctx.m.mcaptreg, 0, idx));
|
|
op ctx (OEnumField (r, ctx.m.mcaptreg, 0, idx));
|
|
- r)
|
|
|
|
|
|
+ r) (to_type ctx e.etype) e.epos
|
|
| TReturn None ->
|
|
| TReturn None ->
|
|
before_return ctx;
|
|
before_return ctx;
|
|
let r = alloc_tmp ctx HVoid in
|
|
let r = alloc_tmp ctx HVoid in
|
|
@@ -1650,15 +1650,16 @@ and eval_expr ctx e =
|
|
r
|
|
r
|
|
| _ ->
|
|
| _ ->
|
|
error ("Unknown native call " ^ v.v_name) e.epos)
|
|
error ("Unknown native call " ^ v.v_name) e.epos)
|
|
- | TCall (ec,el) ->
|
|
|
|
|
|
+ | TCall (ec,args) ->
|
|
let real_type = (match ec.eexpr with
|
|
let real_type = (match ec.eexpr with
|
|
| TField (_,f) -> field_type ctx f ec.epos
|
|
| TField (_,f) -> field_type ctx f ec.epos
|
|
| TLocal v -> v.v_type
|
|
| TLocal v -> v.v_type
|
|
| _ -> ec.etype
|
|
| _ -> ec.etype
|
|
) in
|
|
) in
|
|
let tfun = to_type ctx real_type in
|
|
let tfun = to_type ctx real_type in
|
|
- let el() = eval_args ctx el tfun e.epos in
|
|
|
|
|
|
+ let el() = eval_args ctx args tfun e.epos in
|
|
let ret = alloc_tmp ctx (match tfun with HFun (_,r) -> r | _ -> HDyn) in
|
|
let ret = alloc_tmp ctx (match tfun with HFun (_,r) -> r | _ -> HDyn) in
|
|
|
|
+ let def_ret = ref None in
|
|
(match get_access ctx ec with
|
|
(match get_access ctx ec with
|
|
| AStaticFun f ->
|
|
| AStaticFun f ->
|
|
(match el() with
|
|
(match el() with
|
|
@@ -1689,9 +1690,14 @@ and eval_expr ctx e =
|
|
op ctx (OCallClosure (ret, r, el())); (* if it's a value, it's a closure *)
|
|
op ctx (OCallClosure (ret, r, el())); (* if it's a value, it's a closure *)
|
|
| _ ->
|
|
| _ ->
|
|
let r = eval_null_check ctx ec in
|
|
let r = eval_null_check ctx ec in
|
|
|
|
+ (* don't use real_type here *)
|
|
|
|
+ let tfun = to_type ctx ec.etype in
|
|
|
|
+ let el() = eval_args ctx args tfun e.epos in
|
|
|
|
+ let ret = alloc_tmp ctx (match tfun with HFun (_,r) -> r | _ -> HDyn) in
|
|
op ctx (OCallClosure (ret, r, el())); (* if it's a value, it's a closure *)
|
|
op ctx (OCallClosure (ret, r, el())); (* if it's a value, it's a closure *)
|
|
|
|
+ def_ret := Some (unsafe_cast_to ctx ret (to_type ctx e.etype) e.epos);
|
|
);
|
|
);
|
|
- unsafe_cast_to ctx ret (to_type ctx e.etype) e.epos
|
|
|
|
|
|
+ (match !def_ret with None -> unsafe_cast_to ctx ret (to_type ctx e.etype) e.epos | Some r -> r)
|
|
| TField (ec,FInstance({ cl_path = [],"Array" },[t],{ cf_name = "length" })) when to_type ctx t = HDyn ->
|
|
| TField (ec,FInstance({ cl_path = [],"Array" },[t],{ cf_name = "length" })) when to_type ctx t = HDyn ->
|
|
let r = alloc_tmp ctx HI32 in
|
|
let r = alloc_tmp ctx HI32 in
|
|
op ctx (OCall1 (r,alloc_fun_path ctx (["hl";"types"],"ArrayDyn") "get_length", eval_null_check ctx ec));
|
|
op ctx (OCall1 (r,alloc_fun_path ctx (["hl";"types"],"ArrayDyn") "get_length", eval_null_check ctx ec));
|
|
@@ -4443,6 +4449,10 @@ let interp code =
|
|
(function
|
|
(function
|
|
| [VBytes str] -> print_string (hl_to_caml str); VUndef
|
|
| [VBytes str] -> print_string (hl_to_caml str); VUndef
|
|
| _ -> assert false)
|
|
| _ -> assert false)
|
|
|
|
+ | "sys_time" ->
|
|
|
|
+ (function
|
|
|
|
+ | [] -> VFloat (Unix.time())
|
|
|
|
+ | _ -> assert false)
|
|
| "sys_exit" ->
|
|
| "sys_exit" ->
|
|
(function
|
|
(function
|
|
| [VInt code] -> VUndef
|
|
| [VInt code] -> VUndef
|
|
@@ -4467,14 +4477,18 @@ let interp code =
|
|
(function
|
|
(function
|
|
| [VType t;v] -> if v = VNull then v else (match get_type v with None -> assert false | Some vt -> if safe_cast vt t then v else VNull)
|
|
| [VType t;v] -> if v = VNull then v else (match get_type v with None -> assert false | Some vt -> if safe_cast vt t then v else VNull)
|
|
| _ -> assert false)
|
|
| _ -> assert false)
|
|
- | "type_get_class" ->
|
|
|
|
|
|
+ | "type_super" ->
|
|
(function
|
|
(function
|
|
- | [VObj o] -> (match o.oproto.pclass.pclassglobal with None -> VNull | Some g -> globals.(g))
|
|
|
|
- | _ -> VNull)
|
|
|
|
- | "type_get_enum" ->
|
|
|
|
|
|
+ | [VType t] -> VType (match t with HObj { psuper = Some o } -> HObj o | _ -> HVoid)
|
|
|
|
+ | _ -> assert false)
|
|
|
|
+ | "type_get_global" ->
|
|
(function
|
|
(function
|
|
- | [VDyn (_,HEnum e)] -> globals.(e.eglobal)
|
|
|
|
- | _ -> VNull)
|
|
|
|
|
|
+ | [VType t] ->
|
|
|
|
+ (match t with
|
|
|
|
+ | HObj c -> (match c.pclassglobal with None -> VNull | Some g -> globals.(g))
|
|
|
|
+ | HEnum e -> globals.(e.eglobal)
|
|
|
|
+ | _ -> VNull)
|
|
|
|
+ | _ -> assert false)
|
|
| "type_name" ->
|
|
| "type_name" ->
|
|
(function
|
|
(function
|
|
| [VType t] ->
|
|
| [VType t] ->
|
|
@@ -4485,16 +4499,22 @@ let interp code =
|
|
| _ -> assert false)
|
|
| _ -> assert false)
|
|
| "obj_fields" ->
|
|
| "obj_fields" ->
|
|
(function
|
|
(function
|
|
- | [VDynObj o] ->
|
|
|
|
|
|
+ | [VDynObj o; VBool _] ->
|
|
VArray (Array.of_list (Hashtbl.fold (fun n _ acc -> VBytes (caml_to_hl n) :: acc) o.dfields []), HBytes)
|
|
VArray (Array.of_list (Hashtbl.fold (fun n _ acc -> VBytes (caml_to_hl n) :: acc) o.dfields []), HBytes)
|
|
- | [VObj o] ->
|
|
|
|
|
|
+ | [VObj o; VBool isRec] ->
|
|
let rec loop p =
|
|
let rec loop p =
|
|
let fields = Array.map (fun (n,_,_) -> VBytes (caml_to_hl n)) p.pfields in
|
|
let fields = Array.map (fun (n,_,_) -> VBytes (caml_to_hl n)) p.pfields in
|
|
- match p.psuper with None -> [fields] | Some p -> fields :: loop p
|
|
|
|
|
|
+ match p.psuper with Some p when isRec -> fields :: loop p | _ -> [fields]
|
|
in
|
|
in
|
|
VArray (Array.concat (loop o.oproto.pclass), HBytes)
|
|
VArray (Array.concat (loop o.oproto.pclass), HBytes)
|
|
| _ ->
|
|
| _ ->
|
|
VNull)
|
|
VNull)
|
|
|
|
+ | "obj_copy" ->
|
|
|
|
+ (function
|
|
|
|
+ | [VDynObj d] ->
|
|
|
|
+ VDynObj { dfields = Hashtbl.copy d.dfields; dvalues = Array.copy d.dvalues; dtypes = Array.copy d.dtypes; dvirtuals = [] }
|
|
|
|
+ | [_] -> VNull
|
|
|
|
+ | _ -> assert false)
|
|
| "enum_parameters" ->
|
|
| "enum_parameters" ->
|
|
(function
|
|
(function
|
|
| [VDyn (VEnum (idx,pl),HEnum e)] ->
|
|
| [VDyn (VEnum (idx,pl),HEnum e)] ->
|
|
@@ -4554,7 +4574,9 @@ let interp code =
|
|
(function
|
|
(function
|
|
| [o;VInt hash] ->
|
|
| [o;VInt hash] ->
|
|
let f = (try Hashtbl.find hash_cache hash with Not_found -> assert false) in
|
|
let f = (try Hashtbl.find hash_cache hash with Not_found -> assert false) in
|
|
- dyn_get_field o f HDyn
|
|
|
|
|
|
+ (match o with
|
|
|
|
+ | VObj _ | VDynObj _ | VVirtual _ -> dyn_get_field o f HDyn
|
|
|
|
+ | _ -> VNull)
|
|
| _ -> assert false)
|
|
| _ -> assert false)
|
|
| "set_field" ->
|
|
| "set_field" ->
|
|
(function
|
|
(function
|
|
@@ -4580,6 +4602,35 @@ let interp code =
|
|
in
|
|
in
|
|
VBool (loop o)
|
|
VBool (loop o)
|
|
| _ -> assert false)
|
|
| _ -> assert false)
|
|
|
|
+ | "delete_field" ->
|
|
|
|
+ (function
|
|
|
|
+ | [o;VInt hash] ->
|
|
|
|
+ let f = (try Hashtbl.find hash_cache hash with Not_found -> assert false) in
|
|
|
|
+ let rec loop o =
|
|
|
|
+ match o with
|
|
|
|
+ | VDynObj d when Hashtbl.mem d.dfields f ->
|
|
|
|
+ let idx = Hashtbl.find d.dfields f in
|
|
|
|
+ let count = Array.length d.dvalues in
|
|
|
|
+ Hashtbl.remove d.dfields f;
|
|
|
|
+ let fields = Hashtbl.fold (fun name i acc -> (name,if i < idx then i else i - 1) :: acc) d.dfields [] in
|
|
|
|
+ Hashtbl.clear d.dfields;
|
|
|
|
+ List.iter (fun (n,i) -> Hashtbl.add d.dfields n i) fields;
|
|
|
|
+ let vals2 = Array.make (count - 1) VNull in
|
|
|
|
+ let types2 = Array.make (count - 1) HVoid in
|
|
|
|
+ let len = count - idx - 1 in
|
|
|
|
+ Array.blit d.dvalues 0 vals2 0 idx;
|
|
|
|
+ Array.blit d.dvalues (idx + 1) vals2 idx len;
|
|
|
|
+ Array.blit d.dtypes 0 types2 0 idx;
|
|
|
|
+ Array.blit d.dtypes (idx + 1) types2 idx len;
|
|
|
|
+ d.dvalues <- vals2;
|
|
|
|
+ d.dtypes <- types2;
|
|
|
|
+ rebuild_virtuals d;
|
|
|
|
+ true
|
|
|
|
+ | VVirtual v -> loop v.vvalue
|
|
|
|
+ | _ -> false
|
|
|
|
+ in
|
|
|
|
+ VBool (loop o)
|
|
|
|
+ | _ -> assert false)
|
|
| "ucs2length" ->
|
|
| "ucs2length" ->
|
|
(function
|
|
(function
|
|
| [VBytes s; VInt pos] ->
|
|
| [VBytes s; VInt pos] ->
|
|
@@ -4775,6 +4826,10 @@ let interp code =
|
|
regs.(pos) <- to_int (String.length str);
|
|
regs.(pos) <- to_int (String.length str);
|
|
VBytes (caml_to_hl str)
|
|
VBytes (caml_to_hl str)
|
|
| _ -> assert false)
|
|
| _ -> assert false)
|
|
|
|
+ | "random" ->
|
|
|
|
+ (function
|
|
|
|
+ | [VInt max] -> VInt (if max <= 0l then 0l else Random.int32 max)
|
|
|
|
+ | _ -> assert false)
|
|
| _ ->
|
|
| _ ->
|
|
unresolved())
|
|
unresolved())
|
|
| "regexp" ->
|
|
| "regexp" ->
|