Skip to content

Commit 09abbe7

Browse files
authored
[interpreter] Descriptor type validation (#66)
Check that descriptor and described types are properly paired, are structs, and follow the subtyping rules.
1 parent e4a35de commit 09abbe7

File tree

4 files changed

+488
-17
lines changed

4 files changed

+488
-17
lines changed

interpreter/valid/match.ml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,19 @@ and match_deftype c dt1 dt2 =
160160
match_heaptype c (UseHT (Inexact, ut1)) (UseHT (Inexact, (Def dt2)))
161161
) uts1
162162

163+
let match_typeuse c ut1 ut2 (rt1 : rectype) (rt2 : rectype) =
164+
let dt1 = match ut1 with
165+
| Idx x -> lookup c x
166+
| Rec i -> DefT (rt1, i)
167+
| Def dt -> dt
168+
in
169+
let dt2 = match ut2 with
170+
| Idx x -> lookup c x
171+
| Rec i -> DefT (rt2, i)
172+
| Def dt -> dt
173+
in
174+
match_deftype c dt1 dt2
175+
163176
let match_tagtype c (TagT ut1) (TagT ut2) =
164177
match ut1, ut2 with
165178
| Def dt1, Def dt2 -> match_deftype c dt1 dt2 && match_deftype c dt2 dt1

interpreter/valid/match.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ val match_storagetype : context -> storagetype -> storagetype -> bool
2828

2929
val match_comptype : context -> comptype -> comptype -> bool
3030
val match_deftype : context -> deftype -> deftype -> bool
31+
val match_typeuse : context -> typeuse -> typeuse -> rectype -> rectype -> bool
3132

3233
val match_tabletype : context -> tabletype -> tabletype -> bool
3334
val match_memorytype : context -> memorytype -> memorytype -> bool

interpreter/valid/valid.ml

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -157,17 +157,63 @@ let check_comptype (c : context) (ct : comptype) at =
157157
check_resulttype c ts1 at;
158158
check_resulttype c ts2 at
159159

160-
(* TODO: Make sure the describes and descriptor clauses match. *)
161160
let check_desctype (c : context) (dt : desctype) at =
162-
match dt with
163-
| DescT (ht1, ht2, ct) -> check_comptype c ct at
164-
165-
let check_desctype_sub (c : context) (dt : desctype) (dti : desctype) x xi at =
166-
(* TODO: check rules *)
161+
(match dt with
162+
| DescT (None, None, _) -> ()
163+
| DescT (_, _, StructT _) -> ()
164+
| DescT (_, Some _, _) ->
165+
error at "descriptor type must be a struct"
166+
| DescT (Some _, _, _) ->
167+
error at "described type must be a struct");
167168
let DescT (_, _, ct) = dt in
168-
let DescT (_, _, cti) = dti in
169-
require (match_comptype c.types ct cti) at ("sub type " ^ I32.to_string_u x ^
170-
" does not match super type " ^ I32.to_string_u xi)
169+
check_comptype c ct at
170+
171+
let check_desctype_sub (c : context) (dt : desctype) (dt' : desctype) x x' at =
172+
let DefT (rt, _) = type_ c (x @@ at) in
173+
let DefT (rt', _) = type_ c (x' @@ at) in
174+
let DescT (ut1, ut2, ct) = dt in
175+
let DescT (ut1', ut2', ct') = dt' in
176+
match ut1, ut1' with
177+
| (Some ut1, Some ut1') ->
178+
require (match_typeuse c.types ut1 ut1' rt rt') at ("described type " ^
179+
string_of_typeuse ut1 ^ " does not match " ^ string_of_typeuse ut1')
180+
| (Some _, None) | (None, Some _) ->
181+
error at ("sub type " ^ I32.to_string_u x ^ " does not match super type " ^
182+
I32.to_string_u x')
183+
| (None, None) -> ();
184+
match ut2, ut2' with
185+
| (Some ut2, Some ut2') ->
186+
require (match_typeuse c.types ut2 ut2' rt rt') at ("descriptor type " ^
187+
string_of_typeuse ut2 ^ " does not match " ^ string_of_typeuse ut2')
188+
| (None, Some _) ->
189+
error at ("sub type " ^ I32.to_string_u x ^ " does not match super type " ^
190+
I32.to_string_u x')
191+
| (Some _, None) | (None, None) -> ();
192+
require (match_comptype c.types ct ct') at ("sub type " ^ I32.to_string_u x ^
193+
" does not match super type " ^ I32.to_string_u x')
194+
195+
let check_descriptors (dts : deftype list) at =
196+
List.iter (fun dt ->
197+
let DefT ((RecT dts), x) = dt in
198+
let SubT (_, _, DescT (ut1, ut2, _)) = Lib.List32.nth dts x in
199+
Option.iter (fun ut ->
200+
match ut with
201+
| Rec x' ->
202+
let SubT (_, _, DescT (_, ut', _)) = Lib.List32.nth dts x' in
203+
require (ut' = Some (Rec x)) at
204+
"described type is not described by descriptor";
205+
require (x' < x) at "forward use of described type"
206+
| _ -> error at "described type is outside rec group"
207+
) ut1;
208+
Option.iter (fun ut ->
209+
match ut with
210+
| Rec x' ->
211+
let SubT (_, _, DescT (ut', _, _)) = Lib.List32.nth dts x' in
212+
require (ut' = Some (Rec x)) at
213+
"type is not described by its descriptor";
214+
| _ -> error at "descriptor type is outside rec group"
215+
) ut2
216+
) dts
171217

172218
let check_subtype (c : context) (sut : subtype) at =
173219
let SubT (_fin, uts, dt) = sut in
@@ -189,7 +235,9 @@ let check_subtype_sub (c : context) (sut : subtype) x at =
189235
let check_rectype (c : context) (rt : rectype) at : context =
190236
let RecT sts = rt in
191237
let x = Lib.List32.length c.types in
192-
let c' = {c with types = c.types @ roll_deftypes x rt} in
238+
let dts = roll_deftypes x rt in
239+
check_descriptors dts at;
240+
let c' = {c with types = c.types @ dts} in
193241
List.iter (fun st -> check_subtype c' st at) sts;
194242
Lib.List32.iteri
195243
(fun i st -> check_subtype_sub c' st (Int32.add x i) at) sts;

0 commit comments

Comments
 (0)