Skip to content

Latest commit

 

History

History
566 lines (443 loc) · 14.8 KB

wast2json.md

File metadata and controls

566 lines (443 loc) · 14.8 KB

wast2json

wast2json converts a .wast file to a .json file, and a collection of associated .wat file and .wasm files.

Example

# parse spec-test.wast, and write files to spec-test.json. Modules are written
# to spec-test.0.wasm, spec-test.1.wasm, etc.
$ bin/wast2json spec-test.wast -o spec-test.json

Wast

The wast format is described in the spec interpreter. It is an extension of the .wat text format, with additional commands for running scripts. The syntax is repeated here:

script: <cmd>*

cmd:
  <module>                                   ;; define, validate, and initialize module
  ( register <string> <name>? )              ;; register module for imports
module with given failure string
  <action>                                   ;; perform action and print results
  <assertion>                                ;; assert result of an action
  <meta>                                     ;; meta command

module:
  ...
  ( module <name>? binary <string>* )        ;; module in binary format (may be malformed)
  ( module <name>? quote <string>* )         ;; module quoted in text (may be malformed)

action:
  ( invoke <name>? <string> <expr>* )        ;; invoke function export
  ( get <name>? <string> )                   ;; get global export

assertion:
  ( assert_return <action> <result>* )       ;; assert action has expected results
  ( assert_trap <action> <failure> )         ;; assert action traps with given failure string
  ( assert_exhaustion <action> <failure> )   ;; assert action exhausts system resources
  ( assert_malformed <module> <failure> )    ;; assert module cannot be decoded with given failure string
  ( assert_invalid <module> <failure> )      ;; assert module is invalid with given failure string
  ( assert_unlinkable <module> <failure> )   ;; assert module fails to link
  ( assert_trap <module> <failure> )         ;; assert module traps on instantiation

result:
  ( <val_type>.const <numpat> )

numpat:
  <value>                                    ;; literal result
  nan:canonical                              ;; NaN in canonical form
  nan:arithmetic                             ;; NaN with 1 in MSB of payload

meta:
  ( script <name>? <script> )                ;; name a subscript
  ( input <name>? <string> )                 ;; read script or module from file
  ( output <name>? <string>? )               ;; output module to stout or file

wast2json supports all of this format except the meta commands. The meta commands are not used in any of the spec tests.

JSON format

The JSON format has the following structure:

{"source_filename": <string>,
 "commands": [ <commands>* ] }

The source_filename is the name of the input .wast file. Each command is a JSON object. They all have the following structure:

{"type": <string>, "line": <number>, ...}

The line property is the line in the .wast file where this command is defined. The type property can be one of the following. Given the string, the rest of the command object has the given structure:

type extra properties
"module" {..., "name": <string>, "filename": <string>}
"action" {..., "action": <action>}
"assert_return" {..., "action": <action>, "expected": <expected>}
"assert_exhaustion" {..., "action": <action>, "text": <string>}
"assert_trap" {..., "action": <action>, "text": <string>}
"assert_invalid" {..., "filename": <string>, "text": <string>, "module_type": <module_type>}
"assert_malformed" {..., "filename": <string>, "text": <string>, "module_type": <module_type>}
"assert_uninstantiable" {..., "filename": <string>, "text": <string>, "module_type": <module_type>}
"assert_unlinkable" {..., "filename": <string>, "text": <string>, "module_type": <module_type>}
"register" {..., "name": <string>, "as": <string>}

Actions

An action represents the wast action: either an "invoke" or a "get" command. An action can be run with or without an associated assertion.

If this is an "invoke" action, the "field" property represents the name of the exported function to run. If this is a "get" action, the "field" property represents the name of the exported global to access.

An action has an optional module name. If the name is provided, this is the module to run the action on. If the name is not provided, the action is run on the most recently instantiated module.

The complete format for an "invoke" action command is:

{
  "type": "invoke",
  ("module": <string>)?,
  "field": <string>,
  "args": <const_vector>
}

The "args" property represents the parameters to pass to the exported function.

The complete format for a "get" action command is:

{
  "type": "get",
  ("module": <string>)?,
  "field": <string>
}

Const Vectors

A const vector is an array of consts.

[<const>]

Const

A const is a constant value. It contains both a type and a value. The following types are supported, with the given JSON format:

