evalEmitter.ml 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. (*
  2. The Haxe Compiler
  3. Copyright (C) 2005-2019 Haxe Foundation
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  15. *)
  16. open Globals
  17. open EvalHash
  18. open EvalValue
  19. open EvalEncode
  20. open EvalDecode
  21. open EvalContext
  22. open EvalPrinting
  23. open EvalExceptions
  24. open EvalField
  25. open EvalMisc
  26. (* Helper *)
  27. let unexpected_value_p v s p =
  28. let str = match v with
  29. | VNull -> "Null Access"
  30. | _ -> Printf.sprintf "Unexpected value %s, expected %s" (value_string v) s
  31. in
  32. throw_string str p
  33. let as_array p = function
  34. | VArray va -> va
  35. | v -> unexpected_value_p v "Array" p
  36. let as_bytes p = function
  37. | VInstance {ikind = IBytes s} -> s
  38. | v -> unexpected_value_p v "Bytes" p
  39. let as_enum_value p = function
  40. | VEnumValue ve -> ve
  41. | v -> unexpected_value_p v "enum value" p
  42. let as_int p = function
  43. | VInt32 i -> Int32.to_int i
  44. | VFloat f -> int_of_float f
  45. | v -> unexpected_value_p v "int" p
  46. let as_vector p = function
  47. | VVector vv -> vv
  48. | v -> unexpected_value_p v "Vector" p
  49. let cannot_call v p =
  50. throw (EvalString.create_unknown ("Cannot call " ^ (value_string v))) p
  51. let decode_int_p v p = match v with
  52. | VInt32 i -> Int32.to_int i
  53. | VFloat f -> int_of_float f
  54. | _ -> unexpected_value_p v "int" p
  55. let check_stack_depth env =
  56. if env.env_stack_depth > (get_ctx()).max_stack_depth then
  57. exc_string "Stack overflow"
  58. (* Emitter *)
  59. let apply env exec =
  60. exec env
  61. (* Objects and values *)
  62. let emit_null _ = vnull
  63. let emit_local_declaration i exec env =
  64. env.env_locals.(i) <- exec env;
  65. vnull
  66. let emit_capture_declaration i exec env =
  67. env.env_captures.(i) <- exec env;
  68. vnull
  69. let emit_const v _ = v
  70. let emit_null_check exec p env = match exec env with
  71. | VNull -> throw_string "Null Access" p
  72. | v -> v
  73. let emit_new_array env =
  74. encode_array_instance (EvalArray.create [||])
  75. let emit_new_vector_int i p env =
  76. if i < 0 then exc_string_p "Vector size must be >= 0" p;
  77. let a = try
  78. Array.make i vnull
  79. with Invalid_argument _ ->
  80. exc_string_p (Printf.sprintf "Not enough memory to allocate Vector of size %i" i) p;
  81. in
  82. encode_vector_instance a
  83. let emit_new_vector exec p env =
  84. let i = decode_int_p (exec env) p in
  85. emit_new_vector_int i p env
  86. let emit_special_instance f execs env =
  87. let vl = List.map (apply env) execs in
  88. f vl
  89. let emit_object_declaration proto fa env =
  90. let a = Array.make (Array.length fa) vnull in
  91. Array.iter (fun (i,exec) -> a.(i) <- exec env) fa;
  92. vobject {
  93. ofields = a;
  94. oproto = OProto proto;
  95. }
  96. let emit_array_declaration execs env =
  97. let vl = Array.map (apply env) execs in
  98. encode_array_instance (EvalArray.create vl)
  99. let emit_type_expr proto env = proto
  100. let emit_mk_pos exec1 exec2 exec3 env =
  101. let file = exec1 env in
  102. let min = exec2 env in
  103. let max = exec3 env in
  104. encode_pos { pfile = decode_string file; pmin = decode_int min; pmax = decode_int max }
  105. let emit_enum_construction key i execs p env =
  106. encode_enum_value key i (Array.map (apply env) execs) p
  107. (* Branching *)
  108. let emit_if exec_cond exec_then exec_else env =
  109. match exec_cond env with
  110. | VTrue -> exec_then env
  111. | _ -> exec_else env
  112. let emit_switch exec execs patterns exec_def env =
  113. let v1 = exec env in
  114. let rec loop v1 i =
  115. if i >= Array.length patterns then exec_def env
  116. else if List.exists (fun exec -> equals v1 (exec env)) patterns.(i) then
  117. execs.(i) env
  118. else
  119. loop v1 (i + 1)
  120. in
  121. loop v1 0
  122. let emit_int_switch_map exec cases exec_def p env = match exec env with
  123. | VInt32 i32 ->
  124. let i = Int32.to_int i32 in
  125. begin try
  126. (IntMap.find i cases) env
  127. with Not_found ->
  128. exec_def env
  129. end
  130. | VNull ->
  131. exec_def env
  132. | v ->
  133. unexpected_value_p v "int" p
  134. let emit_string_switch_map exec cases exec_def p env = match exec env with
  135. | VString s ->
  136. begin try
  137. (PMap.find s.sstring cases) env
  138. with Not_found ->
  139. exec_def env
  140. end
  141. | VNull ->
  142. exec_def env
  143. | v ->
  144. unexpected_value_p v "string" p
  145. let emit_int_switch_array shift exec cases exec_def p env = match exec env with
  146. | VInt32 i32 ->
  147. let i = Int32.to_int i32 + shift in
  148. if i >= Array.length cases || i < 0 then exec_def env
  149. else (Array.unsafe_get cases i) env
  150. | VNull ->
  151. exec_def env
  152. | v ->
  153. unexpected_value_p v "int" p
  154. let rec run_while_continue exec_cond exec_body env =
  155. try
  156. while is_true (exec_cond env) do ignore(exec_body env) done;
  157. with Continue ->
  158. run_while_continue exec_cond exec_body env
  159. let run_while exec_cond exec_body env =
  160. while is_true (exec_cond env) do exec_body env done
  161. let emit_while_break exec_cond exec_body env =
  162. (try run_while_continue exec_cond exec_body env with Break -> ());
  163. vnull
  164. let emit_while_break_continue exec_cond exec_body env =
  165. (try run_while_continue exec_cond exec_body env with Break -> ());
  166. vnull
  167. let emit_do_while_break_continue exec_cond exec_body env =
  168. begin try
  169. ignore(exec_body env); run_while_continue exec_cond exec_body env
  170. with
  171. | Break -> ()
  172. | Continue -> try run_while_continue exec_cond exec_body env with Break -> ()
  173. end;
  174. vnull
  175. let emit_try exec catches env =
  176. let ctx = get_ctx() in
  177. let eval = env.env_eval in
  178. if ctx.debug.support_debugger then begin
  179. List.iter (fun (_,path,_) -> Hashtbl.add eval.caught_types path true) catches
  180. end;
  181. let restore () =
  182. List.iter (fun (_,path,_) -> Hashtbl.remove eval.caught_types path) catches
  183. in
  184. let v = try
  185. let v = handle_stack_overflow eval (fun() -> exec env) in
  186. restore();
  187. v
  188. with RunTimeException(v,_,_) as exc ->
  189. eval.caught_exception <- vnull;
  190. restore();
  191. build_exception_stack ctx env;
  192. let rec loop () = match eval.env with
  193. | Some env' when env' != env ->
  194. pop_environment ctx env';
  195. loop();
  196. | _ ->
  197. ()
  198. in
  199. loop();
  200. let exec,_,varacc =
  201. try
  202. List.find (fun (_,path,i) -> path = key_Dynamic || is v path) catches
  203. with Not_found ->
  204. raise_notrace exc
  205. in
  206. ignore(varacc (fun _ -> v) env);
  207. exec env
  208. in
  209. v
  210. (* Control flow *)
  211. let emit_value exec env =
  212. exec env
  213. let emit_seq2 exec1 exec2 env =
  214. ignore(exec1 env);
  215. exec2 env
  216. let emit_seq4 exec1 exec2 exec3 exec4 env =
  217. ignore (exec1 env);
  218. ignore (exec2 env);
  219. ignore (exec3 env);
  220. exec4 env
  221. let emit_seq8 exec1 exec2 exec3 exec4 exec5 exec6 exec7 exec8 env =
  222. ignore (exec1 env);
  223. ignore (exec2 env);
  224. ignore (exec3 env);
  225. ignore (exec4 env);
  226. ignore (exec5 env);
  227. ignore (exec6 env);
  228. ignore (exec7 env);
  229. exec8 env
  230. let emit_return_null _ = raise_notrace (Return vnull)
  231. let emit_return_value exec env = raise_notrace (Return (exec env))
  232. let emit_break env = raise_notrace Break
  233. let emit_continue env = raise_notrace Continue
  234. let emit_throw exec p env = throw (exec env) p
  235. let emit_safe_cast exec t p env =
  236. let v1 = exec env in
  237. match vresolve v1 with
  238. | VNull -> v1
  239. | _ -> if not (is v1 t) then throw_string "Class cast error" p else v1
  240. (* Calls *)
  241. (* super.call() - immediate *)
  242. let emit_super_field_call slot proto i execs p env =
  243. check_stack_depth env;
  244. let vthis = env.env_locals.(slot) in
  245. let vf = proto.pfields.(i) in
  246. let vl = List.map (apply env) execs in
  247. call_value_on vthis vf vl
  248. (* Type.call() - immediate *)
  249. let emit_proto_field_call v execs p env =
  250. check_stack_depth env;
  251. let f = Lazy.force v in
  252. let vl = List.map (apply env) execs in
  253. env.env_leave_pmin <- p.pmin;
  254. env.env_leave_pmax <- p.pmax;
  255. f vl
  256. (* instance.call() where call is overridden - dynamic dispatch *)
  257. let get_prototype v p = match vresolve v with
  258. | VInstance {iproto = proto} | VPrototype proto -> proto
  259. | VString _ -> (get_ctx()).string_prototype
  260. | VArray _ -> (get_ctx()).array_prototype
  261. | VVector _ -> (get_ctx()).vector_prototype
  262. | _ -> unexpected_value_p v "instance" p
  263. let emit_method_call exec name execs p env =
  264. check_stack_depth env;
  265. let vthis = exec env in
  266. let proto = get_prototype vthis p in
  267. let vf = try proto_field_raise proto name with Not_found -> throw_string (Printf.sprintf "Field %s not found on prototype %s" (rev_hash name) (rev_hash proto.ppath)) p in
  268. let vl = List.map (apply env) execs in
  269. env.env_leave_pmin <- p.pmin;
  270. env.env_leave_pmax <- p.pmax;
  271. call_value_on vthis vf vl
  272. (* instance.call() where call is not a method - lookup + this-binding *)
  273. let emit_field_call exec name execs p env =
  274. check_stack_depth env;
  275. let vthis = exec env in
  276. let vf = field vthis name in
  277. env.env_leave_pmin <- p.pmin;
  278. env.env_leave_pmax <- p.pmax;
  279. call_value_on vthis vf (List.map (apply env) execs)
  280. (* new() - immediate + this-binding *)
  281. let emit_constructor_call proto v execs p env =
  282. check_stack_depth env;
  283. let f = Lazy.force v in
  284. let vthis = create_instance_direct proto INormal in
  285. let vl = List.map (apply env) execs in
  286. env.env_leave_pmin <- p.pmin;
  287. env.env_leave_pmax <- p.pmax;
  288. ignore(f (vthis :: vl));
  289. vthis
  290. (* super() - immediate + this-binding *)
  291. let emit_special_super_call fnew execs env =
  292. check_stack_depth env;
  293. let vl = List.map (apply env) execs in
  294. let vi' = fnew vl in
  295. let vthis = env.env_locals.(0) in
  296. (* This isn't very elegant, but it's probably a rare case to extend these types. *)
  297. begin match vthis,vi' with
  298. | VInstance vi,VInstance vi' -> vi.ikind <- vi'.ikind
  299. | _ -> die "" __LOC__
  300. end;
  301. vnull
  302. let emit_super_call v execs p env =
  303. check_stack_depth env;
  304. let f = Lazy.force v in
  305. let vthis = env.env_locals.(0) in
  306. let vl = List.map (apply env) execs in
  307. env.env_leave_pmin <- p.pmin;
  308. env.env_leave_pmax <- p.pmax;
  309. ignore(f (vthis :: vl));
  310. vthis
  311. (* unknown call - full lookup *)
  312. let emit_call exec execs p env =
  313. check_stack_depth env;
  314. let v1 = exec env in
  315. env.env_leave_pmin <- p.pmin;
  316. env.env_leave_pmax <- p.pmax;
  317. call_value v1 (List.map (apply env) execs)
  318. (* Read *)
  319. let emit_local_read i env = env.env_locals.(i)
  320. let emit_capture_read i env = env.env_captures.(i)
  321. let emit_array_length_read exec p env = vint (as_array p (exec env)).alength
  322. let emit_vector_length_read exec p env = vint (Array.length (as_vector p (exec env)))
  323. let emit_bytes_length_read exec p env = vint (Bytes.length (as_bytes p (exec env)))
  324. let emit_proto_field_read proto i env =
  325. proto.pfields.(i)
  326. let emit_instance_field_read exec p i env = match exec env with
  327. | VInstance vi -> vi.ifields.(i)
  328. | VString s -> vint (s.slength)
  329. | VNull -> throw_string "field access on null" p
  330. | v -> unexpected_value_p v "instance" p
  331. let emit_this_field_read iv i env = match env.env_locals.(iv) with
  332. | VInstance vi -> vi.ifields.(i)
  333. | v -> unexpected_value v "instance"
  334. let emit_field_closure exec name env =
  335. let v = exec env in
  336. dynamic_field v name
  337. let emit_anon_field_read exec proto i name p env =
  338. match vresolve (exec env) with
  339. | VObject o ->
  340. begin match o.oproto with
  341. | OProto proto' when proto' == proto ->
  342. o.ofields.(i)
  343. | _ ->
  344. object_field o name
  345. end
  346. | VNull -> throw_string "field access on null" p
  347. | v -> field v name
  348. let emit_field_read exec name p env = match exec env with
  349. | VNull -> throw_string "field access on null" p
  350. | v -> field v name
  351. let emit_array_read exec1 p1 exec2 p2 env =
  352. let a = as_array p1 (exec1 env) in
  353. let i = as_int p2 (exec2 env) in
  354. if i < 0 then vnull
  355. else EvalArray.get a i
  356. let emit_vector_read exec1 p1 exec2 p2 env =
  357. let v = as_vector p1 (exec1 env) in
  358. let i = as_int p2 (exec2 env) in
  359. if i < 0 then vnull
  360. else Array.unsafe_get v i
  361. let emit_enum_index exec p env = vint (as_enum_value p (exec env)).eindex
  362. let emit_enum_parameter_read exec i env = match exec env with
  363. | VEnumValue ev -> (try ev.eargs.(i) with Not_found -> vnull)
  364. | v1 -> unexpected_value v1 "enum value"
  365. let emit_string_cca exec1 exec2 p env =
  366. let s = decode_vstring (exec1 env) in
  367. let index = decode_int_p (exec2 env) p in
  368. if index < 0 || index >= s.slength then vnull
  369. else vint (EvalString.char_at s index)
  370. let emit_string_cca_unsafe exec1 exec2 p env =
  371. let s = decode_vstring (exec1 env) in
  372. let index = decode_int_p (exec2 env) p in
  373. vint (EvalString.char_at s index)
  374. (* Write *)
  375. let emit_bytes_length_write exec1 exec2 env =
  376. let v1 = exec1 env in
  377. let v2 = exec2 env in
  378. set_bytes_length_field v1 v2;
  379. v2
  380. let emit_local_write slot exec env =
  381. let v = exec env in
  382. env.env_locals.(slot) <- v;
  383. v
  384. let emit_capture_write slot exec env =
  385. let v = exec env in
  386. env.env_captures.(slot) <- v;
  387. v
  388. let emit_proto_field_write proto i exec2 env =
  389. let v = exec2 env in
  390. proto.pfields.(i) <- v;
  391. v
  392. let emit_instance_field_write exec1 p i exec2 env = match exec1 env with
  393. | VInstance vi ->
  394. let v = exec2 env in
  395. vi.ifields.(i) <- v;
  396. v
  397. | v -> unexpected_value_p v "instance" p
  398. let emit_anon_field_write exec1 p proto i name exec2 env =
  399. let v1 = exec1 env in
  400. let v2 = exec2 env in
  401. begin match vresolve v1 with
  402. | VObject o ->
  403. begin match o.oproto with
  404. | OProto proto' when proto' == proto ->
  405. o.ofields.(i) <- v2;
  406. | _ ->
  407. set_object_field o name v2
  408. end
  409. | VNull ->
  410. throw_string "field access on null" p
  411. | _ ->
  412. set_field v1 name v2;
  413. end;
  414. v2
  415. let emit_field_write exec1 p1 name exec2 env =
  416. let v1 = exec1 env in
  417. let v2 = exec2 env in
  418. (try set_field v1 name v2 with RunTimeException(v,stack,_) -> raise_notrace (RunTimeException(v,stack,p1)));
  419. v2
  420. let emit_array_write exec1 p1 exec2 p2 exec3 p env =
  421. let a = as_array p1 (exec1 env) in
  422. let i = as_int p2 (exec2 env) in
  423. let v3 = exec3 env in
  424. if i < 0 then throw_string (Printf.sprintf "Negative array index: %i" i) p;
  425. EvalArray.set a i v3;
  426. v3
  427. let emit_vector_write exec1 p1 exec2 p2 exec3 p env =
  428. let vv = as_vector p1 (exec1 env) in
  429. let i = as_int p2 (exec2 env) in
  430. let v3 = exec3 env in
  431. if i < 0 then throw_string (Printf.sprintf "Negative vector index: %i" i) p;
  432. Array.unsafe_set vv i v3;
  433. v3
  434. (* Read + write *)
  435. let do_incr v p = match v with
  436. | VInt32 i32 -> vint32 (Int32.add i32 Int32.one)
  437. | VFloat f -> vfloat (f +. 1.)
  438. | v -> unexpected_value_p v "number" p
  439. let emit_local_incr_prefix slot p env =
  440. let v0 = env.env_locals.(slot) in
  441. let v = do_incr v0 p in
  442. env.env_locals.(slot) <- v;
  443. v
  444. let emit_local_incr_postfix slot p env =
  445. let v0 = env.env_locals.(slot) in
  446. let v = do_incr v0 p in
  447. env.env_locals.(slot) <- v;
  448. v0
  449. let emit_local_read_write slot exec fop prefix env =
  450. let v1 = env.env_locals.(slot) in
  451. let v2 = exec env in
  452. let v = fop v1 v2 in
  453. env.env_locals.(slot) <- v;
  454. if prefix then v else v1
  455. let emit_capture_read_write slot exec fop prefix env =
  456. let v1 = (env.env_captures.(slot)) in
  457. let v2 = exec env in
  458. let v = fop v1 v2 in
  459. env.env_captures.(slot) <- v;
  460. if prefix then v else v1
  461. let emit_proto_field_read_write proto i exec2 fop prefix env =
  462. let vf = proto.pfields.(i) in
  463. let v2 = exec2 env in
  464. let v = fop vf v2 in
  465. proto.pfields.(i) <- v;
  466. if prefix then v else vf
  467. let instance_field_read_write vi i exec2 fop prefix env =
  468. let vf = vi.ifields.(i) in
  469. let v2 = exec2 env in
  470. let v = fop vf v2 in
  471. vi.ifields.(i) <- v;
  472. if prefix then v else vf
  473. let emit_instance_field_read_write exec1 p1 i exec2 fop prefix env = match exec1 env with
  474. | VInstance vi -> instance_field_read_write vi i exec2 fop prefix env
  475. | v -> unexpected_value_p v "instance" p1
  476. let emit_field_read_write exec1 p1 name exec2 fop prefix env =
  477. let v1 = exec1 env in
  478. match vresolve v1 with
  479. | VObject o ->
  480. let vf = object_field o name in
  481. let v2 = exec2 env in
  482. let v = fop vf v2 in
  483. set_object_field o name v;
  484. if prefix then v else vf
  485. | VInstance vi ->
  486. let i = get_instance_field_index vi.iproto name null_pos in
  487. instance_field_read_write vi i exec2 fop prefix env
  488. | VPrototype proto ->
  489. let i = get_proto_field_index proto name in
  490. emit_proto_field_read_write proto i exec2 fop prefix env
  491. | _ ->
  492. let vf = field v1 name in
  493. let v2 = exec2 env in
  494. let v = fop vf v2 in
  495. (try set_field v1 name v with RunTimeException(v,stack,_) -> raise_notrace (RunTimeException(v,stack,p1)));
  496. if prefix then v else vf
  497. let emit_array_read_write exec1 p1 exec2 p2 exec3 fop prefix env =
  498. let va = as_array p1 (exec1 env) in
  499. let i = as_int p2 (exec2 env) in
  500. if i < 0 then throw_string (Printf.sprintf "Negative array index: %i" i) p2;
  501. let v = EvalArray.get va i in
  502. let v2 = exec3 env in
  503. let v3 = fop v v2 in
  504. EvalArray.set va i v3;
  505. if prefix then v3 else v
  506. let emit_vector_read_write exec1 p1 exec2 p2 exec3 fop prefix env =
  507. let va = as_vector p1 (exec1 env) in
  508. let i = as_int p2 (exec2 env) in
  509. if i < 0 then throw_string (Printf.sprintf "Negative vector index: %i" i) p2;
  510. let v = Array.unsafe_get va i in
  511. let v2 = exec3 env in
  512. let v3 = fop v v2 in
  513. Array.unsafe_set va i v3;
  514. if prefix then v3 else v
  515. (* Ops *)
  516. let emit_eq_null exec env = match exec env with
  517. | VNull -> VTrue
  518. | _ -> VFalse
  519. let emit_not_eq_null exec env = match exec env with
  520. | VNull -> VFalse
  521. | _ -> VTrue
  522. let emit_op_add p exec1 exec2 env =
  523. let v1 = exec1 env in
  524. let v2 = exec2 env in
  525. op_add p v1 v2
  526. let emit_op_mult p exec1 exec2 env =
  527. let v1 = exec1 env in
  528. let v2 = exec2 env in
  529. op_mult p v1 v2
  530. let emit_op_div p exec1 exec2 env =
  531. let v1 = exec1 env in
  532. let v2 = exec2 env in
  533. op_div p v1 v2
  534. let emit_op_sub p exec1 exec2 env =
  535. let v1 = exec1 env in
  536. let v2 = exec2 env in
  537. op_sub p v1 v2
  538. let emit_op_eq exec1 exec2 env =
  539. let v1 = exec1 env in
  540. let v2 = exec2 env in
  541. vbool (equals v1 v2)
  542. let emit_op_not_eq exec1 exec2 env =
  543. let v1 = exec1 env in
  544. let v2 = exec2 env in
  545. vbool (not (equals v1 v2))
  546. let emit_op_gt exec1 exec2 env =
  547. let v1 = exec1 env in
  548. let v2 = exec2 env in
  549. vbool (compare v1 v2 = CSup)
  550. let emit_op_gte exec1 exec2 env =
  551. let v1 = exec1 env in
  552. let v2 = exec2 env in
  553. vbool (match compare v1 v2 with CSup | CEq -> true | _ -> false)
  554. let emit_op_lt exec1 exec2 env =
  555. let v1 = exec1 env in
  556. let v2 = exec2 env in
  557. vbool (compare v1 v2 = CInf)
  558. let emit_op_lte exec1 exec2 env =
  559. let v1 = exec1 env in
  560. let v2 = exec2 env in
  561. vbool (match compare v1 v2 with CInf | CEq -> true | _ -> false)
  562. let emit_op_and p exec1 exec2 env =
  563. let v1 = exec1 env in
  564. let v2 = exec2 env in
  565. op_and p v1 v2
  566. let emit_op_or p exec1 exec2 env =
  567. let v1 = exec1 env in
  568. let v2 = exec2 env in
  569. op_or p v1 v2
  570. let emit_op_xor p exec1 exec2 env =
  571. let v1 = exec1 env in
  572. let v2 = exec2 env in
  573. op_xor p v1 v2
  574. let emit_op_shl p exec1 exec2 env =
  575. let v1 = exec1 env in
  576. let v2 = exec2 env in
  577. op_shl p v1 v2
  578. let emit_op_shr p exec1 exec2 env =
  579. let v1 = exec1 env in
  580. let v2 = exec2 env in
  581. op_shr p v1 v2
  582. let emit_op_ushr p exec1 exec2 env =
  583. let v1 = exec1 env in
  584. let v2 = exec2 env in
  585. op_ushr p v1 v2
  586. let emit_op_mod p exec1 exec2 env =
  587. let v1 = exec1 env in
  588. let v2 = exec2 env in
  589. op_mod p v1 v2
  590. let emit_not exec env = match exec env with
  591. | VNull | VFalse -> VTrue
  592. | _ -> VFalse
  593. let emit_bool_and exec1 exec2 env =
  594. if is_true (exec1 env) then exec2 env
  595. else VFalse
  596. let emit_bool_or exec1 exec2 env =
  597. if is_true (exec1 env) then VTrue
  598. else exec2 env
  599. let emit_neg exec p env = match exec env with
  600. | VFloat f -> vfloat (-.f)
  601. | VInt32 i -> vint32 (Int32.neg i)
  602. | _ -> throw_string "Invalid operation" p
  603. (* Function *)
  604. let execute_set_local i env v =
  605. env.env_locals.(i) <- v
  606. let execute_set_capture i env v =
  607. env.env_captures.(i) <- v
  608. let process_arguments fl vl env =
  609. let rec loop fl vl = match fl,vl with
  610. | f :: fl,v :: vl ->
  611. f env v;
  612. loop fl vl
  613. | f :: fl,[] ->
  614. f env vnull;
  615. loop fl []
  616. | [],[] ->
  617. ()
  618. | _ ->
  619. exc_string "Something went wrong"
  620. in
  621. loop fl vl
  622. [@@inline]
  623. let create_function_noret ctx eci exec fl vl =
  624. let env = push_environment ctx eci in
  625. process_arguments fl vl env;
  626. let v = exec env in
  627. pop_environment ctx env;
  628. v
  629. let create_function ctx eci exec fl vl =
  630. let env = push_environment ctx eci in
  631. process_arguments fl vl env;
  632. let v = try exec env with Return v -> v in
  633. pop_environment ctx env;
  634. v
  635. let create_closure_noret ctx eci refs exec fl vl =
  636. let env = push_environment ctx eci in
  637. Array.iter (fun (i,vr) -> env.env_captures.(i) <- vr) refs;
  638. process_arguments fl vl env;
  639. let v = exec env in
  640. pop_environment ctx env;
  641. v
  642. let create_closure refs ctx eci exec fl vl =
  643. let env = push_environment ctx eci in
  644. Array.iter (fun (i,vr) -> env.env_captures.(i) <- vr) refs;
  645. process_arguments fl vl env;
  646. let v = try exec env with Return v -> v in
  647. pop_environment ctx env;
  648. v
  649. let emit_closure ctx mapping eci hasret exec fl env =
  650. let refs = Array.map (fun (i,slot) -> i,emit_capture_read slot env) mapping in
  651. let create = match hasret,eci.num_captures with
  652. | true,0 -> create_function
  653. | false,0 -> create_function_noret
  654. | _ -> create_closure refs
  655. in
  656. let f = create ctx eci exec fl in
  657. vstatic_function f