Skip to content

Commit 6192a31

Browse files
committed
formalize component value definitions
Signed-off-by: Roman Volosatovs <[email protected]>
1 parent 1a3e3cf commit 6192a31

File tree

2 files changed

+209
-16
lines changed

2 files changed

+209
-16
lines changed

design/mvp/Binary.md

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ section ::= section_0(<core:custom>) => ϵ
3636
| s: section_9(<start>) => [s]
3737
| i*:section_10(vec(<import>)) => i*
3838
| e*:section_11(vec(<export>)) => e*
39+
| v*:section_12(vec(<value>)) => v*
3940
```
4041
Notes:
4142
* Reused Core binary rules: [`core:section`], [`core:custom`], [`core:module`]
@@ -215,12 +216,14 @@ importdecl ::= in:<importname'> ed:<externdesc> => (import in ed)
215216
exportdecl ::= en:<exportname'> ed:<externdesc> => (export en ed)
216217
externdesc ::= 0x00 0x11 i:<core:typeidx> => (core module (type i))
217218
| 0x01 i:<typeidx> => (func (type i))
218-
| 0x02 t:<valtype> => (value t) 🪙
219+
| 0x02 b:<valuebound> => (value b) 🪙
219220
| 0x03 b:<typebound> => (type b)
220221
| 0x04 i:<typeidx> => (component (type i))
221222
| 0x05 i:<typeidx> => (instance (type i))
222223
typebound ::= 0x00 i:<typeidx> => (eq i)
223224
| 0x01 => (sub resource)
225+
valuebound ::= 0x00 i:<valueidx> => (eq i)
226+
| 0x01 t:<valtype> => t
224227
```
225228
Notes:
226229
* The type opcodes follow the same negative-SLEB128 scheme as Core WebAssembly,
@@ -347,6 +350,61 @@ Notes:
347350
* `<integrity-metadata>` is as defined by the
348351
[SRI](https://www.w3.org/TR/SRI/#dfn-integrity-metadata) spec.
349352

353+
## Value Definitions
354+
355+
(See [Value Definitions](Explainer.md#value-definitions) in the explainer.)
356+
357+
```ebnf
358+
value ::= t:<valtype> v:<val(t)> => (value t v)
359+
val(bool) ::= 0x00 => false
360+
| 0x01 => true
361+
val(u8) ::= v:<core:u8> => v
362+
val(s8) ::= v:<core:s8> => v
363+
val(s16) ::= v:<core:s16> => v
364+
val(u16) ::= v:<core:u16> => v
365+
val(s32) ::= v:<core:s32> => v
366+
val(u32) ::= v:<core:u32> => v
367+
val(s64) ::= v:<core:s64> => v
368+
val(u64) ::= v:<core:u64> => v
369+
val(f32) ::= v:<core:f32> => v
370+
val(f64) ::= v:<core:f64> => v
371+
val(char) ::= v:<core:u32> => v
372+
val(string) ::= v:<core:name> => v
373+
val(i:<typeidx>) ::= v:<val(type-index-space[i])> => v
374+
val((record (field l t)+)) ::= v+:<val(t)>+ => (record v+)
375+
val((variant (case l t?)+) ::= i:<core:u32> v?:<val(t[i])>? => (variant l[i] v?)
376+
val((list t)) ::= v:vec(<val(t)>) => (list v)
377+
val((tuple t+)) ::= v+:<val(t)>+ => (tuple v+)
378+
val((flags l+)) ::= v:<core:uN> => (flags (l[i] for i in 0..N-1 if v & 2^i > 0)) (if N = |l*|)
379+
val((enum l*)) ::= i:<core:u32> => (enum l[i])
380+
val((option t)) ::= 0x00 => none
381+
| 0x01 v:<val(t)> => (some v)
382+
val((result)) ::= 0x00 => ok
383+
| 0x01 => error
384+
val((result t)) ::= 0x00 v:<val(t)> => (ok v)
385+
| 0x01 => error
386+
val((result (error u))) ::= 0x00 => ok
387+
| 0x01 v:<val(u)> => (error v)
388+
val((result t (error u))) ::= 0x00 v:<val(t)> => (ok v)
389+
| 0x01 v:<val(u)> => (error v)
390+
```
391+
392+
Notes:
393+
* Reused Core binary rules:
394+
- [`core:name`]
395+
- [`core:s8`]
396+
- [`core:s16`]
397+
- [`core:s32`]
398+
- [`core:s64`]
399+
- [`core:u8`]
400+
- [`core:u16`]
401+
- [`core:u32`]
402+
- [`core:u64`]
403+
- [`core:uN`]
404+
- [`core:f32`]
405+
- [`core:f64`]
406+
* `&` operator is used to denote bitwise AND operation, which performs AND on every bit of two numbers in their binary form
407+
350408
## Name Section
351409

352410
Like the core wasm [name
@@ -376,7 +434,17 @@ appear once within a `name` section, for example component instances can only be
376434
named once.
377435

378436

437+
[`core:s8`]: https://webassembly.github.io/spec/core/binary/values.html#integers
438+
[`core:u8`]: https://webassembly.github.io/spec/core/binary/values.html#integers
439+
[`core:s16`]: https://webassembly.github.io/spec/core/binary/values.html#integers
440+
[`core:u16`]: https://webassembly.github.io/spec/core/binary/values.html#integers
441+
[`core:s32`]: https://webassembly.github.io/spec/core/binary/values.html#integers
379442
[`core:u32`]: https://webassembly.github.io/spec/core/binary/values.html#integers
443+
[`core:s64`]: https://webassembly.github.io/spec/core/binary/values.html#integers
444+
[`core:u64`]: https://webassembly.github.io/spec/core/binary/values.html#integers
445+
[`core:uN`]: https://webassembly.github.io/spec/core/binary/values.html#integers
446+
[`core:f32`]: https://webassembly.github.io/spec/core/binary/values.html#floating-point
447+
[`core:f64`]: https://webassembly.github.io/spec/core/binary/values.html#floating-point
380448
[`core:section`]: https://webassembly.github.io/spec/core/binary/modules.html#binary-section
381449
[`core:custom`]: https://webassembly.github.io/spec/core/binary/modules.html#custom-section
382450
[`core:module`]: https://webassembly.github.io/spec/core/binary/modules.html#binary-module

design/mvp/Explainer.md

Lines changed: 140 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ JavaScript runtimes. For a more user-focussed explanation, take a look at the
2323
* [Canonical definitions](#canonical-definitions)
2424
* [Canonical ABI](#canonical-built-ins)
2525
* [Canonical built-ins](#canonical-built-ins)
26-
* [Start definitions](#-start-definitions)
26+
* [Value definitions](#value-definitions)
27+
* [Start definitions](#start-definitions)
2728
* [Import and export definitions](#import-and-export-definitions)
2829
* [Component invariants](#component-invariants)
2930
* [JavaScript embedding](#JavaScript-embedding)
@@ -87,6 +88,7 @@ definition ::= core-prefix(<core:module>)
8788
| <start> 🪺
8889
| <import>
8990
| <export>
91+
| <value>
9092
9193
where core-prefix(X) parses '(' 'core' Y ')' when X parses '(' Y ')'
9294
```
@@ -296,7 +298,7 @@ contain any valid UTF-8 string).
296298

297299
🪙 The `value` sort refers to a value that is provided and consumed during
298300
instantiation. How this works is described in the
299-
[start definitions](#start-definitions) section.
301+
[value definitions](#value-definitions) section.
300302

301303
To see a non-trivial example of component instantiation, we'll first need to
302304
introduce a few other definitions below that allow components to import, define
@@ -564,10 +566,12 @@ externdesc ::= (<sort> (type <u32>) )
564566
| <functype>
565567
| <componenttype>
566568
| <instancetype>
567-
| (value <valtype>) 🪙
569+
| (value <valuebound>) 🪙
568570
| (type <typebound>)
569571
typebound ::= (eq <typeidx>)
570572
| (sub resource)
573+
valuebound ::= (eq <valueidx>)
574+
| <valtype>
571575
572576
where bind-id(X) parses '(' sort <id>? Y ')' when X parses '(' sort Y ')'
573577
```
@@ -1341,22 +1345,110 @@ number of threads that can be expected to execute concurrently.
13411345
See the [CanonicalABI.md](CanonicalABI.md#canonical-definitions) for detailed
13421346
definitions of each of these built-ins and their interactions.
13431347

1348+
### 🪙 Value Definitions
13441349

1345-
### 🪙 Start Definitions
1350+
Value definitions (in the value index space) are like immutable `global` definitions
1351+
in Core WebAssembly except that validation requires them to be consumed exactly
1352+
once at instantiation-time (i.e., they are [linear]).
1353+
1354+
Components may define values in the value index space using following syntax:
13461355

1347-
Like modules, components can have start functions that are called during
1348-
instantiation. Unlike modules, components can call start functions at multiple
1349-
points during instantiation with each such call having parameters and results.
1350-
Thus, `start` definitions in components look like function calls:
13511356
```ebnf
1352-
start ::= (start <funcidx> (value <valueidx>)* (result (value <id>?))*)
1357+
value ::= (value <id>? <valtype> <val>)
1358+
val ::= false | true
1359+
| <core:u8>
1360+
| <core:s8>
1361+
| <core:s16>
1362+
| <core:u16>
1363+
| <core:s32>
1364+
| <core:u32>
1365+
| <core:s64>
1366+
| <core:u64>
1367+
| <core:f32>
1368+
| <core:f64>
1369+
| '<core:char>'
1370+
| "<core:name>"
1371+
| (record <val>+)
1372+
| (variant "<label>" <val>?)
1373+
| (list <val>*)
1374+
| (tuple <val>+)
1375+
| (flags "<label>"*)
1376+
| (enum "<label>")
1377+
| none | (some <val>)
1378+
| ok | (ok <val>) | error | (error <val>)
1379+
```
1380+
1381+
Where `val` definition must match the `valtype` specified as defined in [Binary.md](Binary.md).
1382+
1383+
For example:
1384+
```wasm
1385+
(component
1386+
(value $a bool true)
1387+
(value $b u8 1)
1388+
(value $c u16 2)
1389+
(value $d u32 3)
1390+
(value $e u64 4)
1391+
(value $f u8 5)
1392+
(value $g u16 6)
1393+
(value $h u32 7)
1394+
(value $i u64 8)
1395+
(value $j f32 9.1)
1396+
(value $k f64 9.2)
1397+
(value $l char 'a')
1398+
(value $m string "hello")
1399+
(value $n (record (field "a" bool) (field "b" u8)) (record true 1))
1400+
(value $o (variant (case "a" bool) (case "b" u8)) (variant "b" 1))
1401+
(value $p (list (result (option u8)))
1402+
(list
1403+
error
1404+
(ok (some 1))
1405+
(ok none)
1406+
error
1407+
(ok (some 2))
1408+
)
1409+
)
1410+
(value $q (tuple u8 u16 u32) (tuple 1 2 3))
1411+
1412+
(type $abc (flags "a" "b" "c"))
1413+
(value $r $abc (flags "a" "c"))
1414+
1415+
(value $s (enum "a" "b" "c") (enum "b"))
1416+
1417+
(type $complex
1418+
(tuple
1419+
(record
1420+
(field "a" (option string))
1421+
(field "b" (tuple (option u8) string))
1422+
)
1423+
(list char)
1424+
$abc
1425+
string
1426+
)
1427+
)
1428+
(value $complex1 $complex
1429+
(tuple
1430+
(record
1431+
none
1432+
(tuple none "empty")
1433+
)
1434+
(list)
1435+
(flags)
1436+
""
1437+
)
1438+
)
1439+
(value $complex2 $complex
1440+
(tuple
1441+
(record
1442+
(some "example")
1443+
(tuple (some 42) "hello")
1444+
)
1445+
(list 'a' 'b' 'c')
1446+
(flags "b" "a")
1447+
"hi"
1448+
)
1449+
)
1450+
)
13531451
```
1354-
The `(value <valueidx>)*` list specifies the arguments passed to `funcidx` by
1355-
indexing into the *value index space*. Value definitions (in the value index
1356-
space) are like immutable `global` definitions in Core WebAssembly except that
1357-
validation requires them to be consumed exactly once at instantiation-time
1358-
(i.e., they are [linear]). The arity and types of the two value lists are
1359-
validated to match the signature of `funcidx`.
13601452

13611453
As with all definition sorts, values may be imported and exported by
13621454
components. As an example value import:
@@ -1366,6 +1458,28 @@ components. As an example value import:
13661458
As this example suggests, value imports can serve as generalized [environment
13671459
variables], allowing not just `string`, but the full range of `valtype`.
13681460

1461+
Example of a value export:
1462+
```wasm
1463+
(value $default_url string "https://example.com")
1464+
(export "default-url" (value $default_url))
1465+
;; `default-url` value export will infer `(eq $default_url)` value bound in the component type,
1466+
;; include a type ascription to explicitly set type to `string`:
1467+
(export "default-url-string" (value $default_url) (value string))
1468+
```
1469+
1470+
### 🪙 Start Definitions
1471+
1472+
Like modules, components can have start functions that are called during
1473+
instantiation. Unlike modules, components can call start functions at multiple
1474+
points during instantiation with each such call having parameters and results.
1475+
Thus, `start` definitions in components look like function calls:
1476+
```ebnf
1477+
start ::= (start <funcidx> (value <valueidx>)* (result (value <id>?))*)
1478+
```
1479+
The `(value <valueidx>)*` list specifies the arguments passed to `funcidx` by
1480+
indexing into the *value index space*. The arity and types of the two value lists are
1481+
validated to match the signature of `funcidx`.
1482+
13691483
With this, we can define a component that imports a string and computes a new
13701484
exported string at instantiation time:
13711485
```wasm
@@ -1927,6 +2041,17 @@ and will be added over the coming months to complete the MVP proposal:
19272041
[Index Space]: https://webassembly.github.io/spec/core/syntax/modules.html#indices
19282042
[Abbreviations]: https://webassembly.github.io/spec/core/text/conventions.html#abbreviations
19292043

2044+
[`core:s8`]: https://webassembly.github.io/spec/core/syntax/values.html#integers
2045+
[`core:u8`]: https://webassembly.github.io/spec/core/syntax/values.html#integers
2046+
[`core:s16`]: https://webassembly.github.io/spec/core/syntax/values.html#integers
2047+
[`core:u16`]: https://webassembly.github.io/spec/core/syntax/values.html#integers
2048+
[`core:s32`]: https://webassembly.github.io/spec/core/syntax/values.html#integers
2049+
[`core:u32`]: https://webassembly.github.io/spec/core/syntax/values.html#integers
2050+
[`core:s64`]: https://webassembly.github.io/spec/core/syntax/values.html#integers
2051+
[`core:u64`]: https://webassembly.github.io/spec/core/syntax/values.html#integers
2052+
[`core:f32`]: https://webassembly.github.io/spec/core/syntax/values.html#floating-point
2053+
[`core:f64`]: https://webassembly.github.io/spec/core/syntax/values.html#floating-point
2054+
[`core:char`]: https://webassembly.github.io/spec/core/syntax/values.html#syntax-name
19302055
[`core:name`]: https://webassembly.github.io/spec/core/syntax/values.html#syntax-name
19312056
[`core:module`]: https://webassembly.github.io/spec/core/text/modules.html#text-module
19322057
[`core:type`]: https://webassembly.github.io/spec/core/text/modules.html#types

0 commit comments

Comments
 (0)