diff --git a/component-model/examples/example-host/README.md b/component-model/examples/example-host/README.md index 38107ff..43d9a4e 100644 --- a/component-model/examples/example-host/README.md +++ b/component-model/examples/example-host/README.md @@ -5,10 +5,10 @@ This is a native Rust CLI application that can run components of the following parameters. ```wit -package example:component +package example:component; world example { - export add: func(x: s32, y: s32) -> s32 + export add: func(x: s32, y: s32) -> s32; } ``` diff --git a/component-model/examples/example-host/add.wit b/component-model/examples/example-host/add.wit index 4f8cc18..703ed7e 100644 --- a/component-model/examples/example-host/add.wit +++ b/component-model/examples/example-host/add.wit @@ -1,5 +1,5 @@ -package example:component +package example:component; world example { - export add: func(x: s32, y: s32) -> s32 + export add: func(x: s32, y: s32) -> s32; } diff --git a/component-model/examples/tutorial/README.md b/component-model/examples/tutorial/README.md index 7bb6f7d..d16920a 100644 --- a/component-model/examples/tutorial/README.md +++ b/component-model/examples/tutorial/README.md @@ -6,26 +6,26 @@ add an `op` enum that delineates each operator. The following example interface has an `add` operation: ```wit -package docs:calculator@0.1.0 +package docs:calculator@0.1.0; interface calculate { enum op { add, } - eval-expression: func(op: op, x: u32, y: u32) -> u32 + eval-expression: func(op: op, x: u32, y: u32) -> u32; } interface add { - add: func(a: u32, b: u32) -> u32 + add: func(a: u32, b: u32) -> u32; } world adder { - export add + export add; } world calculator { - export calculate - import add + export calculate; + import add; } ``` diff --git a/component-model/examples/tutorial/wit/calculator.wit b/component-model/examples/tutorial/wit/calculator.wit index f46b6fb..ebfd234 100644 --- a/component-model/examples/tutorial/wit/calculator.wit +++ b/component-model/examples/tutorial/wit/calculator.wit @@ -1,25 +1,25 @@ -package docs:calculator@0.1.0 +package docs:calculator@0.1.0; interface calculate { enum op { add, } - eval-expression: func(op: op, x: u32, y: u32) -> u32 + eval-expression: func(op: op, x: u32, y: u32) -> u32; } interface add { - add: func(a: u32, b: u32) -> u32 + add: func(a: u32, b: u32) -> u32; } world adder { - export add + export add; } world calculator { - export calculate - import add + export calculate; + import add; } world app { - import calculate -} \ No newline at end of file + import calculate; +} diff --git a/component-model/src/creating-and-consuming/composing.md b/component-model/src/creating-and-consuming/composing.md index 784711c..a91f84e 100644 --- a/component-model/src/creating-and-consuming/composing.md +++ b/component-model/src/creating-and-consuming/composing.md @@ -16,28 +16,28 @@ When you compose components, you wire up the imports of one "primary" component For example, consider two components with the following worlds: -``` +```wit // component `validator` -package docs:validator@0.1.0 +package docs:validator@0.1.0; interface validator { - validate-text: func(text: string) -> string + validate-text: func(text: string) -> string; } world { - export validator - import docs:regex/match@0.1.0 + export validator; + import docs:regex/match@0.1.0; } // component 'regex' -package docs:regex@0.1.0 +package docs:regex@0.1.0; interface match { - first-match: func(regex: string, text: string) -> string + first-match: func(regex: string, text: string) -> string; } world { - export match + export match; } ``` diff --git a/component-model/src/design/wit.md b/component-model/src/design/wit.md index 6ede530..c1e0c24 100644 --- a/component-model/src/design/wit.md +++ b/component-model/src/design/wit.md @@ -53,14 +53,14 @@ WIT defines special comment formats for documentation: For example: -```rust +```wit /// Prints "hello". -print-hello: func() +print-hello: func(); /** Prints "hello". */ -print-hello: func() +print-hello: func(); ``` ## Identifiers @@ -101,7 +101,7 @@ WIT defines the following primitive types: `list` for any type T denotes an ordered sequence of values of type T. T can be any type, built-in or user-defined: -``` +```wit list // byte buffer list // a list of customers ``` @@ -112,7 +112,7 @@ This is similar to Rust `Vec`, or Java `List`. `option` for any type T may contain a value of type T, or may contain no value. T can be any type, built-in or user-defined. For example, a lookup function might return an option, allowing for the possibility that the lookup key wasn't found: -``` +```wit option ``` @@ -124,7 +124,7 @@ This is similar to Rust `Option`, C++ `std::optional`, or Haskell `Maybe`. `result` for any types T and E may contain a value of type T _or_ a value of type E (but not both). This is typically used for "value or error" situations; for example, a HTTP request function might return a result, with the success case (the T type) representing a HTTP response, and the error case (the E type) representing the various kinds of error that might occur: -``` +```wit result ``` @@ -134,7 +134,7 @@ This is similar to Rust `Result`, or Haskell `Either`. Sometimes there is no data associated with one or both of the cases. For example, a `print` function could return an error code if it fails, but has nothing to return if it succeeds. In this case, you can omit the corresponding type as follows: -``` +```wit result // no data associated with the error case result<_, u32> // no data associated with the success case result // no data associated with either case @@ -144,7 +144,7 @@ result // no data associated with either case A tuple type is an ordered _fixed length_ sequence of values of specified types. It is similar to a [_record_](#records), except that the fields are identified by their order instead of by names. -``` +```wit tuple // An integer and a string tuple // An integer, then a string, then an integer ``` @@ -159,7 +159,7 @@ You can define your own types within an `interface` or `world`. WIT offers sever A record type declares a set of named fields, each of the form `name: type`, separated by commas. A record instance contains a value for every field. Field types can be built-in or user-defined. The syntax is as follows: -``` +```wit record customer { id: u64, name: string, @@ -176,7 +176,7 @@ Records are similar to C or Rust `struct`s. A variant type declares one or more cases. Each case has a name and, optionally, a type of data associated with that case. A variant instance contains exactly one case. Cases are separated by commas. The syntax is as follows: -``` +```wit variant allowed-destinations { none, any, @@ -192,7 +192,7 @@ Variants are similar to Rust `enum`s or OCaml discriminated unions. The closest An enum type is a variant type where none of the cases have associated data: -``` +```wit enum color { hot-pink, lime-green, @@ -206,7 +206,7 @@ This can provide a simpler representation in languages without discriminated uni A flags type is a set of named booleans. In an instance of the type, each flag will be either true or false. -``` +```wit flags allowed-methods { get, post, @@ -221,34 +221,34 @@ flags allowed-methods { You can define a new named type using `type ... = ...`. This can be useful for giving shorter or more meaningful names to types: -``` -type buffer = list -type http-result = result +```wit +type buffer = list; +type http-result = result; ``` ## Functions -A function is defined by a name and a function type. Like in record fields, the name is separated from the type by a colon: +A function is defined by a name and a function type. Like in record fields, the name is separated from the type by a colon: -``` -do-nothing: func() +```wit +do-nothing: func(); ``` The function type is the word `func`, followed by a parenthesised, comma-separated list of parameters (names and types). If the function returns a value, this is expressed as an arrow symbol (`->`) followed by the return type: -``` +```wit // This function does not return a value -print: func(message: string) +print: func(message: string); // These functions return values -add: func(a: u64, b: u64) -> u64 -lookup: func(store: kv-store, key: string) -> option +add: func(a: u64, b: u64) -> u64; +lookup: func(store: kv-store, key: string) -> option; ``` A function can have multiple return values. In this case the return values must be named, similar to the parameter list. All return values must be populated (in the same way as tuple or record fields). -``` -get-customers-paged: func(cont: continuation-token) -> (customers: list, cont: continuation-token) +```wit +get-customers-paged: func(cont: continuation-token) -> (customers: list, cont: continuation-token); ``` A function can be declared as part of an [interface](#interfaces), or can be declared as an import or export in a [world](#worlds). @@ -257,16 +257,16 @@ A function can be declared as part of an [interface](#interfaces), or can be dec An interface is a named set of types and functions, enclosed in braces and introduced with the `interface` keyword: -``` +```wit interface canvas { - type canvas-id = u64 + type canvas-id = u64; record point { x: u32, y: u32, } - draw-line: func(canvas: canvas-id, from: point, to: point) + draw-line: func(canvas: canvas-id, from: point, to: point); } ``` @@ -276,9 +276,9 @@ Notice that items in an interface are _not_ comma-separated. An interface can reuse types declared in another interface via a `use` directive. The `use` directive must give the interface where the types are declared, then a dot, then a braced list of the types to be reused. The interface can then refer to the types named in the `use`. -``` +```wit interface types { - type dimension = u32 + type dimension = u32; record point { x: dimension, y: dimension, @@ -286,9 +286,9 @@ interface types { } interface canvas { - use types.{dimension, point} - type canvas-id = u64 - draw-line: func(canvas: canvas-id, from: point, to: point, thickness: dimension) + use types.{dimension, point}; + type canvas-id = u64; + draw-line: func(canvas: canvas-id, from: point, to: point, thickness: dimension); } ``` @@ -300,22 +300,22 @@ This works across files as long as the files are in the same package (effectivel A world describes a set of imports and exports, enclosed in braces and introduced with the `world` keyword. Roughly, a world describes the contract of a component. Exports are provided by the component, and define what consumers of the component may call; imports are things the component may call. The imports and exports may be interfaces or individual functions. -``` +```wit interface printer { - print: func(text: string) + print: func(text: string); } interface error-reporter { - report-error: func(error-message: string) + report-error: func(error-message: string); } world multi-function-device { // The component implements the `printer` interface - export printer + export printer; // The component implements the `scan` function - export scan: func() -> list + export scan: func() -> list; // The component needs to be supplied with an `error-reporter` - import error-reporter + import error-reporter; } ``` @@ -323,10 +323,10 @@ world multi-function-device { You can import and export interfaces defined in other packages. This can be done using `package/name` syntax: -``` +```wit world http-proxy { - export wasi:http/incoming-handler - import wasi:http/outgoing-handler + export wasi:http/incoming-handler; + import wasi:http/outgoing-handler; } ``` @@ -338,10 +338,10 @@ WIT does not define how packages are resolved - different tools may resolve them Interfaces can be declared inline in a world: -``` +```wit world toy { export example: interface { - do-nothing: func() + do-nothing: func(); } } ``` @@ -350,12 +350,12 @@ world toy { You can `include` another world. This causes your world to export all that world's exports, and import all that world's imports. -``` +```wit world glow-in-the-dark-multi-function-device { // The component provides all the same exports, and depends on all the same imports, as a `multi-function-device`... - include multi-function-device + include multi-function-device; // ...but also exports a function to make it glow in the dark - export glow: func(brightness: u8) + export glow: func(brightness: u8); } ``` @@ -365,14 +365,14 @@ As with `use` directives, you can `include` worlds from other packages. A package is a set of interfaces and worlds, potentially defined across multiple files. To declare a package, use the `package` directive to specify the package ID. This must include a namespace and name, separated by a colon, and may optionally include a semver-compliant version: -``` -package documentation:example -package documentation:example@1.0.1 +```wit +package documentation:example; +package documentation:example@1.0.1; ``` If a package spans multiple files, only one file needs to contain a package declaration (but if multiple files contain declarations then they must all be the same). All files must have the `.wit` extension and must be in the same directory. For example, the following `documentation:http` package is spread across four files: -``` +```wit // types.wit interface types { record request { /* ... */ } @@ -381,22 +381,22 @@ interface types { // incoming.wit interface incoming-handler { - use types.{request, response} + use types.{request, response}; // ... } // outgoing.wit interface outgoing-handler { - use types.{request, response} + use types.{request, response}; // ... } // http.wit -package documentation:http@1.0.0 +package documentation:http@1.0.0; world proxy { - export incoming-handler - import outgoing-handler + export incoming-handler; + import outgoing-handler; } ``` diff --git a/component-model/src/language-support.md b/component-model/src/language-support.md index 1fb3545..45f07d9 100644 --- a/component-model/src/language-support.md +++ b/component-model/src/language-support.md @@ -45,10 +45,10 @@ working with WebAssembly modules and components. 2. The `add` function is defined inside the following `example` world: ```wit - package example:component + package example:component; world example { - export add: func(x: s32, y: s32) -> s32 + export add: func(x: s32, y: s32) -> s32; } ``` diff --git a/component-model/src/language-support/rust.md b/component-model/src/language-support/rust.md index 24d48ee..73f7e42 100644 --- a/component-model/src/language-support/rust.md +++ b/component-model/src/language-support/rust.md @@ -56,10 +56,10 @@ You can use `wasm-tools component wit` to output the WIT package of the componen ```sh $ wasm-tools component wit add/target/wasm32-wasi/release/add.wasm -package root:component +package root:component; world root { - export add: func(x: s32, y: s32) -> s32 + export add: func(x: s32, y: s32) -> s32; } ``` @@ -83,15 +83,15 @@ See [the language guide](../language-support.md#building-a-component-with-cargo- The [sample `add.wit` file](https://github.com/bytecodealliance/component-docs/tree/main/component-model/examples/example-host/add.wit) exports a function. However, to use your component from another component, it must export an interface. This results in slightly fiddlier bindings. For example, to implement the following world: -``` -package docs:adder@0.1.0 +```wit +package docs:adder@0.1.0; interface add { - add: func(a: u32, b: u32) -> u32 + add: func(a: u32, b: u32) -> u32; } world adder { - export add + export add; } ``` @@ -122,19 +122,19 @@ If your component consumes other components, you can edit the `world.wit` file t For example, suppose you have created and built an adder component as explained in the [exporting an interface section](#exporting-an-interface-with-cargo-component) and want to use that component in a calculator component. Here is a partial example world for a calculator that imports the add interface: -``` +```wit // in the 'calculator' project // wit/world.wit -package docs:calculator +package docs:calculator; interface calculate { - eval-expression: func(expr: string) -> u32 + eval-expression: func(expr: string) -> u32; } world calculator { - export calculate - import docs:adder/add@0.1.0 + export calculate; + import docs:adder/add@0.1.0; } ``` @@ -182,12 +182,12 @@ When you build this using `cargo component build`, the `add` interface remains i $ cargo component build --release $ wasm-tools component wit ./target/wasm32-wasi/release/calculator.wasm -package root:component +package root:component; world root { - import docs:adder/add@0.1.0 + import docs:adder/add@0.1.0; - export docs:calculator/calculate@0.1.0 + export docs:calculator/calculate@0.1.0; } ``` @@ -228,11 +228,11 @@ As mentioned above, `cargo component build` doesn't generate a WIT file for a co 1. Add a `wit/world.wit` to your project, and write a WIT world that imports the interface(s) you want to use. For example: -``` -package docs:app +```wit +package docs:app; world app { - import docs:calculator/calculate@0.1.0 + import docs:calculator/calculate@0.1.0; } ``` diff --git a/component-model/src/tutorial.md b/component-model/src/tutorial.md index d1eb61c..ef796a4 100644 --- a/component-model/src/tutorial.md +++ b/component-model/src/tutorial.md @@ -35,30 +35,30 @@ For tutorial purposes, we are going to define all our interfaces in one WIT pack ```wit // calculator.wit -package docs:calculator@0.1.0 +package docs:calculator@0.1.0; interface calculate { enum op { add, } - eval-expression: func(op: op, x: u32, y: u32) -> u32 + eval-expression: func(op: op, x: u32, y: u32) -> u32; } interface add { - add: func(a: u32, b: u32) -> u32 + add: func(a: u32, b: u32) -> u32; } world adder { - export add + export add; } world calculator { - export calculate - import add + export calculate; + import add; } world app { - import calculate + import calculate; } ```