blob: e82706478be88c50cd2e84e5f7fca569ad2ca8f8 [file] [log] [blame] [edit]
open Types
(* Context *)
type context = deftype list
let lookup c x = Lib.List32.nth c x
(* Extremas *)
let abs_of_comptype _c = function
| StructT _ | ArrayT _ -> StructHT
| FuncT _ -> FuncHT
let rec top_of_comptype c ct =
top_of_heaptype c (abs_of_comptype c ct)
and top_of_typeuse c = function
| Idx x -> top_of_comptype c (expand_deftype (lookup c x))
| Rec _ -> assert false
| Def dt -> top_of_comptype c (expand_deftype dt)
and top_of_heaptype c = function
| AnyHT | NoneHT | EqHT | StructHT | ArrayHT | I31HT -> AnyHT
| FuncHT | NoFuncHT -> FuncHT
| ExnHT | NoExnHT -> ExnHT
| ExternHT | NoExternHT -> ExternHT
| UseHT ut -> top_of_typeuse c ut
| BotHT -> assert false
let top_of_valtype c = function
| NumT _ as t -> t
| VecT _ as t -> t
| RefT (_, ht) -> RefT (Null, top_of_heaptype c ht)
| BotT -> BotT (* well.. *)
let rec bot_of_comptype c ct =
bot_of_heaptype c (abs_of_comptype c ct)
and bot_of_typeuse c = function
| Idx x -> bot_of_comptype c (expand_deftype (lookup c x))
| Rec _ -> assert false
| Def dt -> bot_of_comptype c (expand_deftype dt)
and bot_of_heaptype c = function
| AnyHT | NoneHT | EqHT | StructHT | ArrayHT | I31HT -> NoneHT
| FuncHT | NoFuncHT -> NoFuncHT
| ExnHT | NoExnHT -> NoExnHT
| ExternHT | NoExternHT -> NoExternHT
| UseHT ut -> bot_of_typeuse c ut
| BotHT -> assert false
(* Subtyping *)
let match_null _c nul1 nul2 =
match nul1, nul2 with
| NoNull, Null -> true
| _, _ -> nul1 = nul2
let match_limits _c lim1 lim2 =
I64.ge_u lim1.min lim2.min &&
match lim1.max, lim2.max with
| _, None -> true
| None, Some _ -> false
| Some i, Some j -> I64.le_u i j
let match_numtype _c t1 t2 =
t1 = t2
let match_vectype _c t1 t2 =
t1 = t2
let rec match_heaptype c t1 t2 =
match t1, t2 with
| EqHT, AnyHT -> true
| StructHT, AnyHT -> true
| ArrayHT, AnyHT -> true
| I31HT, AnyHT -> true
| I31HT, EqHT -> true
| StructHT, EqHT -> true
| ArrayHT, EqHT -> true
| NoneHT, t -> match_heaptype c t AnyHT
| NoFuncHT, t -> match_heaptype c t FuncHT
| NoExnHT, t -> match_heaptype c t ExnHT
| NoExternHT, t -> match_heaptype c t ExternHT
| UseHT (Idx x1), _ -> match_heaptype c (UseHT (Def (lookup c x1))) t2
| _, UseHT (Idx x2) -> match_heaptype c t1 (UseHT (Def (lookup c x2)))
| UseHT (Def dt1), UseHT (Def dt2) -> match_deftype c dt1 dt2
| UseHT (Def dt), t ->
(match expand_deftype dt, t with
| StructT _, AnyHT -> true
| StructT _, EqHT -> true
| StructT _, StructHT -> true
| ArrayT _, AnyHT -> true
| ArrayT _, EqHT -> true
| ArrayT _, ArrayHT -> true
| FuncT _, FuncHT -> true
| _ -> false
)
| BotHT, _ -> true
| _, _ -> t1 = t2
and match_reftype c t1 t2 =
match t1, t2 with
| (nul1, t1'), (nul2, t2') ->
match_null c nul1 nul2 && match_heaptype c t1' t2'
and match_valtype c t1 t2 =
match t1, t2 with
| NumT t1', NumT t2' -> match_numtype c t1' t2'
| VecT t1', VecT t2' -> match_vectype c t1' t2'
| RefT t1', RefT t2' -> match_reftype c t1' t2'
| BotT, _ -> true
| _, _ -> false
and match_resulttype c ts1 ts2 =
List.length ts1 = List.length ts2 &&
List.for_all2 (match_valtype c) ts1 ts2
and match_packtype _c t1 t2 =
t1 = t2
and match_storagetype c st1 st2 =
match st1, st2 with
| ValStorageT t1, ValStorageT t2 -> match_valtype c t1 t2
| PackStorageT t1, PackStorageT t2 -> match_packtype c t1 t2
| _, _ -> false
and match_fieldtype c (FieldT (mut1, st1)) (FieldT (mut2, st2)) =
mut1 = mut2 && match_storagetype c st1 st2 &&
match mut1 with
| Cons -> true
| Var -> match_storagetype c st2 st1
and match_comptype c ct1 ct2 =
match ct1, ct2 with
| StructT fts1, StructT fts2 ->
List.length fts1 >= List.length fts2 &&
List.for_all2 (match_fieldtype c) (Lib.List.take (List.length fts2) fts1) fts2
| ArrayT ft1, ArrayT ft2 ->
match_fieldtype c ft1 ft2
| FuncT (ts11, ts12), FuncT (ts21, ts22) ->
match_resulttype c ts21 ts11 && match_resulttype c ts12 ts22
| _, _ -> false
and match_deftype c dt1 dt2 =
dt1 == dt2 || (* optimisation *)
let s = subst_of c in subst_deftype s dt1 = subst_deftype s dt2 ||
let SubT (_fin, uts1, _st) = unroll_deftype dt1 in
List.exists (fun ut1 -> match_heaptype c (UseHT ut1) (UseHT (Def dt2))) uts1
let match_tagtype c (TagT ut1) (TagT ut2) =
match ut1, ut2 with
| Def dt1, Def dt2 -> match_deftype c dt1 dt2 && match_deftype c dt2 dt1
| _, _ -> assert false
let match_globaltype c (GlobalT (mut1, t1)) (GlobalT (mut2, t2)) =
mut1 = mut2 && match_valtype c t1 t2 &&
match mut1 with
| Cons -> true
| Var -> match_valtype c t2 t1
let match_memorytype c (MemoryT (at1, lim1)) (MemoryT (at2, lim2)) =
at1 = at2 && match_limits c lim1 lim2
let match_tabletype c (TableT (at1, lim1, t1)) (TableT (at2, lim2, t2)) =
at1 = at2 && match_limits c lim1 lim2 &&
match_reftype c t1 t2 && match_reftype c t2 t1
let match_externtype c xt1 xt2 =
match xt1, xt2 with
| ExternTagT tt1, ExternTagT tt2 -> match_tagtype c tt1 tt2
| ExternGlobalT gt1, ExternGlobalT gt2 -> match_globaltype c gt1 gt2
| ExternMemoryT mt1, ExternMemoryT mt2 -> match_memorytype c mt1 mt2
| ExternTableT tt1, ExternTableT tt2 -> match_tabletype c tt1 tt2
| ExternFuncT (Def dt1), ExternFuncT (Def dt2) -> match_deftype c dt1 dt2
| _, _ -> false