package wax-lib

All checked builds pass
  1. Overview
  2. Docs
Libraries for Wax, a Rust-like syntax for WebAssembly

Install

dune-project
 Dependency

Authors

Maintainers

Sources

wax-v0.3.0.tbz
sha256=cc19989d0db930d9300d7356c8f127309424a82767dd3c91ffd19a0bfd20e3a6
sha512=14ff9219dc6c4e8855c3cb895bd1af6fd81d1c521afefe1e7f69208a2e37abc7ec0946f188198a26780aa405fd43a526b938158334a019f7a5d991d8efc437c3

doc/src/wax-lib.wasm/recover.ml.html

Source file recover.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
(* Token classification for the WAT parser's panic-mode error recovery
   ({!Wax_utils.Parsing.Make.parse_recover}). WAT is fully parenthesized, so unlike Wax
   there are no [Boundary]/[Leader] anchors: every construct is [( … )], and the
   only resynchronization points are the parentheses. Recovery therefore leans on
   the nesting-aware skip and on [close_pending] auto-closing with [")"]: an
   error inside a construct is repaired by inserting the [")"]s needed to close
   the pending constructs, so what parsed so far reduces into the best-effort AST
   rather than being unwound away when the enclosing [")"] is reached.

   Every opener — the bare [LPAREN] and the compound [(param]/[(result]/… tokens
   the lexer folds — is [Open]; [RPAREN] is [Close]; end-of-input is [Terminal];
   everything else (keywords, mnemonics, literals) is [Skip]. *)
let sync : Tokens.token -> Wax_utils.Parsing.sync_class = function
  | Tokens.LPAREN | Tokens.LPAREN_DESCRIPTOR | Tokens.LPAREN_DESCRIBES
  | Tokens.LPAREN_CATCH | Tokens.LPAREN_CATCH_ALL | Tokens.LPAREN_CATCH_ALL_REF
  | Tokens.LPAREN_CATCH_REF | Tokens.LPAREN_ON | Tokens.LPAREN_EXPORT
  | Tokens.LPAREN_IMPORT | Tokens.LPAREN_LOCAL | Tokens.LPAREN_PARAM
  | Tokens.LPAREN_RESULT | Tokens.LPAREN_THEN | Tokens.LPAREN_TYPE ->
      Open
  | Tokens.RPAREN -> Close
  | Tokens.EOF -> Terminal
  | _ -> Skip

(* The closing bracket recovery may insert to auto-close a construct still open
   in front of a boundary (or at end of input); passed as [?closers]. Each is
   paired with its source spelling, so a validated auto-close can offer the
   concatenation of the closers it inserted as a machine-applicable quick fix. *)
let closers = [ (Tokens.RPAREN, ")") ]

(* WAT has no statement separator, but a missing {e operand} is the common
   mid-typing slip — [(call)] wants an index, [(i32.const)] a number. Offering a
   zero-width placeholder repairs the group in place, keeping the instruction in
   the best-effort AST (with a "Missing …" diagnostic) instead of dropping the
   whole group. Two candidates, tried in order, so the diagnostic names what is
   actually missing: a named index [$_] first — accepted exactly where an index
   is expected (a func / label / type / … use), which a bare number would also
   fit but describe less accurately — then a [0], accepted at the numeric-literal
   positions an index is not (the const family, lane / align operands, where a
   float may equally be wanted, hence "number" not "integer"). The parser picks
   the first candidate its erroring state can shift, so index positions report
   "Missing index" and the rest "Missing number". Passed as [?insert]. *)
let insert =
  [
    ( Tokens.ID (Wax_utils.Ast.no_loc "_"),
      Wax_utils.Message.text "Missing index.",
      false,
      "$_" );
    (Tokens.NAT "0", Wax_utils.Message.text "Missing number.", false, "0");
    (Tokens.I32, Wax_utils.Message.text "Missing type.", false, "i32");
    (Tokens.FUNCREF, Wax_utils.Message.text "Missing type.", false, "funcref");
  ]

(* A missing closer — [(module (func … (func …] with a [)] left out — surfaces
   as a field-opening keyword offered where an instruction was expected. This
   [barrier] lets [Wax_utils.Parsing.parse_recover] close the enclosing field and restart
   at the new one instead of letting paren-depth counting swallow it. It has
   three parts: the bare [(] to re-offer; the predicate recognizing a field
   keyword written after a bare [(] (offered as the pair [( ; keyword]); and the
   predicate recognizing a {e fused} field opener the lexer folds into one token
   ([(type]/[(import]/[(export]), offered alone. The bare field keywords have no
   fused form; the fused openers are also valid nested (a [(type …)] typeuse, an
   inline [(import …)]/[(export …)]), so both predicates fire only at the
   enclosing recovery level, never on skipped nested content. Passed as
   [?barrier]. *)
let barrier =
  ( Tokens.LPAREN,
    (function
    | Tokens.FUNC | Tokens.GLOBAL | Tokens.MEMORY | Tokens.TABLE | Tokens.ELEM
    | Tokens.DATA | Tokens.TAG | Tokens.START | Tokens.REC | Tokens.MODULE ->
        true
    | _ -> false),
    function
    | Tokens.LPAREN_TYPE | Tokens.LPAREN_IMPORT | Tokens.LPAREN_EXPORT -> true
    | _ -> false )