Skip to content

Commit 3d487bf

Browse files
committed
[spectec] Split def of context's RECS field; make struct extension work correctly
1 parent 18e6ed1 commit 3d487bf

11 files changed

Lines changed: 240 additions & 203 deletions

File tree

document/core/appendix/properties.rst

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,7 @@ Contexts
2929
In order to check :ref:`rolled up <aux-roll-rectype>` recursive types,
3030
the :ref:`context <context>` is locally extended with an additional component that records the :ref:`sub type <syntax-subtype>` corresponding to each :ref:`recursive type index <syntax-rectypeidx>` within the current :ref:`recursive type <syntax-rectype>`:
3131

32-
.. math::
33-
\begin{array}{llll}
34-
\production{context} & C &::=&
35-
\{~ \dots, \CRECS ~ \subtype^\ast ~\} \\
36-
\end{array}
32+
$${syntax: context/sem}
3733

3834

3935
.. index:: value type, reference type, heap type, bottom type, sub type, recursive type, recursive type index

document/core/valid/conventions.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ Validity of an individual definition is specified relative to a *context*,
218218
which collects relevant information about the surrounding :ref:`module <syntax-module>` and the definitions in scope:
219219

220220
* *Types*: the list of :ref:`types <syntax-type>` defined in the current module.
221-
* *Recursive Types*: the list of :ref:`sub types <syntax-subtype>` in the current group of recursive types.
221+
.. * *Recursive Types*: the list of :ref:`sub types <syntax-subtype>` in the current group of recursive types.
222222
* *Functions*: the list of :ref:`functions <syntax-func>` declared in the current module, represented by a :ref:`defined type <syntax-deftype>` that :ref:`expands <aux-expand-deftype>` to their :ref:`function type <syntax-functype>`.
223223
* *Tables*: the list of :ref:`tables <syntax-table>` declared in the current module, represented by their :ref:`table type <syntax-tabletype>`.
224224
* *Memories*: the list of :ref:`memories <syntax-mem>` declared in the current module, represented by their :ref:`memory type <syntax-memtype>`.
@@ -238,7 +238,10 @@ The label stack is the only part of the context that changes as validation of an
238238

239239
More concretely, contexts are defined as :ref:`records <notation-record>` ${:C} with abstract syntax:
240240

241-
$${syntax: context}
241+
$${syntax: context/syn}
242+
243+
.. note::
244+
The definition of contexts is :ref:`extended <context-ext>` with additional fields for the purpose of proving :ref:`type soundness <soundness>`.
242245

243246

244247
.. index:: ! type closure

document/core/valid/instructions.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Two degrees of polymorphism can be distinguished:
3333
the entire (or most of the) :ref:`instruction type <syntax-instrtype>` ${instrtype: t_1* -> t_2*} of the instruction is unconstrained.
3434
That is the case for all :ref:`control instructions <valid-instr-control>` that perform an *unconditional control transfer*, such as ${:UNREACHABLE}, ${:BR}, or ${:RETURN}.
3535

36-
In both cases, the unconstrained types or type sequences can be chosen arbitrarily, as long as they meet the constraints imposed for the surrounding parts of the program.
36+
In both cases, the unconstrained types or type sequences can be chosen arbitrarily, as long as they are valid in the current :ref:`context <context>` and meet the constraints imposed for the surrounding parts of the program.
3737

3838
.. note::
3939
For example, the ${:SELECT} instruction is valid with type ${instrtype: t t I32 -> t}, for any possible :ref:`number type <syntax-numtype>` ${:t}.

specification/wasm-latest/2.0-validation.contexts.spectec

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ var it : instrtype
2121

2222
;; Contexts
2323

24-
syntax context hint(desc "context") hint(macro "%" "C%") =
24+
syntax context/syn hint(desc "context") hint(macro "%" "C%") =
2525
{ TYPES deftype* hint(desc "type"),
26-
RECS subtype* hint(desc "recursive type"),
2726
TAGS tagtype* hint(desc "tag"),
2827
GLOBALS globaltype* hint(desc "global"),
2928
MEMS memtype* hint(desc "memory"),
@@ -34,7 +33,13 @@ syntax context hint(desc "context") hint(macro "%" "C%") =
3433
LOCALS localtype* hint(desc "local"),
3534
LABELS resulttype* hint(desc "label"),
3635
RETURN resulttype? hint(desc "result"),
37-
REFS funcidx*
36+
REFS funcidx* hint(desc "references"),
37+
...
38+
}
39+
40+
syntax context/sem hint(macro "%" "C%") =
41+
{ ...,
42+
RECS subtype* hint(desc "recursive type")
3843
}
3944

4045
var C : context
0 Bytes
Binary file not shown.

spectec/src/backend-latex/render.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1704,6 +1704,8 @@ let () = render_args_fwd := render_args
17041704