type JSON format
"i32" {"type": "i32", "value": <string>}
"i64" {"type": "i64", "value": <string>}
"f32" {"type": "f32", "value": <string>}
"f64" {"type": "f64", "value": <string>}

The reference-types proposal adds three more valid types. In each case the value can either be an integer or "null":

type JSON format
"externref" {"type": "externref", "value": <string>}
"funcref" {"type": "funcref", "value": <string>}
"exnref" {"type": "exnref", "value": <string>}

The simd proposal adds another type, with a slightly different syntax.

{
  "type": "v128",
  "lane_type": "i8" | "i16" | "i32" | "f32" | "f64",
  "value": [ (<string>,)* ]
}

All numeric value are stored as strings, since JSON numbers are not guaranteed to be precise enough to store all Wasm values. Values are always written as decimal numbers. For example, the following const has the type "i32" and the value 34.

("type": "i32", "value": "34"}

For floats, the numbers are written as the decimal encoding of the binary representation of the number. For example, the following const has the type "f32" and the value 1.0. The value is 1065353216 because that is equivalent to hexadecimal 0x3f800000, which is the binary representation of 1.0 as a 32-bit float.

("type": "f32", "value": "1065353216"}

A "v128" value stores each of its lanes as a separate string. The number of lanes depends on the "lane_type" property:

"lane_type" #lanes
"i8" 16
"i16" 8
"i32" 4
"i64" 2
"f32" 4
"f64" 2

For example, a "v128" const with lane type "i32" and lanes 0, 1, 2, 3 would be written:

{
  "type": "v128",
  "lane_type": "i32",
  "value": ["0", "1", "2", "3"]
}

Expected

Expected values are similar to a const vector. They are always arrays, and they typically contain const values. For example, the following expected value is the same as a const vector, and has the type "i32" and the value "1":

[
  {"type": "i32", "value": "1"}
]

However, an expected value can also contain a pattern. In particular, for "f32" and "f64" types (and simd lanes), the pattern can also be "nan:canonical" or "nan:arithmetic". For example, the following expected value has the type "f32" and must be a canonical NaN:

[
  {"type": "f32", "value": "nan:canonical"}
]

The simd proposal extends this pattern for multiple lanes, where each lane can be a const or a pattern. For example, the following expected value has four lanes, each of type "f32", two of which have const values (lanes 0 and 2), and two of which are patterns (lanes 1 and 3):

[
  {
    "type": "v128",
    "lane_type": "f32",
    "value": [
      "0",
      "nan:arithmetic",
      "0",
      "nan:arithmetic",
    ]
  }
]

The multi-value proposal allows for multiple return values from a function, which is why the expected values is always an array. For example, the following example has two expected values:

[
  {"type": "i32", "value": "1"},
  {"type": "i64", "value": "2"}
]

"module" command

The "module" JSON command represents the wast module command. It compiles and instantiates a new module, which then becomes the default target for future assertions.

The complete format for the "module" command is:

{
 "type": "module",
 "line": <number>,
 ("name": <string>,)?
 "filename": <string>
}

Optionally, the module can be given a name via the "name" property. If given, this name can be used in action commands to refer to this module instead of the most recently instantiated one.

The "filename" property specifies the path to the .wasm file for this module. The path is always relative to the JSON file.

"action" command

{
 "type": "action",
 "line": <number>,
 "action": <action>
}

The "action" JSON command represents a wast action (either invoke or get) that does not have an associated assertion).

"assert_return" command

{
 "type": "assert_return",
 "line": <number>,
 "action": <action>
 "expected": <expected>
}

The "assert_return" JSON command represents the wast assert_return command. It runs an action and checks that the result is an expected value.

"assert_exhaustion" command

{
 "type": "assert_exhaustion",
 "line": <number>,
 "action": <action>,
 "text": <string>
}

The "assert_exhaustion" JSON command represents the wast assert_exhaustion command. It runs an action, and checks whether this produces a stack overflow.

The "text" property specifies the text expected by the rerefence interpreter.

"assert_trap" command

{
 "type": "assert_trap",
 "line": <number>,
 "action": <action>,
 "text": <string>
}

The "assert_trap" JSON command represents the action form of the wast assert_trap command. The wast format also has an assert_trap that operates on a module which is called "assert_uninstantiable" in the JSON format.

