blob: 90fcd5ee09b07a398b2c888832d7f02e82b93498 [file] [log] [blame] [view]
# wast2json
`wast2json` converts a `.wast` file to a `.json` file, and a collection of
associated `.wat` file and `.wasm` files.
## Example
```sh
# 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](https://github.com/WebAssembly/spec/tree/master/interpreter#scripts).
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:
```wasm
(import "my_module" "my_export" ...)
```
## Full Example
Assume we have the following `.wast` file:
```wasm
(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"
}
]
}
```