package wax-lib

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Module Wax_lang.TypingSource

Type checking and validation for Wax modules.

Sourcetype typed_module_annotation = Ast.storagetype option array * Ast.location
Sourcetype inferred_module_annotation = Infer.inferred_type Infer.Cell.t array * Ast.location

The typed-tree annotation before the inference cells are resolved to typed_module_annotation: each node carries the inference cells for the values it leaves on the stack, plus its span. Unlike the resolved form it keeps the distinctions Infer.output_inferred_type renders — flexible numeric literals (number/int/…), unknown/unreachable types (any), and inline anonymous composite types — which resolution collapses. Produced by f_infer.

Sourcetype types
Sourceval f : ?simplify:bool -> ?warn_unused:bool -> ?suggest:bool -> ?faithful:bool -> ?width_check:[ `Off | `Repair | `Report ] -> ?features:Wax_utils.Feature.set -> Wax_utils.Diagnostic.context -> Ast.location Ast.module_ -> types * typed_module_annotation Ast.module_

f fields performs type checking on the given list of Wax module fields. It verifies types, signatures, and other semantic rules.

When simplify is set (default false), the typed AST is also rewritten: casts the inferred types make redundant are dropped, and &?extern/&?any casts of non-nullable arguments are tightened to &extern/&any. This is intended for the Wasm-to-Wax conversion, where casts are inserted to pin types; hand-written Wax is left untouched.

When faithful is set (default false, the --faithful decompilation mode, mutually exclusive with simplify), casts are kept as under a plain re-type EXCEPT the From_wasm scaffolding cast on a call_ref callee, which is still dropped when redundant so it does not re-lower to a spurious ref.cast.

When warn_unused is set (default false), a let-bound local that is never read is reported as a warning (unless its name starts with _). A conditional module is checked per reachable configuration, so the warning fires there too.

When suggest is set (default false), machine-applicable simplifications are reported as Suggestion diagnostics (see check); it is mutually exclusive with simplify.

width_check (default `Off) reconciles the type the Wasm-to-Wax conversion recorded on a node (Ast.instr's expected) with the type resolved here — a disagreement means the Wax about to be printed would recompile at a different opcode width. It is about the decompiler, not the module, so it does nothing for a module that carries no recorded expectation (anything but Wax_conversion.From_wasm output).

  • `Repair is what the decompilation pipelines pass: a value whose type merely DEFAULTED to the wrong width is repaired in place — wrapped in the identity cast that pins it at the recorded width, the grounding pin the conversion should have placed — so a missing pin becomes correct output rather than a silent miscompile.
  • `Report reports the same disagreement as an error instead of repairing it (the --debug width-check switch). That is what lets the fuzzing harness see a missing conversion pin at all, rather than a healed one.
  • A disagreement no pin can fix — the value's type is fixed by its context, so a cast would convert the value rather than ground it — is reported as an error in BOTH modes.
Sourceval reserved_type_names : string list

The built-in type names a type declaration (or a rec member) may not take: the value types (i32v128), the abstract heap types, and the atomic intrinsic namespace. The typer rejects such a declaration; From_wasm renames a colliding $type name.

Sourcetype hover_target =
  1. | Value_type of Infer.inferred_valtype
  2. | Type_def of Ast.subtype
    (*

    What a resolved reference summarises for a hover on a name that is not itself an expression: a variable's type, or a referenced type's definition. Kept as data so the consumer renders only the one it needs (a check formats nothing).

    *)
Sourcetype reference = {
  1. use : Ast.location;
  2. definitions : Ast.location list;
  3. hover : hover_target option;
}

A resolved name or label reference: the source span of a *use*, the span(s) of the *definition(s)* it binds to — several only under conditional compilation — and, for a name that is not itself an expression (a type reference, an assignment target, a bare global), what it resolves to for a hover. Collected by f_infer for go-to-definition and hover.

Sourceval f_infer : ?simplify:bool -> ?warn_unused:bool -> ?suggest:bool -> ?resolve_links:reference list ref option -> ?pun_spans:Ast.location list ref option -> ?member_completions:(Ast.location * Members.member_receiver) list ref option -> ?faithful:bool -> ?features:Wax_utils.Feature.set -> Wax_utils.Diagnostic.context -> Ast.location Ast.module_ -> types * inferred_module_annotation Ast.module_

As f, but returns the typed tree with its inference cells intact rather than resolved to storage types — f is exactly f_infer followed by that resolution, and both emit the same diagnostics. Lets a consumer render types the way diagnostics do (via Infer.output_inferred_type); used by the editor for hover.

When resolve_links is a Some ref, every name and label reference resolved while type checking is appended to it as a reference (use span -> definition spans), for go-to-definition. When pun_spans is a Some ref, the span of each punned struct-literal field (the bare-name form x for x: x) is appended to it — such a span is both a field name and a variable use, so a rename must expand it rather than replace it. When member_completions is a Some ref, each member access recv.field appends the field's span and a Members.member_receiver describing what it is on, from which Members.member_candidates derives the completion list on demand. All default to None, so an ordinary run records nothing.

Sourceval check : ?warn_unused:bool -> ?suggest:bool -> ?features:Wax_utils.Feature.set -> Wax_utils.Diagnostic.context -> Ast.location Ast.module_ -> unit

check type-checks the module for errors like f, but does not build the typed module. Use it on the validation-only paths (a same-format wax -> wax conversion, the check command) that discard the typed AST; f is reserved for conversion to Wasm/WAT, which consumes it.

warn_unused behaves as for f. When suggest is set (default false), simplifications the typer would apply under simplify (redundant-cast removal, a redundant let annotation), plus struct-field punning and compound assignment, are reported as Suggestion diagnostics carrying a machine-applicable Wax_utils.Diagnostic.edit — for editor quick fixes and wax check. The AST is not rewritten.

erase_types modul removes type annotations from the module, returning it to its original location-only annotation state.

Sourceval plan_shape : guards:bool -> Ast.location Ast.module_ -> Wax_wasm.Cond_plan.item list

The shape of a module's conditionals for Wax_wasm.Cond_plan: the field-level conditionals in order, each holding its nested ones, and the bodies (initializers at rank 0, function bodies at rank 1) holding the statement-level ones. With guards, a per-attribute if guard is a conditional with two empty branches — the checking plan's shape; without, the build plan's, which Wax_wasm.Cond_plan.text_shape mirrors over the Wasm text a Wasm→Wax conversion started from.

Sourceval get_type_definition : Wax_utils.Diagnostic.context -> types -> (string, Ast.location) Ast.annotated -> Ast.subtype option

get_type_definition context types id returns the subtype definition for the given identifier, if it exists.

Sourceval in_branch : types -> Ast.location -> bool -> (unit -> 'a) -> 'a

in_branch types location side f runs f with the type table in force inside the branch side (true: then) of the conditional annotation at location — a field-level #[if] block or a statement-level one. A name declared in two branches has a different definition in each; the lowering wraps its conversion of each branch in this so get_type_definition resolves the branch's own. Outside any conditional the primary configuration's table is in force.