17051705
let merge_typ t1 t2 =
17061706
match t1.it, t2.it with
1707+
| StrT (dots1, ids1, fields1, _), StrT (_, ids2, fields2, dots2) ->
1708+
StrT (dots1, ids1 @ strip_nl ids2, fields1 @ strip_nl fields2, dots2) $ t1.at
17071709
| CaseT (dots1, ids1, cases1, _), CaseT (_, ids2, cases2, dots2) ->
17081710
CaseT (dots1, ids1 @ strip_nl ids2, cases1 @ strip_nl cases2, dots2) $ t1.at
17091711
| _, _ -> assert false

spectec/src/frontend/elab.ml

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,30 @@ let is_variant_typ = is_x_typ as_variant_typ
640640
let is_notation_typ = is_x_typ as_notation_typ
641641
let is_empty_notation_typ = is_x_typ as_empty_notation_typ
642642

643+
let rec find_typfield atom = function
644+
| [] -> None
645+
| ((atom', _, _) as tf1)::tfs when atom'.it = atom.it -> Some (tf1, tfs)
646+
| tf1::tfs ->
647+
match find_typfield atom tfs with
648+
| None -> None
649+
| Some (tf, tfs') -> Some (tf, tf1::tfs')
650+
651+
let rec find_expfield atom = function
652+
| [] -> None
653+
| ((atom', _) as ef1)::efs when atom'.it = atom.it -> Some (ef1, efs)
654+
| ef1::efs ->
655+
match find_expfield atom efs with
656+
| None -> None
657+
| Some (ef, efs') -> Some (ef, ef1::efs')
658+
659+
let rec order_expfields efs = function
660+
| [] -> []
661+
| (atom, _, _)::tfs' ->
662+
(* TODO(4, rossberg): make this not quadratic *)
663+
match find_expfield atom efs with
664+
| None -> assert false
665+
| Some (ef1, efs') -> ef1 :: order_expfields efs' tfs'
666+
643667

644668
(* Type Equivalence and Shallow Numeric Subtyping *)
645669

@@ -1469,26 +1493,32 @@ and elab_exp_list env (es : exp list) (xts : (id * Il.typ) list) at
14691493
fail at "arity mismatch for expression list"
14701494

14711495
and elab_expfields env tid (efs : expfield list) (tfs : Il.typfield list) (t0 : Il.typ) at
1496+
: Il.expfield list attempt =
1497+
let* efs = elab_expfields' env tid efs tfs t0 at in
1498+
Ok (order_expfields efs tfs)
1499+
1500+
and elab_expfields' env tid (efs : expfield list) (tfs : Il.typfield list) (t0 : Il.typ) at
14721501
: Il.expfield list attempt =
14731502
Debug.(log_in_at "el.elab_expfields" at
14741503
(fun _ -> fmt "{%s} : {%s} = %s" (list el_expfield efs) (list il_typfield tfs) (il_typ t0))
14751504
);
14761505
assert (valid_tid tid);
14771506
match efs, tfs with
14781507
| [], [] -> Ok []
1479-
| (atom1, e)::efs2, (atom2, (tF, _qs, prems), _)::tfs2 when atom1.it = atom2.it ->
1480-
let* e' = elab_exp env e tF in
1481-
let* efs2' = elab_expfields env tid efs2 tfs2 t0 at in
1482-
let e' = if prems = [] then e' else tup_exp' [e'] e.at in
1483-
Ok ((elab_atom atom1 tid, e') :: efs2')
1484-
| _, (atom, (tF, _qs, prems), _)::tfs2 ->
1508+
| [], (atom, (tF, _qs, prems), _)::tfs2 ->
14851509
let atom' = string_of_atom atom in
14861510
let* e1' = cast_empty ("omitted record field `" ^ atom' ^ "`") env tF at in
14871511
let e' = if prems = [] then e1' else tup_exp' [e1'] at in
14881512
let* efs2' = elab_expfields env tid efs tfs2 t0 at in
14891513
Ok ((elab_atom atom tid, e') :: efs2')
1490-
| (atom, e)::_, [] ->
1491-
fail_atom e.at atom t0 "undefined or misplaced record field"
1514+
| (atom, e)::efs2, tfs ->
1515+
match find_typfield atom tfs with
1516+
| None -> fail_atom e.at atom t0 "undefined or misplaced record field"
1517+
| Some ((_, (tF, _qs, prems), _), tfs2) ->
1518+
let* e' = elab_exp env e tF in
1519+
let* efs2' = elab_expfields env tid efs2 tfs2 t0 at in
1520+
let e' = if prems = [] then e' else tup_exp' [e'] e.at in
1521+
Ok ((elab_atom atom tid, e') :: efs2')
14921522

14931523
and elab_exp_iter env (es : exp list) (t1, iter) t at : Il.exp attempt =
14941524
let* e' = elab_exp_iter' env es (t1, iter) t at in

0 commit comments

Comments
 (0)