The "assert_trap" command runs an action with the expectation that it will trap.

The "text" property specifies the text expected by the rerefence interpreter.

"assert_invalid" command

{
  "type": "assert_invalid",
  "line": <number>,
  "filename": <string>,
  "text": <string>,
  "module_type": "binary" | "text"
}

The "assert_invalid" JSON command represents the wast assert_invalid command. It reads a module with the expectation that it will not validate.

The "filename" property specifies the path to the .wasm or .wat file for this module. The path is always relative to the JSON file.

The "text" property specifies the error text expected by the reference interpreter.

The "module_type" property specifies whether this module is in text or binary format.

"assert_malformed" command

{
  "type": "assert_malformed",
  "line": <number>,
  "filename": <string>,
  "text": <string>,
  "module_type": "binary" | "text"
}

The "assert_malformed" JSON command represents the wast assert_malformed command. It reads a module with the expectation that it is malformed. Note that this is different than being invalid; a malformed module is one that doesn't obey the syntax rules of the binary or text format.

The "filename" property specifies the path to the .wasm or .wat file for this module. The path is always relative to the JSON file.

The "text" property specifies the error text expected by the reference interpreter.

The "module_type" property specifies whether this module is in text or binary format.

"assert_uninstantiable" command

{
  "type": "assert_uninstantiable",
  "line": <number>,
  "filename": <string>,
  "text": <string>,
  "module_type": "binary" | "text"
}

The "assert_uninstantiable" JSON command represents the module form of the wast assert_trap command. The wast format also has an assert_trap command that runs an action, which is called "assert_trap" in the JSON format.

An uninstantiable module is one where the linking step succeeds, but the start function traps.

The "filename" property specifies the path to the .wasm or .wat file for this module. The path is always relative to the JSON file.

The "text" property specifies the error text expected by the reference interpreter.

The "module_type" property specifies whether this module is in text or binary format.

"assert_unlinkable" command

{
  "type": "assert_unlinkable",
  "line": <number>,
  "filename": <string>,
  "text": <string>,
  "module_type": "binary" | "text"
}

The "assert_unlinkable" JSON command represents the wast assert_unlinkable command. It reads a module with the expectation that it will not link with the other modules provided; i.e., one of its imports is not provided or does not match.

The "filename" property specifies the path to the .wasm or .wat file for this module. The path is always relative to the JSON file.

The "text" property specifies the error text expected by the reference interpreter.

The "module_type" property specifies whether this module is in text or binary format.

"register" command

{
  "type": "register",
  ("name": <string>,)?
  "as": <string>
}

The "register" JSON command represents the wast register command. It registers the exports of the given module as a given name.

The "name" property specifies the module to be registered. If it is empty, the most recently instantiated module is used.

The "as" property specifies the name to use in the registry. For example, if a module is registered as:

{
  "type": "register",
  "as": "my_module"
}

Then its exports can be imported as:

(import "my_module" "my_export" ...)

Full Example

Assume we have the following .wast file:

(module
  (func (export "add") (param i32 i32) (result i32)
    local.get 0
    local.get 1
    i32.add)

  (func (export "trap")
    unreachable)
)

(assert_return (invoke "add" (i32.const 11) (i32.const 22)) (i32.const 33))

(assert_trap (invoke "trap") "unreachable")

(assert_malformed
  (module quote "(modulee)")
  "syntax error"
)

The following JSON file will be generated (with added whitespace for clarity):

{
  "source_filename": "example.wast",
  "commands": [
    {
      "type": "module",
      "line": 1,
      "filename": "example.0.wasm"
    },

    {
      "type": "assert_return",
      "line": 11,
      "action": {
        "type": "invoke",
        "field": "add",
        "args": [
          {"type": "i32", "value": "11"},
          {"type": "i32", "value": "22"}
        ]
      },
      "expected": [
        {"type": "i32", "value": "33"}
      ]
    },

    {
      "type": "assert_trap",
      "line": 13,
      "action": {
        "type": "invoke",
        "field": "trap",
        "args": []
      },
      "text": "unreachable",
    },

    {
      "type": "assert_malformed",
      "line": 16,
      "filename": "example.1.wat",
      "text": "syntax error",
      "module_type": "text"
    }
  ]
}