@@ -199,6 +199,68 @@ let heap_type_sub (ty : W.heap_type) (ty' : W.heap_type) st =
199
199
(* I31, struct, array and none have no other subtype *)
200
200
| _ , (I31 | Type _ | Struct | Array | None_ ) -> false , st
201
201
202
+ (* ZZZ*)
203
+ let rec type_index_lub ty ty' st =
204
+ if Var. equal ty ty'
205
+ then Some ty
206
+ else
207
+ let type_field = Var.Hashtbl. find st.context.types ty in
208
+ match type_field.supertype with
209
+ | None -> None
210
+ | Some ty -> (
211
+ match type_index_lub ty ty' st with
212
+ | Some ty -> Some ty
213
+ | None -> (
214
+ let type_field = Var.Hashtbl. find st.context.types ty' in
215
+ match type_field.supertype with
216
+ | None -> None
217
+ | Some ty' -> type_index_lub ty ty' st))
218
+
219
+ let heap_type_lub (ty : W.heap_type ) (ty' : W.heap_type ) =
220
+ match ty, ty' with
221
+ | (Func | Extern ), _ | _ , (Func | Extern ) -> assert false
222
+ | None_ , _ -> return ty'
223
+ | _ , None_ | Struct , Struct | Array , Array -> return ty
224
+ | Any , _ | _ , Any -> return W. Any
225
+ | Eq , _
226
+ | _, Eq
227
+ | (Struct | Array | Type _), I31
228
+ | I31 , (Struct | Array | Type _)
229
+ | Struct , Array
230
+ | Array , Struct -> return (Eq : W.heap_type )
231
+ | Struct , Type t | Type t , Struct -> (
232
+ fun st ->
233
+ let type_field = Var.Hashtbl. find st.context.types t in
234
+ match type_field.typ with
235
+ | Struct _ -> W. Struct , st
236
+ | Array _ | Func _ -> W. Eq , st)
237
+ | Array , Type t | Type t , Array -> (
238
+ fun st ->
239
+ let type_field = Var.Hashtbl. find st.context.types t in
240
+ match type_field.typ with
241
+ | Array _ -> W. Struct , st
242
+ | Struct _ | Func _ -> W. Eq , st)
243
+ | Type t , Type t' -> (
244
+ let * r = fun st -> type_index_lub t t' st, st in
245
+ match r with
246
+ | Some t'' -> return (Type t'' : W.heap_type )
247
+ | None -> (
248
+ fun st ->
249
+ let type_field = Var.Hashtbl. find st.context.types t in
250
+ let type_field' = Var.Hashtbl. find st.context.types t' in
251
+ match type_field.typ, type_field'.typ with
252
+ | Struct _ , Struct _ -> (Struct : W.heap_type ), st
253
+ | Array _ , Array _ -> W. Array , st
254
+ | (Array _ | Struct _ | Func _ ), (Array _ | Struct _ | Func _ ) -> W. Eq , st))
255
+ | I31 , I31 -> return W. I31
256
+
257
+ let value_type_lub (ty : W.value_type ) (ty' : W.value_type ) =
258
+ match ty, ty' with
259
+ | Ref { nullable; typ } , Ref { nullable = nullable' ; typ = typ' } ->
260
+ let * typ = heap_type_lub typ typ' in
261
+ return (W. Ref { nullable = nullable || nullable'; typ })
262
+ | _ -> assert false
263
+
202
264
let register_global name ?exported_name ?(constant = false ) typ init st =
203
265
st.context.other_fields < -
204
266
W. Global { name; exported_name; typ; init } :: st.context.other_fields;
@@ -703,13 +765,28 @@ let push e =
703
765
instr (Push e')
704
766
| _ -> instr (Push e)
705
767
768
+ let blk' ty l st =
769
+ let instrs = st.instrs in
770
+ let () , st = l { st with instrs = [] } in
771
+ let ty, st =
772
+ match st.instrs with
773
+ | Push e :: _ ->
774
+ (let * ty' = expression_type e in
775
+ match ty' with
776
+ | None -> return ty
777
+ | Some ty' -> return { ty with W. result = [ ty' ] })
778
+ st
779
+ | _ -> ty, st
780
+ in
781
+ (List. rev st.instrs, ty), { st with instrs }
782
+
706
783
let loop ty l =
707
- let * instrs = blk l in
708
- instr (Loop (ty, instrs))
784
+ let * instrs, ty' = blk' ty l in
785
+ instr (Loop (ty' , instrs))
709
786
710
787
let block ty l =
711
- let * instrs = blk l in
712
- instr (Block (ty, instrs))
788
+ let * instrs, ty' = blk' ty l in
789
+ instr (Block (ty' , instrs))
713
790
714
791
let block_expr ty l =
715
792
let * instrs = blk l in
@@ -782,7 +859,7 @@ let init_code context = instrs context.init_code
782
859
783
860
let function_body ~context ~param_names ~body =
784
861
let st = { var_count = 0 ; vars = Var.Map. empty; instrs = [] ; context } in
785
- let () , st = body st in
862
+ let res , st = body st in
786
863
let local_count, body = st.var_count, List. rev st.instrs in
787
864
let local_types = Array. make local_count (Var. fresh () , None ) in
788
865
List. iteri ~f: (fun i x -> local_types.(i) < - x, None ) param_names;
@@ -800,4 +877,10 @@ let function_body ~context ~param_names ~body =
800
877
|> (fun a -> Array. sub a ~pos: param_count ~len: (Array. length a - param_count))
801
878
|> Array. to_list
802
879
in
803
- locals, body
880
+ locals, res, body
881
+
882
+ let eval ~context e =
883
+ let st = { var_count = 0 ; vars = Var.Map. empty; instrs = [] ; context } in
884
+ let r, st = e st in
885
+ assert (st.var_count = 0 && List. is_empty st.instrs);
886
+ r
0 commit comments