@@ -199,6 +199,68 @@ let heap_type_sub (ty : W.heap_type) (ty' : W.heap_type) st =
199199 (* I31, struct, array and none have no other subtype *)
200200 | _ , (I31 | Type _ | Struct | Array | None_ ) -> false , st
201201
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 = 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 = 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 = 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 = 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 = Hashtbl. find st.context.types t in
250+ let type_field' = 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+
202264let register_global name ?exported_name ?(constant = false ) typ init st =
203265 st.context.other_fields < -
204266 W. Global { name; exported_name; typ; init } :: st.context.other_fields;
@@ -701,13 +763,28 @@ let push e =
701763 instr (Push e')
702764 | _ -> instr (Push e)
703765
766+ let blk' ty l st =
767+ let instrs = st.instrs in
768+ let () , st = l { st with instrs = [] } in
769+ let ty, st =
770+ match st.instrs with
771+ | Push e :: _ ->
772+ (let * ty' = expression_type e in
773+ match ty' with
774+ | None -> return ty
775+ | Some ty' -> return { ty with W. result = [ ty' ] })
776+ st
777+ | _ -> ty, st
778+ in
779+ (List. rev st.instrs, ty), { st with instrs }
780+
704781let loop ty l =
705- let * instrs = blk l in
706- instr (Loop (ty, instrs))
782+ let * instrs, ty' = blk' ty l in
783+ instr (Loop (ty' , instrs))
707784
708785let block ty l =
709- let * instrs = blk l in
710- instr (Block (ty, instrs))
786+ let * instrs, ty' = blk' ty l in
787+ instr (Block (ty' , instrs))
711788
712789let block_expr ty l =
713790 let * instrs = blk l in
@@ -780,7 +857,7 @@ let init_code context = instrs context.init_code
780857
781858let function_body ~context ~param_names ~body =
782859 let st = { var_count = 0 ; vars = Var.Map. empty; instrs = [] ; context } in
783- let () , st = body st in
860+ let res , st = body st in
784861 let local_count, body = st.var_count, List. rev st.instrs in
785862 let local_types = Array. make local_count (Var. fresh () , None ) in
786863 List. iteri ~f: (fun i x -> local_types.(i) < - x, None ) param_names;
@@ -798,4 +875,10 @@ let function_body ~context ~param_names ~body =
798875 |> (fun a -> Array. sub a ~pos: param_count ~len: (Array. length a - param_count))
799876 |> Array. to_list
800877 in
801- locals, body
878+ locals, res, body
879+
880+ let eval ~context e =
881+ let st = { var_count = 0 ; vars = Var.Map. empty; instrs = [] ; context } in
882+ let r, st = e st in
883+ assert (st.var_count = 0 && List. is_empty st.instrs);
884+ r
0 commit comments