diff --git a/.docs-plan/motoko-repo-sync-proposal.md b/.docs-plan/motoko-repo-sync-proposal.md new file mode 100644 index 00000000..61de5b70 --- /dev/null +++ b/.docs-plan/motoko-repo-sync-proposal.md @@ -0,0 +1,1070 @@ +# Proposal: Transform-free Motoko docs sync + +**Context:** `docs.internetcomputer.org` syncs Motoko language documentation from +`caffeinelabs/motoko` as a git submodule. Currently a 200-line bash script +(`sync-motoko.sh`) plus a 300-line Node.js post-processor (`postprocess-motoko.mjs`) +are needed on every release to: flatten numbered directories, strip numeric prefixes, +convert Docusaurus-specific syntax to Starlight syntax, rewrite relative links to +match the flattened structure, and expand file-embed code blocks. + +The goal is to reach a state where syncing is just a file copy: no structural +transformation, no syntax conversion, no link rewriting needed. + +--- + +## Problems with the current setup + +### 1. Numbered directories and files + +``` +fundamentals/ + 1-basic-syntax/ + 1-defining-an-actor.md + 8-functions.md ← same slug as types/3-functions.md after stripping + 3-types/ + 3-functions.md ← collision! both flatten to "functions.md" +``` + +Numeric prefixes encode ordering in Docusaurus (which uses `_category_.yml`). +Starlight uses `sidebar: { order: N }` frontmatter instead, so the prefix +serves no purpose once the files are in Starlight. Removing the prefixes and +using frontmatter order avoids the collision problem and removes the need to +strip prefixes during sync. + +### 2. Docusaurus-specific frontmatter + +```yaml +sidebar_position: 8 # Docusaurus +``` + +Starlight uses: + +```yaml +sidebar: + order: 8 +``` + +`sidebar_position` is silently ignored by Starlight, leaving all pages in +undefined (alphabetical) order until the consuming site explicitly enumerates +them in its sidebar config. + +### 3. Docusaurus file-embed syntax + +```` +```motoko file=../examples/counter.mo#L1-L30 +``` +```` + +This site has a `remark-include-file` plugin that runs at build time and handles +`file=` syntax. Both historical gaps have been resolved on the developer-docs +side: + +- **Line-range slicing**: the plugin now supports `#L-L` suffixes. Of + the file-embed blocks in the Motoko source, roughly 9 use line ranges and 38 + embed whole files — both forms now work. +- **Path incompatibility**: synced files land in `docs/languages/motoko/...` while + examples stay in `.sources/motoko/doc/md/examples/`. The `` + placeholder bridges this: `postprocess-motoko.mjs` rewrites `../examples/` → + `/` at sync time, and `remark-include-file` resolves the + placeholder to the examples directory inside the pinned submodule at build time. + +The upstream change (Proposed Change §3 below) makes this bridge permanent by +adopting `` paths directly in the source, after which the sync-time +rewrite becomes a no-op. + +### 4. Links to retired portal URLs + +Many files reference `internetcomputer.org/docs/...`, which is the retired +DFINITY portal. The sync post-processor maintains a rewrite table to map these +to internal developer-docs paths, but that table needs manual updates with +every Motoko release. + +### 5. `base/` and `core/` library links + +Several files link to `./base/.md` or `./core/.md` — both +excluded sections. These are post-processed to `https://mops.one/core/docs/` +because `mo:base` is deprecated in favour of `mo:core`. Using the mops.one URL +directly in the source removes the need for this rewrite. + +The `core/` directory (49 files: `Array.md`, `Map.md`, etc.) is auto-generated +from `caffeinelabs/motoko-core` using `mo-doc` as a separate CI step in the +motoko repo. Once all `./core/.md` links are replaced with mops.one +URLs, the generated `doc/md/core/` directory is no longer needed in the docs +tree and the CI generation step can be dropped from the motoko repo. + +### 6. Docusaurus-specific aside types + +``` +:::info ← ~21 occurrences in synced sections (60+ across full doc/md tree) +:::warn ← 1 occurrence in synced sections +:::info [Link](url) ← link in aside title (Starlight titles are plain text) +``` + +Starlight supports `:::note`, `:::tip`, `:::caution`, `:::danger`, and +`:::warning` (the full word). It does NOT support `:::info` (renders as plain +text) or `:::warn` (the shortened form — also renders as plain text). The +post-processor maps `:::info` → `:::note` and `:::warn` → `:::caution`. Aside +titles that are markdown links (`:::info [Iter](url)`) are also rewritten to +strip the URL (Starlight titles cannot contain links). + +**Important distinction:** `:::warning` (full word) IS a valid Starlight type +(rendered as `:::caution`). Only `:::warn` (three-letter shorthand) is invalid +in Starlight. The source currently uses both — `:::warn` appears once +(`fundamentals/3-types/12-advanced-types.md:235`) and `:::warning` appears twice +(`fundamentals/3-types/9-mutable-arrays.md:89`, `12-base-core-migration.md:31`). +Only `:::warn` needs to be replaced; `:::warning` is already valid. + +Docusaurus supports all four Starlight types natively, so switching `:::info` → +`:::note` and `:::warn` → `:::caution` in the upstream source is a safe change +with no effect on the Docusaurus site. + +### 7. Docusaurus REPL meta flags + +The old DFINITY developer portal (`internetcomputer.org/docs`) wrapped Docusaurus's +`CodeBlock` component with a custom React component that embedded the `moc` +interpreter in the browser. It added the following code-fence meta flags: + +| Flag | Docusaurus behaviour | +|---|---| +| `` ```motoko `` (bare, no flag) | Syntax highlighting + **Run** button; output shown on click | +| `` ```motoko run `` | Same as bare but auto-runs on page load | +| `` ```motoko no-repl `` | Syntax highlighting only; no button | +| `` ```motoko name=X `` | Saves block as `X.mo` so other blocks can `include=X` it | +| `` ```motoko include=X,Y `` | Runs `X.mo`, `Y.mo` as context before executing this block | +| `` ```motoko _include=X `` | Like `include=X` but the included code is not shown | + +This site uses Astro + Starlight with the Expressive Code syntax highlighter. +**No REPL or interpreter exists on this site.** Expressive Code silently ignores +all unrecognised meta flags. This has been verified in the built HTML output: +the `figcaption` for a `name=int` block is empty, no Run button is injected, and +the code renders as plain syntax-highlighted Motoko — indistinguishable from a +`no-repl` block. + +**Distribution in the sections this site syncs** (counted against the source): + +| Section | `no-repl` | bare `motoko` | `name=X` | `_include=X` | `run` / `include=` | +|---|---|---|---|---|---| +| `fundamentals/` | 216 | 97 | ~15 (8 files) | ~5 (2 files) | 0 | +| `icp-features/` | 20 | 8 | 0 | 0 | 0 | +| `language-manual.md` | 1 | 19 | 0 | 0 | 0 | +| **Total synced** | **237** | **124** | **~15** | **~5** | **0** | + +The `run` and `include=` (without underscore) flags — the most REPL-intensive — do +not appear in any of the synced sections. They exist only in `core/` (35 files), +`base/` (25 files), and `old/` — all of which are deliberately excluded from sync. + +**The `name=` blocks that appear in `fundamentals/`** are standalone, complete +examples that each make sense on their own. The `name=` label was only meaningful +to the REPL cross-reference mechanism; on this site it does nothing. Examples: +`name=int` labels the `Int.toText` snippet, `name=List` labels a recursive list +type definition, `name=max` labels a generic max function. + +**The `_include=X no-repl` blocks** show a usage example of a named block without +re-executing it. The `_include=` part is a no-op without the REPL; `no-repl` is +already the correct flag for this site. + +**The bare `` ```motoko `` blocks** (97 in `fundamentals/`, 8 in `icp-features/`, +19 in `language-manual.md`) implicitly had a Run button in the portal. On this +site they render identically to `no-repl` blocks — Expressive Code ignores the +missing flag. However, they signal intent incorrectly to anyone reading the source. + +### 8. Internal relative links use numeric-prefixed paths + +Every relative cross-reference in the source uses the current numeric-prefixed +directory and file names. For example, from `fundamentals/3-types/14-subtyping.md`: + +```markdown +[immutable arrays (`[T]`)](../3-types/8-immutable-arrays.md) +[mutable arrays](../3-types/9-mutable-arrays.md) +[functions](../3-types/3-functions.md) +``` + +And from top-level fundamentals files like `0-hello-world.md`: + +```markdown +[actor](../fundamentals/2-actors/1-actors-async.md) +[stable variable](../fundamentals/3-types/13-stable-types.md) +``` + +After the directory and file renames in Proposed Change §1, all of these paths +become invalid. The consuming site's post-processor (`postprocess-motoko.mjs`) +currently rewrites every relative link by stripping numeric prefixes and doing a +slug-index lookup. For a transform-free sync, the upstream must update all +relative links to reflect the post-rename paths. + +In the sections this site syncs, **~146 relative links across ~20 files** use +numeric-prefixed paths. The affected files are concentrated in `fundamentals/` +(subdirs `types/`, `actors/`, `declarations/`, `control-flow/`, `basic-syntax/` +and top-level standalone files) and `reference/1-error-codes.md`. + +**Content quality issue to fix during this pass:** `fundamentals/1-basic-syntax/3-printing-values.md` +links to `../3-types/3-functions.md` (post-rename: `types/function-types.md`) using +the link text "pure functions". However, `function-types.md` has no heading or +anchor for "pure functions" — the concept is only implicit in the "## Local functions" +section. When updating this link's path in Change §8, also fix the link destination: +either add a `{#pure-functions}` anchor inside `function-types.md` (preferred — makes +the concept explicit) or point to `function-types.md#local-functions` and adjust the +link text to "local functions". Without this fix, readers who click "pure functions" +land at the top of `function-types.md` with no indication where the concept is. + +### 9. `changelog.mdx` contains a Docusaurus `md reference` block + +`doc/md/reference/3-changelog.mdx` contains: + +```` +```md reference +https://github.com/caffeinelabs/motoko/blob/master/Changelog.md +``` +```` + +This is a Docusaurus-specific directive that fetches the content of +`Changelog.md` from GitHub at build time. It has no equivalent in Starlight or +standard Markdown — the page renders blank on this site (except for the title) +unless the post-processor inlines the content at sync time. + +The post-processor currently reads `Changelog.md` from the pinned submodule +(`./sources/motoko/Changelog.md`) and inlines it. This works but creates a +dependency on postprocess-motoko.mjs for what should be a simple file copy. + +`Changelog.md` is 2474 lines and grows with every release. The consumer site +is pinned to a specific submodule commit. If the changelog content lived +directly in `doc/md/reference/changelog.md` at the same commit, there can be +no drift: the file always reflects exactly the entries up to that release. + +### 10. `motoko-tooling` links in `comments.md` + +`doc/md/fundamentals/1-basic-syntax/10-comments.md` links to the `motoko-tooling/` +section (excluded from sync) via two relative paths: + +```markdown +[mo-doc](../../motoko-tooling/3-mo-doc.md) +``` + +The `motoko-tooling/` section covers: Canpack, dev containers, mo-doc, and the +Motoko VS Code extension. It is excluded from sync because it uses `dfx` commands +(banned in developer-docs) and contains Docusaurus JSX (`import Tabs`). + +The post-processor previously rewrote these links to `https://docs.motoko.org`, +which does not exist. This is now fixed: the postprocessor redirects both +`motoko-tooling/` relative paths and the `docs.motoko.org` domain to the +internal developer-docs page at `/developer-tools/#mo-doc`. + +--- + +## Proposed changes to `caffeinelabs/motoko` + +### 1. Remove numeric prefixes from all directories and files + +> **Optional for the current sync.** `sync-motoko.sh` already strips numeric +> prefixes via `strip_num()` and handles the one slug collision +> (`types/functions.md` → `function-types.md`) with an explicit rename rule. +> §1 is only *required* if the goal is a fully transform-free rsync with no +> post-processing at all. If the Motoko team prefers to keep numbers for local +> navigation clarity, they can skip §1 and §8 entirely — the sync handles both +> automatically. The remaining 9 changes (§2–§7, §9–§11) are independent of +> whether files are numbered. + +Change the directory structure from: + +``` +doc/md/ + 12-base-core-migration.md + 14-style.md + 15-compiler-ref.md + 16-language-manual.md + fundamentals/ + 0-hello-world.md + 1-basic-syntax/ + 1-defining-an-actor.md + 8-functions.md + 3-types/ + 3-functions.md ← rename to function-types.md to resolve slug collision + ... +``` + +to: + +``` +doc/md/ + base-core-migration.md + style-guide.md ← also rename style.md → style-guide.md for clarity + compiler-ref.md + language-manual.md + fundamentals/ + hello-world.md + basic-syntax/ + defining-an-actor.md + functions.md + types/ + function-types.md ← renamed to avoid collision with basic-syntax/functions.md + ... +``` + +Files that currently share a basename after prefix-stripping need distinct names +(the one collision today is `types/functions.md` vs `basic-syntax/functions.md`; +proposed rename: `types/function-types.md`). + +`fundamentals/2-actors/6-orthogonal-persistence/index.md` must be renamed to +`overview.md` (not just stripped of its prefix). Unlike the other `index.md` files +in `fundamentals/` subdirs — which are Docusaurus navigation pages replaced by +metadata stubs in §11 — this file contains real overview content comparing both +persistence modes. Renaming it to `overview.md` distinguishes it as a content page +rather than an ordering stub. + +### 2. Replace `sidebar_position` with Starlight-native `sidebar.order` + +In every file, replace: + +```yaml +--- +sidebar_position: 8 +--- +``` + +with: + +```yaml +--- +sidebar: + order: 8 +--- +``` + +This allows `icp-features/` and `reference/` to use Starlight `autogenerate`. +`fundamentals/` must stay as an explicitly listed sidebar (see below for why). + +**Section-specific notes:** + +`icp-features/` — flat structure, autogenerate works. `sidebar_position` maps +directly to `sidebar.order` 1–1. `icp-features/7-view-queries.md` has no +`sidebar_position`; add `sidebar: { order: 7 }` to fix. + +`reference/` — after the rename, all six files share one directory but come from +two different legacy position namespaces (reference/ subdir had 1–3; top-level +files had 14–16). Mechanical substitution gives the wrong order. The six files +must be renumbered to match the desired display order: + +| File (post-rename) | Old `sidebar_position` | Correct `sidebar.order` | +|---|---|---| +| `language-manual.md` | 16 | 1 | +| `error-codes.md` | 1 | 2 | +| `motoko-grammar.md` | 2 | 3 | +| `style-guide.md` | 14 | 4 | +| `compiler-ref.md` | 15 | 5 | +| `changelog.md` | 3 | 6 | + +`fundamentals/` — **cannot use autogenerate** without the subdir `index.md` +ordering stubs from Change §11. After removing numeric prefixes, subdirectory +names sort alphabetically: `actors`, `basic-syntax`, `control-flow`, `declarations`, +`types` — but the desired display order is `basic-syntax`, `actors`, `types`, +`declarations`, `control-flow`. Starlight overrides alphabetical directory order +only via `sidebar.order` in a directory's `index.md`. Change §11 adds these +stubs; the new sync uses `--exclude='/index.md'` (anchored to the transfer root), +which keeps the subdir stubs while dropping only the top-level +`fundamentals/index.md` section landing page. + +**Without Change §11:** keep the explicit `sidebar-motoko.mjs` enumeration. +**With Change §11 (recommended):** switch `fundamentals/` to `autogenerate` and +delete `sidebar-motoko.mjs`. + +`actors/` duplicate values — both `4-compatibility.md` and `5-messaging.md` +carry `sidebar_position: 4`. Fix so values are unique and match the numeric +filename order. + +**Add `title:` and `description:` frontmatter to every file, and remove the H1 +heading from the body.** Starlight requires `title:` as a schema field — without +it the build fails. All 68 synced upstream files currently carry `# Title` as an +H1 heading (Docusaurus convention) but have no `title:` in frontmatter. The +developer-docs postprocessor currently bridges this by extracting the H1 as +`title:` and adding a generic `description: "Motoko language documentation"` +fallback. Moving this into the upstream source eliminates that extraction step and +is a prerequisite for the symlink approach. + +The `title:` value is derived from the existing H1 heading. `description:` should +be a genuine one-line summary for each page; the postprocessor's generic fallback +is acceptable as a placeholder during the transition. + +After adding `title:` frontmatter, remove the `# Title` H1 from the body — Starlight +renders the page heading from `title:` frontmatter and would show it twice otherwise. + +Three files have no frontmatter at all: + +- `fundamentals/2-actors/7-mixins.md` — add `title`, `description`, and `sidebar: { order: 7 }` +- `fundamentals/10-contextual-dot.md` — add `title`, `description`, and `sidebar: { order: N }` +- `fundamentals/11-implicit-parameters.md` — add `title`, `description`, and `sidebar: { order: N }` + +### 3. Use `` paths for file-embed blocks + +Replace Docusaurus-relative paths in file-embed blocks: + +```` +```motoko file=../examples/counter.mo +```motoko file=../../examples/todo-error.mo#L49-L58 +``` +```` + +with the `` placeholder: + +```` +```motoko file=/counter.mo +```motoko file=/todo-error.mo#L49-L58 +``` +```` + +`` is a path placeholder recognised by the `remark-include-file` +build plugin on `docs.internetcomputer.org`. It resolves to +`.sources/motoko/doc/md/examples/` — the examples directory inside the pinned +`caffeinelabs/motoko` submodule — at Astro build time. This means: + +- Examples are always live: the plugin reads from the pinned submodule at build + time, so a submodule bump automatically picks up updated examples. +- No sync-time processing: the path rewrite that `postprocess-motoko.mjs` + currently performs (`../examples/` → `/`) will become a + no-op once the upstream source uses `` paths directly, and + can then be removed from the postprocess script. +- `#L-L` line-range suffixes are supported as-is; the plugin slices + the specified lines and raises a hard build error if the range is out of bounds. + +This is a mechanical search-and-replace in the upstream source: +```bash +# In caffeinelabs/motoko — replace all relative example paths +find doc/md -name '*.md' -o -name '*.mdx' | \ + xargs sed -i 's|file=\(\.\./\)*examples/|file=/|g' +``` + +### 4. Replace `./core/` and `./base/` links with mops.one URLs, then remove those directories + +A core maintainer confirmed: "I'd honestly prefer that. Mops docs should be the +single source of truth." — mops.one is the intended canonical home for `mo:core` +library docs. This makes the link replacement + directory removal the actively +desired outcome, not just a side-effect. + +**Step 1 — replace links:** Replace all `./base/.md` and +`./core/.md` links with `https://mops.one/core/docs/`. The +module name matches the source file name exactly; the mapping is mechanical. + +```markdown +[Map](./core/Map.md) → [Map](https://mops.one/core/docs/Map) +[Bool](./base/Bool.md) → [Bool](https://mops.one/core/docs/Bool) +``` + +**Step 2 — remove `doc/md/core/` and its CI generation step:** Once all +`./core/.md` links are replaced, the auto-generated `doc/md/core/` +directory (49 files) is no longer needed and should be deleted. The CI step +that runs `mo-doc` to generate those files from `caffeinelabs/motoko-core` can +be dropped at the same time. This removes a CI dependency and keeps the doc tree +clean. + +**Step 3 — consider removing `doc/md/base/`:** `mo:base` is deprecated in +favour of `mo:core`. Once `./base/.md` links are replaced with mops.one +URLs, the `doc/md/base/` directory is also redundant and can be removed. + +The mops.one URL pattern uses the exact module name: `https://mops.one/core/docs/Map`, +`https://mops.one/core/docs/List`, etc. The module name matches the source file +name in `caffeinelabs/motoko-core/src/.mo` exactly, so the mapping is +mechanical and stable across releases. + +### 5. Use `docs.internetcomputer.org` internal paths + +Replace all `internetcomputer.org/docs/...` links with the canonical +developer-docs paths (relative or absolute using `docs.internetcomputer.org`). +The mapping for common links: + +All `internetcomputer.org/docs/...` URLs currently in the synced source files +(verified against source at time of writing), with specific section anchors +wherever the target page has a matching section: + +| Old portal URL | Current developer-docs path | +|---|---| +| `building-apps/essentials/canisters` | `/concepts/canisters` | +| `building-apps/essentials/message-execution` | `/references/message-execution-properties` | +| `building-apps/interact-with-canisters/update-calls` | `/concepts/canisters#update-calls` | +| `building-apps/interact-with-canisters/query-calls` | `/concepts/canisters#query-calls` | +| `building-apps/interact-with-canisters/query-calls#composite-queries` | `/concepts/canisters#composite-queries` | +| `building-apps/interact-with-canisters/candid/candid-concepts` | `/guides/canister-calls/candid` | +| `building-apps/interact-with-canisters/candid/using-candid` | `/guides/canister-calls/candid` | +| `building-apps/interact-with-canisters/agents/overview` | `/guides/canister-calls/calling-from-clients` | +| `building-apps/canister-management/upgrade` | `/guides/canister-management/lifecycle#upgrade-a-canister` | +| `building-apps/canister-management/snapshots` | `/guides/canister-management/snapshots` | +| `building-apps/canister-management/storage` | `/concepts/orthogonal-persistence` | +| `building-apps/canister-management/storage#heap-memory` | `/concepts/orthogonal-persistence#heap-wasm-linear-memory` | +| `building-apps/canister-management/storage#stable-memory` | `/concepts/orthogonal-persistence#stable-memory` | +| `building-apps/canister-management/storage#motoko-storage-handling` | `/concepts/orthogonal-persistence#motoko-true-orthogonal-persistence` | +| `building-apps/canister-management/resource-limits` | `/guides/canister-management/large-wasm` | +| `building-apps/network-features/periodic-tasks-timers` | `/guides/backends/timers` | +| `building-apps/network-features/periodic-tasks-timers#timers` | `/guides/backends/timers#recurring-timers` | +| `building-apps/network-features/randomness` | `/guides/backends/randomness` | +| `references/async-code` | `/references/message-execution-properties` | +| `references/ic-interface-spec` | `/references/ic-interface-spec/` | +| `references/ic-interface-spec#ic-raw_rand` | `/references/ic-interface-spec/management-canister#ic-raw_rand` | +| `references/ic-interface-spec#global-timer` | `/references/ic-interface-spec/canister-interface#global-timer` | +| `references/ic-interface-spec#system-api-inspect-message` | `/references/ic-interface-spec/canister-interface#system-api-inspect-message` | +| `references/ic-interface-spec#heartbeat` | `/references/ic-interface-spec/canister-interface#heartbeat` | +| `references/candid-ref` | `/references/candid-spec` | +| `references/system-canisters/management-canister` | `/references/management-canister` | + +Notes on anchored entries: +- The ic-interface-spec is split across multiple pages on developer-docs. Old + portal anchors map to specific sub-files. `#heartbeat` has no explicit + `{#heartbeat}` attribute in `canister-interface.md` — Starlight auto-generates + the slug `heartbeat` from the `#### Heartbeat` heading, so the link resolves. +- `building-apps/canister-management/storage` (with and without fragments) maps + to `/concepts/orthogonal-persistence`. The old portal anchors differ: `#heap-memory` + → `#heap-wasm-linear-memory`, `#motoko-storage-handling` → `#motoko-true-orthogonal-persistence`, + `#stable-memory` is an exact match. The postprocessor handles these with explicit + anchored entries in the rewrite map and tries the full URL (with anchor) before + stripping — entries without anchors act as a fallback for bare URLs. +- `building-apps/canister-management/logs` and `building-apps/security/iam/` + appeared in an earlier version of the source but are no longer present. No + action needed for those two. + +**developer-docs side — postprocessor update when §5 lands:** the current +`externalToInternal` map in `postprocess-motoko.mjs` handles the old +`internetcomputer.org/docs/...` pattern. After §5 replaces those with +`docs.internetcomputer.org/...` paths, add a general prefix rule to the map: +```javascript +['docs.internetcomputer.org/', '/'] +``` +This single entry rewrites all `docs.internetcomputer.org/` links to +root-relative `/` internal paths, replacing the entire set of specific +entries above. Remove the `internetcomputer.org/docs/...` entries at the same +time — they will no longer appear in the upstream source. + +### 6. Use Starlight-native aside types + +Replace Docusaurus-only aside types with their Starlight equivalents: + +- `:::info` → `:::note` (both are supported by Docusaurus; no effect on the Docusaurus site) +- `:::warn` → `:::caution` (same: Docusaurus supports both). **Do not change `:::warning`** (full word) — it is already a valid Starlight type and renders correctly on both sites. +- `:::info [LinkText](url)` → `:::note[LinkText]` (strip URL from title; link text becomes plain-text title) + +### 7. Normalize REPL meta flags to `no-repl` + +The REPL meta flags are Docusaurus-specific and have no effect on this site (see +Problem §7). Cleaning them up makes the source readable without assuming any +REPL infrastructure: + +- **Bare `` ```motoko ``** → `` ```motoko no-repl ``: the implicit Run button + no longer exists; `no-repl` makes the intent explicit. Scope: all files in the + sections this site syncs (`fundamentals/`, `icp-features/`, `language-manual.md`). + This is safe for the Docusaurus site too — Docusaurus renders bare `motoko` + and `no-repl` identically when no REPL component is mounted. + +- **`` ```motoko name=X ``** → `` ```motoko no-repl ``: the `name` label has no + purpose without the REPL. The code itself is a self-contained example and + should render as a static block. Applies to all `name=X` blocks in the synced + sections (~15 occurrences in 8 files under `fundamentals/`). + +- **`` ```motoko name=X no-repl ``** → `` ```motoko no-repl ``: strip the unused + `name=X` attribute, keep `no-repl`. + +- **`` ```motoko _include=X no-repl ``** → `` ```motoko no-repl ``: strip the + `_include=X` attribute (it was a no-op display hint for the REPL; the block + already carries `no-repl`). Applies to ~5 occurrences in `fundamentals/`. + +- **`` ```motoko run ``**: not present in any synced section — no action needed. + Only appears in `core/` and `base/` which are excluded from sync. + +- **`` ```motoko include=X ``** (without underscore): not present in any synced + section — no action needed. + +**Important:** a significant portion of code fences in the source use +`` ``` motoko `` (with a space between the backticks and the language name), +not `` ```motoko ``. This space variant must be normalised first, otherwise +the subsequent `sed` commands that anchor to `^```motoko` will miss those blocks. + +This cleanup can be done with the following targeted commands, scoped to the +sections this site syncs: + +```bash +# In caffeinelabs/motoko — scoped to synced sections only +# (do NOT apply to core/, base/, old/ — they have active REPL usage) + +SYNCED_DIRS="doc/md/fundamentals doc/md/icp-features doc/md/reference" +SYNCED_TOP="doc/md/16-language-manual.md doc/md/14-style.md doc/md/15-compiler-ref.md doc/md/12-base-core-migration.md" + +# Step 1: normalise the space-before-language variant (``` motoko → ```motoko) +# This is required first so the patterns below can match consistently. +for dir in $SYNCED_DIRS; do + find "$dir" \( -name '*.md' -o -name '*.mdx' \) \ + | xargs sed -i 's/^``` motoko/```motoko/g' +done +sed -i 's/^``` motoko/```motoko/g' $SYNCED_TOP + +# Step 2: bare ```motoko → ```motoko no-repl +for dir in $SYNCED_DIRS; do + find "$dir" \( -name '*.md' -o -name '*.mdx' \) \ + | xargs sed -i 's/^```motoko$/```motoko no-repl/' +done +sed -i 's/^```motoko$/```motoko no-repl/' $SYNCED_TOP + +# Step 3: strip name=X attribute (with or without no-repl) +for dir in $SYNCED_DIRS; do + find "$dir" \( -name '*.md' -o -name '*.mdx' \) \ + | xargs sed -i 's/^```motoko\(.*\) name=[^ ]*/```motoko\1/g' +done + +# Step 4: strip _include=X attribute (always paired with no-repl) +for dir in $SYNCED_DIRS; do + find "$dir" \( -name '*.md' -o -name '*.mdx' \) \ + | xargs sed -i 's/ _include=[^ ]*//g' +done +``` + +`no-repl` is already recognised by both Docusaurus (disables the Run button) and +this site (syntax highlighting only). The cleanup is a safe no-op for the +Docusaurus site. + +### 8. Update all internal relative links to use post-rename paths + +> **Only needed if §1 is done.** If numeric prefixes are kept, skip this +> section — `postprocess-motoko.mjs` already rewrites all numeric-prefixed +> relative links via its `syncRenames` map and slug-index lookup. + +After the directory and file renames in Change §1, every relative cross-reference +in the source that uses numeric-prefixed path components must be updated. This +applies to ~146 links across ~20 files in the synced sections. + +The pattern is mechanical: strip the numeric prefix from each path component in +relative links, and apply the special renames from Change §1 (`3-functions.md` → +`function-types.md`, `index.md` → `overview.md`, `14-style.md` → `style-guide.md`). + +Examples of required rewrites: + +| Before | After | +|---|---| +| `../3-types/8-immutable-arrays.md` | `../types/immutable-arrays.md` | +| `../2-actors/1-actors-async.md` | `../actors/actors-async.md` | +| `../fundamentals/3-types/13-stable-types.md` | `./types/stable-types.md` | +| `../fundamentals/2-actors/6-orthogonal-persistence/enhanced.md` | `./actors/orthogonal-persistence/enhanced.md` | +| `../5-control-flow/5-switch.md` | `../control-flow/switch.md` | + +This step **must be completed alongside Change §1** — the renames and link +updates form one atomic change. A broken intermediate state (files renamed but +links not yet updated) would prevent the Docusaurus site from building. + +There is no single `sed` command for this — the correct replacement depends on +each link's context (depth in the tree, target file, special renames). The +recommended approach is to run the renames first, then use a link-checker to +enumerate broken links, and update each one. The consuming site's +`postprocess-motoko.mjs` contains the full mapping table in `syncRenames` and +the slug index logic, which can serve as a reference for the expected post-rename +paths. + +### 9. Replace the `changelog.mdx` Docusaurus `md reference` block + +`doc/md/reference/3-changelog.mdx` (after prefix removal: `reference/changelog.mdx`) +contains the following Docusaurus-specific directive that has no standard Markdown +equivalent: + +```` +```md reference +https://github.com/caffeinelabs/motoko/blob/master/Changelog.md +``` +```` + +Docusaurus fetches the content of `Changelog.md` from GitHub and renders it +inline. Starlight and standard Markdown processors ignore this block entirely, +leaving the changelog page blank except for the frontmatter title. + +The post-processor currently handles this by reading `Changelog.md` from the +pinned submodule (`.sources/motoko/Changelog.md`) and inlining its full contents. + +There is no need to copy `Changelog.md` — it already exists at exactly the right +version in the submodule root at the pinned commit. The fix has two parts: + +**developer-docs side (already done with this PR):** `remark-include-file` now +supports inline markdown inclusion. A code fence with language `md` and a `file=` +attribute is replaced with the parsed AST of the referenced file, so the content +renders as prose (headings, lists, etc.), not as a code block. The new +`` placeholder resolves to `.sources/motoko/` at build time. + +**Upstream fix:** replace the `md reference` block with a single inline include +directive and rename the file from `changelog.mdx` to `changelog.md`: + +```markdown +--- +title: "Changelog" +description: "Motoko compiler changelog" +sidebar: + order: 3 +--- + +```md file=/Changelog.md +``` +``` + +(The `` placeholder is developer-docs-specific and is a no-op on +the Docusaurus site — Docusaurus ignores unknown code fence attributes and will +render this as an empty fenced block. The Docusaurus site can keep its `md reference` +block separately, or the two directives can coexist in the same file since only one +will be processed at a time depending on the build environment.) + +The post-processor's changelog inlining step can be removed once the upstream +adopts this. The `changelog.mdx` file can be renamed `changelog.md` at the same +time (the MDX extension was only needed for the `md reference` directive). + +### 10. Replace `motoko-tooling` links with a valid URL + +`doc/md/fundamentals/1-basic-syntax/10-comments.md` (after rename: +`fundamentals/basic-syntax/comments.md`) contains two links to the +`motoko-tooling/` section, which is excluded from sync: + +```markdown +[mo-doc](../../motoko-tooling/3-mo-doc.md) +``` + +These appear twice: once inline in the text (line 17) and once in a "See also" +list (line 49). + +The post-processor previously rewrote these to `https://docs.motoko.org`, which +does not exist. This is now fixed: both `motoko-tooling/` relative paths and the +`docs.motoko.org` domain redirect to `/developer-tools/#mo-doc`. + +**Upstream fix:** replace both occurrences with the developer-docs mo-doc page: + +```markdown +[mo-doc](https://docs.internetcomputer.org/developer-tools/#mo-doc) +``` + +**developer-docs side (done):** `docs/developer-tools/index.md` now has a +dedicated `### mo-doc` section covering what it does, how to install it from the +Motoko compiler tarball, and usage examples. The `motoko-tooling/` section +remains excluded from sync because it still contains `dfx` commands and +Docusaurus JSX — see the note on `dfx` references below. + +--- + +## Known content issues — outside the sync scope + +The items below are content quality issues found in synced files. They are upstream +problems that cannot be fixed on the developer-docs side (synced files must not be +edited directly). They should be addressed in a separate upstream PR, independent +of the sync reorganization effort. + +### `dfx` references in prose + +Several synced files contain `dfx` and `dfx.json` references in prose and code +examples: `compatibility.md`, `data-persistence.md`, +`orthogonal-persistence/classical.md`, `orthogonal-persistence/enhanced.md`, +`modules-imports.md`, and `reference/changelog.md` (historical entries). + +Upstream PR [caffeinelabs/motoko#6069](https://github.com/caffeinelabs/motoko/pull/6069) +is a first attempt at replacing these. **It should not be merged before the sync +reorganization PR (§1–§11) lands**: §1 renames files, so #6069's branch needs to +be rebased on the post-reorganization state and extended with any remaining `dfx` +references before merging. Em-dash fixes (see below) can be included in the same +follow-up PR. + +### Em-dashes in prose + +`enhanced-multi-migration.md` and `compatibility.md` contain em-dashes in body +prose. Em-dashes are banned in developer-docs content. These should be replaced +with colons, semicolons, or commas in the upstream source. + +--- + +## What the sync becomes after these changes + +With the above changes in place, `sync-motoko.sh` reduces to a plain file copy: + +```bash +rsync -r --delete .sources/motoko/doc/md/fundamentals/ docs/languages/motoko/fundamentals/ +rsync -r --delete .sources/motoko/doc/md/icp-features/ docs/languages/motoko/icp-features/ +rsync -r --delete .sources/motoko/doc/md/reference/ docs/languages/motoko/reference/ +cp .sources/motoko/doc/md/language-manual.md docs/languages/motoko/reference/language-manual.md +cp .sources/motoko/doc/md/style-guide.md docs/languages/motoko/reference/style-guide.md +cp .sources/motoko/doc/md/compiler-ref.md docs/languages/motoko/reference/compiler-ref.md +cp .sources/motoko/doc/md/base-core-migration.md docs/languages/motoko/base-core-migration.md +``` + +No exclude flags needed: upstream deletes `_category_.yml` files (§11) and the +top-level section `index.md` nav pages as part of the Docusaurus cleanup. + +### Symlink alternative + +Once all upstream changes are in place, the copy step could be replaced entirely +with committed symlinks: + +``` +docs/languages/motoko/fundamentals → ../../.sources/motoko/doc/md/fundamentals +docs/languages/motoko/icp-features → ../../.sources/motoko/doc/md/icp-features +docs/languages/motoko/reference → ../../.sources/motoko/doc/md/reference +``` + +Astro follows symlinks (the site already uses them for `src/content/docs/`), so +this works. Bumping the submodule is the entire update — no sync script runs. + +**The copy approach is preferred.** Three reasons: + +1. **Internal links**: the postprocessor converts `docs.internetcomputer.org/` + absolute URLs to root-relative `/` internal paths. Internal paths are + validated at Astro build time, work in local dev (`npm run dev`), and work in + preview deployments. Symlinks leave these as absolute external URLs, which skip + build-time validation and always point to production regardless of environment. +2. **Anchor routing**: the postprocessor maps old portal anchor slugs to the + correct developer-docs sub-page (e.g. `#global-timer` → + `canister-interface#global-timer`). Upstream cannot encode this mapping — + it requires knowledge of the developer-docs structure that lives here. +3. **Auditability**: every submodule bump produces a reviewable `git diff` showing + exactly what changed in the docs. With symlinks, content changes are invisible + in this repo. + +`postprocess-motoko.mjs` can be deleted entirely once §2 is fully completed +upstream, including adding `title:` and `description:` frontmatter to every file +and removing the `# Title` H1 heading from the body. Without `title:` in the +upstream frontmatter, Starlight's build schema validation fails; this is a hard +prerequisite for the symlink approach. + +Once §2 lands, the postprocessor's H1-extraction step becomes a no-op and the +remaining tasks split by approach: + +- **Copy approach (preferred for auditability):** the postprocessor rewrites + `docs.internetcomputer.org/` links to root-relative `/` internal + links. Every submodule bump produces a reviewable `git diff`. +- **Symlink approach:** `docs.internetcomputer.org/` links remain as absolute + external URLs pointing to the consumer site itself (self-referential but + acceptable). Bumping the submodule is the entire update. + +In both cases, `` paths are handled by `remark-include-file` at +build time — no sync-time file expansion is needed. + +`sidebar.mjs` changes after the upstream PR: +- `icp-features/` — switch to `autogenerate: { directory: "languages/motoko/icp-features" }`. + Already autogenerated today; no change to this block. +- `reference/` — switch to `autogenerate: { directory: "languages/motoko/reference" }`. + Correct because all six files will have sequential `sidebar.order` 1–6. +- `fundamentals/` — switch to `autogenerate: { directory: "languages/motoko/fundamentals" }` + once Change §11 lands. The subdir `index.md` stubs copied by the anchored + `--exclude='/index.md'` carry the `sidebar.order` values Starlight needs to + override alphabetical sort. Delete `sidebar-motoko.mjs` at the same time. + +--- + +## Migration path + +**developer-docs side (already done):** +- `remark-include-file` supports `` and `#L-L` ranges. +- `postprocess-motoko.mjs` rewrites `../examples/` → `/` at + sync time as a bridge until the upstream adopts the placeholder directly. + +**upstream side (one PR in `caffeinelabs/motoko`):** + +**Required (fix rendering/content bugs in the consumer site):** §2, §3, §4, §5, §6, §9, §10 +**Required for `fundamentals/` autogenerate (eliminates manual sidebar maintenance):** §11 +**Optional — only needed for a fully transform-free rsync:** §1 + §8 (do both or neither) +**Optional cleanup (silently handled today):** §7 +_(Note: §4 also includes removing `doc/md/core/`, `doc/md/base/`, and the CI generation step once links are replaced — confirmed as desired by a core maintainer.)_ + +1. Remove numeric prefixes from all directories and files (including top-level + `14-style.md` → `style-guide.md`, `15-compiler-ref.md` → `compiler-ref.md`, + `16-language-manual.md` → `language-manual.md`, + `12-base-core-migration.md` → `base-core-migration.md`). + Rename `fundamentals/2-actors/6-orthogonal-persistence/index.md` → + `overview.md` to distinguish it as a content page from the ordering stubs + added in step 11. +2. Replace `sidebar_position: N` with `sidebar: { order: N }` in every file. + Fix duplicate `sidebar_position` values in `2-actors/`. Add `sidebar_position` + to `icp-features/7-view-queries.md` (currently missing). Add complete + frontmatter (`title`, `description`, `sidebar_position`) to `7-mixins.md`, + `10-contextual-dot.md`, and `11-implicit-parameters.md` (currently have none). +3. Replace `file=../examples/` (and `file=../../examples/`) with + `file=/` throughout — one `sed` command covers all cases. +4. Replace `./base/.md` and `./core/.md` links with + `https://mops.one/core/docs/`. +5. Replace `internetcomputer.org/docs/...` links using the mapping table above. +6. Replace `:::info` → `:::note` and `:::warn` → `:::caution` throughout. + Do NOT change `:::warning` (full word) — it is already valid in Starlight. + Strip URLs from aside titles that use a markdown link as the title + (`:::info [LinkText](url)` → `:::note[LinkText]`). +7. Normalize REPL meta flags in `fundamentals/`, `icp-features/`, `reference/`, + and the four top-level synced files: normalise space variant + (`` ``` motoko `` → `` ```motoko ``); bare `` ```motoko `` → `` ```motoko no-repl ``; + strip `name=X` and `_include=X` attributes (use `no-repl` instead). +8. Update all ~146 internal relative links to use the post-rename paths (no + numeric prefixes, apply the special renames from step 1). Do this atomically + with the renames — the Docusaurus site must not have broken links at any + intermediate commit. +9. Replace the `md reference` block in `reference/changelog.mdx` with + `` ```md file=/Changelog.md ``` `` plus frontmatter. + Rename `changelog.mdx` → `changelog.md` (MDX was only needed for the + Docusaurus directive). No release automation needed — the file is a static + stub; `Changelog.md` at the same commit is always the correct version. +10. Replace the two `../../motoko-tooling/3-mo-doc.md` links in + `fundamentals/basic-syntax/comments.md` with + `https://docs.internetcomputer.org/developer-tools/#mo-doc`. +11. Replace the `index.md` files in each `fundamentals/` subdirectory with a + metadata-only version containing just `sidebar.order` and `sidebar.label` + frontmatter (no content). Also add a new `fundamentals/actors/index.md` + which currently does not exist. Add `sidebar: { hidden: true }` to + `base-core-migration.md`. These three changes are what allow developer-docs + to switch `fundamentals/` from an explicit sidebar list to `autogenerate`. + See the table below. Without this step, developer-docs must maintain an + explicit fundamentals page list in `sidebar-motoko.mjs` and update it + manually every time a fundamentals page is added or removed. + + | Subdir | Action | `sidebar.order` | + |---|---|---| + | `fundamentals/basic-syntax/` | replace `index.md` with metadata stub | 1 | + | `fundamentals/actors/` | add new `index.md` (currently missing) | 2 | + | `fundamentals/types/` | replace `index.md` with metadata stub | 3 | + | `fundamentals/declarations/` | replace `index.md` with metadata stub | 4 | + | `fundamentals/control-flow/` | replace `index.md` with metadata stub | 5 | + | `base-core-migration.md` | add `sidebar: { hidden: true }` | n/a | + + The metadata stub format: + ```yaml + --- + sidebar: + order: 1 + label: "Basic syntax" + --- + ``` + + The `fundamentals/index.md` (top-level section landing page) is still + excluded by the sync — only subdir `index.md` files are kept. + +**developer-docs side (done in PR 261 — `docs/motoko-sync-fixes`):** +- `remark-include-file` supports `` placeholder and inline markdown + inclusion (`md` language code fence → rendered prose, not a code block). +- `remark-include-file` supports `` and `#L-L` ranges. +- `postprocess-motoko.mjs` rewrites `../examples/` → `/` at + sync time as a bridge until the upstream adopts the placeholder directly. +- `sidebar-motoko.mjs` contains the explicit Motoko sidebar as a transitional + file. It is deleted in the step below once step 11 above lands. + +**developer-docs side (separate PR — do after upstream PR merges):** + +The following changes must NOT be merged until the upstream reorganization PR +has landed and the submodule has been bumped. Merging them early permanently +breaks the automated weekly sync CI (`sync-motoko.yml` runs `npm run sync:motoko` +weekly; it would fail on the structure guard with every new Motoko release until +the upstream changes are in place). + +1. Replace `sync-motoko.sh` with the simplified rsync version shown above. Add a + structure guard at the top: if `$SOURCE_DIR/fundamentals/1-basic-syntax` still + exists (old numeric-prefix layout), exit with a clear error. Once upstream + deletes the top-level section `index.md` files, the `--exclude='index.md'` flags + become no-ops and can be removed. Remove the postprocess call. +2. Delete `postprocess-motoko.mjs`. +3. Delete `sidebar-motoko.mjs`. Replace its import in `sidebar.mjs` with: + ```js + export const motokoSidebar = { + label: "Motoko", + collapsed: true, + autogenerate: { directory: "languages/motoko" }, + }; + ``` + New pages in any section appear automatically. No sidebar config to maintain. + +The Docusaurus site in `caffeinelabs/motoko` is unaffected: Docusaurus ignores +`sidebar.order` and continues to use `_category_.yml` position values. +Both `sidebar_position` and `sidebar.order` can coexist in the same frontmatter +during the transition period. + +--- + +## Appendix: additional decisions + +### If Docusaurus is dropped from the upstream repo + +The motoko team is considering moving away from Docusaurus in `caffeinelabs/motoko`. +If that happens, some of the changes above become simpler or can be deferred: + +- **§2 (sidebar.order)**: If Docusaurus is dropped, `sidebar_position` can be + removed entirely rather than migrated. `sidebar.order` in Starlight frontmatter + remains the right replacement. +- **§6 (aside types)**: Without Docusaurus compatibility to maintain, `:::info` can + simply become `:::note` with no concern about backward breakage on the docs site. +- **§7 (REPL flags)**: `no-repl` is Docusaurus-specific. Without Docusaurus, REPL + flags can be removed entirely rather than normalized. Bare `` ```motoko `` is the + correct form for a static site. +- **§9 (changelog)**: The `md reference` block is Docusaurus-specific and would + need replacing regardless of which framework replaces it. +- **§1, §3, §4, §5, §8, §10**: Framework-independent — required regardless of + which docs tool the upstream uses. + +In practice: proceed with this plan without waiting for a Docusaurus decision. The +changes are safe whether Docusaurus stays or goes. + +### Upstream agent instructions: `_category_.yml` and `index.md` + +The upstream `caffeinelabs/motoko` currently uses two Docusaurus-specific +constructs for sidebar navigation that have no equivalent in Starlight. Both +must be replaced as part of the reorganization (or removed if Docusaurus is +dropped). + +#### `_category_.yml` files + +Each `_category_.yml` defines the label, position, and collapsed state for a +directory in the Docusaurus sidebar. In Starlight, this information goes into +an `index.md` file in the same directory with `sidebar.order` and +`sidebar.label` frontmatter. + +**Mapping for all `_category_.yml` files in the synced sections:** + +| Directory (post-rename) | `_category_.yml` | Action | +|---|---|---| +| `fundamentals/` | `position: 3, label: 'Fundamentals'` | Delete — label comes from `sidebar.mjs` in developer-docs, not from upstream | +| `fundamentals/basic-syntax/` | `position: 2, label: 'Basic syntax'` | Create `index.md` stub with `sidebar: { order: 1, label: "Basic syntax" }` | +| `fundamentals/actors/` | `position: 3, label: 'Actors'` | Create `index.md` stub with `sidebar: { order: 2, label: "Actors" }` | +| `fundamentals/types/` | `position: 4, label: 'Types'` | Create `index.md` stub with `sidebar: { order: 3, label: "Types" }` | +| `fundamentals/declarations/` | `position: 5, label: 'Declarations'` | Create `index.md` stub with `sidebar: { order: 4, label: "Declarations" }` | +| `fundamentals/control-flow/` | `position: 6, label: 'Control flow'` | Create `index.md` stub with `sidebar: { order: 5, label: "Control flow" }` | +| `icp-features/` | `position: 4, label: 'ICP features'` | Delete — label comes from `sidebar.mjs` | +| `reference/` | `position: 13, label: 'Motoko references'` | Delete — label comes from `sidebar.mjs` | + +Note: the Starlight `sidebar.order` values (1–5) for fundamentals subdirs do +not match the Docusaurus `position` values (2–6). The difference is that +Docusaurus counts `hello-world.md` (position 1) as a sibling, while Starlight +uses the subdir `index.md` order only among subdirs. What matters is the +relative order among the five subdirs, not the absolute number. + +The metadata stub format: +```yaml +--- +sidebar: + order: 1 + label: "Basic syntax" +--- +``` +No title, description, or body content. This is a Starlight navigation +control file only. + +After creating the `index.md` stubs, delete every `_category_.yml` in the repo +(they have no meaning outside Docusaurus). + +#### `index.md` files in `fundamentals/` subdirs + +The current `index.md` files in `fundamentals/1-basic-syntax/`, +`fundamentals/3-types/`, `fundamentals/4-declarations/`, and +`fundamentals/5-control-flow/` are Docusaurus section landing pages. Their +content is a numbered list of links to pages in the section — useful in +Docusaurus where the section heading is a clickable link. In Starlight, the +sidebar handles navigation automatically; these pages are not needed. + +**Replace** each of these `index.md` files with the metadata stub described +above (matching the `_category_.yml` values for that directory). The existing +list content is Docusaurus navigation scaffold and can be discarded. + +`fundamentals/2-actors/` currently has no `index.md`. **Create** one with the +stub for order 2 / label "Actors" (the `_category_.yml` position and label). + +**Do NOT touch** `fundamentals/2-actors/6-orthogonal-persistence/index.md` — +this file contains real conceptual content comparing both persistence modes. +It must be **renamed** to `overview.md` (Change §1) to distinguish it as a +content page from the ordering stubs. + +The top-level `fundamentals/index.md`, `icp-features/index.md`, and +`reference/index.md` are Docusaurus section landing pages (nav scaffold with +no Starlight equivalent). **Delete them** as part of the Docusaurus cleanup. + +### `base-core-migration.md` in the sidebar + +`base-core-migration.md` is currently excluded from the sidebar and linked from +the Motoko overview (`docs/languages/motoko/index.md`) only. This is the right +call: `mo:base` has been deprecated for a while and most new developers will never +need the migration guide. Keeping it off the sidebar avoids adding a dead-weight +entry that implies the base library is still relevant. The guide remains fully +discoverable via site search and via the overview link for developers who do need +it. No change recommended. diff --git a/.github/workflows/deploy-ic.yml b/.github/workflows/deploy-ic.yml index cbff567e..2381a968 100644 --- a/.github/workflows/deploy-ic.yml +++ b/.github/workflows/deploy-ic.yml @@ -24,10 +24,10 @@ jobs: steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - name: Initialize examples submodule + - name: Initialize submodules run: | git config --global url."https://github.com/".insteadOf "git@github.com:" - git submodule update --init --depth 1 .sources/examples + git submodule update --init --depth 1 .sources/examples .sources/motoko - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: diff --git a/.github/workflows/preview-deployment.yml b/.github/workflows/preview-deployment.yml index 60d53160..ad99cbdf 100644 --- a/.github/workflows/preview-deployment.yml +++ b/.github/workflows/preview-deployment.yml @@ -15,10 +15,10 @@ jobs: steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 - - name: Initialize examples submodule + - name: Initialize submodules run: | git config --global url."https://github.com/".insteadOf "git@github.com:" - git submodule update --init --depth 1 .sources/examples + git submodule update --init --depth 1 .sources/examples .sources/motoko - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: diff --git a/docs/developer-tools/index.md b/docs/developer-tools/index.md index b8774c00..6cafe7b9 100644 --- a/docs/developer-tools/index.md +++ b/docs/developer-tools/index.md @@ -1,11 +1,11 @@ --- title: "Developer tools" -description: "Overview of the ICP developer toolchain: icp-cli, CDKs, JS SDK, PocketIC, and more" +description: "Overview of the ICP developer toolchain: icp-cli, Motoko, CDKs, JS SDK, PocketIC, and more" sidebar: hidden: true --- -Developer tools are used to create, manage, and interact with canisters. ICP provides tooling across several categories: command-line tools, canister development kits (CDKs), client libraries, testing tools, browser-based IDEs, and Candid tooling. +Developer tools are used to create, manage, and interact with canisters. ICP provides tooling across several categories: command-line tools, Motoko, canister development kits (CDKs), client libraries, testing tools, browser-based IDEs, and Candid tooling. ## Command-line tools @@ -44,18 +44,38 @@ Quill is suited for: Resources: - [Quill GitHub repo](https://github.com/dfinity/quill) -## Canister development kits (CDKs) - -A canister development kit (CDK) provides a programming language with the libraries and toolchain support needed to compile code to WebAssembly and interact with the ICP system API. - -### Motoko +## Motoko -Motoko is ICP's native programming language, designed around the actor model, orthogonal persistence, and asynchronous message passing. It compiles directly to WebAssembly and includes a standard library (`mo:core`) with modules for common data structures, cryptography, and system interaction. +Motoko is ICP's native programming language, designed specifically for the actor model, orthogonal persistence, and asynchronous message passing. It compiles directly to WebAssembly without requiring a separate CDK and includes a standard library (`mo:core`) with modules for common data structures, cryptography, and system interaction. Third-party Motoko libraries are distributed through [Mops](https://mops.one), the Motoko package manager. Use `mops add ` to add a dependency to your project. For language documentation, see [languages/motoko](../languages/motoko/index.md). +### Motoko VS Code extension + +The [Motoko extension for VS Code](https://github.com/caffeinelabs/vscode-motoko) adds Motoko language support to VS Code: syntax highlighting, type checking, auto-completion, and inline diagnostics. Install by searching for "Motoko" in the VS Code extensions panel. + +### mo-doc + +`mo-doc` generates documentation for Motoko source code from `///` doc comments, producing HTML (default), Markdown (`--format plain`), or AsciiDoc (`--format adoc`) output. + +Install: `mo-doc` is bundled inside the Motoko compiler tarball. Download the archive for your platform from the [Motoko releases page](https://github.com/caffeinelabs/motoko/releases), then extract it; the binary is at `bin/mo-doc` inside the archive. + +```bash +# Platform: Darwin-arm64, Darwin-x86_64, Linux-aarch64, Linux-x86_64 +tar xzf motoko--.tar.gz +./bin/mo-doc # HTML output to ./docs +./bin/mo-doc --format plain --output ./api-docs # Markdown output to ./api-docs +./bin/mo-doc --source ./src --output ./out # custom source and output paths +``` + +For how to write doc comments in Motoko source, see [Comments](../languages/motoko/fundamentals/basic-syntax/comments.md). + +## Canister development kits (CDKs) + +A canister development kit (CDK) provides an existing programming language with the libraries and toolchain support needed to compile code to WebAssembly and interact with the ICP system API. + ### Rust CDK (`ic-cdk`) The Rust CDK (`ic-cdk`) is the official DFINITY-maintained library for building canisters in Rust. It exposes the ICP system API as safe Rust abstractions, including: @@ -144,14 +164,6 @@ Limitations: - Projects are limited to 5 MB and 2 canisters - ICP Ninja is not a replacement for icp-cli for production workflows -## Editor tooling - -### Motoko VS Code extension - -The [Motoko extension for VS Code](https://github.com/dfinity/vscode-motoko) (`dfinity/vscode-motoko`) adds Motoko language support to VS Code: syntax highlighting, type checking, auto-completion, and inline diagnostics. - -Install by searching for "Motoko" in the VS Code extensions panel, or visit the [vscode-motoko repository](https://github.com/dfinity/vscode-motoko) for details. - ## Candid tools ### didc @@ -162,7 +174,7 @@ Install: download a prebuilt binary from the [releases page](https://github.com/ Resources: - [Candid GitHub repo](https://github.com/dfinity/candid) -- Candid specification: [candid-spec.md](candid-spec.md) +- Candid specification: [candid-spec.md](../references/candid-spec.md) ## Next steps @@ -170,4 +182,4 @@ Resources: - **Rust development:** [Rust language guide](../languages/rust/index.md) - **Motoko development:** [Motoko language guide](../languages/motoko/index.md) - + diff --git a/docs/guides/backends/data-persistence.mdx b/docs/guides/backends/data-persistence.mdx index a8b14ae5..dcb4e84f 100644 --- a/docs/guides/backends/data-persistence.mdx +++ b/docs/guides/backends/data-persistence.mdx @@ -253,7 +253,7 @@ When upgrading a Motoko canister, the type of every persistent field must be com **Unsafe changes (will trap on upgrade):** - Remove or rename a persistent field -- Change a field's type (e.g., `Nat` → `Int`) +- Change a field's type to an incompatible type (e.g., `Int` → `Float`, or `Nat` → `Text`) - Change a non-optional field to a different type diff --git a/docs/languages/motoko/fundamentals/actors-async.md b/docs/languages/motoko/fundamentals/actors/actors-async.md similarity index 94% rename from docs/languages/motoko/fundamentals/actors-async.md rename to docs/languages/motoko/fundamentals/actors/actors-async.md index ffa27a78..a1594095 100644 --- a/docs/languages/motoko/fundamentals/actors-async.md +++ b/docs/languages/motoko/fundamentals/actors/actors-async.md @@ -4,7 +4,7 @@ description: "Motoko language documentation" title: "Actors & async data" --- -The actor programming model was designed to solve concurrency issues by encapsulating [state](/languages/motoko/fundamentals/state) and computation within independent units called **actors**. +The actor programming model was designed to solve concurrency issues by encapsulating [state](/languages/motoko/fundamentals/actors/state) and computation within independent units called **actors**. The actor model is built on four key principles: @@ -68,35 +68,7 @@ A trap will only revoke changes made since the last commit point. In particular, Consider the following stateful `Atomicity` actor: -```motoko -persistent actor Atomicity { - - transient var s = 0; - transient var pinged = false; - - public func ping() : async () { - pinged := true; - }; - - // an atomic method - public func atomic() : async () { - s := 1; - ignore ping(); - ignore 0/0; // trap! - }; - - // a non-atomic method - public func nonAtomic() : async () { - s := 1; - let f = ping(); // this will not be rolled back! - s := 2; - await f; - s := 3; // this will not be rolled back! - await f; - ignore 0/0; // trap! - }; - -}; +```motoko no-repl file=/atomicity.mo ``` Calling the shared function `atomic()` results in an error because it traps before completing. Since the trap happens before any `await` or return, all changes are discarded. The variable `s` stays at 0, and `pinged` remains false. Even though `atomic()` calls `ping()`, that message is only queued and never sent because no commit point is reached. @@ -108,20 +80,7 @@ Calling `nonAtomic()` also fails with an error, but the state is partially updat Here is an example program that uses async functions: -```motoko -persistent actor Counter { - - var count = 0; - - public shared func inc() : async () { count += 1 }; - - public shared func read() : async Nat { count }; - - public shared func bump() : async Nat { - count += 1; - count; - }; -}; +```motoko file=/counter-actor.mo ``` The `Counter` actor declares one field and three public, shared functions: @@ -257,7 +216,7 @@ In other languages without these features, developers often need to use advanced To demonstrate how asynchronous actors work, consider the following example. -Customers place orders at a pizza restaurant, but the chef can only make one pizza at a time. Orders are taken **[asynchronously](/languages/motoko/fundamentals/actors-async#async--await)**, meaning customers do not have to wait for previous orders to be completed before placing their own. However, each pizza is prepared sequentially. This is representative of an asynchronous actor. +Customers place orders at a pizza restaurant, but the chef can only make one pizza at a time. Orders are taken **[asynchronously](/languages/motoko/fundamentals/actors/actors-async#async--await)**, meaning customers do not have to wait for previous orders to be completed before placing their own. However, each pizza is prepared sequentially. This is representative of an asynchronous actor. ```motoko no-repl import Array "mo:core/Array"; diff --git a/docs/languages/motoko/fundamentals/compatibility.md b/docs/languages/motoko/fundamentals/actors/compatibility.md similarity index 66% rename from docs/languages/motoko/fundamentals/compatibility.md rename to docs/languages/motoko/fundamentals/actors/compatibility.md index d8a4b0a7..a2544354 100644 --- a/docs/languages/motoko/fundamentals/compatibility.md +++ b/docs/languages/motoko/fundamentals/actors/compatibility.md @@ -12,40 +12,20 @@ When upgrading a canister, it is important to verify that the upgrade can procee - Breaking clients due to a Candid interface change. `dfx` checks these properties statically before attempting the upgrade. -Moreover, with [enhanced orthogonal persistence](/languages/motoko/fundamentals/orthogonal-persistence-enhanced), Motoko rejects incompatible changes of stable declarations. +Moreover, with [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced), Motoko rejects incompatible changes of stable declarations. ## Upgrade example The following is a simple example of how to declare a stateful counter: -```motoko -import Debug "mo:core/Debug"; - -persistent actor Counter_v1 { - var state : Nat = 0; // implicitly `stable` - - public func increment() : async () { - state += 1; - Debug.print(debug_show (state)); - }; -}; +```motoko no-repl file=/count-v1.mo ``` Importantly, in this example, when the counter is upgraded, its state is preserved and the counter will resume from its last value before the upgrade. This is because actor variables are by default `stable`, meaning their state is persisted across upgrades. The above actor is equivalent to using an explicit `stable` declaration: -```motoko -import Debug "mo:core/Debug"; - -persistent actor Counter_v1 { - stable var state : Nat = 0; // explicitly `stable` - - public func increment() : async () { - state += 1; - Debug.print(debug_show (state)); - }; -}; +```motoko no-repl file=/count-v1stable.mo ``` Sometime, you won't want an actor field to be preserved, either because it contains a value tied to the current version (say the version number), or @@ -53,17 +33,7 @@ because it has a non-`stable` type that cannot be stored in stable field (an obj In that case, you can declare the field transient: -```motoko -import Debug "mo:core/Debug"; - -persistent actor Counter_v0 { - transient var state : Nat = 0; - - public func increment() : async () { - state += 1; - Debug.print(debug_show (state)); - }; -}; +```motoko no-repl file=/count-v0transient.mo ``` With the `transient` declaration, the state will always restart from `0`, even after an upgrade. @@ -72,17 +42,7 @@ With the `transient` declaration, the state will always restart from `0`, even a Changing counter from `Nat` to `Int` is a compatible change in stable declarations. The counter value is retained during the upgrade. -```motoko -import Debug "mo:core/Debug"; - -persistent actor Counter_v2 { - var state : Int = 0; // promoted from `Nat` to `Int`, implicitly stable - - public func increment() : async () { - state += 1; - Debug.print(debug_show (state)); - }; -}; +```motoko no-repl file=/count-v2.mo ``` ## Stable type signatures @@ -92,42 +52,19 @@ You can think of this as the interior interface of the actor, that it presents t For example, `v1`'s stable types: -```motoko -// Version: 1.0.0 -actor { - stable var state : Nat -}; +```motoko no-repl file=/count-v1.most ``` An upgrade from `v1` to `v2`'s stable types consumes a [`Nat`](https://mops.one/core/docs/Nat) as an [`Int`](https://mops.one/core/docs/Nat), which is valid because `Nat <: Int`, that is, `Nat` is a subtype of `Int`. -```motoko -// Version: 1.0.0 -actor { - stable var state : Int -}; +```motoko no-repl file=/count-v2.most ``` ## Evolving the Candid interface In this extension of the interface, old clients remain satisfied, while new ones get extra features such as the `decrement` function and the `read` query in this example. -```motoko -persistent actor Counter_v3 { - var state : Int = 0; // implicitly `stable` - - public func increment() : async () { - state += 1; - }; - - public func decrement() : async () { - state -= 1; - }; - - public query func read() : async Int { - return state; - }; -}; +```motoko no-repl file=/count-v3.mo ``` ## Dual interface evolution @@ -141,88 +78,41 @@ Consider the following four versions of the counter example: Version `v0` with Candid interface `v0.did` and stable type interface `v0.most`: -```candid -service : { - increment: () -> (); -} +```candid file=/count-v0.did ``` -```motoko -// Version: 1.0.0 -actor { - -}; +```motoko no-repl file=/count-v0.most ``` Version `v1` with Candid interface `v1.did` and stable type interface `v1.most`, -```candid -service : { - increment: () -> (); -} +```candid file=/count-v1.did ``` -```motoko -// Version: 1.0.0 -actor { - stable var state : Nat -}; +```motoko no-repl file=/count-v1.most ``` Version `v2` with Candid interface `v2.did` and stable type interface `v2.most`, -```candid -service : { - increment: () -> (); -} +```candid file=/count-v2.did ``` -```motoko -// Version: 1.0.0 -actor { - stable var state : Int -}; +```motoko no-repl file=/count-v2.most ``` Version `v3` with Candid interface `v3.did` and stable type interface `v3.most`: -```candid -service : { - decrement: () -> (); - increment: () -> (); - read: () -> (int) query; -} +```candid file=/count-v3.did ``` -```motoko -// Version: 1.0.0 -actor { - stable var state : Int -}; +```motoko no-repl file=/count-v3.most ``` ## Incompatible upgrade Let's take a look at another example where the counter's type is again changed, this time from [`Int`](https://mops.one/core/docs/Int) to [`Float`](https://mops.one/core/docs/Float): -```motoko -import Float "mo:core/Float"; - -persistent actor Counter_v4 { - var state : Float = 0.0; // implicitly `stable` - - public func increment() : async () { - state += 0.5; - }; - - public func decrement() : async () { - state -= 0.5; - }; - - public query func read() : async Float { - return state; - }; -}; +```motoko no-repl file=/count-v4.mo ``` This version is neither compatible to stable type declarations, nor to the Candid interface. @@ -231,7 +121,7 @@ This version is neither compatible to stable type declarations, nor to the Candi - The change in the return type of `read` is also not safe. If the change were accepted, then existing clients of the `read` method, that still expect to receive integers, would suddenly start receiving incompatible floats. -With [enhanced orthogonal persistence](/languages/motoko/fundamentals/orthogonal-persistence-enhanced), Motoko actively rejects any upgrades that require type-incompatible state changes. +With [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced), Motoko actively rejects any upgrades that require type-incompatible state changes. This is to guarantee that the stable state is always kept safe. @@ -244,7 +134,7 @@ In addition to Motoko's runtime check, `dfx` raises a warning message for these Motoko tolerates Candid interface changes, since these are more likely to be intentional, breaking changes. :::danger -Versions of Motoko using [classical orthogonal persistence](/languages/motoko/fundamentals/orthogonal-persistence-classical) will drop the state and reinitialize the counter with `0.0`, if the `dfx` warning is ignored. +Versions of Motoko using [classical orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/classical) will drop the state and reinitialize the counter with `0.0`, if the `dfx` warning is ignored. For this reason, users should always heed any compatibility warnings issued by `dfx`. ::: @@ -263,30 +153,7 @@ For this purpose, a user-instructed migration can be done in three steps: While the previous attempt of changing state from [`Int`](https://mops.one/core/docs/Int) to [`Nat`](https://mops.one/core/docs/Nat) was invalid, you now can realize the desired change as follows: -```motoko -import Runtime "mo:core/Runtime"; -import Float "mo:core/Float"; - -persistent actor Counter_v5 { - var state : Int = 0; // implicitly `stable` - var newState : Float = Float.fromInt(state); // implicitly `stable` - - public func increment() : async () { - newState += 0.5; - }; - - public func decrement() : async () { - newState -= 0.5; - }; - - public query func read() : async Int { - Runtime.trap("No longer supported: Use `readFloat`"); - }; - - public query func readFloat() : async Float { - return newState; - }; -}; +```motoko no-repl file=/count-v5.mo ``` To also keep the Candid interface, the `readFloat` has been added, while the old `read` is retired by keeping its declaration and raising a trap internally. @@ -295,61 +162,12 @@ To also keep the Candid interface, the `readFloat` has been added, while the old In versions of Motoko prior to 0.14.6, you could simply remove the old variable or keep it but change the type to `Any`, implying that the variable is no longer useful. -```motoko -import Runtime "mo:core/Runtime"; -import Float "mo:core/Float"; - -persistent actor Counter_v6 { - var newState : Float = 0.0; // implicitly `stable` - - public func increment() : async () { - newState += 0.5; - }; - - public func decrement() : async () { - newState -= 0.5; - }; - - public query func read() : async Int { - Runtime.trap("No longer supported: Use `readFloat`"); - }; - - public query func readFloat() : async Float { - return newState; - }; -}; +```motoko no-repl file=/count-v6.mo ``` For added safety, since version 0.14.6 you can only discard data or promote it to a lossy supertype such as `Any`, using a migration function: -```motoko -import Runtime "mo:core/Runtime"; -import Float "mo:core/Float"; - -(with migration = - func (_ : {var state : Int}) : {} { // discard old state - {} - } -) -persistent actor Counter_v6 { - var newState : Float = 0.0; // implicitly `stable` - - public func increment() : async () { - newState += 0.5; - }; - - public func decrement() : async () { - newState -= 0.5; - }; - - public query func read() : async Int { - Runtime.trap("No longer supported: Use `readFloat`"); - }; - - public query func readFloat() : async Float { - return newState; - }; -}; +```motoko no-repl file=/count-v6b.mo ``` ### Explicit migration using a migration function @@ -381,35 +199,7 @@ by running the initialization expression in the field's declaration. The migration function, when required, is declared using a parenthetical expression immediately preceding the actor or actor class declaration, for example: -```motoko -import Runtime "mo:core/Runtime"; -import Float "mo:core/Float"; - -(with migration = - // an explicit migration function - func (old : { var state : Int }) : { var newState : Float } { - { var newState = Float.fromInt(old.state) }; - }) -persistent actor Counter_v7 { - - var newState : Float = 0.0; // implicitly `stable` - - public func increment() : async () { - newState += 0.5; - }; - - public func decrement() : async () { - newState -= 0.5; - }; - - public query func read() : async Int { - Runtime.trap("No longer supported: Use `readFloat`"); - }; - - public query func readFloat() : async Float { - return newState; - }; -}; +```motoko no-repl file=/count-v7.mo ``` The syntax employs Motoko's new parenthetical expressions to modify ugrade behaviour. @@ -421,46 +211,12 @@ just before upgrade. Employing a migration function offers another advantage: it lets you re-use the name of an existing field, even when its type has changed: -```motoko -import Runtime "mo:core/Runtime"; -import Float "mo:core/Float"; -import {migration} "Migration"; - -(with migration) // declare the migration function (using field punning) -persistent actor Counter_v8 { - - var state : Float = 0.0; // implicitly `stable` - - public func increment() : async () { - state += 0.5; - }; - - public func decrement() : async () { - state -= 0.5; - }; - - public query func read() : async Int { - Runtime.trap("No longer supported: Use `readFloat`"); - }; - - public query func readFloat() : async Float { - return state; - }; -}; +```motoko no-repl file=/count-v8.mo ``` Here, the migration code is in a separate library: -```motoko -import Float "mo:core/Float"; - -module Migration { - - public func migration(old : { var state : Int }) : { var state : Float } { - { var state = Float.fromInt(old.state) }; - } - -} +```motoko no-repl file=/Migration.mo ``` The migration function can be selective and only consume or produce a subset of the old and new stable variables. Other stable variables can be declared as usual. @@ -468,43 +224,7 @@ The migration function can be selective and only consume or produce a subset of For example, here, with the same migration function, you can also declare a new stable variable, `lastModified` that records the time of the last update, without having to mention that field in the migration function: -```motoko -import Runtime "mo:core/Runtime"; -import Float "mo:core/Float"; -import Time "mo:core/Time"; -import {migration} "Migration"; - -(with migration) // use the imported migration function -persistent actor - Counter_v9 { - - var state : Float = 0.0; // expicitly migrated - - var lastModified : Time.Time = Time.now(); // implicitly migrated - - public func increment() : async () { - lastModified := Time.now(); - state += 0.5; - }; - - public func decrement() : async () { - lastModified := Time.now(); - state -= 0.5; - }; - - public query func read() : async Int { - Runtime.trap("No longer supported: Use `readFloat`"); - }; - - public query func readFloat() : async Float { - return state; - }; - - public query func lastAccess() : async Time.Time { - return lastModified; - }; - -}; +```motoko no-repl file=/count-v9.mo ``` The stable signature of an actor with a migration function now consists of two ordinary stable signatures, the pre-signature (before the upgrade), and the post-signature (after the upgrade). @@ -512,15 +232,7 @@ The stable signature of an actor with a migration function now consists of two o For example, this is the combined signature of the previous example: -```motoko -// Version: 3.0.0 -actor ({ - stable var lastModified : Int; - in var state : Int -}, { - stable var lastModified : Int; - stable var state : Float -}) ; +```motoko no-repl file=/count-v9.most ``` The second signature is determined solely by the actor's stable variable declarations. @@ -532,7 +244,7 @@ The migration function can be deleted or adjusted on the next upgrade. ## Enhanced stable signatures -When using [enhanced multi-migration](/languages/motoko/fundamentals/enhanced-multi-migration), the compiler produces an **enhanced stable signature** that records the entire migration chain alongside the actor's final stable fields. This extended signature enables the tooling to verify upgrade compatibility across the full history of migrations. +When using [enhanced multi-migration](/languages/motoko/fundamentals/actors/enhanced-multi-migration), the compiler produces an **enhanced stable signature** that records the entire migration chain alongside the actor's final stable fields. This extended signature enables the tooling to verify upgrade compatibility across the full history of migrations. ### Stable signature versions @@ -540,24 +252,12 @@ Motoko uses three versions of the stable signature format, each corresponding to **Version 1.0.0 — Single.** The original format, listing the actor's stable fields. Used when the actor has no migration function. -```motoko -// Version: 1.0.0 -actor { - stable var state : Nat -}; +```motoko no-repl file=/count-v1.most ``` **Version 3.0.0 — Pre/Post.** Used when the actor declares a single migration function via `(with migration = ...)`. The signature contains a pre-signature (the fields the migration function consumes from the old actor) and a post-signature (the new actor's stable fields): -```motoko -// Version: 3.0.0 -actor ({ - stable var lastModified : Int; - in var state : Int -}, { - stable var lastModified : Int; - stable var state : Float -}) ; +```motoko no-repl file=/count-v9.most ``` Fields marked `in` are required inputs that must be present in the previous actor. Fields marked `stable` are carried through or newly declared. @@ -668,10 +368,10 @@ cannot be consumed at new type var Float ``` -With [enhanced orthogonal persistence](/languages/motoko/fundamentals/orthogonal-persistence-enhanced), compatibility errors of stable variables are always detected in the runtime system and if failing, the upgrade is safely rolled back. +With [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced), compatibility errors of stable variables are always detected in the runtime system and if failing, the upgrade is safely rolled back. :::danger -With [classical orthogonal persistence](/languages/motoko/fundamentals/orthogonal-persistence-classical), however, an upgrade attempt from `v2.wasm` to `v3.wasm` is unpredictable and may lead to partial or complete data loss if the `dfx` warning is ignored. +With [classical orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/classical), however, an upgrade attempt from `v2.wasm` to `v3.wasm` is unpredictable and may lead to partial or complete data loss if the `dfx` warning is ignored. ::: ## Adding record fields @@ -680,27 +380,12 @@ A common, real-world example of an incompatible upgrade can be found [on the for In that example, a user was attempting to add a field to the record payload of an array, by upgrading from stable type interface: -```motoko -persistent actor { - type Card = { - title : Text; - }; - - var map : [(Nat32, Card)] = []; -}; +```motoko no-repl file=/Card-v0.mo ``` to *incompatible* stable type interface: -```motoko -persistent actor { - type Card = { - title : Text; - description : Text; - }; - - var map : [(Nat32, Card)] = []; -}; +```motoko no-repl file=/Card-v1.mo ``` ### Problem @@ -718,8 +403,8 @@ cannot be consumed at new type Do you want to proceed? yes/No ``` -It is recommended not to continue, as you will lose the state in older versions of Motoko that use [classical orthogonal persistence](/languages/motoko/fundamentals/orthogonal-persistence-classical). -Upgrading with [enhanced orthogonal persistence](/languages/motoko/fundamentals/orthogonal-persistence-enhanced) will trap and roll back, keeping the old state. +It is recommended not to continue, as you will lose the state in older versions of Motoko that use [classical orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/classical). +Upgrading with [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced) will trap and roll back, keeping the old state. Adding a new record field to the type of existing stable variable is not supported. The reason is simple: the upgrade would need to supply values for the new field out of thin air. In this example, the upgrade would need to conjure up some value for the `description` field of every existing `card` in `map`. Moreover, allowing adding optional fields is also a problem, as a record can be shared from various variables with different static types, some of them already declaring the added field or adding a same-named optional field with a potentially different type (and/or different semantics). @@ -734,40 +419,13 @@ There are two solutions: using a sequence of simple upgrades, or the second, rec 2. You can introduce a new variable `newMap` and copy the old state to the new one, initializing the new field as needed. 3. Then, upgrade to this new version. -```motoko -import Array "mo:core/Array"; - -persistent actor { - type OldCard = { - title : Text; - }; - - type NewCard = { - title : Text; - description : Text; - }; - - var map : [(Nat32, OldCard)] = []; - - var newMap : [(Nat32, NewCard)] = Array.map<(Nat32, OldCard), (Nat32, NewCard)>( - map, - func(key, { title }) { (key, { title; description = "" }) }, - ); -}; +```motoko no-repl file=/Card-v1a.mo ``` 4. **After** you have successfully upgraded to this new version, you can upgrade once more to a version, that drops the old `map`. -```motoko -persistent actor { - type Card = { - title : Text; - description : Text; - }; - - var newMap : [(Nat32, Card)] = []; -}; +```motoko no-repl file=/Card-v1b.mo ``` `dfx` will issue a warning that `map` will be dropped. @@ -788,65 +446,19 @@ Instead of the previous two step solution, you can upgrade in one step using a m 1. Define a migration module and function that transforms the old stable variable, at its current type, into the new stable variable at its new type. -```motoko -// CardMigration.mo -import Array "mo:core/Array"; - -module CardMigration { - type OldCard = { - title : Text; - }; - - type NewCard = { - title : Text; - description : Text; - }; - - // our migration function - public func migration(old : { - var map : [(Nat32, OldCard)] // old type - }) : - { - var map : [(Nat32, NewCard)] // new type - } { - { var map : [(Nat32, NewCard)] = - Array.map<(Nat32, OldCard), (Nat32, NewCard)>( - old.map, - func(key, { title }) { (key, { title; description = "" }) }) } - } - -} +```motoko no-repl file=/CardMigration.mo ``` 2. Specify the migration function as the migration expression of your actor declaration: -```motoko -import {migration} "CardMigration"; - -(with migration) // Declare the migration function -persistent actor { - type Card = { - title : Text; - description : Text; - }; - - var map : [(Nat32, Card)] = []; // Initialized by migration on upgrade -}; +```motoko no-repl file=/Card-v1c.mo ``` **After** you have successfully upgraded to this new version, you can also upgrade once more to a version that drops the migration code. -```motoko -persistent actor { - type Card = { - title : Text; - description : Text; - }; - - var map : [(Nat32, Card)] = []; -}; +```motoko no-repl file=/Card-v1d.mo ``` However, removing or adjusting the migration code can also be delayed to the next, proper upgrade that fixes bugs or extends functionality. diff --git a/docs/languages/motoko/fundamentals/data-persistence.md b/docs/languages/motoko/fundamentals/actors/data-persistence.md similarity index 89% rename from docs/languages/motoko/fundamentals/data-persistence.md rename to docs/languages/motoko/fundamentals/actors/data-persistence.md index 4c76933e..598e812f 100644 --- a/docs/languages/motoko/fundamentals/data-persistence.md +++ b/docs/languages/motoko/fundamentals/actors/data-persistence.md @@ -28,16 +28,7 @@ You can only use the `stable`, `transient` (or legacy `flexible`) modifier on `l The following is a simple example of how to declare a stable counter that can be upgraded while preserving the counter’s value: -```motoko -persistent actor Counter { - - var value = 0; - - public func inc() : async Nat { - value += 1; - return value; - }; -} +```motoko file=/StableCounter.mo ``` When you compile and deploy a canister for the first time, all transient and stable variables in the actor are initialized in sequence. When a canister is upgraded, all stable variables that existed in the previous version of the actor are pre-initialized with their old values and the remaining transient and any newly-added stable variables are initialized in sequence. @@ -46,16 +37,7 @@ Starting with Motoko v0.13.5, if you prefix the `actor` keyword with the keyword Using a `persistent` actor can help avoid unintended data loss. It is the recommended declaration syntax for actors and actor classes. The non-`persistent` declaration is provided for backwards compatibility. -```motoko -persistent actor Counter { - - var value = 0; // implicitly stable! - - public func inc() : async Nat { - value += 1; - value; - }; -} +```motoko file=/PersistentCounter.mo ``` ## Stable types @@ -88,25 +70,7 @@ Unlike stable data structures in the Rust CDK, these modules do not use stable m For example, the stable type `TemperatureSeries` covers the persistent data, while the non-stable type `Weather` wraps this with additional methods (local function types). -```motoko -persistent actor { - type TemperatureSeries = [Float]; - - class Weather(temperatures : TemperatureSeries) { - public func averageTemperature() : Float { - var sum = 0.0; - var count = 0.0; - for (value in temperatures.values()) { - sum += value; - count += 1; - }; - return sum / count; - }; - }; - - var temperatures : TemperatureSeries = [30.0, 31.5, 29.2]; - transient var weather = Weather(temperatures); -}; +```motoko no-repl file=/WeatherActor.mo ``` __Discouraged and not recommended__: [Pre- and post-upgrade hooks](#preupgrade-and-postupgrade-system-methods) allow copying non-stable types to stable types during upgrades. This approach is error-prone and does not scale for large data. **Per best practices, using these methods should be avoided if possible.** Conceptually, it also does not align well with the idea of orthogonal persistence. @@ -156,7 +120,7 @@ When upgrading a canister, it is important to verify that the upgrade can procee - Introducing an incompatible change in stable declarations. - Breaking clients due to a Candid interface change. -With [enhanced orthogonal persistence](/languages/motoko/fundamentals/orthogonal-persistence-enhanced), Motoko rejects incompatible changes of stable declarations during an upgrade attempt. +With [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced), Motoko rejects incompatible changes of stable declarations during an upgrade attempt. Moreover, `dfx` checks the two conditions before attempting the upgrade and warns users as necessary. A Motoko canister upgrade is safe provided: @@ -165,7 +129,7 @@ A Motoko canister upgrade is safe provided: - The canister’s Motoko stable signature evolves to a stable-compatible one. :::danger -With [classical orthogonal persistence](/languages/motoko/fundamentals/orthogonal-persistence-classical), the upgrade can still fail due to resource constraints. This is problematic as the canister can then not be upgraded. It is therefore strongly advised to test the scalability of upgrades extensively. This does not apply to enhanced orthogonal persistence. +With [classical orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/classical), the upgrade can still fail due to resource constraints. This is problematic as the canister can then not be upgraded. It is therefore strongly advised to test the scalability of upgrades extensively. This does not apply to enhanced orthogonal persistence. ::: @@ -214,8 +178,8 @@ A cleaner, more maintainable solution, is to declare an explicit migration expre Both of these data migration paths are supported by static and dynamic checks that prevent data loss or corruption. A user may still lose data due to coding errors, so should tread carefully. -For more information, see the [example of explicit migration](/languages/motoko/fundamentals/compatibility#explicit-migration-using-a-migration-function) and the -reference material on [migration expressions](https://docs.motoko.org#migration-expressions). +For more information, see the [example of explicit migration](/languages/motoko/fundamentals/actors/compatibility#explicit-migration-using-a-migration-function) and the +reference material on [migration expressions](/languages/motoko/reference/language-manual#migration-expressions). ## Legacy features diff --git a/docs/languages/motoko/fundamentals/enhanced-multi-migration.md b/docs/languages/motoko/fundamentals/actors/enhanced-multi-migration.md similarity index 98% rename from docs/languages/motoko/fundamentals/enhanced-multi-migration.md rename to docs/languages/motoko/fundamentals/actors/enhanced-multi-migration.md index b4b03d0c..5ae4f468 100644 --- a/docs/languages/motoko/fundamentals/enhanced-multi-migration.md +++ b/docs/languages/motoko/fundamentals/actors/enhanced-multi-migration.md @@ -20,7 +20,7 @@ With enhanced multi-migration you: The compiler reads all migration modules in lexicographic order, checks that they compose correctly, and compiles them into the actor. At runtime, only migrations that have not yet been applied are executed — already-applied migrations are skipped automatically. :::note -Enhanced multi-migration requires enhanced orthogonal persistence. It cannot be combined with the inline `(with migration = ...)` syntax used for [single migration functions](/languages/motoko/fundamentals/compatibility#explicit-migration-using-a-migration-function). +Enhanced multi-migration requires enhanced orthogonal persistence. It cannot be combined with the inline `(with migration = ...)` syntax used for [single migration functions](/languages/motoko/fundamentals/actors/compatibility#explicit-migration-using-a-migration-function). ::: ## Getting started @@ -412,6 +412,6 @@ moc --enhanced-orthogonal-persistence \ ## See also -- [Data persistence](/languages/motoko/fundamentals/data-persistence) -- [Verifying upgrade compatibility](/languages/motoko/fundamentals/compatibility) -- [Enhanced orthogonal persistence](/languages/motoko/fundamentals/orthogonal-persistence-enhanced) +- [Data persistence](/languages/motoko/fundamentals/actors/data-persistence) +- [Verifying upgrade compatibility](/languages/motoko/fundamentals/actors/compatibility) +- [Enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced) diff --git a/docs/languages/motoko/fundamentals/messaging.md b/docs/languages/motoko/fundamentals/actors/messaging.md similarity index 94% rename from docs/languages/motoko/fundamentals/messaging.md rename to docs/languages/motoko/fundamentals/actors/messaging.md index beb32a13..c3c057bd 100644 --- a/docs/languages/motoko/fundamentals/messaging.md +++ b/docs/languages/motoko/fundamentals/actors/messaging.md @@ -4,7 +4,7 @@ description: "Motoko language documentation" title: "Messaging" --- -ICP enforces rules on when and how [canisters](https://internetcomputer.org/docs/building-apps/essentials/canisters) communicate. Motoko includes static (compile-time) messaging restrictions to help prevent certain execution errors. +ICP enforces rules on when and how [canisters](/concepts/canisters) communicate. Motoko includes static (compile-time) messaging restrictions to help prevent certain execution errors. For example, a canister cannot send messages during installation, which helps avoid errors during deployment. Query functions cannot send messages either, because they run locally and do not trigger updates. Additionally, shared functions cannot be called in a synchronous context since shared calls require asynchronous execution. diff --git a/docs/languages/motoko/fundamentals/mixins.md b/docs/languages/motoko/fundamentals/actors/mixins.md similarity index 100% rename from docs/languages/motoko/fundamentals/mixins.md rename to docs/languages/motoko/fundamentals/actors/mixins.md diff --git a/docs/languages/motoko/fundamentals/orthogonal-persistence-classical.md b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/classical.md similarity index 90% rename from docs/languages/motoko/fundamentals/orthogonal-persistence-classical.md rename to docs/languages/motoko/fundamentals/actors/orthogonal-persistence/classical.md index 7120a17f..5d87d27b 100644 --- a/docs/languages/motoko/fundamentals/orthogonal-persistence-classical.md +++ b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/classical.md @@ -17,10 +17,10 @@ Upon upgrade, the classical orthogonal persistence mechanism serializes all stab :::danger The above-mentioned issues can lead to a stuck canister that can no longer be upgraded. Therefore, it is absolutely necessary to thoroughly test how much data an upgrade of your application can handle and then conservatively limit the data held by that canister. -Moreover, it is ideal to have a backup plan to rescue data even if upgrades fail, e.g. by controller-privileged data query calls. Another option is to [snapshot](https://internetcomputer.org/docs/building-apps/canister-management/snapshots) the canister before attempting the upgrade. +Moreover, it is ideal to have a backup plan to rescue data even if upgrades fail, e.g. by controller-privileged data query calls. Another option is to [snapshot](/guides/canister-management/snapshots) the canister before attempting the upgrade. ::: -These issues are solved by [enhanced orthogonal persistence](/languages/motoko/fundamentals/orthogonal-persistence-enhanced). +These issues are solved by [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced). :::note diff --git a/docs/languages/motoko/fundamentals/orthogonal-persistence-enhanced.md b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced.md similarity index 94% rename from docs/languages/motoko/fundamentals/orthogonal-persistence-enhanced.md rename to docs/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced.md index 65d0943c..ba4c49be 100644 --- a/docs/languages/motoko/fundamentals/orthogonal-persistence-enhanced.md +++ b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced.md @@ -19,8 +19,8 @@ Moreover, it is advised to have a backup possibility for rescuing data even when ::: :::note -[Classical orthogonal persistence](/languages/motoko/fundamentals/orthogonal-persistence-classical) with 32-bit main memory and Candid stabilization was the previous default compilation mode for `moc`. If necessary, it can be re-enabled with compiler flag `--legacy-persistence`. -See [orthogonal persistence modes](/languages/motoko/fundamentals/) for a comparison. +[Classical orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/classical) with 32-bit main memory and Candid stabilization was the previous default compilation mode for `moc`. If necessary, it can be re-enabled with compiler flag `--legacy-persistence`. +See [orthogonal persistence modes](/languages/motoko/fundamentals/actors/orthogonal-persistence/overview) for a comparison. ::: ## Design @@ -53,7 +53,7 @@ Compatible changes for immutable types are largely analogous to the allowed Moto The runtime system checks migration compatibility on upgrade, and if not fulfilled, rolls back the upgrade. This compatibility check serves as an additional safety measure on top of the `dfx` warning that can be bypassed by users. -Any more complex change can be performed with programmatic instruction, see [explicit migration](/languages/motoko/fundamentals/data-persistence#explicit-migration). +Any more complex change can be performed with programmatic instruction, see [explicit migration](/languages/motoko/fundamentals/actors/data-persistence#explicit-migration). ### Migration path When migrating from the old serialization-based stabilization to the new persistent heap, the old data is deserialized one last time from stable memory and then placed in the new persistent heap layout. Once operating on the persistent heap, the system should prevent downgrade attempts to the old serialization-based persistence. diff --git a/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/overview.md b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/overview.md new file mode 100644 index 00000000..51b7da82 --- /dev/null +++ b/docs/languages/motoko/fundamentals/actors/orthogonal-persistence/overview.md @@ -0,0 +1,30 @@ +--- +sidebar_position: 1 +description: "Motoko language documentation" +title: "What is orthogonal persistence?" +--- + +Orthogonal persistence is the ability to for a program to automatically preserve its state across transactions and canister upgrades without requiring manual intervention. This means that data persists seamlessly, without the need for a database, stable memory APIs, or specialized stable data structures. + +Although Motoko’s persistence model is complex under the hood, it’s designed to be both safe and efficient. By simply using the `persistent` (actors) or `stable` (data structures) keyword, developers can mark pieces of their program as persistent. This abstraction significantly reduces the risk of data loss or corruption during upgrades. + +In contrast, other canister development languages like Rust require explicit handling of persistence. Developers must manually manage stable memory and use specialized data structures to ensure data survives upgrades. These languages lack orthogonal persistence, and may rearrange memory unpredictably during recompilation or runtime, making safe persistence more error-prone and labor-intensive. + +Motoko features two implementations for orthogonal persistence: + +* [Enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced) provides very fast upgrades, scaling independently of the heap size. This is realized by retaining the entire Wasm main memory on an upgrade and simply performing a type-driven upgrade safety check. By using 64-bit address space, it is designed to scale beyond 4 GiB and in the future, offer the same capacity like stable memory. + +* [Classical orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/classical) is the old implementation of orthogonal persistence that is superseded by enhanced orthogonal persistence. On an upgrade, the runtime system first serializes the persistent data to stable memory and then deserializes it back again to main memory. While this is both inefficient and unscalable, it exhibits problems on shared immutable data (potentially leading to state explosion), deep structures (call stack overflow) and larger heaps (the implementation limits the stable data to at most 2 GiB). + +:::note + +Since version 0.15.0, the `moc` compiler enables enhanced orthogonal persistence by default. +Classical orthogonal persistence, the default compilation mode in previous versions has been deprecated and can only be re-enabled with a compiler flag (`--legacy-persistence`). + +Although it is possible to upgrade a canister compiled with classical persistence to one compiled with enhanced-orthogonal-persistence, downgrades from enhanced to classical are *not* supported. + +As a safeguard, to protect users from unwittingly, and irreversibly, upgrading from classical to enhanced orthogonal persistence, such upgrades will fail unless the new code is compiled with flag `--enhanced-orthogonal-persistence` explicitly set. + +New projects should not require the flag at all (#5308) and will simply adopt enhanced mode. Only projects that wish to transition from classical to enhanced orthogonal persistence should explicitly set `--enhanced-orthogonal-persistence` to disable the safeguard and opt-in to enhanced mode. + +::: \ No newline at end of file diff --git a/docs/languages/motoko/fundamentals/state.md b/docs/languages/motoko/fundamentals/actors/state.md similarity index 100% rename from docs/languages/motoko/fundamentals/state.md rename to docs/languages/motoko/fundamentals/actors/state.md diff --git a/docs/languages/motoko/fundamentals/characters-text.md b/docs/languages/motoko/fundamentals/basic-syntax/characters-text.md similarity index 98% rename from docs/languages/motoko/fundamentals/characters-text.md rename to docs/languages/motoko/fundamentals/basic-syntax/characters-text.md index 0da6c325..10260012 100644 --- a/docs/languages/motoko/fundamentals/characters-text.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/characters-text.md @@ -17,7 +17,7 @@ let symbol : Char = '✮'; ``` -:::note [Iter](https://mops.one/core/docs/Iter) +:::note[Iter] An `Iter` is an object that sequentially produces values of specified type `T` until no more values remain. ::: ``` motoko diff --git a/docs/languages/motoko/fundamentals/comments.md b/docs/languages/motoko/fundamentals/basic-syntax/comments.md similarity index 76% rename from docs/languages/motoko/fundamentals/comments.md rename to docs/languages/motoko/fundamentals/basic-syntax/comments.md index b4d720dc..dfaef518 100644 --- a/docs/languages/motoko/fundamentals/comments.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/comments.md @@ -14,7 +14,7 @@ Use `//` for comments that extend to the end of a line. // This is a single-line comment ``` -Use `///` for function or module documentation (also known as "doc comments"). Module documentation can be exported into documentation files such as Markdown or HTML using [mo-doc](https://docs.motoko.org). +Use `///` for function or module documentation (also known as "doc comments"). Module documentation can be exported into documentation files such as Markdown or HTML using [mo-doc](../../../../developer-tools/index.md#mo-doc). ```motoko no-repl /// Returns the sum of two integers. @@ -44,7 +44,7 @@ Multi-line comments can be nested within each other. ## Resources -- [Comment style guide](https://docs.motoko.org#comments) +- [Comment style guide](/languages/motoko/reference/style-guide#comments) -- [Generating Motoko documentation](https://docs.motoko.org) +- [Generating Motoko documentation](../../../../developer-tools/index.md#mo-doc) diff --git a/docs/languages/motoko/fundamentals/defining-an-actor.md b/docs/languages/motoko/fundamentals/basic-syntax/defining-an-actor.md similarity index 77% rename from docs/languages/motoko/fundamentals/defining-an-actor.md rename to docs/languages/motoko/fundamentals/basic-syntax/defining-an-actor.md index bbf03d2f..5410897d 100644 --- a/docs/languages/motoko/fundamentals/defining-an-actor.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/defining-an-actor.md @@ -5,9 +5,9 @@ title: "Defining an actor" hide_table_of_contents: true --- -In Motoko, an **actor** is a computational process with its own [state](/languages/motoko/fundamentals/state) and behavior. Actors are declared with the `actor` keyword. +In Motoko, an **actor** is a computational process with its own [state](/languages/motoko/fundamentals/actors/state) and behavior. Actors are declared with the `actor` keyword. -Unlike traditional functions or objects in other programming languages, actors operate independently and communicate via [asynchronous](/languages/motoko/fundamentals/actors-async#async--await) messaging. Each actor maintains its own message queue, enabling concurrent execution. +Unlike traditional functions or objects in other programming languages, actors operate independently and communicate via [asynchronous](/languages/motoko/fundamentals/actors/actors-async#async--await) messaging. Each actor maintains its own message queue, enabling concurrent execution. An actor's state is defined by its private variables, while its behavior is defined by the public functions it exposes to other actors. @@ -53,7 +53,7 @@ persistent actor Main { This code defines an actor that can be deployed on ICP. The actor is declared as `persistent` so that its state, `count`, will be preserved when the actor is upgraded. -Learn more about [persistence](/languages/motoko/fundamentals/data-persistence). +Learn more about [persistence](/languages/motoko/fundamentals/actors/data-persistence). ::: Another actor can call `Main.greet()` with an argument and await the result: @@ -62,7 +62,7 @@ Another actor can call `Main.greet()` with an argument and await the result: await Main.greet("Programmer"); ``` -A Motoko actor always presents its interface as a suite of named [functions](/languages/motoko/fundamentals/functions) (also called methods) with defined argument and return types. When Motoko code is compiled, this interface is automatically translated to [Candid](https://internetcomputer.org/docs/building-apps/interact-with-canisters/candid/candid-concepts), an interface description language. The Candid description can be consumed by other canisters, including canisters written in another language such as Rust. +A Motoko actor always presents its interface as a suite of named [functions](/languages/motoko/fundamentals/basic-syntax/functions) (also called methods) with defined argument and return types. When Motoko code is compiled, this interface is automatically translated to [Candid](/guides/canister-calls/candid), an interface description language. The Candid description can be consumed by other canisters, including canisters written in another language such as Rust. The above example's corresponding Candid interface can be found below. @@ -76,5 +76,5 @@ service : { ## Resources -- [Actors](/languages/motoko/fundamentals/actors-async) +- [Actors](/languages/motoko/fundamentals/actors/actors-async) diff --git a/docs/languages/motoko/fundamentals/basic-syntax/functions.md b/docs/languages/motoko/fundamentals/basic-syntax/functions.md new file mode 100644 index 00000000..a0bee145 --- /dev/null +++ b/docs/languages/motoko/fundamentals/basic-syntax/functions.md @@ -0,0 +1,86 @@ +--- +sidebar_position: 8 +description: "Motoko language documentation" +title: "Functions" +hide_table_of_contents: true +--- + +Functions in Motoko can have various attributes, the most fundamental being whether they are public or private. Public functions can be called by users or other [canisters](/concepts/canisters), while private functions are only accessible within the program that defines them. + +The most basic Motoko [function declaration](/languages/motoko/fundamentals/declarations/function-declarations) is: + +```motoko no-repl +func exampleFunction() : () {}; +``` + +In objects, modules, and actors, all functions are private by default unless explicitly declared as `public`. + +```motoko +object Counter { + var value = 0; + func reset() { value := 0 }; + public func inc() { value := 1}; + public func get() : Nat { value }; +} +``` + +The object `Counter` has two public methods, the functions `Counter.inc()` and `Counter.get()`. Both `value` and `reset()` are implicitly `private`. Any attempts to access `Counter.reset()` and `Counter.value` produce type errors. + +A function should specify a return type. If a return type is not declared or otherwise determined from the context, it defaults to the unit `()` return type. + +```motoko no-repl +func exampleFunction(x : Nat) : Nat { + x; +}; +``` + +:::note[Understanding function types] + +Motoko functions vary by access and behavior: + +The public functions of an actor are a special kind of function called shared functions. These functions can only be declared within actors and, unlike ordinary functions, their values can be sent to (i.e., shared with) other actors. +Shared functions come in several forms: + +- `shared` functions, which can modify an actor's state. + +- `shared query` functions, which can read the actor's state without making observable changes and cannot send further messages. + +- `shared composite query` functions, which behave like queries but can also call other queries. +All shared function, unlike ordinary functions, provide access to the identity of their caller, for applications like access control. + +[Learn more about function types](/languages/motoko/fundamentals/types/function-types). + +::: + +For example, you can rewrite the object above as an actor: + +``` motoko +persistent actor Digit { + var value = 0; + func reset() { value := 0 }; + public shared func inc() : async (){ + value += 1; + if (value == 10) reset(); + }; + public shared query func get() : async Nat { + value + }; +} +``` + +Since the public functions of an actor must be `shared`, you can omit the `shared` keyword: + +``` motoko +persistent actor Digit { + var value = 0; + func reset() { value := 0 }; + public func inc() : async () { + value += 1; + if (value == 10) reset(); + }; + public query func get() : async Nat { + value + }; +} +``` + diff --git a/docs/languages/motoko/fundamentals/identifiers.md b/docs/languages/motoko/fundamentals/basic-syntax/identifiers.md similarity index 78% rename from docs/languages/motoko/fundamentals/identifiers.md rename to docs/languages/motoko/fundamentals/basic-syntax/identifiers.md index d629a5ba..739e3cd2 100644 --- a/docs/languages/motoko/fundamentals/identifiers.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/identifiers.md @@ -16,4 +16,4 @@ let snake_case_identifier = "for compatibility with other languages"; ## Reserved syntax keywords -Motoko reserves [keywords](https://docs.motoko.org#keywords) for its syntax and they cannot be used as identifiers. +Motoko reserves [keywords](/languages/motoko/reference/language-manual#keywords) for its syntax and they cannot be used as identifiers. diff --git a/docs/languages/motoko/fundamentals/imports.md b/docs/languages/motoko/fundamentals/basic-syntax/imports.md similarity index 98% rename from docs/languages/motoko/fundamentals/imports.md rename to docs/languages/motoko/fundamentals/basic-syntax/imports.md index 1ba12221..c0cb12a7 100644 --- a/docs/languages/motoko/fundamentals/imports.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/imports.md @@ -48,4 +48,4 @@ import { compare } "mo:core/Nat"; import { type Result; mapOk } "mo:core/Result"; ``` -Learn more about [modules and imports](/languages/motoko/fundamentals/imports). +Learn more about [modules and imports](/languages/motoko/fundamentals/basic-syntax/imports). diff --git a/docs/languages/motoko/fundamentals/literals.md b/docs/languages/motoko/fundamentals/basic-syntax/literals.md similarity index 91% rename from docs/languages/motoko/fundamentals/literals.md rename to docs/languages/motoko/fundamentals/basic-syntax/literals.md index 6b7e4e60..eec4035c 100644 --- a/docs/languages/motoko/fundamentals/literals.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/literals.md @@ -25,5 +25,5 @@ You can use literals directly in expressions. ## Resources -- [Literals](https://docs.motoko.org#literals) +- [Literals](/languages/motoko/reference/language-manual#literals) diff --git a/docs/languages/motoko/fundamentals/numbers.md b/docs/languages/motoko/fundamentals/basic-syntax/numbers.md similarity index 100% rename from docs/languages/motoko/fundamentals/numbers.md rename to docs/languages/motoko/fundamentals/basic-syntax/numbers.md diff --git a/docs/languages/motoko/fundamentals/operators.md b/docs/languages/motoko/fundamentals/basic-syntax/operators.md similarity index 100% rename from docs/languages/motoko/fundamentals/operators.md rename to docs/languages/motoko/fundamentals/basic-syntax/operators.md diff --git a/docs/languages/motoko/fundamentals/printing-values.md b/docs/languages/motoko/fundamentals/basic-syntax/printing-values.md similarity index 84% rename from docs/languages/motoko/fundamentals/printing-values.md rename to docs/languages/motoko/fundamentals/basic-syntax/printing-values.md index d36e9e58..b59379e7 100644 --- a/docs/languages/motoko/fundamentals/printing-values.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/printing-values.md @@ -25,7 +25,7 @@ Debug.print(debug_show {life = 42} ); // "{life = 42}" Functions like `Debug.print("Hello, World!")` are considered **impure functions** because they cause a side effect by printing to the console or log. -In contrast, [**pure functions**](/languages/motoko/fundamentals/functions) return values that do not modify output or have other side effects like sending messages. For example `Nat.toText(42)` is pure because it always returns `"42"` with no other effect. +In contrast, [**pure functions**](/languages/motoko/fundamentals/types/function-types) return values that do not modify output or have other side effects like sending messages. For example `Nat.toText(42)` is pure because it always returns `"42"` with no other effect. ## Resources diff --git a/docs/languages/motoko/fundamentals/traps.md b/docs/languages/motoko/fundamentals/basic-syntax/traps.md similarity index 100% rename from docs/languages/motoko/fundamentals/traps.md rename to docs/languages/motoko/fundamentals/basic-syntax/traps.md diff --git a/docs/languages/motoko/fundamentals/whitespace.md b/docs/languages/motoko/fundamentals/basic-syntax/whitespace.md similarity index 90% rename from docs/languages/motoko/fundamentals/whitespace.md rename to docs/languages/motoko/fundamentals/basic-syntax/whitespace.md index 7a60a39b..0e0ade53 100644 --- a/docs/languages/motoko/fundamentals/whitespace.md +++ b/docs/languages/motoko/fundamentals/basic-syntax/whitespace.md @@ -25,5 +25,5 @@ persistent actor Counter { ## Resources -- [Motoko style guide](https://docs.motoko.org) +- [Motoko style guide](/languages/motoko/reference/style-guide) diff --git a/docs/languages/motoko/fundamentals/contextual-dot.md b/docs/languages/motoko/fundamentals/contextual-dot.md index 587ac851..fd0b0437 100644 --- a/docs/languages/motoko/fundamentals/contextual-dot.md +++ b/docs/languages/motoko/fundamentals/contextual-dot.md @@ -162,4 +162,4 @@ Contextual dot notation has some intentional limitations: ## See also - [Modules and imports](modules-imports) -- [Language reference](https://docs.motoko.org#dotted-function-calls) \ No newline at end of file +- [Language reference](/languages/motoko/reference/language-manual#dotted-function-calls) \ No newline at end of file diff --git a/docs/languages/motoko/fundamentals/basic-control-flow.md b/docs/languages/motoko/fundamentals/control-flow/basic-control-flow.md similarity index 96% rename from docs/languages/motoko/fundamentals/basic-control-flow.md rename to docs/languages/motoko/fundamentals/control-flow/basic-control-flow.md index bb8c2adb..e8b852e4 100644 --- a/docs/languages/motoko/fundamentals/basic-control-flow.md +++ b/docs/languages/motoko/fundamentals/control-flow/basic-control-flow.md @@ -134,7 +134,7 @@ let o4 = addOpt(null, null); // null Instead of having to switch on the options `n` and `m` in a verbose manner the use of the postfix operator `!` makes it easy to unwrap their values but exit the block with `null` when either is `null`. -A more interesting example of option blocks can be found at the end of the section on [switch](/languages/motoko/fundamentals/switch). +A more interesting example of option blocks can be found at the end of the section on [switch](/languages/motoko/fundamentals/control-flow/switch). ## `label` and `break` @@ -278,7 +278,7 @@ You can also exit any loop in a function using `return` or (in an asynchronous f ## Function calls -A function call executes a function by passing arguments and receiving a result. In Motoko, function calls can be synchronous (executing immediately within the same [canister](https://internetcomputer.org/docs/building-apps/essentials/canisters)) or [asynchronous](/languages/motoko/fundamentals/actors-async#async--await) (message passing between canisters). Asynchronous calls use `async`/`await` and are essential for inter-canister communication. +A function call executes a function by passing arguments and receiving a result. In Motoko, function calls can be synchronous (executing immediately within the same [canister](/concepts/canisters)) or [asynchronous](/languages/motoko/fundamentals/actors/actors-async#async--await) (message passing between canisters). Asynchronous calls use `async`/`await` and are essential for inter-canister communication. ```motoko no-repl persistent actor { diff --git a/docs/languages/motoko/fundamentals/blocks.md b/docs/languages/motoko/fundamentals/control-flow/blocks.md similarity index 100% rename from docs/languages/motoko/fundamentals/blocks.md rename to docs/languages/motoko/fundamentals/control-flow/blocks.md diff --git a/docs/languages/motoko/fundamentals/conditionals.md b/docs/languages/motoko/fundamentals/control-flow/conditionals.md similarity index 100% rename from docs/languages/motoko/fundamentals/conditionals.md rename to docs/languages/motoko/fundamentals/control-flow/conditionals.md diff --git a/docs/languages/motoko/fundamentals/loops.md b/docs/languages/motoko/fundamentals/control-flow/loops.md similarity index 100% rename from docs/languages/motoko/fundamentals/loops.md rename to docs/languages/motoko/fundamentals/control-flow/loops.md diff --git a/docs/languages/motoko/fundamentals/switch.md b/docs/languages/motoko/fundamentals/control-flow/switch.md similarity index 100% rename from docs/languages/motoko/fundamentals/switch.md rename to docs/languages/motoko/fundamentals/control-flow/switch.md diff --git a/docs/languages/motoko/fundamentals/class-declarations.md b/docs/languages/motoko/fundamentals/declarations/class-declarations.md similarity index 91% rename from docs/languages/motoko/fundamentals/class-declarations.md rename to docs/languages/motoko/fundamentals/declarations/class-declarations.md index 094bfd29..72f04a4e 100644 --- a/docs/languages/motoko/fundamentals/class-declarations.md +++ b/docs/languages/motoko/fundamentals/declarations/class-declarations.md @@ -4,7 +4,7 @@ description: "Motoko language documentation" title: "Class declarations" --- -A class in Motoko serves as a blueprint for creating [objects](/languages/motoko/fundamentals/object-declaration) that encapsulate both [state](/languages/motoko/fundamentals/state) and behavior. It defines fields to hold data and methods to operate on that data. Unlike records and plain objects, classes support constructors, allowing developers to initialize each instance with unique values at creation time. +A class in Motoko serves as a blueprint for creating [objects](/languages/motoko/fundamentals/declarations/object-declaration) that encapsulate both [state](/languages/motoko/fundamentals/actors/state) and behavior. It defines fields to hold data and methods to operate on that data. Unlike records and plain objects, classes support constructors, allowing developers to initialize each instance with unique values at creation time. Classes in Motoko are not the same as classes in other object oriented programming languages, but they serve the same purpose. Motoko also doesn’t have a `this` or `self` keyword because you can simply call other methods directly by name or name the entire object using an identifier of your choice. @@ -165,5 +165,5 @@ Using this `system` syntax, developers can: - Manually install, upgrade, or reinstall canisters. - Access lower-level canister management features provided by ICP. -[Learn more about actor class management](https://docs.motoko.org#actor-class-management). +[Learn more about actor class management](/languages/motoko/reference/language-manual#actor-class-management). diff --git a/docs/languages/motoko/fundamentals/expression-declarations.md b/docs/languages/motoko/fundamentals/declarations/expression-declarations.md similarity index 98% rename from docs/languages/motoko/fundamentals/expression-declarations.md rename to docs/languages/motoko/fundamentals/declarations/expression-declarations.md index 3796e1c1..7e82f078 100644 --- a/docs/languages/motoko/fundamentals/expression-declarations.md +++ b/docs/languages/motoko/fundamentals/declarations/expression-declarations.md @@ -31,7 +31,7 @@ In Motoko, expressions of type `()` play the role of statements in other languag ## Basic usage -Expression declarations are commonly used for functions or operations that produce side effects, such as printing or modifying [state](/languages/motoko/fundamentals/state). +Expression declarations are commonly used for functions or operations that produce side effects, such as printing or modifying [state](/languages/motoko/fundamentals/actors/state). ```motoko no-repl Debug.print("Hello, Motoko!"); diff --git a/docs/languages/motoko/fundamentals/function-declarations.md b/docs/languages/motoko/fundamentals/declarations/function-declarations.md similarity index 96% rename from docs/languages/motoko/fundamentals/function-declarations.md rename to docs/languages/motoko/fundamentals/declarations/function-declarations.md index e718b186..0255de7e 100644 --- a/docs/languages/motoko/fundamentals/function-declarations.md +++ b/docs/languages/motoko/fundamentals/declarations/function-declarations.md @@ -98,7 +98,7 @@ assert echoTwice("Hello") == "Hello!!"; ## Shared functions in actors -In actors, functions can be marked as `shared` to allow [asynchronous](/languages/motoko/fundamentals/actors-async#async--await) [inter-canister](https://internetcomputer.org/docs/references/async-code) communication. +In actors, functions can be marked as `shared` to allow [asynchronous](/languages/motoko/fundamentals/actors/actors-async#async--await) [inter-canister](/references/message-execution-properties) communication. ```motoko no-repl actor Counter { diff --git a/docs/languages/motoko/fundamentals/module-declarations.md b/docs/languages/motoko/fundamentals/declarations/module-declarations.md similarity index 100% rename from docs/languages/motoko/fundamentals/module-declarations.md rename to docs/languages/motoko/fundamentals/declarations/module-declarations.md diff --git a/docs/languages/motoko/fundamentals/object-declaration.md b/docs/languages/motoko/fundamentals/declarations/object-declaration.md similarity index 95% rename from docs/languages/motoko/fundamentals/object-declaration.md rename to docs/languages/motoko/fundamentals/declarations/object-declaration.md index 1a3324ad..ac82e228 100644 --- a/docs/languages/motoko/fundamentals/object-declaration.md +++ b/docs/languages/motoko/fundamentals/declarations/object-declaration.md @@ -8,7 +8,7 @@ In Motoko, records and objects are both used to group related values using named While records expressions are ideal for lightweight data representation, objects expressions are more verbose. Object expressions can define full objects in the sense of object-oriented programming where an object is a collection of named fields and methods acting on private state. In Motoko, the private declarations define the encapsulated state, while the public definitions define the object's visible members. -Record and object both use the `var` keyword to define [mutable](/languages/motoko/fundamentals/variable-declarations) and declarations. Both records and objects support `and` and `with` for merging and updating object fields to create new records and objects. +Record and object both use the `var` keyword to define [mutable](/languages/motoko/fundamentals/declarations/variable-declarations) and declarations. Both records and objects support `and` and `with` for merging and updating object fields to create new records and objects. **Record expressions** are used to construct simple data structures that consist of named fields holding values. The fields can be mutable or immutable. The fields of a record cannot refer to each other by name and are mainly used to store plain data, like the records in a database. diff --git a/docs/languages/motoko/fundamentals/type-declarations.md b/docs/languages/motoko/fundamentals/declarations/type-declarations.md similarity index 93% rename from docs/languages/motoko/fundamentals/type-declarations.md rename to docs/languages/motoko/fundamentals/declarations/type-declarations.md index 1db09f7d..528e11a8 100644 --- a/docs/languages/motoko/fundamentals/type-declarations.md +++ b/docs/languages/motoko/fundamentals/declarations/type-declarations.md @@ -42,7 +42,7 @@ Structural typing means that the types `User` and `Person` are interchangeable b ## Record types -In Motoko, a type can define a structured [record](/languages/motoko/fundamentals/records) with labeled fields. Each field has a specific type, and you can access them using dot notation. Records are useful for organizing related data clearly and safely. +In Motoko, a type can define a structured [record](/languages/motoko/fundamentals/types/records) with labeled fields. Each field has a specific type, and you can access them using dot notation. Records are useful for organizing related data clearly and safely. ```motoko no-repl // A reusable record @@ -145,8 +145,8 @@ type Seq = ?(T, Seq<[T]>); ## Resources -- [`Record`](/languages/motoko/fundamentals/records) -- [`Variant`](/languages/motoko/fundamentals/variants) +- [`Record`](/languages/motoko/fundamentals/types/records) +- [`Variant`](/languages/motoko/fundamentals/types/variants) diff --git a/docs/languages/motoko/fundamentals/variable-declarations.md b/docs/languages/motoko/fundamentals/declarations/variable-declarations.md similarity index 100% rename from docs/languages/motoko/fundamentals/variable-declarations.md rename to docs/languages/motoko/fundamentals/declarations/variable-declarations.md diff --git a/docs/languages/motoko/fundamentals/error-handling.md b/docs/languages/motoko/fundamentals/error-handling.md index 4905e655..6562929e 100644 --- a/docs/languages/motoko/fundamentals/error-handling.md +++ b/docs/languages/motoko/fundamentals/error-handling.md @@ -17,30 +17,12 @@ In the following example, if the `markDone` function sometimes fails and returns Function definition: -```motoko -switch (Map.get(todos, Int.compare, id)) { - case (?(#todo(todo))) { - let now = Time.now(); - Map.add(todos, Int.compare, id, #done(now)); - ?(secondsBetween(todo.opened, now)) - }; - case _ { null }; - } - }; +```motoko no-repl file=/todo-error.mo#L49-L58 ``` Function callsite: -```motoko -switch (await Todo.markDoneOption(id)) { - case null { - "Something went wrong." - }; - case (?seconds) { - "Congrats! That took " # Int.toText(seconds) # " seconds." - }; - }; - }; +```motoko no-repl file=/todo-error.mo#L117-L126 ``` The main drawback of using option types to signal errors is that all failures are represented by a single, non-descriptive `null` value. This means important information about why something failed is lost. As a result, the only message the program can show the user might be something vague like `"Something went wrong."` @@ -57,77 +39,33 @@ type Result = { #ok : Ok; #err : Err } Unlike option types, the Result type includes a second type parameter `Err` which allows you to specify exactly what kind of error occurred. This makes error handling more informative and flexible. -```motoko - +```motoko no-repl file=/todo-error.mo#L60-L60 ``` The previous example can be revised to use `Result` types: Function definition: -```motoko -switch (Map.get(todos, Int.compare, id)) { - case (?(#todo(todo))) { - let now = Time.now(); - Map.add(todos, Int.compare, id, #done(now)); - #ok(secondsBetween(todo.opened, now)) - }; - case (?(#done(time))) { - #err(#alreadyDone(time)) - }; - case null { - #err(#notFound) - }; - } - }; +```motoko no-repl file=/todo-error.mo#L62-L76 ``` Function callsite: -```motoko -switch (await Todo.markDoneResult(id)) { - case (#err(#notFound)) { - "There is no Todo with that ID." - }; - case (#err(#alreadyDone(at))) { - let doneAgo = secondsBetween(at, Time.now()); - "You've already completed this todo " # Int.toText(doneAgo) # " seconds ago." - }; - case (#ok(seconds)) { - "Congrats! That took " # Int.toText(seconds) # " seconds." - }; - }; - }; +```motoko no-repl file=/todo-error.mo#L128-L141 ``` ## Pattern matching The most common way of working with `Option` and `Result` is to use pattern matching. If you have a value of type `?Text`, you can use the `switch` keyword to access the potential [`Text`](https://mops.one/core/docs/Text) contents: -```motoko -func greetOptional(optionalName : ?Text) : Text { - switch (optionalName) { - case (null) { "No name to be found." }; - case (?name) { "Hello, " # name # "!" }; - } -}; -assert(greetOptional(?"Dominic") == "Hello, Dominic!"); -assert(greetOptional(null) == "No name to be found"); +```motoko no-repl file=/error-examples.mo#L3-L10 ``` Motoko does not let you access the optional value without also considering the case that it is missing. With a `Result` type, you can use pattern matching to handle both success and error cases. Unlike option types, the `#err` case carries detailed information about what went wrong, not just a `null` value. -```motoko -func greetResult(resultName : Result) : Text { - switch (resultName) { - case (#err(error)) { "No name: " # error }; - case (#ok(name)) { "Hello, " # name }; - } -}; -assert(greetResult(#ok("Dominic")) == "Hello, Dominic!"); -assert(greetResult(#err("404 Not Found")) == "No name: 404 Not Found"); +```motoko no-repl file=/error-examples.mo#L12-L19 ``` Sometimes you need to convert between `Option` and `Result` types. For example, a HashMap lookup returns `null` on failure (an `Option`), but if the caller has more context, they can turn that failure into a meaningful `Result` with an error message. On the other hand, sometimes you don’t need the extra detail from a `Result` and just want to convert any error (`#err`) into `null`. @@ -146,38 +84,17 @@ Here’s how the `markDone` function might look using exceptions: Function definition: -```motoko -switch (Map.get(todos, Int.compare, id)) { - case (?(#todo(todo))) { - let now = Time.now(); - Map.add(todos, Int.compare, id, #done(now)); - secondsBetween(todo.opened, now) - }; - case (?(#done _)) { - throw Error.reject("Already done") - }; - case null { - throw Error.reject("Not Found") - }; - } - }; +```motoko no-repl file=/todo-error.mo#L78-L92 ``` Function callsite: -```motoko -try { - let seconds = await Todo.markDoneException(id); - "Congrats! That took " # Int.toText(seconds) # " seconds."; - } catch _ { - "Something went wrong."; - } - }; +```motoko no-repl file=/todo-error.mo#L143-L150 ``` ## Traps -Traps immediately stop execution and roll back [state](/languages/motoko/fundamentals/state). They are used for fatal errors that cannot be recovered. +Traps immediately stop execution and roll back [state](/languages/motoko/fundamentals/actors/state). They are used for fatal errors that cannot be recovered. ```motoko no-repl import Runtime "mo:core/Runtime"; diff --git a/docs/languages/motoko/fundamentals/hello-world.md b/docs/languages/motoko/fundamentals/hello-world.md index 4023021c..2576ae72 100644 --- a/docs/languages/motoko/fundamentals/hello-world.md +++ b/docs/languages/motoko/fundamentals/hello-world.md @@ -29,12 +29,12 @@ persistent actor HelloWorld { In this example: -1. The code begins by defining an [actor](/languages/motoko/fundamentals/actors-async) named `HelloWorld`. In Motoko, an actor is an object capable of maintaining state and communicating with other entities via message passing. +1. The code begins by defining an [actor](/languages/motoko/fundamentals/actors/actors-async) named `HelloWorld`. In Motoko, an actor is an object capable of maintaining state and communicating with other entities via message passing. -2. It then declares the variable `greeting`. This is a [stable variable](/languages/motoko/fundamentals/stable-types) because the actor is declared with the keyword `persistent`. Stable variables are used to store data that persists across canister upgrades. [Read more about canister upgrades.](https://internetcomputer.org/docs/building-apps/canister-management/upgrade) +2. It then declares the variable `greeting`. This is a [stable variable](/languages/motoko/fundamentals/types/stable-types) because the actor is declared with the keyword `persistent`. Stable variables are used to store data that persists across canister upgrades. [Read more about canister upgrades.](/guides/canister-management/lifecycle) -3. An [update method](https://internetcomputer.org/docs/building-apps/interact-with-canisters/update-calls) named `setGreeting` is used to modify the canister’s state. This method specifically updates the value stored in `greeting`. +3. An [update method](/concepts/canisters) named `setGreeting` is used to modify the canister’s state. This method specifically updates the value stored in `greeting`. -4. Finally, a [query method](https://internetcomputer.org/docs/building-apps/interact-with-canisters/query-calls) named `greet` is defined. Query methods are read-only and return information from the canister without changing its state. This method returns the current `greeting` value, followed by the input text. The method body produces a response by concatenating `"Hello, "` with the input `name`, followed by an exclamation point. +4. Finally, a [query method](/concepts/canisters) named `greet` is defined. Query methods are read-only and return information from the canister without changing its state. This method returns the current `greeting` value, followed by the input text. The method body produces a response by concatenating `"Hello, "` with the input `name`, followed by an exclamation point. -[Learn more about actors and basic syntax](/languages/motoko/fundamentals/defining-an-actor). \ No newline at end of file +[Learn more about actors and basic syntax](/languages/motoko/fundamentals/basic-syntax/defining-an-actor). \ No newline at end of file diff --git a/docs/languages/motoko/fundamentals/implicit-parameters.md b/docs/languages/motoko/fundamentals/implicit-parameters.md index 0e413c4f..98e4e6b2 100644 --- a/docs/languages/motoko/fundamentals/implicit-parameters.md +++ b/docs/languages/motoko/fundamentals/implicit-parameters.md @@ -282,4 +282,4 @@ Implicit arguments have no runtime overhead. The comparison function is resolved ## See also -- [Language reference](https://docs.motoko.org#function-calls) +- [Language reference](/languages/motoko/reference/language-manual#function-calls) diff --git a/docs/languages/motoko/fundamentals/modules-imports.md b/docs/languages/motoko/fundamentals/modules-imports.md index f9e12ae2..33fb18b9 100644 --- a/docs/languages/motoko/fundamentals/modules-imports.md +++ b/docs/languages/motoko/fundamentals/modules-imports.md @@ -110,7 +110,7 @@ import PureList "mo:core/pure/List"; ## Importing from another canister -Actors and their functions can be imported from other [canisters](https://internetcomputer.org/docs/building-apps/essentials/canisters) using the `canister:` prefix. +Actors and their functions can be imported from other [canisters](/concepts/canisters) using the `canister:` prefix. ```motoko no-repl import BigMap "canister:BigMap"; @@ -146,7 +146,7 @@ When importing from another canister, the canister must be listed as a dependenc ## Importing actor classes -When imported, an [actor](/languages/motoko/fundamentals/actors-async) class provides a type definition describing the class interface and a function that returns an instance of the class. +When imported, an [actor](/languages/motoko/fundamentals/actors/actors-async) class provides a type definition describing the class interface and a function that returns an instance of the class. For example, if you define the following actor class: @@ -183,7 +183,7 @@ persistent actor CountToTen { }; ``` -`Counters.Counter(1)` installs a new counter on the network. Installation is [asynchronous](/languages/motoko/fundamentals/actors-async#async--await), so the result is awaited. If the actor class is not named, it will result in a bad import error because actor class imports cannot be anonymous. +`Counters.Counter(1)` installs a new counter on the network. Installation is [asynchronous](/languages/motoko/fundamentals/actors/actors-async#async--await), so the result is awaited. If the actor class is not named, it will result in a bad import error because actor class imports cannot be anonymous. ## Importing `Blob` values diff --git a/docs/languages/motoko/fundamentals/advanced-types.md b/docs/languages/motoko/fundamentals/types/advanced-types.md similarity index 95% rename from docs/languages/motoko/fundamentals/advanced-types.md rename to docs/languages/motoko/fundamentals/types/advanced-types.md index b52b7cbe..47aa3982 100644 --- a/docs/languages/motoko/fundamentals/advanced-types.md +++ b/docs/languages/motoko/fundamentals/types/advanced-types.md @@ -8,7 +8,7 @@ Advanced type features enable more flexible and expressive type definitions, inc ## Structural equality -Structural equality determines whether two values are equal based on their contents. This applies to immutable data structures, such as [records](/languages/motoko/fundamentals/records) and [variants](/languages/motoko/fundamentals/variants), but does not apply to mutable structures for safety reasons. +Structural equality determines whether two values are equal based on their contents. This applies to immutable data structures, such as [records](/languages/motoko/fundamentals/types/records) and [variants](/languages/motoko/fundamentals/types/variants), but does not apply to mutable structures for safety reasons. ```motoko type Point = { x : Int; y : Int }; @@ -34,7 +34,7 @@ p1 == p2; // true (structural equality at type `Point`) ## Generic types -Generic types are used to define type parameters that work with multiple data types, commonly used in [functions](/languages/motoko/fundamentals/functions), [classes](/languages/motoko/fundamentals/objects-classes), and data structures. +Generic types are used to define type parameters that work with multiple data types, commonly used in [functions](/languages/motoko/fundamentals/types/function-types), [classes](/languages/motoko/fundamentals/types/objects-classes), and data structures. ```motoko // Generic function @@ -180,7 +180,7 @@ let ghost = { name = "Motoko"; age = 30 }; printName(ghost); // Allowed since 'ghost' has a 'name' field. ``` -In the example above, `T <: { name : Text }` requires that any type used for `T` must be a subtype of the [record](/languages/motoko/fundamentals/records) `{ name : Text }`, that is, it must have at least a `name` field of type [`Text`](https://mops.one/core/docs/Text). Extra fields are permitted, but the `name` field is mandatory. +In the example above, `T <: { name : Text }` requires that any type used for `T` must be a subtype of the [record](/languages/motoko/fundamentals/types/records) `{ name : Text }`, that is, it must have at least a `name` field of type [`Text`](https://mops.one/core/docs/Text). Extra fields are permitted, but the `name` field is mandatory. Type bounds are not limited to records. In general, the notation `T <: A` in a parameter declaration mandates that any type provided for type parameter `T` must be a subtype of the specified type `A`. diff --git a/docs/languages/motoko/fundamentals/functions.md b/docs/languages/motoko/fundamentals/types/function-types.md similarity index 88% rename from docs/languages/motoko/fundamentals/functions.md rename to docs/languages/motoko/fundamentals/types/function-types.md index 24fd9825..2d2fdb0d 100644 --- a/docs/languages/motoko/fundamentals/functions.md +++ b/docs/languages/motoko/fundamentals/types/function-types.md @@ -16,7 +16,7 @@ Motoko offers different types of functions, each with distinct capabilities: - **Local functions**, declared using the `func` keyword, are typically synchronous but can be asynchronous if their body contains an `async` expression. A local function is only available within the actor that defines it; it cannot be called from another actor or sent to another actor in a message. -- **Shared functions**, declared using the `shared`, `shared query`, or `shared composite query` keywords, are asynchronous by nature. Calling a shared function sends a message to another actor. The caller is typically another Motoko actor, a [canister](https://internetcomputer.org/docs/building-apps/essentials/canisters), or an [agent](https://internetcomputer.org/docs/building-apps/interact-with-canisters/agents/overview). +- **Shared functions**, declared using the `shared`, `shared query`, or `shared composite query` keywords, are asynchronous by nature. Calling a shared function sends a message to another actor. The caller is typically another Motoko actor, a [canister](/concepts/canisters), or an [agent](/guides/canister-calls/calling-from-clients). An actor's shared functions are always called as the result of the actor receiving some message. Shared functions that return a result have `async` return types. @@ -29,12 +29,12 @@ Motoko provides different types of functions based on where in the program they | Keyword | Function | |-------------|--------------| | `shared` | Used to enable async communication between actors. Exposes the caller’s identity. | -| `async` | Runs the function [asynchronously](/languages/motoko/fundamentals/actors-async#async--await) and returns its result in a future. | -| `query` | Optimized for reading data but cannot modify [state](/languages/motoko/fundamentals/state). | +| `async` | Runs the function [asynchronously](/languages/motoko/fundamentals/actors/actors-async#async--await) and returns its result in a future. | +| `query` | Optimized for reading data but cannot modify [state](/languages/motoko/fundamentals/actors/state). | ## Function comparison -| Function type | Mutates [state](/languages/motoko/fundamentals/state) | Calls updates | Calls queries | Asynchronous | External calls | +| Function type | Mutates [state](/languages/motoko/fundamentals/actors/state) | Calls updates | Calls queries | Asynchronous | External calls | |------------------------------|---------------|------------------|------------------|---------------|---------------| | Local (synchronous) | Yes | No | No | No | No | | Local (asynchronous) | Yes | Yes | Yes | Yes | No | @@ -44,7 +44,7 @@ Motoko provides different types of functions based on where in the program they ## Local functions -Local functions run within the canister's [actor](/languages/motoko/fundamentals/actors-async). They cannot call other [canisters](https://internetcomputer.org/docs/building-apps/essentials/canisters). Local functions are cheap to call and execute synchronously. +Local functions run within the canister's [actor](/languages/motoko/fundamentals/actors/actors-async). They cannot call other [canisters](/concepts/canisters). Local functions are cheap to call and execute synchronously. ```motoko persistent actor CommonDivisor{ @@ -173,7 +173,7 @@ The second call increments the balance from `50` to `100`, returning `100`. Since `Account.deposit` is asynchronous, its results are returned in futures of type `async Nat`. Calling `await` on each future extracts the results of the calls when they become available (so `b1` is `50` and `b2` is `100`). -**Example use case**: Transactions, user [state](/languages/motoko/fundamentals/state) updates, or anything that modifies persistent data. +**Example use case**: Transactions, user [state](/languages/motoko/fundamentals/actors/state) updates, or anything that modifies persistent data. ### One-way functions @@ -204,7 +204,7 @@ Again, the shared keyword is optional. Note that `Account.credit(100` just retur ## Query functions -[Query](https://internetcomputer.org/docs/building-apps/interact-with-canisters/query-calls) functions are designed for retrieving data. They cannot permanently update [state](/languages/motoko/fundamentals/state) and execute faster than [update](https://internetcomputer.org/docs/building-apps/interact-with-canisters/update-calls) functions because they do not go through consensus. Query functions are identified with the `query` keyword. Any function without the `query` keyword is an [update](https://internetcomputer.org/docs/building-apps/interact-with-canisters/update-calls) function. +[Query](/concepts/canisters) functions are designed for retrieving data. They cannot permanently update [state](/languages/motoko/fundamentals/actors/state) and execute faster than [update](/concepts/canisters) functions because they do not go through consensus. Query functions are identified with the `query` keyword. Any function without the `query` keyword is an [update](/concepts/canisters) function. ```motoko no-repl public query func greet(name : Text) : async Text { @@ -236,11 +236,11 @@ persistent actor Account { The `getBalance` function has function type `shared query () -> async Nat`. -**Example use case:** Fetching data quickly without modifying the canister [state](/languages/motoko/fundamentals/state). +**Example use case:** Fetching data quickly without modifying the canister [state](/languages/motoko/fundamentals/actors/state). ### Composite queries -[Composite queries](https://internetcomputer.org/docs/building-apps/interact-with-canisters/query-calls#composite-queries) chain multiple query calls together within the same function. +[Composite queries](/concepts/canisters#composite-queries) chain multiple query calls together within the same function. A good example of a composite query might be a bank that holds references to its individual accounts, implemented as separate actors, and provides a composite query that sums the deposits in all its accounts: @@ -305,7 +305,7 @@ Functions can accept multiple arguments and return multiple results by enclosing ### Using a record as an argument -Multiple values can be passed as a single argument by encapsulating them within a [record](/languages/motoko/fundamentals/records) type. +Multiple values can be passed as a single argument by encapsulating them within a [record](/languages/motoko/fundamentals/types/records) type. ```motoko no-repl func userName(user: { name : Text; age : Nat }) : Text { diff --git a/docs/languages/motoko/fundamentals/immutable-arrays.md b/docs/languages/motoko/fundamentals/types/immutable-arrays.md similarity index 90% rename from docs/languages/motoko/fundamentals/immutable-arrays.md rename to docs/languages/motoko/fundamentals/types/immutable-arrays.md index 87eab412..7366bdc4 100644 --- a/docs/languages/motoko/fundamentals/immutable-arrays.md +++ b/docs/languages/motoko/fundamentals/types/immutable-arrays.md @@ -4,7 +4,7 @@ description: "Motoko language documentation" title: "Immutable arrays" --- -Immutable arrays are fixed-size, read-only data structures that allow efficiently storing elements of the same type. Unlike [mutable arrays](/languages/motoko/fundamentals/mutable-arrays), they cannot be modified after creation, ensuring data integrity and predictable behavior. +Immutable arrays are fixed-size, read-only data structures that allow efficiently storing elements of the same type. Unlike [mutable arrays](/languages/motoko/fundamentals/types/mutable-arrays), they cannot be modified after creation, ensuring data integrity and predictable behavior. ## When to use immutable arrays @@ -30,7 +30,7 @@ The size of an array `a` is available as `a.size()`, a `Nat`. Array elements are zero-indexed, allowing indices `0` up to `a.size() - 1`. -Attempting to access an array's index that does not exist will cause a [trap](/languages/motoko/fundamentals/traps). Attempting to modify an immutable array will result in an error `expected mutable assignment target(M0073)`. +Attempting to access an array's index that does not exist will cause a [trap](/languages/motoko/fundamentals/basic-syntax/traps). Attempting to modify an immutable array will result in an error `expected mutable assignment target(M0073)`. ```motoko import Debug "mo:core/Debug"; @@ -148,7 +148,7 @@ transformArray(); To demonstrate nested immutable arrays, consider the following: -A chessboard is a fixed `8×8` grid. Using immutable arrays to represent the initial [state](/languages/motoko/fundamentals/state) of the board ensures that the setup remains unchanged, preventing accidental modifications. This is useful because the starting position of pieces in chess is fixed, and any changes should be intentional, such as when making a move. Immutable arrays provide stability and help maintain the integrity of the initial board [state](/languages/motoko/fundamentals/state). +A chessboard is a fixed `8×8` grid. Using immutable arrays to represent the initial [state](/languages/motoko/fundamentals/actors/state) of the board ensures that the setup remains unchanged, preventing accidental modifications. This is useful because the starting position of pieces in chess is fixed, and any changes should be intentional, such as when making a move. Immutable arrays provide stability and help maintain the integrity of the initial board [state](/languages/motoko/fundamentals/actors/state). ```motoko no-repl import Array "mo:core/Array"; diff --git a/docs/languages/motoko/fundamentals/mutable-arrays.md b/docs/languages/motoko/fundamentals/types/mutable-arrays.md similarity index 93% rename from docs/languages/motoko/fundamentals/mutable-arrays.md rename to docs/languages/motoko/fundamentals/types/mutable-arrays.md index 2d339aa0..c4580146 100644 --- a/docs/languages/motoko/fundamentals/mutable-arrays.md +++ b/docs/languages/motoko/fundamentals/types/mutable-arrays.md @@ -4,7 +4,7 @@ description: "Motoko language documentation" title: "Mutable arrays" --- -Mutable arrays allow direct modification of elements, making them suitable for scenarios where data needs to be updated frequently. Unlike [immutable arrays](/languages/motoko/fundamentals/immutable-arrays), which require creating a new array to reflect changes, mutable arrays support in place modifications, improving performance in some cases. +Mutable arrays allow direct modification of elements, making them suitable for scenarios where data needs to be updated frequently. Unlike [immutable arrays](/languages/motoko/fundamentals/types/immutable-arrays), which require creating a new array to reflect changes, mutable arrays support in place modifications, improving performance in some cases. ## Creating a mutable array @@ -107,7 +107,7 @@ mutableArray; ## Accessing and modifying elements -Mutable array elements can be read and modified using indexed access. Attempting to access an index that does not exist will result in a [trap](/languages/motoko/fundamentals/traps). +Mutable array elements can be read and modified using indexed access. Attempting to access an index that does not exist will result in a [trap](/languages/motoko/fundamentals/basic-syntax/traps). ```motoko let numbers : [var Nat] = [var 10, 20, 30]; @@ -119,7 +119,7 @@ debug_show(numbers[0]); // 100 The size of an array `a` is available as `a.size()`, a `Nat`. Array elements are zero-indexed, allowing indices `0` up to `a.size() - 1`. -Attempting to access an array's index that does not exist will cause a [trap](/languages/motoko/fundamentals/traps). +Attempting to access an array's index that does not exist will cause a [trap](/languages/motoko/fundamentals/basic-syntax/traps). ```motoko no-repl let numbers : [var Nat] = [var 10, 20, 30]; @@ -157,7 +157,7 @@ for (i in arr.keys()) { ## Converting a mutable array to an immutable array -You can convert a mutable array into an immutable array using `Array.freeze`, ensuring that the contents cannot be modified after conversion. Since mutable arrays are not [sharable](/languages/motoko/fundamentals/shared-types), freezing them is useful when passing data across [functions](/languages/motoko/fundamentals/functions) or [actors](/languages/motoko/fundamentals/actors-async) to ensure immutability. +You can convert a mutable array into an immutable array using `Array.freeze`, ensuring that the contents cannot be modified after conversion. Since mutable arrays are not [sharable](/languages/motoko/fundamentals/types/shared-types), freezing them is useful when passing data across [functions](/languages/motoko/fundamentals/types/function-types) or [actors](/languages/motoko/fundamentals/actors/actors-async) to ensure immutability. ```motoko no-repl import Array "mo:core/Array"; diff --git a/docs/languages/motoko/fundamentals/objects-classes.md b/docs/languages/motoko/fundamentals/types/objects-classes.md similarity index 95% rename from docs/languages/motoko/fundamentals/objects-classes.md rename to docs/languages/motoko/fundamentals/types/objects-classes.md index 18fb4fde..6cc9c6f9 100644 --- a/docs/languages/motoko/fundamentals/objects-classes.md +++ b/docs/languages/motoko/fundamentals/types/objects-classes.md @@ -9,7 +9,7 @@ title: "Objects & classes" In Motoko, an object is a collection of named fields that hold values. These values can be plain data or functions. Each field can be either **mutable** or **immutable** depending on whether it's declared with `var` or not. A simple object containing just fields of data is like a record in a database. -Motoko's light-weight [record](/languages/motoko/fundamentals/records) syntax makes it easy to construct such objects. +Motoko's light-weight [record](/languages/motoko/fundamentals/types/records) syntax makes it easy to construct such objects. When fields contain function values, Motoko objects can represent traditional objects with methods, familiar from object-oriented programming (OOP). From an OOP perspective, an object is an abstraction, defined by the behavior of its methods. Methods are typically used to modify or observe some encapsulated (i.e. hidden) state of an object. @@ -34,7 +34,7 @@ object Account { ## Classes -An object declaration just declares a single object. To declare a function that generates objects of a similar type, Motoko offer classes. A class acts as a blueprint for creating multiple objects with independent [state](/languages/motoko/fundamentals/state). +An object declaration just declares a single object. To declare a function that generates objects of a similar type, Motoko offer classes. A class acts as a blueprint for creating multiple objects with independent [state](/languages/motoko/fundamentals/actors/state). ```motoko class Account(initialBalance : Nat) { @@ -189,5 +189,5 @@ withdrawFromAccount(_premiumAccount); // withdrawFromAccount(_basicAccount); // type error: (missing withdraw) ``` -[Learn more about subtyping](/languages/motoko/fundamentals/subtyping). +[Learn more about subtyping](/languages/motoko/fundamentals/types/subtyping). diff --git a/docs/languages/motoko/fundamentals/options.md b/docs/languages/motoko/fundamentals/types/options.md similarity index 97% rename from docs/languages/motoko/fundamentals/options.md rename to docs/languages/motoko/fundamentals/types/options.md index 04d1f813..844c1ac9 100644 --- a/docs/languages/motoko/fundamentals/options.md +++ b/docs/languages/motoko/fundamentals/types/options.md @@ -53,7 +53,7 @@ if (Option.isSome(value)) { } ``` -By leveraging the `Option` module, handling optional values becomes more concise and expressive, reducing the need for explicit [`switch`](/languages/motoko/fundamentals/switch) statements. +By leveraging the `Option` module, handling optional values becomes more concise and expressive, reducing the need for explicit [`switch`](/languages/motoko/fundamentals/control-flow/switch) statements. ### Providing default values @@ -67,7 +67,7 @@ Option.get(username, "Guest"); // "Guest" if username is null ### Using options for error handling -Options can be used to catch expected failures instead of calling a [`trap`](/languages/motoko/fundamentals/traps), making a function return `null` when it encounters an invalid input. +Options can be used to catch expected failures instead of calling a [`trap`](/languages/motoko/fundamentals/basic-syntax/traps), making a function return `null` when it encounters an invalid input. ```motoko func safeDivide(a : Int, b : Int) : ?Int { diff --git a/docs/languages/motoko/fundamentals/primitive-types.md b/docs/languages/motoko/fundamentals/types/primitive-types.md similarity index 100% rename from docs/languages/motoko/fundamentals/primitive-types.md rename to docs/languages/motoko/fundamentals/types/primitive-types.md diff --git a/docs/languages/motoko/fundamentals/records.md b/docs/languages/motoko/fundamentals/types/records.md similarity index 95% rename from docs/languages/motoko/fundamentals/records.md rename to docs/languages/motoko/fundamentals/types/records.md index 0d18816b..fbd7d65f 100644 --- a/docs/languages/motoko/fundamentals/records.md +++ b/docs/languages/motoko/fundamentals/types/records.md @@ -5,7 +5,7 @@ title: "Records" --- Records allow you to group related values using named fields, with each field potentially having a different type. -Unlike [tuples](/languages/motoko/fundamentals/tuples), which use positional access, records provide field-based access, improving readability and maintainability. +Unlike [tuples](/languages/motoko/fundamentals/types/tuples), which use positional access, records provide field-based access, improving readability and maintainability. Records also support **mutable fields**, declared using the `var` keyword. In contrast, all fields in a tuple are always **immutable**. @@ -120,7 +120,7 @@ let individual : Individual = { ## Pattern matching on records -Records can be destructured using [`switch`](/languages/motoko/fundamentals/switch), allowing selective extraction of fields. This approach makes accessing deeply nested fields more explicit and readable. +Records can be destructured using [`switch`](/languages/motoko/fundamentals/control-flow/switch), allowing selective extraction of fields. This approach makes accessing deeply nested fields more explicit and readable. ```motoko type Address = { diff --git a/docs/languages/motoko/fundamentals/results.md b/docs/languages/motoko/fundamentals/types/results.md similarity index 100% rename from docs/languages/motoko/fundamentals/results.md rename to docs/languages/motoko/fundamentals/types/results.md diff --git a/docs/languages/motoko/fundamentals/shared-types.md b/docs/languages/motoko/fundamentals/types/shared-types.md similarity index 75% rename from docs/languages/motoko/fundamentals/shared-types.md rename to docs/languages/motoko/fundamentals/types/shared-types.md index 11202541..52252024 100644 --- a/docs/languages/motoko/fundamentals/shared-types.md +++ b/docs/languages/motoko/fundamentals/types/shared-types.md @@ -4,7 +4,7 @@ description: "Motoko language documentation" title: "Shared types" --- -All Motoko types are divided into sets. The smallest is the set of shared types. Shared types are part of the larger set of [stable types](/languages/motoko/fundamentals/stable-types). +All Motoko types are divided into sets. The smallest is the set of shared types. Shared types are part of the larger set of [stable types](/languages/motoko/fundamentals/types/stable-types). A shared type's value can be easily exchanged with other actors. To prevent issues associated with sharing mutable state across actors, **all shared types are immutable**. This immutability allows values to be transmitted safely by copying data, avoiding the complexity and risks of sharing stateful or mutable objects. @@ -22,14 +22,14 @@ Shareability is essential for several reasons: - Shared types ensure data can be safely serialized and deserialized across network boundaries. - Restricting sharing to immutable data prevents synchronization issues between canisters. -- Shared types map directly to [Candid](https://internetcomputer.org/docs/building-apps/interact-with-canisters/candid/candid-concepts), enabling interaction between canisters written in different languages. +- Shared types map directly to [Candid](/guides/canister-calls/candid), enabling interaction between canisters written in different languages. - Web and mobile frontends communicate with canisters using shared types. ## Common shared types ### Primitive types -Most [primitive types](/languages/motoko/fundamentals/primitive-types) are shared by default. +Most [primitive types](/languages/motoko/fundamentals/types/primitive-types) are shared by default. ```motoko no-repl // Numbers, text, and booleans are shared @@ -40,7 +40,7 @@ let flag : Bool = true; ### Immutable collections -Collections that cannot be modified after creation are shared, including [immutable arrays](/languages/motoko/fundamentals/immutable-arrays) and [tuples](/languages/motoko/fundamentals/tuples). +Collections that cannot be modified after creation are shared, including [immutable arrays](/languages/motoko/fundamentals/types/immutable-arrays) and [tuples](/languages/motoko/fundamentals/types/tuples). ```motoko no-repl // Immutable arrays are shared @@ -52,7 +52,7 @@ let person : (Text, Nat) = ("Motoko", 25); ### Records with immutable fields -Objects with immutable fields containing shared types are shared, including [records](/languages/motoko/fundamentals/records). +Objects with immutable fields containing shared types are shared, including [records](/languages/motoko/fundamentals/types/records). ```motoko no-repl // Records with immutable fields are shared @@ -65,7 +65,7 @@ let user = { ### Variants with shared type tags -[Variant types](/languages/motoko/fundamentals/variants) are shared when their tags contain shared types. +[Variant types](/languages/motoko/fundamentals/types/variants) are shared when their tags contain shared types. ```motoko no-repl // Variant types with shared tags are shared @@ -80,7 +80,7 @@ let failure : Result = #error("Operation failed"); ### Option types -[Option types](/languages/motoko/fundamentals/options) are shared when they contain shared types. +[Option types](/languages/motoko/fundamentals/types/options) are shared when they contain shared types. ```motoko no-repl // Option types with shared inner types are shared @@ -90,7 +90,7 @@ let nothing : ?Nat = null; ### Actor references -References to [actors](/languages/motoko/fundamentals/actors-async) are shared, allowing [canisters](https://internetcomputer.org/docs/building-apps/essentials/canisters) to call each other. +References to [actors](/languages/motoko/fundamentals/actors/actors-async) are shared, allowing [canisters](/concepts/canisters) to call each other. ```motoko no-repl // Actor types are shared @@ -102,7 +102,7 @@ type CounterActor = actor { ### Shared functions -[Function types](/languages/motoko/fundamentals/functions) marked as `shared` are sharable. +[Function types](/languages/motoko/fundamentals/types/function-types) marked as `shared` are sharable. ```motoko no-repl // Shared function types are shared @@ -111,7 +111,7 @@ type Callback = shared (Nat) -> async (); ## Non-shared types -Certain types cannot be shared between [canisters](https://internetcomputer.org/docs/building-apps/essentials/canisters). +Certain types cannot be shared between [canisters](/concepts/canisters). ### Mutable collections diff --git a/docs/languages/motoko/fundamentals/stable-types.md b/docs/languages/motoko/fundamentals/types/stable-types.md similarity index 88% rename from docs/languages/motoko/fundamentals/stable-types.md rename to docs/languages/motoko/fundamentals/types/stable-types.md index dadd17bd..96e71762 100644 --- a/docs/languages/motoko/fundamentals/stable-types.md +++ b/docs/languages/motoko/fundamentals/types/stable-types.md @@ -4,7 +4,7 @@ description: "Motoko language documentation" title: "Stable types" --- -**Stable types** include all [shared types](/languages/motoko/fundamentals/shared-types) and represent the kinds of values that can be stored in the `stable` declarations of a Motoko actor. +**Stable types** include all [shared types](/languages/motoko/fundamentals/types/shared-types) and represent the kinds of values that can be stored in the `stable` declarations of a Motoko actor. Storing a value in a `stable` declaration ensures that it persists across canister upgrades. This enables state preservation without the need for an external file system or database. The set of stable types defines the kinds of values that can be transferred from an actor to its future upgraded versions. @@ -26,7 +26,7 @@ To give the user more flexibility, the set of stable types is larger than the se ## Stable vs shared types -While all shared types are stable, the reverse is not true. Some stable types cannot be shared across [canisters](https://internetcomputer.org/docs/building-apps/essentials/canisters). +While all shared types are stable, the reverse is not true. Some stable types cannot be shared across [canisters](/concepts/canisters). | Type | Stable | Shared | |----------------------------------------------------------------------------------------------|--------|--------| @@ -55,7 +55,7 @@ Non-shared functions and futures (`async T`) and computations (`async* T`) depen ### Primitive types -Most [primitive types](/languages/motoko/fundamentals/primitive-types) in Motoko are stable. +Most [primitive types](/languages/motoko/fundamentals/types/primitive-types) in Motoko are stable. ```motoko no-repl persistent actor { @@ -83,7 +83,7 @@ persistent actor { ### Records with mutable or immutable fields -[Records](/languages/motoko/fundamentals/records) that contain only stable types remain stable, regardless of whether their fields are mutable or immutable. +[Records](/languages/motoko/fundamentals/types/records) that contain only stable types remain stable, regardless of whether their fields are mutable or immutable. ```motoko no-repl persistent actor { @@ -104,7 +104,7 @@ persistent actor { ### Variants with stable type tags -[Variants](/languages/motoko/fundamentals/variants) are stable when their tags contain only stable types. +[Variants](/languages/motoko/fundamentals/types/variants) are stable when their tags contain only stable types. ```motoko no-repl persistent actor { @@ -122,7 +122,7 @@ persistent actor { ### Option types -[Option](/languages/motoko/fundamentals/options) types are stable when they contain stable types. +[Option](/languages/motoko/fundamentals/types/options) types are stable when they contain stable types. ```motoko no-repl persistent actor { @@ -145,7 +145,7 @@ persistent actor { ### Actor references -References to [actors](/languages/motoko/fundamentals/actors-async) are stable, allowing stable canister-to-canister interactions. +References to [actors](/languages/motoko/fundamentals/actors/actors-async) are stable, allowing stable canister-to-canister interactions. ```motoko no-repl persistent actor { diff --git a/docs/languages/motoko/fundamentals/subtyping.md b/docs/languages/motoko/fundamentals/types/subtyping.md similarity index 94% rename from docs/languages/motoko/fundamentals/subtyping.md rename to docs/languages/motoko/fundamentals/types/subtyping.md index 0368e5bd..d7586feb 100644 --- a/docs/languages/motoko/fundamentals/subtyping.md +++ b/docs/languages/motoko/fundamentals/types/subtyping.md @@ -125,7 +125,7 @@ discard("abc"); // Allowed, since `Text <: Any` ## Options -If `T <: U`, then `?T <: ?U` because option subtyping is covariant. This means an [optional value](/languages/motoko/fundamentals/options) of a subtype can be used as an optional value of a supertype. +If `T <: U`, then `?T <: ?U` because option subtyping is covariant. This means an [optional value](/languages/motoko/fundamentals/types/options) of a subtype can be used as an optional value of a supertype. ```motoko no-repl let a : ?Nat = ?5; @@ -144,7 +144,7 @@ let ot : ?Text = n; // Allowed, since `Null <: ?Text` ## Records and objects -[Records](/languages/motoko/fundamentals/records) and, more generally, [objects](/languages/motoko/fundamentals/objects-classes) +[Records](/languages/motoko/fundamentals/types/records) and, more generally, [objects](/languages/motoko/fundamentals/types/objects-classes) support subtyping, both in the required fields and the types of those fields. An object type `T` is a subtype of another object type `U`, if `T` requires all the fields required by `U`, @@ -182,7 +182,7 @@ However, both `A` and `B` are still subtypes of `C`, since `C` lacks the `age` f ## Variants -[Variants](/languages/motoko/fundamentals/variants) also support subtyping, both in the allowed fields and the types of those fields. +[Variants](/languages/motoko/fundamentals/types/variants) also support subtyping, both in the allowed fields and the types of those fields. A variant type `T` is a subtype of another variant type `U` if every value in `T` also appears in `U`, and the associated types in `T` are subtypes of those in `U`. `T` may allow fewer fields than `U`. @@ -227,7 +227,7 @@ let rok : Result = ok; // Allowed, since `{#ok : Nat} <: {#ok : Int; ## Immutable arrays -[Immutable arrays (`[T]`)](/languages/motoko/fundamentals/immutable-arrays) support covariant subtyping, meaning if `T <: U`, then `[T] <: [U]`. +[Immutable arrays (`[T]`)](/languages/motoko/fundamentals/types/immutable-arrays) support covariant subtyping, meaning if `T <: U`, then `[T] <: [U]`. If `T <: U`, then an (immutable) array of type `[T]` can be used as an array of type `[U]`. @@ -238,7 +238,7 @@ let ints : [Int] = nats; // Allowed, since `Nat <: Int` we also have `[Nat] <: ## Mutable arrays -[Mutable arrays](/languages/motoko/fundamentals/mutable-arrays) of the form `[var T]` do not support interesting subtyping. +[Mutable arrays](/languages/motoko/fundamentals/types/mutable-arrays) of the form `[var T]` do not support interesting subtyping. The mutable array constructor `[var T]` is invariant in `T`. This means that `[var T]` is a subtype of `[var U]` only if `T` and `U` are equivalent types, that is, both `T <: U` and `U <: T` must hold. @@ -252,7 +252,7 @@ let ints : [var Int] = nats; // Not allowed, because `[var Nat] T2` is a subtype of another function type `U1 -> U2` provided that: 1. The argument types are related in the opposite direction (`U1 <: T1` ). @@ -298,7 +298,7 @@ In the case of actors, which can only contain shared functions as fields, this m ## Recursive and generic types -[Recursive and generic types](/languages/motoko/fundamentals/advanced-types) can be subtypes of each other when their definitions allow it. +[Recursive and generic types](/languages/motoko/fundamentals/types/advanced-types) can be subtypes of each other when their definitions allow it. Consider the following recursive point types, where the second extends the first by adding a color field: diff --git a/docs/languages/motoko/fundamentals/tuples.md b/docs/languages/motoko/fundamentals/types/tuples.md similarity index 99% rename from docs/languages/motoko/fundamentals/tuples.md rename to docs/languages/motoko/fundamentals/types/tuples.md index 9d742241..b9ecddc2 100644 --- a/docs/languages/motoko/fundamentals/tuples.md +++ b/docs/languages/motoko/fundamentals/types/tuples.md @@ -59,7 +59,7 @@ Tuples can be stored in arrays or other data structures. Tuples can be construct let users : [(Text, Nat)] = [("Motoko", 25), ("Ghost", 30)]; ``` -This structure efficiently represents a collection of key-value pairs without requiring a dedicated [record](/languages/motoko/fundamentals/records) type. +This structure efficiently represents a collection of key-value pairs without requiring a dedicated [record](/languages/motoko/fundamentals/types/records) type. ## Pattern matching on tuples diff --git a/docs/languages/motoko/fundamentals/type-conversions.md b/docs/languages/motoko/fundamentals/types/type-conversions.md similarity index 95% rename from docs/languages/motoko/fundamentals/type-conversions.md rename to docs/languages/motoko/fundamentals/types/type-conversions.md index 28519598..5626f5f6 100644 --- a/docs/languages/motoko/fundamentals/type-conversions.md +++ b/docs/languages/motoko/fundamentals/types/type-conversions.md @@ -162,7 +162,7 @@ assert arrayOfNatToText([1, 2, 3]) == "1 2 3"; ### `Array` of tuples to an object -Motoko lacks support for dynamic objects, so an array of tuples is converted into a [record](/languages/motoko/fundamentals/records) or a structured representation. +Motoko lacks support for dynamic objects, so an array of tuples is converted into a [record](/languages/motoko/fundamentals/types/records) or a structured representation. ```motoko no-repl import HashMap "mo:core/HashMap"; @@ -181,7 +181,7 @@ persistent actor MapConverter { arrayToMap([("Motoko", 4), ("Ghost", 21)]); ``` -To convert an array of tuples `[(Text, Nat)]` into a custom [record](/languages/motoko/fundamentals/records) type, such as `User`, `Array.map` is used to transform each tuple into a structured [record](/languages/motoko/fundamentals/records). +To convert an array of tuples `[(Text, Nat)]` into a custom [record](/languages/motoko/fundamentals/types/records) type, such as `User`, `Array.map` is used to transform each tuple into a structured [record](/languages/motoko/fundamentals/types/records). ```motoko no-repl import Array "mo:core/Array"; diff --git a/docs/languages/motoko/fundamentals/variants.md b/docs/languages/motoko/fundamentals/types/variants.md similarity index 86% rename from docs/languages/motoko/fundamentals/variants.md rename to docs/languages/motoko/fundamentals/types/variants.md index fff7dec7..175378a1 100644 --- a/docs/languages/motoko/fundamentals/variants.md +++ b/docs/languages/motoko/fundamentals/types/variants.md @@ -4,7 +4,7 @@ description: "Motoko language documentation" title: "Variants" --- -Variant type describe values that take on one of several forms, each labeled with a distinct tag. Unlike [records](/languages/motoko/fundamentals/records), where all fields exist at once, a value of a variant type holds exactly one of the type's possible values. This makes variants useful for representing mutually exclusive alternatives such as states, enumerations, categories and even trees. +Variant type describe values that take on one of several forms, each labeled with a distinct tag. Unlike [records](/languages/motoko/fundamentals/types/records), where all fields exist at once, a value of a variant type holds exactly one of the type's possible values. This makes variants useful for representing mutually exclusive alternatives such as states, enumerations, categories and even trees. ## Defining a variant @@ -29,7 +29,7 @@ let bannedUser = #Banned("Violation of rules"); ## Accessing a variant's value -To work with a variant, use a [`switch`](/languages/motoko/fundamentals/switch) expression to match each possible case. +To work with a variant, use a [`switch`](/languages/motoko/fundamentals/control-flow/switch) expression to match each possible case. ```motoko no-repl import Debug "mo:core/Debug"; @@ -59,7 +59,7 @@ A traffic light cycles between three distinct states: - Yellow: Vehicles should prepare to stop. - Green: Vehicles may proceed. -Since the traffic light can only be in one of these states at a time, a variant is well-suited to model it. There is no invalid [state](/languages/motoko/fundamentals/state), as every possible value is explicitly defined. The transitions are controlled and predictable. +Since the traffic light can only be in one of these states at a time, a variant is well-suited to model it. There is no invalid [state](/languages/motoko/fundamentals/actors/state), as every possible value is explicitly defined. The transitions are controlled and predictable. ### Defining the traffic light state @@ -73,7 +73,7 @@ type TrafficLight = { ### Transitioning between states -A function can define how the traffic light cycles from one [state](/languages/motoko/fundamentals/state) to the next. +A function can define how the traffic light cycles from one [state](/languages/motoko/fundamentals/actors/state) to the next. ```motoko no-repl func nextState(light : TrafficLight) : TrafficLight { @@ -183,7 +183,7 @@ traverseInOrder(tree); ### Using generic types -Currently, the example tree only supports [`Nat`](https://mops.one/core/docs/Nat) values. To allow it to store any type of data, a [generic type](/languages/motoko/fundamentals/advanced-types#generic-types) can be used. A generic type allows a data structure to work with multiple types by using a placeholder type `T`, which is replaced with a specific type when used. +Currently, the example tree only supports [`Nat`](https://mops.one/core/docs/Nat) values. To allow it to store any type of data, a [generic type](/languages/motoko/fundamentals/types/advanced-types#generic-types) can be used. A generic type allows a data structure to work with multiple types by using a placeholder type `T`, which is replaced with a specific type when used. ```motoko no-repl type Tree = { diff --git a/docs/languages/motoko/icp-features/caller-identification.md b/docs/languages/motoko/icp-features/caller-identification.md index cc697935..10391907 100644 --- a/docs/languages/motoko/icp-features/caller-identification.md +++ b/docs/languages/motoko/icp-features/caller-identification.md @@ -1,5 +1,6 @@ --- -sidebar_position: 3 +sidebar: + order: 3 description: "Motoko language documentation" title: "Caller identification" --- @@ -34,46 +35,14 @@ Access control can be added to an application by recording a caller's principal For example, if you have an actor called `Counter`, you can record the principal that installed the actor by binding it to an `owner` variable. Then, you can implement a check that verifies that the caller of each method the actor exposes is equal to the principal stored in `owner`: -```motoko -shared(msg) persistent actor class Counter(init : Nat) { - - transient let owner = msg.caller; - - var count = init; - - public shared(msg) func inc() : async () { - assert (owner == msg.caller); - count += 1; - }; - - public func read() : async Nat { - count - }; - - public shared(msg) func bump() : async Nat { - assert (owner == msg.caller); - count := 1; - count; - }; -} +```motoko file=/Counters-caller.mo ``` In this example, the `assert (owner == msg.caller)` expression causes the functions `inc()` and `bump()` to trap if the call is unauthorized, preventing any modification of the `count` variable. However, the `read()` function permits any caller. The argument to `shared` is just a pattern. You can rewrite the above to use pattern matching: -```motoko -shared({caller = owner}) persistent actor class Counter(init : Nat) { - - var count : Nat = init; - - public shared({caller}) func inc() : async () { - assert (owner == caller); - count += 1; - }; - - // ... -} +```motoko file=/Counters-caller-pat.mo ``` :::note @@ -101,32 +70,7 @@ The data type of `Principal` in Motoko supports equality, ordering, and hashing. Below is an example of how you can record a function's caller `Principal`s in a set and check if a caller is already in the set: -```motoko -import Principal "mo:core/Principal"; -import Set "mo:core/pure/Set"; -import Error "mo:core/Error"; - -persistent actor { - - // Create set to record principals - var principals : Set.Set = Set.empty(); - - // Check if principal is recorded - public shared query(msg) func isRecorded() : async Bool { - let caller = msg.caller; - Set.contains(principals, Principal.compare, caller); - }; - - // Record a new principal - public shared(msg) func recordPrincipal() : async () { - let caller = msg.caller; - if (Principal.isAnonymous(caller)) { - throw Error.reject("Anonymous principal not allowed"); - }; - - principals := Set.add(principals, Principal.compare, caller) - }; -}; +```motoko file=/RecordPrincipals.mo ``` diff --git a/docs/languages/motoko/icp-features/candid-serialization.md b/docs/languages/motoko/icp-features/candid-serialization.md index 5f2721f5..64f7f700 100644 --- a/docs/languages/motoko/icp-features/candid-serialization.md +++ b/docs/languages/motoko/icp-features/candid-serialization.md @@ -1,5 +1,6 @@ --- -sidebar_position: 4 +sidebar: + order: 4 description: "Motoko language documentation" title: "Candid serialization" --- @@ -10,9 +11,9 @@ Motoko automatically generates Candid interfaces for canisters and provides buil ## Autogenerated Candid interfaces -When Motoko code is compiled, a Candid interface file [(`.did`)](https://internetcomputer.org/docs/building-apps/interact-with-canisters/candid/using-candid#the-did-file) for the canister's public methods is automatically generated. This file is used to ensure data passed into and returned from these methods is automatically encoded to and decoded from Candid’s binary format. +When Motoko code is compiled, a Candid interface file [(`.did`)](/guides/canister-calls/candid#the-did-file) for the canister's public methods is automatically generated. This file is used to ensure data passed into and returned from these methods is automatically encoded to and decoded from Candid’s binary format. -Motoko canisters automatically handle the serialization and deserialization of data when the canister interacts with [inter-canister calls or ingress messages](https://internetcomputer.org/docs/building-apps/essentials/message-execution). +Motoko canisters automatically handle the serialization and deserialization of data when the canister interacts with [inter-canister calls or ingress messages](/references/message-execution-properties). ## Candid operators @@ -131,6 +132,6 @@ While dynamic calls offer more flexibility, they should be used judiciously. In For more detailed information on Candid, refer to: -- [What is Candid?](https://internetcomputer.org/docs/building-apps/interact-with-canisters/candid/candid-concepts) -- [Using Candid](https://internetcomputer.org/docs/building-apps/interact-with-canisters/candid/using-candid) -- [Candid Specification](https://internetcomputer.org/docs/references/candid-ref) +- [What is Candid?](/guides/canister-calls/candid) +- [Using Candid](/guides/canister-calls/candid) +- [Candid Specification](/references/candid-spec) diff --git a/docs/languages/motoko/icp-features/randomness.md b/docs/languages/motoko/icp-features/randomness.md index 2456fe52..d185764c 100644 --- a/docs/languages/motoko/icp-features/randomness.md +++ b/docs/languages/motoko/icp-features/randomness.md @@ -1,12 +1,13 @@ --- -sidebar_position: 1 +sidebar: + order: 1 description: "Motoko language documentation" title: "Randomness" --- -[Randomness](https://internetcomputer.org/docs/building-apps/network-features/randomness) is used for generating unique identifiers, ensuring fairness in games, cryptographic protocols, and much more. On ICP, all computations, including [randomness](https://internetcomputer.org/docs/building-apps/network-features/randomness), must be **verifiable and reproducible** across the network's nodes. +[Randomness](/guides/backends/randomness) is used for generating unique identifiers, ensuring fairness in games, cryptographic protocols, and much more. On ICP, all computations, including [randomness](/guides/backends/randomness), must be **verifiable and reproducible** across the network's nodes. -The network provides a **verifiable random function (VRF)** through the [management canister](https://internetcomputer.org/docs/references/system-canisters/management-canister) that produces random values that are unpredictable yet verifiable, ensuring fairness and security while maintaining network consensus. It guarantees cryptographic security, making it suitable for use cases such as cryptographic key generation. +The network provides a **verifiable random function (VRF)** through the [management canister](/references/management-canister) that produces random values that are unpredictable yet verifiable, ensuring fairness and security while maintaining network consensus. It guarantees cryptographic security, making it suitable for use cases such as cryptographic key generation. The VRF generates 256-bit random `Blob`s in each execution round. A canister can request one of these random `Blob`s via the management canister's `raw_rand` method. @@ -27,7 +28,7 @@ Before using the [`fuzz`](https://mops.one/fuzz) or [`idempotency-keys`](https:/ ## `raw_rand` -The `raw_rand` function is a system API provided by the [ICP management canister](https://internetcomputer.org/docs/references/system-canisters/management-canister) for requesting cryptographic randomness derived from the network’s verifiable random function. `raw_rand` generates fresh entropy in every execution round, making it suitable for applications requiring high security such as key generation or applications where fairness is a legal requirement. +The `raw_rand` function is a system API provided by the [ICP management canister](/references/management-canister) for requesting cryptographic randomness derived from the network’s verifiable random function. `raw_rand` generates fresh entropy in every execution round, making it suitable for applications requiring high security such as key generation or applications where fairness is a legal requirement. Since `raw_rand` operates asynchronously, canisters must await its response before using the generated bytes. Each call returns a 32-byte (256-bit) random `Blob`. @@ -104,7 +105,7 @@ persistent actor { ## Resources -- [`raw_rand`](https://internetcomputer.org/docs/references/ic-interface-spec#ic-raw_rand) +- [`raw_rand`](/references/ic-interface-spec/#ic-raw_rand) - [`Random`](https://mops.one/core/docs/Random) - [`fuzz`](https://mops.one/fuzz) - [`idempotency-keys`](https://mops.one/idempotency-keys) diff --git a/docs/languages/motoko/icp-features/stable-memory.md b/docs/languages/motoko/icp-features/stable-memory.md index 0df985f6..2b1363df 100644 --- a/docs/languages/motoko/icp-features/stable-memory.md +++ b/docs/languages/motoko/icp-features/stable-memory.md @@ -1,17 +1,18 @@ --- -sidebar_position: 5 +sidebar: + order: 5 description: "Motoko language documentation" title: "Stable memory and regions" --- -Canisters have two types of storage: Wasm memory and stable memory. The Wasm memory is often referred to as the [heap memory](https://internetcomputer.org/docs/building-apps/canister-management/storage#heap-memory). It is automatically used for heap-allocated objects and has a maximum size limitation of 4 GiB or 6 GiB respective to whether you are using 32-bit or 64-bit heap storage without enhanced orthogonal persistence. When a canister is upgraded, the heap memory is cleared, only retaining data stored in stable variables. +Canisters have two types of storage: Wasm memory and stable memory. The Wasm memory is often referred to as the [heap memory](/concepts/orthogonal-persistence#heap-wasm-linear-memory). It is automatically used for heap-allocated objects and has a maximum size limitation of 4 GiB or 6 GiB respective to whether you are using 32-bit or 64-bit heap storage without enhanced orthogonal persistence. When a canister is upgraded, the heap memory is cleared, only retaining data stored in stable variables. -Stable memory has a maximum size of 500 GiB and is preserved across canister upgrades. Motoko utilizes [stable memory](https://internetcomputer.org/docs/building-apps/canister-management/storage#stable-memory) through the [stable storage feature](https://internetcomputer.org/docs/building-apps/canister-management/storage#motoko-storage-handling) to preserve data across canister upgrades. Stable regions extend this functionality to allow more structured and flexible memory management. +Stable memory has a maximum size of 500 GiB and is preserved across canister upgrades. Motoko utilizes [stable memory](/concepts/orthogonal-persistence#stable-memory) through the [stable storage feature](/concepts/orthogonal-persistence#motoko-true-orthogonal-persistence) to preserve data across canister upgrades. Stable regions extend this functionality to allow more structured and flexible memory management. The system automatically commits all memory modifications, both Wasm and stable, after the successful execution of a message. If a message execution fails, the changes are not committed. :::caution -The `Regions` library should only be used if [enhanced orthogonal persistence](/languages/motoko/fundamentals/orthogonal-persistence-enhanced) does not fit your use case. +The `Regions` library should only be used if [enhanced orthogonal persistence](/languages/motoko/fundamentals/actors/orthogonal-persistence/enhanced) does not fit your use case. ::: ## What is a `Region`? @@ -56,7 +57,7 @@ let previousSize = Region.grow(myRegion, 10); // Add 10 pages (640 KiB) ### Growing a `Region` safely -`Regions` can only grow, never shrink. Growth may fail due to [ICP resource limitations](https://internetcomputer.org/docs/building-apps/canister-management/resource-limits) and it is recommended to use the minimum pages needed to conserve resources. +`Regions` can only grow, never shrink. Growth may fail due to [ICP resource limitations](/guides/canister-management/large-wasm) and it is recommended to use the minimum pages needed to conserve resources. Growing a [`Region`](https://mops.one/core/docs/Region) safely requires checking the current allocated size and ensuring that the required space does not exceed available capacity. Since stable memory is allocated in fixed-size pages of 64 KiB, any expansion must be done in page increments. To determine how many additional pages are needed, the difference between the required memory and the current capacity is calculated and rounded up to the nearest page boundary. Once the necessary pages are determined, the [`Region`](https://mops.one/core/docs/Region) is expanded accordingly. After growth, verifying that the expansion was successful ensures stability and prevents unintended memory access issues. diff --git a/docs/languages/motoko/icp-features/system-functions.md b/docs/languages/motoko/icp-features/system-functions.md index 071edd7a..e2d8e627 100644 --- a/docs/languages/motoko/icp-features/system-functions.md +++ b/docs/languages/motoko/icp-features/system-functions.md @@ -1,24 +1,25 @@ --- -sidebar_position: 6 +sidebar: + order: 6 description: "Motoko language documentation" title: "System functions" --- ICP supports five system functions that canisters can call to interact with the ICP runtime environment: -- [`timer`](https://internetcomputer.org/docs/references/ic-interface-spec#global-timer) +- [`timer`](/references/ic-interface-spec/#global-timer) - [`preupgrade`](#preupgrade) - [`postupgrade`](#postupgrade) - [`lowmemory`](#lowmemory) -- [`inspect`](https://internetcomputer.org/docs/references/ic-interface-spec#system-api-inspect-message) -- [`heartbeat`](https://internetcomputer.org/docs/references/ic-interface-spec#heartbeat) +- [`inspect`](/references/ic-interface-spec/#system-api-inspect-message) +- [`heartbeat`](/references/ic-interface-spec/#heartbeat) Declaring any other system function will result in an error. Canisters can use these functions to efficiently manage state transitions, automate tasks, or handle system-level operations. ## `timer()` -The [`timer()` system function](https://internetcomputer.org/docs/building-apps/network-features/periodic-tasks-timers#timers) lets canisters schedule a task to execute after a specified delay. To make the timer repeat, the function must explicitly call `setGlobalTimer()` within its body to reset the timer. It accepts a single argument to set the global timer and returns `async ()`. +The [`timer()` system function](/guides/backends/timers#timers) lets canisters schedule a task to execute after a specified delay. To make the timer repeat, the function must explicitly call `setGlobalTimer()` within its body to reset the timer. It accepts a single argument to set the global timer and returns `async ()`. Unlike `heartbeat()`, which runs automatically every subnet round, `timer()` requires manual rescheduling after each execution. This design gives canisters precise control over whether the timer runs once or continuously, depending on if and when `setGlobalTimer()` is called again. @@ -121,11 +122,11 @@ The following properties apply to the low memory hook: ## `inspect()` -The [`inspect()` system function](https://internetcomputer.org/docs/references/ic-interface-spec#system-api-inspect-message) allows a canister to inspect ingress messages before execution, determining whether to accept or reject them. The function receives a record of message attributes, including the caller’s principal, the raw argument `Blob`, and a variant identifying the target function. +The [`inspect()` system function](/references/ic-interface-spec/#system-api-inspect-message) allows a canister to inspect ingress messages before execution, determining whether to accept or reject them. The function receives a record of message attributes, including the caller’s principal, the raw argument `Blob`, and a variant identifying the target function. -It returns a `Bool`, where `true` permits execution and `false` rejects the message. Similar to a [query](https://internetcomputer.org/docs/building-apps/essentials/message-execution), any side effects are discarded. If `inspect()` traps, it is equivalent to returning `false`. Unlike other system functions, the argument type of `inspect()` depends on the actor's exposed interface, meaning it can selectively handle different methods or ignore unnecessary fields. +It returns a `Bool`, where `true` permits execution and `false` rejects the message. Similar to a [query](/references/message-execution-properties), any side effects are discarded. If `inspect()` traps, it is equivalent to returning `false`. Unlike other system functions, the argument type of `inspect()` depends on the actor's exposed interface, meaning it can selectively handle different methods or ignore unnecessary fields. -However, `inspect()` should not be used for definitive access control because it runs on a single replica without going through consensus, making it susceptible to boundary node spoofing. Additionally, `inspect()` only applies to [ingress messages](https://internetcomputer.org/docs/building-apps/essentials/message-execution), not [inter-canister calls](https://internetcomputer.org/docs/references/async-code), meaning secure access control must still be enforced within shared functions. +However, `inspect()` should not be used for definitive access control because it runs on a single replica without going through consensus, making it susceptible to boundary node spoofing. Additionally, `inspect()` only applies to [ingress messages](/references/message-execution-properties), not [inter-canister calls](/references/message-execution-properties), meaning secure access control must still be enforced within shared functions. The following actor defines an inspect function that blocks anonymous callers, limits message size, and rejects specific argument values. @@ -172,12 +173,12 @@ persistent actor Counter { Heartbeats are computationally expensive for both the network and user, and instead you should use a timer if possible. ::: -Canisters can opt to receive [heartbeat messages](https://internetcomputer.org/docs/building-apps/network-features/periodic-tasks-timers#heartbeats) by exposing a `canister_heartbeat` function. In Motoko, this is achieved by declaring the system function `heartbeat`, which takes no arguments and returns an asynchronous unit type (`async ()`). +Canisters can opt to receive [heartbeat messages](/guides/backends/timers#heartbeats) by exposing a `canister_heartbeat` function. In Motoko, this is achieved by declaring the system function `heartbeat`, which takes no arguments and returns an asynchronous unit type (`async ()`). Since `heartbeat()` is async, it can invoke other asynchronous functions and await their results. This function executes on every **subnet heartbeat**, enabling periodic task execution without requiring external triggers. Since subnet heartbeats operate at the protocol level, their timing is not precise and depends on network conditions and execution load. As a result, using heartbeats for high-frequency or time-sensitive operations should be done cautiously, as there is no guarantee of real-time execution. Every async call in Motoko causes a context switch, which means the actual execution of the heartbeat function may be delayed relative to when the subnet triggers it. The function’s result is ignored, so any errors or traps during execution do not impact future heartbeat calls. -If a canister exports a function named `canister_heartbeat`, it must have the type `() -> ()`, ensuring it adheres to the expected [system function signature](https://internetcomputer.org/docs/references/ic-interface-spec#heartbeat). +If a canister exports a function named `canister_heartbeat`, it must have the type `() -> ()`, ensuring it adheres to the expected [system function signature](/references/ic-interface-spec/#heartbeat). Heartbeats should be considered deprecated as they have been superseded by timers. diff --git a/docs/languages/motoko/icp-features/timers.md b/docs/languages/motoko/icp-features/timers.md index 36ef5eae..1b7a6d4b 100644 --- a/docs/languages/motoko/icp-features/timers.md +++ b/docs/languages/motoko/icp-features/timers.md @@ -1,5 +1,6 @@ --- -sidebar_position: 2 +sidebar: + order: 2 description: "Motoko language documentation" title: "Timers" --- @@ -10,29 +11,10 @@ Canisters can set recurring timers that execute a piece of code after a specifie A simple example is a periodic reminder that logs a new year's message: -```motoko -import { print } = "mo:core/Debug"; -import { abs } = "mo:core/Int"; -import { now } = "mo:core/Time"; -import { setTimer; recurringTimer } = "mo:core/Timer"; - -persistent actor Reminder { - - transient let solarYearSeconds = 356_925_216; - - private func remind() : async () { - print("Happy New Year!"); - }; - - ignore setTimer(#seconds (solarYearSeconds - abs(now() / 1_000_000_000) % solarYearSeconds), - func () : async () { - ignore recurringTimer(#seconds solarYearSeconds, remind); - await remind(); - }); -} +```motoko no-repl file=/Reminder.mo ``` -The underlying mechanism is a [global timer](https://internetcomputer.org/docs/references/ic-interface-spec#timer) that, by default, is issued with appropriate callbacks from a priority queue maintained by the Motoko runtime. +The underlying mechanism is a [global timer](/references/ic-interface-spec/#timer) that, by default, is issued with appropriate callbacks from a priority queue maintained by the Motoko runtime. The timer mechanism can be disabled completely by passing the `--no-timer` flag to `moc`. diff --git a/docs/languages/motoko/index.md b/docs/languages/motoko/index.md index 872d98b6..704705c3 100644 --- a/docs/languages/motoko/index.md +++ b/docs/languages/motoko/index.md @@ -5,7 +5,6 @@ sidebar: order: 1 --- - Motoko is a next-generation, high-level programming language designed to empower AI agents building backends for apps and services on the Internet Computer cloud network. While it channels several popular modern languages, it introduces groundbreaking new features such as actor-based concurrency, orthogonal persistence, and seamless WebAssembly integration. ## Key features @@ -109,4 +108,4 @@ If you have an existing project using `base`, you can migrate incrementally; bot - [Orthogonal persistence](../../concepts/orthogonal-persistence.md): how persistent memory works at the platform level - [Motoko GitHub](https://github.com/caffeinelabs/motoko): compiler source and issue tracker - + diff --git a/docs/languages/motoko/reference/changelog.md b/docs/languages/motoko/reference/changelog.md index 27d3e755..2159ac54 100644 --- a/docs/languages/motoko/reference/changelog.md +++ b/docs/languages/motoko/reference/changelog.md @@ -898,7 +898,7 @@ $(dfx cache show)/moc --version ensures that no cleanup is required. The relevant security best practices are accessible at - https://internetcomputer.org/docs/current/developer-docs/security/security-best-practices/inter-canister-calls#recommendation + /guides/security/inter-canister-calls#recommendation BREAKING CHANGE (Minor): `finally` is now a reserved keyword, programs using this identifier will break. diff --git a/docs/languages/motoko/reference/compiler-ref.md b/docs/languages/motoko/reference/compiler-ref.md new file mode 100644 index 00000000..3be90c0f --- /dev/null +++ b/docs/languages/motoko/reference/compiler-ref.md @@ -0,0 +1,78 @@ +--- +sidebar_position: 15 +description: "Motoko language documentation" +title: "Compiler reference" +--- + +The Motoko compiler (`moc`) is the primary tool for compiling Motoko programs into executable WebAssembly (Wasm) modules. The compiler runs in the background when you build projects using the [IC SDK](https://github.com/dfinity/sdk). If you invoke the compiler directly on the command-line, you can press CTRL-C to exit. + +This section provides compiler command-line reference information. + +## moc + +Use the Motoko compiler (`moc`) to compile Motoko programs into executable WebAssembly (Wasm) modules. + +### Basic usage + +``` bash +moc [option] [file ...] +``` + +### Options + +You can use the following options with the `moc` command. + +| Option | Description | +|-------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------| +| `--ai-errors` | Emit AI tailored error messages. | +| `--actor-idl ` | Specifies a path to actor IDL (Candid) files. | +| `--actor-alias ` | Specifies an actor import alias. | +| `--args ` | Read additional newline separated command line arguments from ``. | +| `--args0 ` | Read additional `NUL` separated command line arguments from ``. | +| `-c` | Compile to WebAssembly. | +| `--check` | Performs type checking only. | +| `--compacting-gc` | Use compacting GC (only available with legacy/classical persistence). | +| `--copying-gc` | Use copying GC (only available with legacy/classical persistence). | +| `--debug` | Respects debug expressions in the source (the default). | +| `--enhanced-orthogonal-persistence` | Use enhanced orthogonal persistence (default): Scalable and fast upgrades using a persistent 64-bit main memory. | +| `--enhanced-migration ` | Enable enhanced migration system: requires initializers for all stable variables, disallows side-effects in actor bodies; only available with enhanced orthogonal persistence. | +| `--error-detail ` | Set level of error message detail for syntax errors, n in \[0..3\] (default 2). | +| `--experimental-stable-memory ` | Select support for the deprecated `ExperimentalStableMemory.mo` library (n < 0: error, n = 0: warn, n > 0: allow) (default 0). | +| `-fno-shared-code` | Do not share low-level utility code: larger code size but decreased cycle consumption (default). | +| `--generational-gc` | Use generational GC (only available with legacy/classical persistence). | +| `-fshared-code` | Do share low-level utility code: smaller code size but increased cycle consumption. | +| `--generate-view-queries` | Auto-generate queries for stable variables; preferring applicable .view() methods (default false) | +| `-help`,`--help` | Displays usage information. | +| `--hide-warnings` | Hides compiler warnings. | +| `-Werror` | Treat warnings as errors. | +| `-A ` | Disable (Allow) comma-separated warning codes, e.g. `-A M0194,M0223` | +| `-W ` | Enable (Warn) comma-separated warning codes, e.g. `-W M0223` | +| `-E ` | Treat as error comma-separated warning codes, e.g. `-E M0217` | +| `--warn-help` | Show available warning codes, current lint level, and descriptions | +| `--incremental-gc` | Use incremental GC (default, works with both enhanced orthogonal persistence and legacy/classical persistence). | +| `--idl` | Compile binary and emit Candid IDL specification to `.did` file. | +| `-i` | Runs the compiler in an interactive read–eval–print loop (REPL) shell so you can evaluate program execution (implies -r). | +| `--legacy-persistence` | Use legacy (classical) persistence. This also enables the usage of --copying-gc, --compacting-gc, and --generational-gc. Deprecated in favor of the new enhanced orthogonal persistence, which is default. Legacy persistence will be removed in the future.| +| `--map` | Outputs a JavaScript source map. | +| `--max-stable-pages ` | Set maximum number of pages available for library `ExperimentStableMemory.mo` (default 65536). | +| `-no-system-api` | Disables system API imports. | +| `-no-timer` | Disables timer API imports and hides timer primitives. | +| `-o ` | Specifies the output file. | +| `-p ` | Sets the print depth. | +| `--package ` | Specifies a `` `` pair, separated by a space. | +| `--public-metadata ` | Emit ICP custom section `` (`candid:args` or `candid:service` or `motoko:stable-types` or `motoko:compiler`) as `public` (default is `private`).| +| `--omit-metadata ` | Omit ICP custom section `` (`candid:args` or `candid:service` or `motoko:stable-types` or `motoko:compiler`). | +| `--print-deps` | Prints the dependencies for a given source file. | +| `-r` | Interprets programs. | +| `--release` | Ignores debug expressions in the source. | +| `--stable-regions` | Force eager initialization of stable regions metadata (for testing purposes); consumes between 386KiB or 8MiB of additional physical stable memory, depending on current use of ExperimentalStableMemory. | +| `--stable-types` | Compile binary and emit signature of stable types to `.most` file. | +| `--stable-compatible
 `        | Test upgrade compatibility between stable-type signatures `
` and ``.                                                                       |
+| `--rts-stack-pages `                   | Set maximum number of pages available for runtime system stack (only supported with classical persistence, default 32).                               |
+| `--trap-on-call-error`                    | Trap, don't throw an [`Error`](https://mops.one/core/docs/Error), when an IC call fails due to destination queue full or freezing threshold is crossed. Emulates behavior of moc versions < 0.8.0.                                                                                                                                           |
+| `-t`                                      | Activates tracing in interpreter.                                                                                                                     |
+| `-v`                                      | Generates verbose output.                                                                                                                             |
+| `--version`                               | Displays version information.                                                                                                                         |
+| `-wasi-system-api`                        | Uses the WASI system API (`wasmtime`).                                                                                                                |
+
+
diff --git a/docs/languages/motoko/reference/error-codes.md b/docs/languages/motoko/reference/error-codes.md
index df716e3f..cab2c229 100644
--- a/docs/languages/motoko/reference/error-codes.md
+++ b/docs/languages/motoko/reference/error-codes.md
@@ -17,7 +17,7 @@ title: "Error code reference"
 | M0030 | Type field does not exist in type. | ```type Person = { name : Text }; func getName(p : Person) : Nat { p.age }``` | The field `age` doesn't exist in the `Person` type. |
 | M0031 | Shared function has non-shared parameter type. | ```public shared func process(obj : { var count : Nat }) { ... }``` | Shared functions cannot have mutable types as parameters. |
 | M0032 | Shared function has non-shared return type. | ```public shared func getData() : { var data : [Nat] } { ... }``` | Shared functions cannot return mutable types. |
-| M0033 | Async has non-shared content type. | ```async { var counter = 0 }``` | Async blocks cannot contain mutable [state](/languages/motoko/fundamentals/state). |
+| M0033 | Async has non-shared content type. | ```async { var counter = 0 }``` | Async blocks cannot contain mutable [state](/languages/motoko/fundamentals/actors/state). |
 | M0036 | Invalid return type for shared query function. | ```public shared query func getUsers() : async [User] { ... }``` | Query functions cannot return async types. |
 | M0038 | Misplaced await. | ```func compute() { let x = await promise; }``` | `await` can only be used in an async function or block. |
 | M0045 | Wrong number of type arguments. | ```func process(x : Array) { ... }``` | `Array` type expects one type parameter, not two. |
@@ -33,7 +33,7 @@ title: "Error code reference"
 | M0082 | Expected iterable type. | ```for (item in 42) { ... }``` | The value `42` is not an iterable type for a for-loop. |
 | M0088 | Expected async type. | ```let result = await 42;``` | Cannot `await` on a non-async value. |
 | M0089 | Redundant ignore. | ```ignore (5);``` | The `ignore` is unnecessary for a value that doesn't need to be ignored. |
-| M0090 | Actor reference must have an [actor](/languages/motoko/fundamentals/actors-async) type .| ```let a = actor { ... }; a.someMethod();``` | The variable `a` must have an explicit [actor](/languages/motoko/fundamentals/actors-async) type to call its methods. |
+| M0090 | Actor reference must have an [actor](/languages/motoko/fundamentals/actors/actors-async) type .| ```let a = actor { ... }; a.someMethod();``` | The variable `a` must have an explicit [actor](/languages/motoko/fundamentals/actors/actors-async) type to call its methods. |
 | M0096 | Expression can't produce expected type. | ```func getValue() : Bool { return "true"; }``` | String cannot be returned where a [`Bool`](https://mops.one/core/docs/Bool) is expected. |
 | M0097 | Expected function type. | ```let x = 5; x();``` | Cannot call a non-function value. |
 | M0098 | Cannot instantiate function type. | ```type Func = (Nat) -> Nat; let f = Func();``` | Function types cannot be instantiated directly. |
@@ -44,8 +44,8 @@ title: "Error code reference"
 | M0139 | Inner actor classes are not supported. | ```class Outer() { actor class Inner() { ... } }``` | Actor classes cannot be nested inside other classes. |
 | M0141 | Forbidden declaration in program. | ```import Prim "mo:prim";``` | Certain imports/declarations are not allowed in normal user code. |
 | M0145 | Pattern does not cover value. | ```switch (option) { case (null) { ... } };``` (missing `?some` case) | Switch statement doesn't handle all possible values. |
-| M0149 | An immutable [record](/languages/motoko/fundamentals/records) field (declared without `var`) was supplied where a mutable [record](/languages/motoko/fundamentals/records) field (specified with `var`), was expected. | ```type Mutable = { var x : Nat }; func set(r : Mutable) { ... }; set({ x = 10 });``` | Immutable [record](/languages/motoko/fundamentals/records) provided where mutable was expected. |
-| M0150 | A mutable [record](/languages/motoko/fundamentals/records) field (declared with `var`) was supplied where an immutable [record](/languages/motoko/fundamentals/records) field (specified without `var`) was expected. | ```type Immutable = { x : Nat }; let record : Immutable = { var x = 10 };``` | Mutable field provided where immutable was expected. |
+| M0149 | An immutable [record](/languages/motoko/fundamentals/types/records) field (declared without `var`) was supplied where a mutable [record](/languages/motoko/fundamentals/types/records) field (specified with `var`), was expected. | ```type Mutable = { var x : Nat }; func set(r : Mutable) { ... }; set({ x = 10 });``` | Immutable [record](/languages/motoko/fundamentals/types/records) provided where mutable was expected. |
+| M0150 | A mutable [record](/languages/motoko/fundamentals/types/records) field (declared with `var`) was supplied where an immutable [record](/languages/motoko/fundamentals/types/records) field (specified without `var`) was expected. | ```type Immutable = { x : Nat }; let record : Immutable = { var x = 10 };``` | Mutable field provided where immutable was expected. |
 | M0151 | A object literal is missing some fields. | ```type Person = { name : Text; age : Nat }; let p : Person = { name = "John" };``` | The `age` field is missing from the object literal. |
 | M0153 | An imported Candid file (.did) mentions types that cannot be represented in Motoko. | ```import Types from "types.did";``` (where `types.did` contains incompatible types) | The imported Candid file contains types that don't map to Motoko types. |
 | M0154 | Deprecation annotation. | ```@deprecated("Use newFunction instead") func oldFunction() { ... }``` | Using a deprecated function or feature that has been marked with `@deprecated`. |
diff --git a/docs/languages/motoko/reference/language-manual.md b/docs/languages/motoko/reference/language-manual.md
new file mode 100644
index 00000000..f766ea5d
--- /dev/null
+++ b/docs/languages/motoko/reference/language-manual.md
@@ -0,0 +1,2999 @@
+---
+sidebar_position: 16
+description: "Motoko language documentation"
+title: "Language reference"
+---
+
+
+
+
+
+This reference page provides technical details of interest to the following audiences:
+
+-   Authors providing the higher-level documentation about the Motoko programming language.
+
+-   Compiler experts interested in the details of Motoko and its compiler.
+
+-   Advanced programmers who want to learn more about the lower-level details of Motoko.
+
+This page is intended to provide complete reference information about Motoko, but this section does not provide explanatory text or usage information. Therefore, this section is typically not suitable for readers who are new to programming languages or who are looking for a general introduction to using Motoko.
+
+In this documentation, the term canister is used to refer to an Internet Computer smart contract.
+
+## Basic language syntax
+
+This section describes the basic language conventions of Motoko.
+
+### Whitespace
+
+Space, newline, horizontal tab, carriage return, line feed and form feed are considered as whitespace. Whitespace is ignored but used to separate adjacent keywords, identifiers and operators.
+
+In the definition of some lexemes, the quick reference uses the symbol `␣` to denote a single whitespace character.
+
+### Comments
+
+Single line comments are all characters following `//` until the end of the same line.
+
+``` motoko no-repl
+// single line comment
+x = 1
+```
+
+Single or multi-line comments are any sequence of characters delimited by `/*` and `*/`:
+
+``` motoko no-repl
+/* multi-line comments
+   look like this, as in C and friends */
+```
+
+Comments delimited by `/*` and `*/` may be nested, provided the nesting is well-bracketed.
+
+``` motoko no-repl
+/// I'm a documentation comment
+/// for a function
+```
+
+Documentation comments start with `///` followed by a space until the end of line, and get attached to the definition immediately following them.
+
+Deprecation comments start with `/// @deprecated` followed by a space until the end of line, and get attached to the definition immediately following them. They are only recognized in front of `public` declarations.
+
+All comments are treated as whitespace.
+
+### Keywords
+
+The following keywords are reserved and may not be used as identifiers:
+
+``` bnf
+actor and assert async async* await await? await* break case
+catch class composite continue debug debug_show do else false flexible
+finally for from_candid func if ignore import implicit in include label let
+loop mixin module not null object or persistent private public query
+return shared stable switch system throw to_candid true transient try
+type var weak while with
+```
+
+### Identifiers
+
+Identifiers are alpha-numeric, start with a letter and may contain underscores:
+
+``` bnf
+   ::= Letter (Letter | Digit | _)*
+Letter ::= A..Z | a..z
+Digit  ::= 0..9
+```
+
+### Integers
+
+Integers are written as decimal or hexadecimal, `Ox`-prefixed natural numbers. Subsequent digits may be prefixed a single, semantically irrelevant, underscore.
+
+``` bnf
+digit ::= ['0'-'9']
+hexdigit ::= ['0'-'9''a'-'f''A'-'F']
+num ::= digit ('_'? digit)*
+hexnum ::= hexdigit ('_'? hexdigit)*
+nat ::= num | "0x" hexnum
+```
+
+Negative integers may be constructed by applying a prefix negation `-` operation.
+
+### Floats
+
+Floating point literals are written in decimal or `Ox`-prefixed hexadecimal scientific notation.
+
+``` bnf
+let frac = num
+let hexfrac = hexnum
+let float =
+    num '.' frac?
+  | num ('.' frac?)? ('e' | 'E') sign? num
+  | "0x" hexnum '.' hexfrac?
+  | "0x" hexnum ('.' hexfrac?)? ('p' | 'P') sign? num
+```
+
+The 'e' (or 'E') prefixes a base 10, decimal exponent; 'p' (or 'P') prefixes a base 2, binary exponent. In both cases, the exponent is in decimal notation.
+
+:::note
+
+The use of decimal notation, even for the base 2 exponent, adheres to the established hexadecimal floating point literal syntax of the `C` language.
+
+:::
+
+### Characters
+
+A character is a single quote (`'`) delimited:
+
+-   Unicode character in UTF-8.
+
+-   `\`-escaped newline, carriage return, tab, single or double quotation mark.
+
+-   `\`-prefixed ASCII character (TBR).
+
+-   or `\u{` hexnum `}` enclosed valid, escaped Unicode character in hexadecimal (TBR).
+
+``` bnf
+ascii ::= ['\x00'-'\x7f']
+ascii_no_nl ::= ['\x00'-'\x09''\x0b'-'\x7f']
+utf8cont ::= ['\x80'-'\xbf']
+utf8enc ::=
+    ['\xc2'-'\xdf'] utf8cont
+  | ['\xe0'] ['\xa0'-'\xbf'] utf8cont
+  | ['\xed'] ['\x80'-'\x9f'] utf8cont
+  | ['\xe1'-'\xec''\xee'-'\xef'] utf8cont utf8cont
+  | ['\xf0'] ['\x90'-'\xbf'] utf8cont utf8cont
+  | ['\xf4'] ['\x80'-'\x8f'] utf8cont utf8cont
+  | ['\xf1'-'\xf3'] utf8cont utf8cont utf8cont
+utf8 ::= ascii | utf8enc
+utf8_no_nl ::= ascii_no_nl | utf8enc
+
+escape ::= ['n''r''t''\\''\'''\"']
+
+character ::=
+  | [^'"''\\''\x00'-'\x1f''\x7f'-'\xff']
+  | utf8enc
+  | '\\'escape
+  | '\\'hexdigit hexdigit
+  | "\\u{" hexnum '}'
+  | '\n'        // literal newline
+
+char := '\'' character '\''
+```
+
+### Text
+
+A text literal is `"`-delimited sequence of characters:
+
+``` bnf
+text ::= '"' character* '"'
+```
+
+Note that a text literal may span multiple lines.
+
+### Literals
+
+``` bnf
+ ::=                                     literals
+                                           natural
+                                         float
+                                          character
+                                          Unicode text
+```
+
+Literals are constant values. The syntactic validity of a literal depends on the precision of the type at which it is used.
+
+## Operators and types
+
+To simplify the presentation of available operators, operators and primitive types are classified into basic categories:
+
+| Abbreviation | Category   | Supported operations             |
+| ------------ | ---------- | ------------------------------- |
+| A            | Arithmetic | Arithmetic operations           |
+| B            | Bitwise    | Bitwise and wrapping operations |
+| O            | Ordered    | Comparison                      |
+| T            | Text       | Concatenation                   |
+
+Some types have several categories. For example, type [`Int`](https://mops.one/core/docs/Int) is both arithmetic (A) and ordered (O) and supports both arithmetic addition (`+`) and relational less than (`<`) amongst other operations.
+
+### Unary operators
+
+| `` | Category |                  |
+| -------- | -------- | ---------------- |
+| `-`      | A        | Numeric negation |
+| `+`      | A        | Numeric identity |
+| `^`      | B        | Bitwise negation |
+
+### Relational operators
+
+|           |          |                                                 |
+| --------- | -------- | ----------------------------------------------- |
+| `` | Category |                                                 |
+| `==`      |          | Equals                                          |
+| `!=`      |          | Not equals                                      |
+| `␣<␣`     | O        | Less than (must be enclosed in whitespace)    |
+| `␣>␣`     | O        | Greater than (must be enclosed in whitespace) |
+| `<=`      | O        | Less than or equal                              |
+| `>=`      | O        | Greater than or equal                           |
+
+Note that equality (`==`) and inequality (`!=`) do not have categories. Instead, equality and inequality are applicable to arguments of all shared types, including non-primitive, compound types such as immutable arrays, records, and variants.
+
+Equality and inequality are structural and based on the observable content of their operands as determined by their static type.
+
+### Numeric binary operators
+
+| `` | Category |                |
+| --------- | -------- | -------------- |
+| `+`       | A        | Addition       |
+| `-`       | A        | Subtraction    |
+| `*`       | A        | Multiplication |
+| `/`       | A        | Division       |
+| `%`       | A        | Modulo         |
+| `**`      | A        | Exponentiation |
+
+### Bitwise and wrapping binary operators
+
+| `` | Category |                                                |
+| --------- | -------- | ---------------------------------------------- |
+| `&`       | B        | Bitwise and                                    |
+| | | B        | Bitwise or                                     |
+| `^`       | B        | Exclusive or                                   |
+| `<<`      | B        | Shift left                                     |
+| `␣>>`     | B        | Shift right (must be preceded by whitespace)   |
+| `<<>`     | B        | Rotate left                                    |
+| `<>>`     | B        | Rotate right                                   |
+| `+%`      | A        | Addition (wrap-on-overflow)                    |
+| `-%`      | A        | Subtraction (wrap-on-overflow)                 |
+| `*%`      | A        | Multiplication (wrap-on-overflow)              |
+| `**%`     | A        | Exponentiation (wrap-on-overflow)              |
+
+### Text operators
+
+| `` | Category |               |
+| --------- | -------- | ------------- |
+| `#`       | T        | Concatenation |
+
+### Assignment operators
+
+| `:=`, `=`, `=` | Category |                                            |
+| --------------------------- | -------- | ------------------------------------------ |
+| `:=`                        | \*       | Assignment (in place update)               |
+| `+=`                        | A        | In place add                               |
+| `-=`                        | A        | In place subtract                          |
+| `*=`                        | A        | In place multiply                          |
+| `/=`                        | A        | In place divide                            |
+| `%=`                        | A        | In place modulo                            |
+| `**=`                       | A        | In place exponentiation                    |
+| `&=`                        | B        | In place logical and                       |
+| |=        | B        | In place logical or                        |
+| `^=`                        | B        | In place exclusive or                      |
+| `<<=`                       | B        | In place shift left                        |
+| `>>=`                       | B        | In place shift right                       |
+| `<<>=`                      | B        | In place rotate left                       |
+| `<>>=`                      | B        | In place rotate right                      |
+| `+%=`                       | B        | In place add (wrap-on-overflow)            |
+| `-%=`                       | B        | In place subtract (wrap-on-overflow)       |
+| `*%=`                       | B        | In place multiply (wrap-on-overflow)       |
+| `**%=`                      | B        | In place exponentiation (wrap-on-overflow) |
+| `#=`                        | T        | In place concatenation                     |
+
+The category of a compound assignment `=`/`=` is given by the category of the operator ``/``.
+
+### Operator and keyword precedence
+
+The following table defines the relative precedence and associativity of operators and tokens, ordered from lowest to highest precedence. Tokens on the same line have equal precedence with the indicated associativity.
+
+| Precedence | Associativity | Token                                                                                                                         |
+| ---------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------- |
+| LOWEST     | none          | `if _ _` (no `else`), `loop _` (no `while`)                                                                                   |
+| (higher)   | none          | `else`, `while`                                                                                                               |
+| (higher)   | right         | `:=`, `+=`, `-=`, `*=`, `/=`, `%=`, `**=`, `#=`, `&=`, |=, `^=`, `<<=`, `>>=`, `<<>=`, `<>>=`, `+%=`, `-%=`, `*%=`, `**%=` |
+| (higher)   | left          | `:`                                                                                                                           |
+| (higher)   | left          | |>                                                                                                          |
+| (higher)   | left          | `or`                                                                                                                          |
+| (higher)   | left          | `and`                                                                                                                         |
+| (higher)   | none          | `==`, `!=`, `<`, `>`, `<=`, `>`, `>=`                                                                                         |
+| (higher)   | left          | `+`, `-`, `#`, `+%`, `-%`                                                                                                     |
+| (higher)   | left          | `*`, `/`, `%`, `*%`                                                                                                           |
+| (higher)   | left          | |                                                                                                           |
+| (higher)   | left          | `&`                                                                                                                           |
+| (higher)   | left          | `^`                                                                                                                           |
+| (higher)   | none          | `<<`, `>>`, `<<>`, `<>>`                                                                                                      |
+| HIGHEST    | left          | `**`, `**%`                                                                                                                   |
+
+### Programs
+
+The syntax of a **program** `` is as follows:
+
+``` bnf
+ ::=             programs
+  ;* ;*
+```
+
+A program is a sequence of imports `;*` followed by a sequence of declarations `;*` that ends with an optional actor or actor class declaration. The actor or actor class declaration determines the main actor, if any, of the program.
+
+Compiled programs must obey the following additional restrictions:
+
+-   A `shared` function can only appear as a public field of an actor or actor class.
+
+-   A program may contain at most one actor or actor class declaration, i.e. the final main actor or actor class.
+
+-   Any main actor class declaration should be anonymous. If named, the class name should not be used as a value within the class and will be reported as an unavailable identifier.
+
+These restrictions are not imposed on interpreted programs.
+
+The last two restrictions are designed to forbid programmatic actor class recursion, pending compiler support.
+
+Note that the parameters of an actor class must have [shared type](#shareability). The parameters of a program’s final actor class provide access to the corresponding canister installation argument(s). The Candid type of this argument is determined by the Candid projection of the Motoko type of the class parameter.
+
+### Imports
+
+The syntax of an **import** `` is as follows:
+
+``` bnf
+ ::=                           imports
+  import  =? 
+
+ ::=
+  ""                      Import module from relative .mo
+  "mo:/"    Import module from package
+  "ic:"                 Import external actor by 
+  "canister:"                 Import external actor by 
+  "blob:file:"            Import literal `Blob` value from 
+```
+
+An import introduces a resource referring to a local source module, module from a package of modules, a canister imported as an actor, or a literal [`Blob`](#type-blob) value. The contents of the resource are bound to ``.
+
+Though typically a simple identifier, ``, `` can also be any composite pattern binding selective components of the resource.
+
+The pattern must be irrefutable.
+
+### Libraries
+
+The syntax of a **library** that can be referenced in an import is as follows:
+
+``` bnf
+ ::=                                               Library
+  ;* module ? (: )? =?            Module
+  ;* ? actor ? class          Actor class
+     ?  (: )? 
+  ;* mixin                            Mixin
+```
+
+A library `` is a sequence of imports `;*` followed by:
+
+-   A named or anonymous module declaration, or
+
+-   A named actor class declaration.
+
+-   An anonymous mixin declaration.
+
+Libraries stored in `.mo` files may be referenced by `import` declarations.
+
+In a module library, the optional name `?` is only significant within the library and does not determine the name of the library when imported. Instead, the imported name of a library is determined by the `import` declaration, giving clients of the library the freedom to choose library names e.g. to avoid clashes.
+
+An actor class library, because it defines both a type constructor and a function with name ``, is imported as a module defining both a type and a function named ``. The name `` is mandatory and cannot be omitted. An actor class constructor is always asynchronous, with return type `async T` where `T` is the inferred type of the class body. Because actor construction is asynchronous, an instance of an imported actor class can only be created in an asynchronous context i.e. in the body of a non-`query` `shared` function, asynchronous function, `async` expression or `async*` expression.
+
+### Declaration syntax
+
+The syntax of a declaration is as follows:
+
+``` bnf
+ ::=                                                               Declaration
+                                                                     Expression
+  let  =                                                        Immutable, trap on match failure
+  let  =  else                                    Immutable, handle match failure
+  var  (: )? =                                              Mutable
+  ?  ? (: )? =?                   Object
+  ? func ? ?  (: )? =?         Function
+  type  ? =                                     Type
+  ? ? ? class                            Class
+    ? ?  (: )? 
+  mixin                                                    Mixin
+  include                                                        Mixin inlusion
+
+ ::=           Object body
+  { ;* }       Field declarations
+
+ ::=         Class body
+  = ?       Object body, optionally binding  to 'this' instance
+                Object body
+
+ ::=
+   persistent? actor
+   module
+   object
+
+ ::=       Parenthetical expression
+  ( ? with ;* )   Parenthetical combination/extension
+```
+
+The syntax of a shared function qualifier with call-context pattern is as follows:
+
+``` bnf
+ ::=
+ composite? query
+
+ ::=
+  shared ? ?
+```
+
+For ``, an absent `?` is shorthand for the wildcard pattern `_`.
+
+``` bnf
+ ::=                                object declaration fields
+  ? ?                            field
+
+ ::=                                      field visibility
+  public
+  private
+  system
+
+ ::=                                     field stability (actor only)
+  stable
+  flexible
+  transient                                      (equivalent to flexible)
+```
+
+The **visibility** qualifier `?` determines the accessibility of every field `` declared by ``:
+
+-   An absent `?` qualifier defaults to `private` visibility.
+
+-   Visibility `private` restricts access to `` to the enclosing object, module or actor.
+
+-   Visibility `public` extends `private` with external access to `` using the dot notation `.`.
+
+-   Visibility `system` extends `private` with access by the run-time system.
+
+-   Visibility `system` may only appear on `func` declarations that are actor fields, and **must not** appear anywhere else.
+
+The **stability** qualifier `` determines the **upgrade** behavior of actor fields:
+
+-   A stability qualifier should appear on `let` and `var` declarations that are actor fields.
+    Within a `persistent` actor or actor class, an absent stability qualifier defaults to `stable`.
+    Within a non-`persistent` actor or actor class, an absent stability qualifier defaults to `flexible` (or `transient`).
+    The keywords `transient` and `flexible` are interchangeable.
+
+-   `` qualifiers must not appear on fields of objects or modules.
+
+-   The pattern in a `stable let  = ` declaration must be simple where, a pattern `pat` is simple if it recursively consists of any of the following:
+
+    -   A variable pattern ``.
+
+    -   An annotated simple pattern ` : `.
+
+    -   A parenthesized simple pattern `(  )`.
+
+### Expression syntax
+
+The syntax of an expression is as follows:
+
+``` bnf
+ ::=                                      Expressions
+                                             Variable
+                                            Literal
+                                      Unary operator
+                                Binary operator
+                                Binary relational operator
+  _                                              Placeholder expression
+   |>                                  Pipe operator
+  ( ,* )                                    Tuple
+   .                                   Tuple projection
+  ?                                         Option injection
+  { ;* }                              Object
+  {  (and )* (with ;+)? }   Object combination/extension
+  # id ?                                    Variant injection
+   .                                    Object projection/member access
+   :=                                  Assignment
+  =                                   Unary update
+   =                            Binary update
+  [ var? ,* ]                               Array
+   [  ]                                Array indexing
+  ? func                   Function expression
+  ?  ?        Function call
+  not                                       Negation
+   and                                 Conjunction
+   or                                  Disjunction
+  if   (else )? Conditional
+  switch  { (case  ;)+ } Switch
+  while                       While loop
+  loop  (while )?             Loop
+  for (  in  )           Iteration
+  label  (: )?            Label
+  break  ?                              Break
+  continue                                   Continue
+  return ?                                  Return
+  ? async           Async expression
+  await                            Await future (only in async)
+  await?                           Await future (only in async) without state commit when completed
+  async*                           Delay an asynchronous computation
+  await*                           Await a delayed computation (only in async)
+  throw                                     Raise an error (only in async)
+  try  catch    Catch an error (only in async)
+  try  finally       Guard with cleanup
+  try  catch   finally 
+                                                 Catch an error (only in async) and cleanup
+  assert                           Assertion
+   :                                   Type annotation
+                                            Declaration
+  ignore                           Ignore value
+  do                                      Block as expression
+  do ?                                    Option block
+   !                                        Null break
+  debug                            Debug expression
+  actor                                     Actor reference
+  to_candid ( ,* )                          Candid serialization
+  from_candid                               Candid deserialization
+  (system  . )                          System actor class constructor
+  (  )                                      Parentheses
+
+ ::=
+  
+  
+
+ ::=
+  { ;* }
+```
+
+### Patterns
+
+The syntax of a pattern is as follows:
+
+``` bnf
+ ::=                                      Patterns
+  _                                              Wildcard
+                                             Variable
+  ?                                   Literal
+  ( ,* )                                    Tuple or brackets
+  { ;* }                              Object pattern
+  #  ?                                  Variant pattern
+  ?                                         Option
+   :                                   Type annotation
+   or                                  Disjunctive pattern
+
+ ::=                                Object pattern fields
+   (: )? =                         Field
+   (: )?                                Punned field
+  type                                       Type field
+```
+
+## Type syntax
+
+Type expressions are used to specify the types of arguments, constraints on type parameters, definitions of type constructors, and the types of sub-expressions in type annotations.
+
+``` bnf
+ ::=                                     Type expressions
+   ?                       Constructor
+  ? { ;* }                 Object
+  { ;* }                               Variant
+  { # }                                         Empty variant
+  [ var?  ]                                Array
+  Null                                          Null type
+  ?                                        Option
+  ? ?  ->         Function
+  async                                    Future
+  async*                                   Delayed, asynchronous computation
+  ( ,* )                              Tuple
+  Any                                           Top
+  None                                          Bottom
+   and                                Intersection
+   or                                 Union
+  Error                                         Errors/exceptions
+  (  )                                     Parenthesized type
+
+                                    Type item
+                                           Simple item
+   :                                   Named item
+  implicit :                               Implicit argument
+
+ ::= (actor | module | object)
+
+ ::=                                 Shared function type qualifier
+  shared ?
+
+ ::=                                   Paths
+                                           Type identifier
+   .                                 Projection
+```
+
+An absent `?` abbreviates `object`.
+
+
+Type items of the form ` (implicit : )` and ` : (implicit : ( : ))` are used to indicate implicit and re-named implicit parameters.  The second form is used to override the parameter named `` as implicit parameter named ``.
+These special type items are only meaningful in parameter positions of function types and have no significance elsewhere.
+
+### Primitive types
+
+Motoko provides the following primitive type identifiers, including support for Booleans, signed and unsigned integers and machine words of various sizes, characters and text.
+
+The category of a type determines the operators (unary, binary, relational and in-place update via assignment) applicable to values of that type.
+
+| Identifier                         | Category | Description                                                            |
+| ---------------------------------- | -------- | ---------------------------------------------------------------------- |
+| [`Bool`](https://mops.one/core/docs/Bool)           | L        | Boolean values `true` and `false` and logical operators                |
+| [`Char`](https://mops.one/core/docs/Char)           | O        | Unicode characters                                                     |
+| [`Text`](https://mops.one/core/docs/Text)           | T, O     | Unicode strings of characters with concatenation `_ # _` and iteration |
+| [`Float`](https://mops.one/core/docs/Float)         | A, O     | 64-bit floating point values                                           |
+| [`Int`](https://mops.one/core/docs/Int)             | A, O     | Signed integer values with arithmetic (unbounded)                      |
+| [`Int8`](https://mops.one/core/docs/Int8)          | A, O     | Signed 8-bit integer values with checked arithmetic                    |
+| [`Int16`](https://mops.one/core/docs/Int16)       | A, O     | Signed 16-bit integer values with checked arithmetic                   |
+| [`Int32`](https://mops.one/core/docs/Int32)       | A, O     | Signed 32-bit integer values with checked arithmetic                   |
+| [`Int64`](https://mops.one/core/docs/Int64)         | A, O     | Signed 64-bit integer values with checked arithmetic                   |
+| [`Nat`](https://mops.one/core/docs/Nat)             | A, O     | Non-negative integer values with arithmetic (unbounded)                |
+| [`Nat8`](https://mops.one/core/docs/Nat8)          | A, O     | Non-negative 8-bit integer values with checked arithmetic              |
+| [`Nat16`](https://mops.one/core/docs/Nat16)      | A, O     | Non-negative 16-bit integer values with checked arithmetic             |
+| [`Nat32`](https://mops.one/core/docs/Nat32)      | A, O     | Non-negative 32-bit integer values with checked arithmetic             |
+| [`Nat64`](https://mops.one/core/docs/Nat64)        | A, O     | Non-negative 64-bit integer values with checked arithmetic             |
+| [`Blob`](https://mops.one/core/docs/Blob)          | O        | Binary blobs with iterators                                            |
+| [`Principal`](https://mops.one/core/docs/Principal) | O        | Principals                                                             |
+| [`Error`](https://mops.one/core/docs/Error)         |          | (Opaque) error values                                                  |
+| [`Region`](https://mops.one/core/docs/Region)       |          | (Opaque) stable memory region objects                                  |
+
+Although many of these types have linguistic support for literals and operators, each primitive type also has an eponymous library in the core package providing related [functions and values](https://mops.one/core). For example, the [`Text`](https://mops.one/core/docs/Text) library provides common functions on `Text` values.
+
+### Type [`Bool`](https://mops.one/core/docs/Bool)
+
+The type [`Bool`](https://mops.one/core/docs/Bool) of category L (Logical) has values `true` and `false` and is supported by one and two branch `if _  (else )?`, `not `, `_ and _` and `_ or _` expressions. Expressions `if`, `and` and `or` are short-circuiting.
+
+
+
+### Type `Char`
+
+A `Char` of category O (Ordered) represents a character as a code point in the unicode character set.
+
+Core package function `Char.toNat32(c)` converts a `Char` value, `c` to its [`Nat32`](https://mops.one/core/docs/Nat32) code point. Function `Char.fromNat32(n)` converts a [`Nat32`](https://mops.one/core/docs/Nat32) value, `n`, in the range *0x0..xD7FF* or *0xE000..0x10FFFF* of valid code points to its `Char` value; this conversion traps on invalid arguments. Function `Char.toText(c)` converts the `Char` `c` into the corresponding, single character [`Text`](https://mops.one/core/docs/Text) value.
+
+### Type [`Text`](https://mops.one/core/docs/Text)
+
+The type [`Text`](https://mops.one/core/docs/Text) of categories T and O (Text, Ordered) represents sequences of unicode characters i.e. strings. Function `t.size` returns the number of characters in [`Text`](https://mops.one/core/docs/Text) value `t`. Operations on text values include concatenation (`_ # _`) and sequential iteration over characters via `t.chars` as in `for (c : Char in t.chars()) { …​ c …​ }`.
+
+
+
+### Type `Float`
+
+The type `Float` represents 64-bit floating point values of categories A (Arithmetic) and O (Ordered).
+
+The semantics of `Float` and its operations is in accordance with standard [IEEE 754-2019](https://ieeexplore.ieee.org/document/8766229) (See [References](#references)).
+
+Common functions and values are defined in the [`Float`](https://mops.one/core/docs/Float) core package.
+
+### Types [`Int`](https://mops.one/core/docs/Int) and [`Nat`](https://mops.one/core/docs/Nat)
+
+The types [`Int`](https://mops.one/core/docs/Int) and [`Nat`](https://mops.one/core/docs/Nat) are signed integral and natural numbers of categories A (Arithmetic) and O (Ordered).
+
+Both [`Int`](https://mops.one/core/docs/Int) and [`Nat`](https://mops.one/core/docs/Nat) are arbitrary precision, with only subtraction `-` on [`Nat`](https://mops.one/core/docs/Nat) trapping on underflow.
+
+The subtype relation `Nat <: Int` holds, so every expression of type [`Nat`](https://mops.one/core/docs/Nat) is also an expression of type [`Int`](https://mops.one/core/docs/Int) but not vice versa. In particular, every value of type [`Nat`](https://mops.one/core/docs/Nat) is also a value of type [`Int`](https://mops.one/core/docs/Int), without change of representation.
+
+### Bounded integers [`Int8`](https://mops.one/core/docs/Int8), [`Int16`](https://mops.one/core/docs/Int16), [`Int32`](https://mops.one/core/docs/Int32) and [`Int64`](https://mops.one/core/docs/Int64)
+
+The types [`Int8`](https://mops.one/core/docs/Int8), [`Int16`](https://mops.one/core/docs/Int16), [`Int32`](https://mops.one/core/docs/Int32) and [`Int64`](https://mops.one/core/docs/Int64) represent signed integers with respectively 8, 16, 32 and 64 bit precision. All have categories A (Arithmetic), B (Bitwise) and O (Ordered).
+
+Operations that may under- or overflow the representation are checked and trap on error.
+
+The operations `+%`, `-%`, `*%` and `**%` provide access to wrap-around, modular arithmetic.
+
+As bitwise types, these types support bitwise operations and (`&`), or (`|`) and exclusive-or (`^`). Further, they can be rotated left (`<<>`), right (`<>>`), and shifted left (`<<`), right (`>>`). The right-shift preserves the two’s-complement sign. All shift and rotate amounts are considered modulo the numbers’s bit width `n`.
+
+Bounded integer types are not in subtype relationship with each other or with other arithmetic types, and their literals need type annotation if the type cannot be inferred from context, e.g. `(-42 : Int16)`.
+
+The corresponding module in the core package provides conversion functions:
+
+- Conversion to [`Int`](https://mops.one/core/docs/Int).
+
+- Checked and wrapping conversions from [`Int`](https://mops.one/core/docs/Int).
+
+- Wrapping conversion to the bounded natural type of the same size.
+
+### Bounded naturals [`Nat8`](https://mops.one/core/docs/Nat8), [`Nat16`](https://mops.one/core/docs/Nat16), [`Nat32`](https://mops.one/core/docs/Nat32) and [`Nat64`](https://mops.one/core/docs/Nat64)
+
+The types [`Nat8`](https://mops.one/core/docs/Nat8), [`Nat16`](https://mops.one/core/docs/Nat16), [`Nat32`](https://mops.one/core/docs/Nat32) and [`Nat64`](https://mops.one/core/docs/Nat64) represent unsigned integers with respectively 8, 16, 32 and 64 bit precision. All have categories A (Arithmetic), B (Bitwise) and O (Ordered).
+
+Operations that may under- or overflow the representation are checked and trap on error.
+
+The operations `+%`, `-%`, `*%` and `**%` provide access to the modular, wrap-on-overflow operations.
+
+As bitwise types, these types support bitwise operations and (`&`), or (`|`) and exclusive-or (`^`). Further, they can be rotated left (`<<>`), right (`<>>`), and shifted left (`<<`), right (`>>`). The right-shift is logical. All shift and rotate amounts are considered modulo the number’s bit width *n*.
+
+The corresponding module in the core package provides conversion functions:
+
+- Conversion to [`Nat`](https://mops.one/core/docs/Nat).
+
+- Checked and wrapping conversions from [`Nat`](https://mops.one/core/docs/Nat).
+
+- Wrapping conversion to the bounded, signed integer type of the same size.
+
+### Type [`Blob`](https://mops.one/core/docs/Blob)
+
+The type [`Blob`](https://mops.one/core/docs/Blob) of category O (Ordered) represents binary blobs or sequences of bytes. Function `b.size()` returns the number of characters in [`Blob`](https://mops.one/core/docs/Blob) value `b`. Operations on blob values include sequential iteration over bytes via function `b.values()` as in `for (v : Nat8 in b.values()) { …​ v …​ }`.
+
+### Type [`Principal`](https://mops.one/core/docs/Principal)
+
+The type [`Principal`](https://mops.one/core/docs/Principal) of category O (Ordered) represents opaque principals such as canisters and users that can be used to identify callers of shared functions and used for simple authentication. Although opaque, principals may be converted to binary [`Blob`](https://mops.one/core/docs/Blob) values for more efficient hashing and other applications.
+
+### Error type
+
+Assuming core package import:
+
+``` motoko no-repl
+import E "mo:core/Error";
+```
+
+Errors are opaque values constructed and examined with operations:
+
+-   `E.reject : Text -> Error`
+
+-   `E.code : Error -> E.ErrorCode`
+
+-   `E.message : Error -> Text`
+
+Type `E.ErrorCode` is equivalent to variant type:
+
+``` motoko no-repl
+type ErrorCode = {
+  // Fatal error.
+  #system_fatal;
+  // Transient error.
+  #system_transient;
+  // Response unknown due to missed deadline.
+  #system_unknown;
+  // Destination invalid.
+  #destination_invalid;
+  // Explicit reject by canister code.
+  #canister_reject;
+  // Canister trapped.
+  #canister_error;
+  // Future error code (with unrecognized numeric code).
+  #future : Nat32;
+  // Error issuing inter-canister call
+  // (indicating destination queue full or freezing threshold crossed).
+  #call_error : { err_code : Nat32 }
+};
+```
+
+A constructed error `e = E.reject(t)` has `E.code(e) = #canister_reject` and `E.message(e) = t`.
+
+[`Error`](https://mops.one/core/docs/Error) values can be thrown and caught within an `async` expression or `shared` function only. See [throw](#throw) and [try](#try).
+
+Errors with codes other than `#canister_reject`, i.e. system errors, may be caught and thrown but not user-constructed.
+
+:::note
+
+Exiting an async block or shared function with a non-`#canister-reject` system error exits with a copy of the error with revised code `#canister_reject` and the original [`Text`](https://mops.one/core/docs/Text) message. This prevents programmatic forgery of system errors.
+
+:::
+
+:::note
+
+On ICP, the act of issuing a call to a canister function can fail, so that the call cannot (and will not be) performed.
+This can happen due to a lack of canister resources, typically because the local message queue for the destination canister is full,
+or because performing the call would reduce the current cycle balance of the calling canister to a level below its freezing threshold.
+Such call failures are reported by throwing an [`Error`](https://mops.one/core/docs/Error) with code `#call_error { err_code = n }`, where `n` is the non-zero `err_code` value returned by ICP.
+Like other errors, call errors can be caught and handled using `try ... catch ...` expressions, if desired.
+
+:::
+
+### Type `Region`
+
+The type `Region` represents opaque stable memory regions. Region objects are dynamically allocated and independently growable. They represent isolated partitions of IC stable memory.
+
+The region type is stable but not shared and its objects, which are stateful, may be stored in stable variables and data structures.
+
+Objects of type `Region` are created and updated using the functions provided by base libary `Region`. See [stable regions](/languages/motoko/icp-features/stable-memory) and library [Region](https://mops.one/core/docs/Region) for more information.
+
+### Constructed types
+
+` ?` is the application of a type identifier or path, either built-in (i.e. [`Int`](https://mops.one/core/docs/Int)) or user defined, to zero or more type arguments. The type arguments must satisfy the bounds, if any, expected by the type constructor’s type parameters (see [Well-formed types](#well-formed-types)).
+
+Though typically a type identifier, more generally, `` may be a `.`-separated sequence of actor, object or module identifiers ending in an identifier accessing a type component of a value (for example, `Acme.Collections.List`).
+
+### Object types
+
+`? { ;* }` specifies an object type by listing its zero or more named **type fields**.
+
+Within an object type, the names of fields must be distinct both by name and hash value.
+
+Object types that differ only in the ordering of the fields are equivalent.
+
+When `?` is `actor`, all fields have `shared` function type for specifying messages.
+
+### Variant types
+
+`{ ;* }` specifies a variant type by listing its variant type fields as a sequence of ``s.
+
+Within a variant type, the tags of its variants must be distinct both by name and hash value.
+
+Variant types that differ only in the ordering of their variant type fields are equivalent.
+
+`{ # }` specifies the empty variant type.
+
+### Array types
+
+`[ var?  ]` specifies the type of arrays with elements of type ``.
+
+Arrays are immutable unless specified with qualifier `var`.
+
+### Null type
+
+The `Null` type has a single value, the literal `null`. `Null` is a subtype of the option `? T`, for any type `T`.
+
+### Option types
+
+`? ` specifies the type of values that are either `null` or a proper value of the form `? ` where `` has type ``.
+
+### Weak reference types
+
+`weak ` specifies the type of weak references to values of type ``.
+
+### Function types
+
+Type `? ?  -> ` specifies the type of functions that consume optional type parameters ``, consume a value parameter of type `` and produce a result of type ``.
+
+Both `` and `` may reference type parameters declared in ``.
+
+If `` or `` or both is a tuple type, then the length of that tuple type determines the argument or result *arity* of the function type.
+The arity is the number of arguments or results a function returns.
+
+The optional `` qualifier specifies whether the function value is shared, which further constrains the form of ``, `` and `` (see [sharability](#shareability) below).
+
+Note that a `` function may itself be `shared` or `shared query` or `shared composite query`, determining the persistence of its state changes.
+
+### Async types
+
+`async ` specifies a future producing a value of type ``.
+
+Future types typically appear as the result type of a `shared` function that produces an `await`-able value.
+
+### Async* types
+
+`async* ` specifies a delayed, asynchronous computation producing a value of type ``.
+
+Computation types typically appear as the result type of a `local` function that produces an `await*`-able value.
+
+They cannot be used as the return types of `shared` functions.
+
+### Tuple types
+
+`( (( :)? ),* )` specifies the type of a tuple with zero or more ordered components.
+
+The optional identifier ``, naming its components, is for documentation purposes only and cannot be used for component access. In particular, tuple types that differ only in the names of components are equivalent.
+
+The empty tuple type `()` is called the *unit type*.
+
+### Any type
+
+Type `Any` is the top type, i.e. the supertype of all types. All values have type `Any`.
+
+### None type
+
+Type `None` is the bottom type, the subtype of all other types. No value has type `None`.
+
+As an empty type, `None` can be used to specify the impossible return value of an infinite loop or unconditional trap.
+
+### Intersection type
+
+The type expression ` and ` denotes the syntactic **intersection** between its two type operands, that is, the greatest type that is a subtype of both. If both types are incompatible, the intersection is `None`.
+
+The intersection is syntactic, in that it does not consider possible instantiations of type variables. The intersection of two type variables is `None`, unless they are equal, or one is declared to be a (direct or indirect) subtype of the other.
+
+### Union type
+
+The type expression ` or ` denotes the syntactic **union** between its two type operands, that is, the smallest type that is a supertype of both. If both types are incompatible, the union is `Any`.
+
+The union is syntactic, in that it does not consider possible instantiations of type variables. The union of two type variables is the union of their bounds, unless the variables are equal, or one is declared to be a direct or indirect subtype of the other.
+
+### Parenthesized type
+
+A function that takes an immediate, syntactic tuple of length `n \>= 0` as its domain or range is a function that takes and respectively returns `n` values.
+
+When enclosing the argument or result type of a function, which is itself a tuple type, `(  )` declares that the function takes or returns a single boxed value of type ``.
+
+In all other positions, `(  )` has the same meaning as ``.
+
+### Type fields
+
+``` bnf
+ ::=                               Object type fields
+   :                                   Immutable value
+  var  :                               Mutable value
+   ?  :             Function value (short-hand)
+  type  ? =           Type component
+```
+
+A type field specifies the name and type of a value field of an object, or the name and definition of a type component of an object. The value field names within a single object type must be distinct and have non-colliding hashes. The type component names within a single object type must also be distinct and have non-colliding hashes. Value fields and type components reside in separate name spaces and thus may have names in common.
+
+` : ` : Specifies an **immutable** field, named `` of type ``.
+
+`var  : ` : Specifies a **mutable** field, named `` of type ``.
+
+`type  ? = ` : Specifies a **type component**, with field name ``, abbreviating parameterized type ``.
+
+Unlike type declarations, a type component is not, in itself, recursive though it may abbreviate an existing recursive type.
+In particular, the name `` is not bound in `` nor in any other fields of the enclosing object type. The name `` only determines the label to use when accessing the definition through a record of this type using the dot notation.
+
+
+### Variant type fields
+
+``` bnf
+ ::=                                 Variant type fields
+  #  :                                 Tag
+  #                                         Unit tag (short-hand)
+```
+
+A variant type field specifies the tag and type of a single variant of an enclosing variant type. The tags within a single variant type must be distinct and have non-colliding hashes.
+
+`#  : ` specifies an immutable field, named `` of type ``. `# ` is sugar for an immutable field, named `` of type `()`.
+
+### Sugar
+
+When enclosed by an `actor` object type, ` ?  : ` is syntactic sugar for an immutable field named `` of `shared` function type `shared ? `.
+
+When enclosed by a non-`actor` object type, ` ?  : ` is syntactic sugar for an immutable field named `` of ordinary function type `? `.
+
+### Type parameters
+
+``` bnf
+ ::=                              Type parameters
+  < typ-param,* >
+
+   <:                                Constrained type parameter
+                                          Unconstrained type parameter
+```
+
+``` bnf
+ ::=                         Type parameters to type constructors
+  < typ-param,* >
+
+ ::=                              Function type parameters
+  < typ-param,* >                             Type parameters
+  < system (, *)) >                System capability prefixed type parameters
+
+
+   <:                                Constrained type parameter
+                                          Unconstrained type parameter
+
+```
+
+A type constructor may be parameterized by a vector of comma-separated, optionally constrained, type parameters.
+
+A function, class constructor or function type may be parameterized by a vector of comma-separated, optionally constrained, type parameters.
+The first of these may be the special, pseudo type parameter `system`.
+
+` <: ` declares a type parameter with constraint ``. Any instantiation of `` must subtype `` at that same instantiation.
+
+Syntactic sugar `` declares a type parameter with implicit, trivial constraint `Any`.
+
+The names of type parameters in a vector must be distinct.
+
+All type parameters declared in a vector are in scope within its bounds.
+
+The `system` pseudo-type parameter on function types indicates that a value of that type requires `system` capability in order to be called and may itself call functions requiring `system` capability during its execution.
+
+### Type arguments
+
+``` bnf
+ ::=                           Type arguments to type constructors
+  < ,* >
+
+
+ ::=                                Type arguments to functions
+  < ,* >                                   Plain type arguments
+  < system (, *) >                         System capability prefixed type arguments
+
+```
+
+Type constructors and functions may take type arguments.
+
+The number of type arguments must agree with the number of declared type parameters of the type constructor.
+
+For a function, the number of type arguments, when provided, must agree with the number of declared type parameters of the function’s type. Note that type arguments in function applications can typically be omitted and inferred by the compiler.
+
+Given a vector of type arguments instantiating a vector of type parameters, each type argument must satisfy the instantiated bounds of the corresponding type parameter.
+
+In function calls, supplying the `system` pseudo type argument grants system capability to the function that requires it.
+
+System capability is available only in the following syntactic contexts:
+
+- In the body of an actor expression or actor class.
+- In the body of a (non-`query`) `shared` function, asynchronous function, `async` expression or `async*` expression.
+- In the body of a function or class that is declared with `system` pseudo type parameter.
+- In system functions `preupgrade` and `postupgrade`.
+
+No other context provides `system` capabilities, including `query` and `composite query` methods.
+
+The `` type parameters of shared and asynchronous functions need not be declared.
+
+
+### Well-formed types
+
+A type `T` is well-formed only if recursively its constituent types are well-formed, and:
+
+-   If `T` is `async U` or `async* U` then `U` is shared, and
+
+-   If `T` is `shared ? U -> V`:
+    - `U` is shared and,
+    - `V == ()` and `?` is absent, or
+    - `V == async W` with `W` shared, and
+
+-   If `T` is `C` where:
+
+    -   A declaration `type C  = …​` is in scope, and
+
+    -   `Ti <: Ui[ T0/X0, …​, Tn/Xn ]`, for each `0 <= i <= n`.
+
+-   If `T` is `actor { …​ }` then all fields in `…​` are immutable and have `shared` function type.
+
+### Subtyping
+
+Two types `T`, `U` are related by subtyping, written `T <: U`, whenever, one of the following conditions is true:
+
+1.   `T` equals `U` (subtyping is *reflexive*).
+
+2.   `U` equals `Any`.
+
+3.   `T` equals `None`.
+
+4.   `T` is a type parameter `X` declared with constraint `U`.
+
+5.   `T` is [`Nat`](https://mops.one/core/docs/Nat) and `U` is [`Int`](https://mops.one/core/docs/Int).
+
+6.   `T` is a tuple `(T0, …​, Tn)`, `U` is a tuple `(U0, …​, Un)`, and for each `0 <= i <= n`, `Ti <: Ui`.
+
+7.   `T` is an immutable array type `[ V ]`, `U` is an immutable array type `[ W ]` and `V <: W`.
+
+8.   `T` is a mutable array type `[ var V ]`, `U` is a mutable array type `[ var W ]` and `V == W`.
+
+9.   `T` is `Null` and `U` is an option type `? W` for some `W`.
+
+10.  `T` is `? V`, `U` is `? W` and `V <: W`.
+
+11.  `T` is `weak V`, `U` is `weak W` and `V <: W`.
+
+12.   `T` is a future `async V`, `U` is a future `async W`, and `V <: W`.
+
+13.   `T` is an object type ` { fts0 }`, `U` is an object type ` { fts1 }` and
+
+      1. `` == ``, and, for all fields,
+
+      2. If field `id : W` is in `fts1` then `id : V` is in `fts0` and `V <: W`, and
+
+      3. If mutable field `var id : W` is in `fts1` then `var id : V` is in `fts0` and `V == W`, and
+
+      4. If type field `type id = V` is in `fts1` then `type id = W` is in `fts0` and `V == W` (up to renaming of type parameters).
+
+      That is, object type `T` is a subtype of object type `U` if they have the same sort, every mutable field in `U` super-types the same field in `T` and every mutable field in `U` is mutable in `T` with an equivalent type. In particular, `T` may specify more fields than `U`.
+      Note that this clause defines subtyping for all sorts of object type, whether `module`, `object` or `actor`.
+
+14.   `T` is a variant type `{ fts0 }`, `U` is a variant type `{ fts1 }` and
+
+       1.   If field `# id : V` is in `fts0` then `# id : W` is in `fts1` and `V <: W`.
+
+       That is, variant type `T` is a subtype of variant type `U` if every field of `T` subtypes the same field of `U`. In particular, `T` may specify fewer variants than `U`.
+
+15.   `T` is a function type `?  T1 -> T2`, `U` is a function type `?  U1 -> U2` and
+
+       1.   `T` and `U` are either both equivalently `?`, and
+
+       2.   Assuming constraints `X0 <: W0, …​, Xn <: Wn` then
+
+            1.   for all `i`, `Wi == Vi`, and
+
+            2.   `U1 <: T1`, and
+
+            3.   `T2 <: U2`.
+
+            That is, function type `T` is a subtype of function type `U` if they have same `?` qualification, they have the same type parameters (modulo renaming) and assuming the bounds in `U`, every bound in `T` supertypes the corresponding parameter bound in `U` (contra-variance), the domain of `T` supertypes the domain of `U` (contra-variance) and the range of `T` subtypes the range of `U` (co-variance).
+
+16.   `T` (respectively `U`) is a constructed type `C` that is equal, by definition of type constructor `C`, to `W`, and `W <: U` (respectively `U <: W`).
+
+17.   `T` (respectively `U`) is an named type typ item `( : W)` that is equal, by definition, to `W`, and `W <: U` (respectively `U <: W`).
+
+18.   For some type `V`, `T <: V` and `V <: U` (*transitivity*).
+
+#### Stable Subtyping
+
+Two types `T`, `U` are related by *stable subtyping*, written `T < U`, (and not to be confused with ordinary subtyping `T <: U`), using the same rules
+as subtyping but replacing occurences of `_ <: _` by `_ < _` and, crucially, excluding rule:
+
+2.   `U` equals `Any`.
+
+And adopting a more restrictive rule for object types:
+
+13.   `T` is an object type ` { fts0 }`, `U` is an object type ` { fts1 }` and
+
+      1. `` == ``, and, for all fields,
+
+      2. Field `id : W` is in `fts1` if, and only if, `id : V` is in `fts0` and `V < W`, and
+
+      3. Mutable field `var id : W` is in `fts1` if, and only if,  `var id : V` is in `fts0` and `V == W`, and
+
+      4. If type field `type id = V` is in `fts1` then `type id = W` is in `fts0` and `V == W` (up to renaming of type parameters).
+
+Note that stable subtyping entails subtyping, i.e. `T < U` implies `T <: U` but is a strictly smaller relation.
+In particular, compared with subtyping, no type other than `Any` is a stable subtype of `Any` and no value field may be dropped from the stable supertype of an object type.
+
+This stricter relation is used to determine the compatibility of stable variables across upgrades while preventing any implicit loss of data that would otherwise
+be allowed by full subtyping.
+
+### Shareability
+
+A type `T` is **shared** if it is:
+
+-   `Any` or `None`, or
+
+-   A primitive type other than [`Error`](https://mops.one/core/docs/Error) and [`Region`](https://mops.one/core/docs/Region), or
+
+-   An option type `? V` where `V` is shared, or
+
+-   A tuple type `(T0, …​, Tn)` where all `Ti` are shared, or
+
+-   An immutable array type `[V]` where `V` is shared, or
+
+-   An `object` type where all fields are immutable and have shared type, or
+
+-   A variant type where all tags have shared type, or
+
+-   A shared function type, or
+
+-   An `actor` type.
+
+### Stability
+
+Stability extends shareability to include mutable types, regions and weak references. More precisely:
+
+A type `T` is **stable** if it is:
+
+-   `Any` or `None`, or
+
+-   A primitive type other than [`Error`](https://mops.one/core/docs/Error), or
+
+-   An option type `? V` where `V` is stable, or
+
+-   An weak reference type `weak V` where `V` is stable, or
+
+-   A tuple type `(T0, …​, Tn)` where all `Ti` are stable, or
+
+-   A (mutable or immutable) array type `[var? V]` where `V` is stable, or
+
+-   An `object` type where all fields have stable type, or
+
+-   A variant type where all tags have stable type, or
+
+-   A shared function type, or
+
+-   An `actor` type.
+
+This definition implies that every shared type is a stable type. The converse does not hold: there are types that are stable but not share, notably types with mutable components.
+
+The types of actor fields declared with the `stable` qualifier must have stable type.
+
+The current value of such a field is preserved upon upgrade, whereas the values of other fields are reinitialized after an upgrade.
+
+Note: the primitive `Region` type is stable.
+
+Note: a weak reference type is stable when its content is stable.
+
+## Static and dynamic semantics
+
+Below is a detailed account of the semantics of Motoko programs.
+
+For each [expression form](#expression-syntax) and each [declaration form](#declaration-syntax), this page summarizes its semantics, both in static terms based on typing and dynamic terms based on program evaluation.
+
+### Programs
+
+A program `;* ;*` has type `T` provided:
+
+-   `;*` has type `T` under the static environment induced by the imports in `;*`.
+
+All type and value declarations within `;*` are mutually-recursive.
+
+A program evaluates by transitively evaluating the imports, binding their values to the identifiers in `;*` and then evaluating the sequence of declarations in `;*`.
+
+### Libraries
+
+Restrictions on the syntactic form of modules means that libraries can have no side-effects.
+
+The imports of a library are local and not re-exported in its interface.
+
+Multiple imports of the same library can be safely deduplicated without loss of side-effects.
+
+#### Module libraries
+
+A library `;* module ? (: )? =? ` is a sequence of imports `;*` followed by a single module declaration.
+
+A library has module type `T` provided:
+
+-   `module ? (: )? =? ` has (module) type `T` under the static environment induced by the imports in `;*`.
+
+A module library evaluates by transitively evaluating its imports, binding their values to the identifiers in `;*` and then evaluating `module ? =? `.
+
+If `(: )?` is present, then `T` must be a subtype of ``.
+
+#### Actor class libraries
+
+The actor class library `;* ` where `` is of the form `? actor class  ?  (: )? ` has type:
+
+``` bnf
+module {
+  type  = T;
+   : (U1,...,Un) -> async T
+}
+```
+
+Provided that the actor class declaration `` has function type `(U1, ...​, Un) -> async T` under the static environment induced by the imports in `;*`.
+
+Notice that the imported type of the function `` must be asynchronous.
+
+An actor class library evaluates by transitively evaluating its imports, binding their values to the identifiers in `;*`, and evaluating the derived module:
+
+``` bnf
+module {
+  
+}
+```
+
+On ICP, if this library is imported as identifier `Lib`, then calling `await Lib.(, ..., )`, installs a fresh instance of the actor class as an isolated IC canister, passing the values of ``, ...​, `` as installation arguments, and returns a reference to a remote actor of type `Lib.`, that is, `T`. Installation is necessarily asynchronous.
+
+
+#### Actor class management
+
+On ICP, the primary constructor of an imported actor class always creates a new principal and installs a fresh instance of the class as the code for that principal.
+While that is one way to install a canister on ICP, it is not the only way.
+
+To provide further control over the installation of actor classes, Motoko endows each imported actor class with an extra, secondary constructor, for use on ICP.
+This constructor takes an additional first argument that tailors the installation. The constructor is only available via special syntax that stresses its
+`system` functionality.
+
+Given some actor class constructor:
+
+``` motoko no-repl
+Lib. : (U1, ...​, Un) -> async T
+```
+
+Its secondary constructor is accessed as `(system Lib.)` with typing:
+
+``` motoko no-repl
+(system Lib.) :
+  { #new : CanisterSettings;
+    #install : Principal;
+    #reinstall : actor {} ;
+    #upgrade : actor {} }  ->
+    (U1, ...​, Un) -> async T
+```
+
+where:
+
+``` motoko no-repl
+  type CanisterSettings = {
+     settings : ?{
+        controllers : ?[Principal];
+        compute_allocation : ?Nat;
+        memory_allocation : ?Nat;
+        freezing_threshold : ?Nat;
+     }
+  }
+```
+
+
+Calling `(system Lib.)()(, ...​, )` uses the first argument ``, a variant value, to control the installation of the canister further. Arguments `(, ..., )` are just the user-declared constructor arguments of types `U1, ..., Un` that would also be passed to the primary constructor.
+
+If `` is:
+
+- `#new s`, where `s` has type `CanisterSettings`:
+
+    - The call creates a fresh ICP principal `p`, with settings `s`, and installs the instance to principal `p`.
+
+- `#install p`, where `p` has type [`Principal`](https://mops.one/core/docs/Principal):
+
+    - The call installs the actor to an already created ICP principal `p`. The principal must be empty, having no previously installed code, or the call will return an error.
+
+-  `#upgrade a`, where `a` has type (or supertype) `actor {}`:
+
+    - The call installs the instance as an upgrade of actor `a`, using its current stable storage to initialize stable variables and stable memory of the new instance.
+
+- `#reinstall a`, where `a` has type (or supertype) `actor {}`:
+
+    - Reinstalls the instance over the existing actor `a`, discarding its stable variables and stable memory.
+
+:::note
+
+On ICP, calling the primary constructor `Lib.` is equivalent to calling the secondary constructor `(system Lib.)` with argument `(#new {settings = null})` i.e. using default settings.
+
+:::
+
+:::note
+
+On ICP, calls to `Lib.` and  `(system Lib.)(#new ...)` must be provisioned with enough cycles for the creation of a new principal. Other call variants will use the cycles of the already allocated principal or actor.
+
+:::
+
+:::danger
+
+The use of `#upgrade a` may be unsafe. Motoko will currently not verify that the upgrade is compatible with the code currently installed at `a`. A future extension may verify compatibility with a dynamic check.
+
+The use of `#reinstall a` may be unsafe. Motoko cannot verify that the reinstall is compatible with the code currently installed in actor `a` even with a dynamic check.
+A change in interface may break any existing clients of `a`. The current state of `a` will be lost.
+
+:::
+
+### Imports and URLs
+
+An import `import  =? ` declares a pattern `` bound to the contents of the text literal ``.
+
+`` is a text literal that designates some resource: a local library specified with a relative path (imported as source), a named module from a named package (imported as source), an external canister, referenced either by numeric canister id or by a named alias (imported as a Motoko actor), or a binary file (imported as a blob).
+
+In detail, if `` is of the form:
+
+-   `""` then `` is bound to the library module defined in file `.mo`. `` is interpreted relative to the absolute location of the enclosing file. Note the `.mo` extension is implicit and should not be included in ``. For example, `import U "lib/Util"` defines `U` to reference the module in local file `./lib/Util.mo`.
+
+-   `"mo:/"` then `` is bound to the library module defined in file `/.mo` in directory `` referenced by package alias ``. The mapping from `` to `` is determined by a compiler command-line argument `--package  `. For example, `import L "mo:core/List"` defines `L` to reference the `List` library in package alias `core`.
+
+-   `"ic:"` then `` is bound to a Motoko actor whose Motoko type is determined by the canister’s IDL interface. The IDL interface of canister `` must be found in file `/.did`. The compiler assumes that `` is specified by command line argument `--actor-idl ` and that file `/.did` exists. For example, `import C "ic:lg264-qjkae"` defines `C` to reference the actor with canister id `lg264-qjkae` and IDL file `lg264-qjkae.did`.
+
+-   `"canister:"` is a symbolic reference to canister alias ``. The compiler assumes that the mapping of `` to `` is specified by command line argument `--actor-alias  ic:`. If so, `"canister:"` is equivalent to `"ic:"` (see above). For example, `import C "canister:counter"` defines `C` to reference the actor otherwise known as `counter`.
+
+-   `"blob:file:"` then `` is bound to a blob containing the contents of the file ``. `` is interpreted relative to the absolute location of the enclosing file. For example, `import image "blob:file:/assets/image.jpg"` defines `image` as the blob with bytes from local file `./assets/image.jpg`. Unlike library imports, `` should include the
+file's extension, if any.
+
+The case sensitivity of file references depends on the host operating system so it is recommended not to distinguish resources by filename casing alone.
+
+When building multi-canister projects with the [IC SDK](https://github.com/dfinity/sdk), Motoko programs can typically import canisters by alias (e.g. `import C "canister:counter"`), without specifying low-level canister ids (e.g. `import C "ic:lg264-qjkae"`). The SDK tooling takes care of supplying the appropriate command-line arguments to the Motoko compiler.)
+
+Sensible choices for `` are identifiers, such as [`Array`](https://mops.one/core/docs/Array), or object patterns like `{ cons; nil = empty }`, which allow selective importing of individual fields, under original or other names.
+
+### Declaration fields
+
+A declaration field `? ? ` defines zero or more fields of an actor or object, according to the set of variables defined by ``.
+
+Any identifier bound by a `public` declaration appears in the type of enclosing object, module or actor and is accessible via the dot notation.
+
+An identifier bound by a `private` or `system` declaration is excluded from the type of the enclosing object, module or actor and thus inaccessible.
+
+In a `persistent` actor or actor class, all declarations are implicitly `stable` unless explicitly declared otherwise.
+In a non-`persistent` actor or actor class, all declarations are implicitly `transient` (equivalently `flexible`) unless explicitly declared otherwise.
+
+The declaration field has type `T` provided:
+
+-   `` has type `T`.
+
+-   If `?` is `stable`  then `T` must be a stable type (see [stability](#stability)).
+
+-   If `?` is absent and the actor or actor class is `persistent`, then `T` must be a stable type (see [stability](#stability)).
+
+Actor fields declared `transient` (or legacy `flexible`) can have any type, but will not be preserved across upgrades.
+
+
+In the absence of any `?` migration expression, sequences of declaration fields are evaluated in order by evaluating their constituent declarations, with the following exception:
+
+  - During an upgrade only, the value of a `stable` declaration is obtained as follows:
+
+    - If the stable declaration was previously declared stable in the retired actor, its initial value is inherited from the retired actor.
+
+    - If the stable declaration was not declared stable in the retired actor, and is thus new, its value is obtained by evaluating ``.
+
+For an upgrade to be safe:
+
+  - Every stable identifier declared with type `T` in the retired actor must be declared stable and of type `U` in the replacement actor and must satisfy `T < U` (stable subtyping).
+
+This condition ensures that every stable variable is either fresh, requiring initialization, or its value can be safely inherited from the retired actor, without any loss of data.
+
+Note that stable variables cannot be implicitly removed across upgrades and cannot be promoted to type `Any`.
+These effects can only be achieved using an explicit [migration expression](#migration-expressions).
+
+
+#### Migration expressions
+
+Actors and actor class declaration may specify a migration expression, using an optional, leading `` expression with a required field named `migration`.
+The value of this field, a function, is applied to the stable variables of an upgraded actor, before initializing any stable fields of the declared actor.
+
+The parenthetical expression must satisfy the following conditions:
+
+* It must be static, that is, have no immediate side effects.
+* Its `migration` field must be present and have a non-shared function type whose domain and codomain are both record types.
+* The domain and the codomain must both be stable.
+* Any field in the codomain must be declared as a stable field in the actor body.
+* The content type of the codomain field must be a subtype of the content type of the actor's stable field.
+
+The migration expression only affects upgrades of the actor and is otherwise ignored during fresh installation of the actor.
+
+On upgrade, the domain of the migration function is used to construct a record of values containing the current contents of the corresponding stable fields
+of the retired actor. If one of the fields is absent, the upgrade traps and is aborted.
+
+Otherwise, we obtain an input record of stable values of the appropriate type.
+
+The migration function is applied to the input record. If the application traps, the upgrade is aborted.
+
+Otherwise, the application produces an output record of stable values whose type is the codomain.
+
+The actor's declarations are evaluated in order by evaluating each declaration as usual except that
+the value of a `stable` declaration is obtained as follows:
+
+- If the stable declaration is present in the codomain, its initial value is obtained from the output record.
+
+- Otherwise, if the stable declaration is not present in the domain and is declared stable in the retired actor,
+  then its initial value is obtained from the retired actor.
+
+- Otherwise, its value is obtained by evaluating the declaration's initalizer.
+
+Thus a stable variable's initializer is run if the variable is not produced by the migration function and either
+consumed by the migration function (by appearing in its domain) or absent in the retired actor.
+
+For the upgrade to be safe:
+
+- Every stable identifier declared with type `U` in the domain of the migration function
+  must be declared stable for some type `T` in the retired actor, with `T < U` (stable subtyping).
+
+- Every stable identifier declared with type `T` in the retired actor, not present in the domain or codomain,
+  and declared stable and of type `U` in the replacement actor, must satisfy `T < U` (stable subtyping).
+
+Thses conditions ensure that every stable variable is either discarded or fresh, requiring initialization,
+or that its value can be safely consumed from the output of migration or the retired actor without loss of date.
+
+The compiler will issue a warning if a migration function appears to be discarding data by consuming a field and not producing it.
+The warnings should be carefully considered to verify any data loss is intentional and not accidental.
+
+#### System fields
+
+The declaration `` of a `system` field must be a manifest `func` declaration with one of the following names and types:
+
+| name          | type                                                          | description         |
+| ------------- | ------------------------------------------------------------- | ------------------- |
+| `heartbeat`   | `() -> async ()`                                              | Heartbeat action    |
+| `timer`       | `(Nat64 -> ()) -> async ()`                                   | Timer action        |
+| `inspect`     | `{ caller : Principal; msg : ; arg : Blob } -> Bool` | Message predicate   |
+| `preupgrade`  | `() -> ()`                                            | Pre upgrade action  |
+| `postupgrade` | `() -> ()`                                            | Post upgrade action |
+
+-   `heartbeat`: When declared, is called on every Internet Computer subnet heartbeat, scheduling an asynchronous call to the `heartbeat` function. Due to its `async` return type, a heartbeat function may send messages and await results. The result of a heartbeat call, including any trap or thrown error, is ignored. The implicit context switch means that the time the heartbeat body is executed may be later than the time the heartbeat was issued by the subnet.
+
+-   `timer`: When declared, is called as a response of the canister global timer's expiration. The canister's global timer can be manipulated with the passed-in function argument of type `Nat64 -> ()` (taking an absolute time in nanoseconds) upon which libraries can build their own abstractions. When not declared (and in absence of the `-no-timer` flag), this system action is provided with default implementation by the compiler (additionally `setTimer` and `cancelTimer` are available as primitives).
+
+-   `inspect`: When declared, is called as a predicate on every Internet Computer ingress message with the exception of HTTP query calls. The return value, a [`Bool`](https://mops.one/core/docs/Bool), indicates whether to accept or decline the given message. The argument type depends on the interface of the enclosing actor (see [inspect](#inspect)).
+
+-   `preupgrade`: When declared, is called during an upgrade, immediately before the current values of the retired actor’s stable variables are transferred to the replacement actor.
+     Its `` type parameter is implicitly assumed and need not be declared.
+
+-   `postupgrade`: When declared, is called during an upgrade, immediately after the replacement actor body has initialized its fields, inheriting values of the retired actors' stable variables, and before its first message is processed. Its `` type parameter is implicitly assumed and need not be declared.
+
+:::danger
+
+Using the pre- and post-upgrade system methods is discouraged. It is error-prone and can render a canister unusable.
+In particular, if a `preupgrade` method traps and cannot be prevented from trapping by other means, then your canister may be left in a state in which it can no longer be upgraded.
+Per best practices, using these methods should be avoided if possible.
+
+:::
+
+These `preupgrade` and `postupgrade` system methods provide the opportunity to save and restore in-flight data structures, e.g. caches, that are better represented using non-stable types.
+
+During an upgrade, a trap occurring in the implicit call to `preupgrade()` or `postupgrade()` causes the entire upgrade to trap, preserving the pre-upgrade actor.
+
+##### `inspect`
+
+Given a record of message attributes, this function produces a [`Bool`](https://mops.one/core/docs/Bool) that indicates whether to accept or decline the message by returning `true` or `false`. The function is invoked by the system on each ingress message issue as an ICP update call, excluding non-replicated query calls. Similar to a query, any side-effects of an invocation are transient and discarded. A call that traps due to some fault has the same result as returning `false` message denial.
+
+The argument type of `inspect` depends on the interface of the enclosing actor. In particular, the formal argument of `inspect` is a record of fields of the following types:
+
+-   `caller : Principal`: The principal, possibly anonymous, of the caller of the message.
+
+-   `arg : Blob`: The raw, binary content of the message argument.
+
+-   `msg : `: A variant of decoding functions, where ` == {…​; #: () → T; …​}` contains one variant per `shared` or `shared query` function, ``, of the actor.
+    The variant’s tag identifies the function to be called; The variant’s argument is a function that, when applied, returns the (decoded) argument of the call as a value of type `T`.
+
+Using a variant, tagged with `#`, allows the return type, `T`, of the decoding function to vary with the argument type (also `T`) of the shared function ``.
+
+The variant’s argument is a function so that one can avoid the expense of message decoding when appropriate.
+
+:::danger
+
+An actor that fails to declare system field `inspect` will simply accept all ingress messages.
+
+:::
+
+:::note
+
+Any `shared composite query` function in the interface is *not* included in `` since, unlike a `shared query`, it can only be invoked as a non-replicated query call, never as an update call.
+
+:::
+
+### Sequence of declarations
+
+A sequence of declarations `;*` occurring in a block, a program or embedded in the `;*` sequence of an object body has type `T` provided:
+
+-   `;*` is empty and `T == ()`, or
+
+-   `;*` is non-empty and:
+
+    -   All value identifiers bound by `;*` are distinct.
+
+    -   All type identifiers bound by `;*` are distinct.
+
+    -   Under the assumption that each value identifier `` in `;*` has type `var_id? Tid`, and assuming the type definitions in `;*`:
+
+        -   Each declaration in `;*` is well-typed,.
+
+        -   Each value identifier `` in bindings produced by `;*` has type `var_id? Tid`.
+
+        -   All but the last `` in `;*` of the form `` has type `()`.
+
+        -   The last declaration in `;*` has type `T`.
+
+Declarations in `;*` are evaluated sequentially. The first declaration that traps causes the entire sequence to trap. Otherwise, the result of the declaration is the value of the last declaration in `;*`. In addition, the set of value bindings defined by `;*` is the union of the bindings introduced by each declaration in `;*`.
+
+It is a compile-time error if any declaration in `;*` might require the value of an identifier declared in `;*` before that identifier’s declaration has been evaluated. Such use-before-define errors are detected by a simple, conservative static analysis not described here.
+
+### Patterns
+
+Patterns bind function parameters, declare identifiers and decompose values into their constituent parts in the cases of a `switch` expression.
+
+Matching a pattern against a value may succeed, binding the corresponding identifiers in the pattern to their matching values, or fail. Thus the result of a match is either a successful binding, mapping identifiers of the pattern to values, or failure.
+
+The consequences of pattern match failure depends on the context of the pattern.
+
+-   In a function application or `let`-binding, failure to match the formal argument pattern or `let`-pattern causes a trap.
+
+-   In a `case` branch of a `switch` expression, failure to match that case’s pattern continues with an attempt to match the next case of the switch, trapping only when no such case remains.
+
+### Wildcard pattern
+
+The wildcard pattern `_` matches a single value without binding its contents to an identifier.
+
+### Identifier pattern
+
+The identifier pattern `` matches a single value and binds it to the identifier ``.
+
+### Literal pattern
+
+The literal pattern `? ` matches a single value against the constant value of literal `` and fails if they are not structurally equal values.
+
+For integer literals only, the optional `` determines the sign of the value to match.
+
+### Tuple pattern
+
+The tuple pattern `( ,* )` matches a n-tuple value against an n-tuple of patterns where both the tuple and pattern must have the same number of items. The set of identifiers bound by each component of the tuple pattern must be distinct.
+
+The empty tuple pattern `()` is called the **unit pattern**.
+
+Pattern matching fails if one of the patterns fails to match the corresponding item of the tuple value. Pattern matching succeeds if every pattern matches the corresponding component of the tuple value. The binding returned by a successful match is the disjoint union of the bindings returned by the component matches.
+
+### Object pattern
+
+The object pattern `{ ;* }` matches an object value, a collection of named field values and named type fields, against a sequence of named pattern fields. The set of identifiers bound by each field of the object pattern must be distinct. The names of the pattern fields in the object pattern must be distinct.
+
+A type `` binds a type component from the matched object for the containing block.
+
+Object patterns support punning for concision. A punned field `` is shorthand for ` = `. Similarly, a typed, punned field ` : ` is short-hand for ` =  : `. Both bind the matched value of the field named `` to the identifier ``.
+
+Pattern matching fails if one of the pattern fields fails to match the corresponding field value of the object value. Pattern matching succeeds if every pattern field matches the corresponding named field of the object value. The binding returned by a successful match is the union of the bindings returned by the field matches.
+
+The `` of the matched object type must be determined by an enclosing type annotation or other contextual type information.
+
+### Variant pattern
+
+The variant pattern `#  ?` matches a variant value (of the form `#  v`) against a variant pattern. An absent `?` is shorthand for the unit pattern (`()`). Pattern matching fails if the tag `` of the value is distinct from the tag `` of the pattern (i.e. `` \<\> ``); or the tags are equal but the value `v` does not match the pattern `?`. Pattern matching succeeds if the tag of the value is `` (i.e. `` = ``) and the value `v` matches the pattern `?`. The binding returned by a successful match is just the binding returned by the match of `v` against `?`.
+
+### Annotated pattern
+
+The annotated pattern ` : ` matches value of `v` type `` against the pattern ``.
+
+` : ` is not a dynamic type test, but is used to constrain the types of identifiers bound in ``, e.g. in the argument pattern to a function.
+
+### Option pattern
+
+The option `? ` matches a value of option type `? `.
+
+The match fails if the value is `null`. If the value is `? v`, for some value `v`, then the result of matching `? ` is the result of matching `v` against ``.
+
+Conversely, the `null` literal pattern may be used to test whether a value of option type is the value `null` and not `? v` for some `v`.
+
+### Or pattern
+
+The or pattern ` or ` is a disjunctive pattern.
+
+The result of matching ` or ` against a value is the result of matching ``, if it succeeds, or the result of matching ``, if the first match fails.
+
+An `or`-pattern may contain identifier (``) patterns with the restriction that both alternatives must bind the same set of identifiers. Each identifier's type is the least upper bound of its type in `` and ``.
+
+### Expression declaration
+
+The declaration `` has type `T` provided the expression `` has type `T` . It declares no bindings.
+
+The declaration `` evaluates to the result of evaluating `` typically for ``'s side-effect.
+
+Note that if `` appears within a sequence of declarations, but not as the last declaration of that sequence, then `T` must be `()`.
+
+### Let declaration
+
+The `let` declaration `let  = ` has type `T` and declares the bindings in `` provided:
+
+-   `` has type `T`, and
+
+-   `` has type `T`.
+
+The declaration `let  = ` evaluates `` to a result `r`. If `r` is `trap`, the declaration evaluates to `trap`. If `r` is a value `v` then evaluation proceeds by matching the value `v` against ``. If matching fails, then the result is `trap`. Otherwise, the result is `v` and the binding of all identifiers in `` to their matching values in `v`.
+
+All bindings declared by a `let` if any are immutable.
+
+### Let-else declaration
+
+The `let-else` declaration `let  =  else ` has type `T` and declares the bindings in `` provided:
+
+-   `` has type `T`,
+
+-   `` has type `T`, and
+
+-   `` has type `None`.
+
+The declaration `let  =  else ` evaluates `` to a result `r`.
+If `r` is `trap`, the declaration evaluates to `trap`.
+If `r` is a value `v` then evaluation proceeds by matching the value `v` against ``.
+If matching succeeds, the result is `v` and the binding of all identifiers in `` to their matching values in `v`.
+
+If matching fails, then evaluation continues with ``, which, having type `None`, cannot proceed to the end of the declaration but may still alter control-flow to, for example `return` or `throw` to exit an enclosing function, `break` from an enclosing expression or simply diverge.
+
+All bindings declared by a `let-else` if any are immutable.
+
+#### Handling pattern match failures
+
+In the presence of refutable patterns, the pattern in a `let` declaration may fail to match the value of its expression.
+In such cases, the `let`-declaration will evaluate to a trap.
+The compiler emits a warning for any `let`-declaration than can trap due to pattern match failure.
+
+Instead of trapping, a user may want to explicitly handle pattern match failures.
+The `let-else` declaration, `let  =  else `, has mostly identical static and dynamic semantics to `let`,
+but diverts the program's control flow to `` when pattern matching fails, allowing recovery from failure.
+The `else` expression, ``, must have type `None` and typically exits the declaration using imperative control flow
+constructs such as `throw`, `return`, `break` or non-returning functions such as `Debug.trap(...)` that all produce a result of type `None`.
+Any compilation warning that is produced for a `let` can be silenced by handling the potential pattern-match failure using `let-else`.
+
+### Var declaration
+
+The variable declaration `var  (: )? = ` declares a mutable variable `` with initial value ``. The variable’s value can be updated by assignment.
+
+The declaration `var ` has type `()` provided:
+
+-   `` has type `T`; and
+
+-   If the annotation `(:)?` is present, then `T` == ``.
+
+Within the scope of the declaration, `` has type `var T` (see [Assignment](#assignment)).
+
+Evaluation of `var  (: )? = ` proceeds by evaluating `` to a result `r`. If `r` is `trap`, the declaration evaluates to `trap`. Otherwise, the `r` is some value `v` that determines the initial value of mutable variable ``. The result of the declaration is `()` and `` is bound to a fresh location that contains `v`.
+
+### Type declaration
+
+The declaration `type  ? = ` declares a new type constructor ``, with optional type parameters `` and definition ``.
+
+The declaration `type C< X0 <: T0, …​, Xn <: Tn > = U` is well-formed provided:
+
+-   Type parameters `X0`, …​, `Xn` are distinct, and
+
+-   Assuming the constraints `X0 <: T0`, …​, `Xn <: Tn`:
+
+    -   Constraints `T0`, …​, `Tn` are well-formed.
+
+    -   Definition `U` is well-formed.
+
+    -   It is productive (see [Productivity](#productivity)).
+
+    -   It is non-expansive (see [Expansiveness](#expansiveness)).
+
+In scope of the declaration `type C< X0<:T0, …​, Xn <: Tn > = U`, any well-formed type `C< U0, …​, Un >` is equivalent to its expansion `U [ U0/X0, …​, Un/Xn ]`. Distinct type expressions that expand to identical types are inter-changeable, regardless of any distinction between type constructor names. In short, the equivalence between types is structural, not nominal.
+
+#### Productivity
+
+A type is **productive** if recursively expanding any outermost type constructor in its definition eventually produces a type other than the application of a type constructor.
+
+Motoko requires all type declarations to be productive.
+
+For example, the following type definitions are all productive and legal:
+
+``` motoko no-repl
+  type Person = { first : Text; last : Text };
+
+  type List = ?(T, List);
+
+  type Fst = T;
+
+  type Ok = Fst>;
+```
+
+But in contrast, the following type definitions are all non-productive, since each definition will enter a loop after one or more expansions of its body:
+
+``` motoko no-repl
+  type C = C;
+
+  type D = D;
+
+  type E = F;
+  type F = E;
+
+  type G = Fst, Any>;
+```
+
+
+#### Expansiveness
+
+A set of mutually recursive type or class declarations will be rejected if the set is **expansive**.
+
+Expansiveness is a syntactic criterion. To determine whether a set of singly or mutually recursive type definitions is expansive, for example:
+
+``` motoko no-repl
+  type C<...,Xi,...> = T;
+  ...
+  type D<...,Yj,...> = U;
+```
+
+Take these definitions and construct a directed graph whose vertices are the formal type parameters identified by position, `C#i`, with the following `{0,1}`-labeled edges:
+
+-   For each occurrence of parameter `C#i` as immediate, `j`-th argument to type `D<…​,C#i,…​>`, add a **non-expansive**, `0`-labeled edge,`C#i -0-> D#j`.
+
+-   For each occurrence of parameter `C#i` as a proper sub-expression of the `j`-th argument to type `D<…​,T[C#i],..>` add an **expansive** `1`-labeled edge, `C#i -1-> D#j`.
+
+The graph is expansive if, and only if, it contains a cycle with at least one expansive edge.
+
+For example, the type definition that recursively instantiates `List` at the same parameter `T`, is non-expansive and accepted:
+
+``` motoko no-repl
+  type List = ?(T, List);
+```
+
+A similar looking definition that recursively instantiates `Seq` with a larger type, `[T]`, containing `T`, is expansive and rejected:
+
+``` motoko no-repl
+  type Seq = ?(T, Seq<[T]>);
+```
+
+-   Type `List` is non-expansive because its graph, `{ List#0 -0-> List#0 }`, though cyclic, has no expansive edge.
+
+-   Type `Seq`, on the other hand, is expansive, because its graph, `{ Seq#0 -1-> Seq#0 }`, has a cycle that includes an expansive edge.
+
+### Object declaration
+
+Declaration ` ? (: )? =? `, where `` is of the form `{ ;* }`, declares an object with optional identifier `` and zero or more fields `;*`. Fields can be declared with `public` or `private` visibility; if the visibility is omitted, it defaults to `private`.
+
+The qualifier `` (one of `persistent? actor ?`, `module` or `object`) specifies the `` of the object’s type (`actor`, `module` or `object`, respectively).
+The sort imposes restrictions on the types of the public object fields.
+
+Let `T =  { [var0] id0 : T0, …​ , [varn] idn : T0 }` denote the type of the object. Let `;*` be the sequence of declarations embedded in `;*`. The object declaration has type `T` provided that:
+
+1.  Type `T` is well-formed for sort ``, and
+
+2.  Under the assumption that ` : T`,
+
+    -   The sequence of declarations `;*` has type `Any` and declares the disjoint sets of private and public identifiers, `Id_private` and `Id_public` respectively, with types `T(id)` for `id` in `Id == Id_private union Id_public`, and
+
+    -   `{ id0, …​, idn } == Id_public`, and
+
+    -   For all `i in 0 <= i <= n`, `[vari] Ti == T(idi)`.
+
+3.  If `` is `module`, then the declarations in `;*` must be *static* (see [static declarations](#static-declarations)).
+
+Note that the first requirement imposes further constraints on the field types of `T`. In particular, if the sort is `actor` then:
+
+-   All public fields must be non-`var` immutable `shared` functions. The public interface of an actor can only provide asynchronous messaging via shared functions.
+
+Because actor construction is asynchronous, an actor declaration can only occur in an asynchronous context, i.e. in the body of a non-`` `shared` function, `async` expression or `async*` expression.
+
+Evaluation of `? ? =? { ;* }` proceeds by binding ``, if present, to the eventual value `v`, and evaluating the declarations in `;*`. If the evaluation of `;*` traps, so does the object declaration. Otherwise, `;*` produces a set of bindings for identifiers in `Id`. let `v0`, …​, `vn` be the values or locations bound to identifiers ``, …​, ``. The result of the object declaration is the object `v ==  {  = v1, …​,  = vn}`.
+
+If `?` is present, the declaration binds `` to `v`. Otherwise, it produces the empty set of bindings.
+
+If `(: )?` is present, then `T` must be a subtype of ``.
+
+:::danger
+
+Actor declaration is implicitly asynchronous and the state of the enclosing actor may change due to concurrent processing of other incoming actor messages. It is the programmer’s responsibility to guard against non-synchronized state changes.
+
+:::
+
+#### Static declarations
+
+A declaration is **static** if it is:
+
+-   A `type` declaration.
+
+-   A `class` declaration.
+
+-   A `let` declaration with a static pattern and a static expression.
+
+-   A module, function or object declaration that de-sugars to a static `let` declaration.
+
+-   A static expression.
+
+An expression is static if it is:
+
+-   A literal expression.
+
+-   A tuple of static expressions.
+
+-   An object of static expressions.
+
+-   A variant or option with a static expression.
+
+-   An immutable array.
+
+-   Field access and projection from a static expression.
+
+-   A module expression.
+
+-   A function expression.
+
+-   A static declaration.
+
+-   An `ignore` of a static expression.
+
+-   A block, all of whose declarations are static.
+
+-   A type annotation with a static expression.
+
+A pattern is static if it is:
+
+-   An identifier.
+
+-   A wildcard.
+
+-   A tuple of static patterns.
+
+-   Type annotation with a static pattern.
+
+
+
+Static phrases are designed to be side-effect free, allowing the coalescing of duplicate library imports.
+
+### Function declaration
+
+The function declaration `? func ? ?  (: )? =? ` is syntactic sugar for a named `let` or anonymous declaration of a function expression.
+
+That is, when `?` is present and the function is named:
+
+``` bnf
+? func  ?  (: )? =?  :=
+  let  = ? func ?  (: )? =? 
+```
+
+But when `?` is absent and the function is anonymous:
+
+``` bnf
+? func ?  (: )? =?  :=
+  ? func ?  (: )? =? 
+```
+
+Named function definitions support recursion, i.e. a named function can call itself.
+
+:::note
+
+In compiled code, `shared` functions can only appear as public actor fields.
+
+:::
+
+### Class declaration
+
+The class declaration `? ? class ? ?  (: )? ` is sugar for pair of a type and function declaration:
+
+``` bnf
+? ? class  ?  (: )?  :=
+  type  ? =  { ;* };
+  ? func  ?  : async?   =
+    async?  ? 
+```
+
+where:
+
+-   `?`, when present, requires `` == `persistent? actor`, and provides access to the `caller` of an `actor` constructor, and
+
+-   `?` and `?` is the sequence of type identifiers bound by `?`, if any, and
+
+-   `;*` is the set of public field types inferred from `;*`.
+
+-   `` is the object body of ``.
+
+-   `?` is the optional **this** or **self** parameter of ``.
+
+-   `async?` is present, if only if, `` == `persistent? actor`.
+
+Note `?` must not be of the form `shared  ?`: a constructor, unlike a function, cannot be a `query` or `composite query`.
+
+An absent `?` defaults to `shared` when `` = `persistent? actor`.
+
+If `sort` is `persistent? actor`, then:
+
+-   `?` must be absent or empty, such that `actor` classes cannot have type parameters.
+
+-   ``'s type must be shared (see [shareability](#shareability)).
+
+-   `(: )?`, if present, must be of the form `: async T` for some actor type `T`. Actor instantiation is asynchronous.
+
+If `(: )` is present, then the type `  {  ;* }` must be a subtype of the annotation ``. In particular, the annotation is used only to check, but not affect, the inferred type of function ``. `` is just `` erasing any `persistent?` modifier.
+
+The class declaration has the same type as function `` and evaluates to the function value ``.
+
+### Mixin declaration
+
+The mixin declaration `mixin  ` declares a mixin and has no effect.
+It can only occur in the body of a library.
+
+The fields of a mixin are stable unless declared `transient`.
+
+### Mixin inclusion
+
+The mixin inclusion `include  ` instantiates a copy of the (imported) mixin ``
+with the value of argument ``.
+
+Mixin inclusion can only occur in the body of an actor, actor class, or another mixin.
+
+The inclusion extends the environment with all the declarations of the mixin body
+(with their declared visibility and stability modifiers).
+
+### Identifiers
+
+The identifier expression `` has type `T` provided `` is in scope, defined and declared with explicit or inferred type `T`.
+
+The expression `` evaluates to the value bound to `` in the current evaluation environment.
+
+### Literals
+
+A literal has type `T` only when its value is within the prescribed range of values of type `T`.
+
+The literal (or constant) expression `` evaluates to itself.
+
+### Unary operators
+
+The unary operator ` ` has type `T` provided:
+
+-   `` has type `T`, and
+
+-   The category of `` is a category of `T`.
+
+The unary operator expression ` ` evaluates `` to a result. If the result is a value `v`, it returns the result of ` v`. If the result is `trap`, the entire expression results in `trap`.
+
+### Binary operators
+
+The binary operator expression `  ` has type `T` provided:
+
+-   `` has type `T`.
+
+-   `` has type `T`.
+
+-   The category of `` is a category of `T`.
+
+The binary operator expression `  ` evaluates `exp1` to a result `r1`. If `r1` is `trap`, the expression results in `trap`.
+
+Otherwise, `exp2` is evaluated to a result `r2`. If `r2` is `trap`, the expression results in `trap`.
+
+Otherwise, `r1` and `r2` are values `v1` and `v2` and the expression returns the result of `v1  v2`.
+
+### Relational operators
+
+The relational expression `  ` has type [`Bool`](https://mops.one/core/docs/Bool) provided:
+
+-   `` has type `T`.
+
+-   `` has type `T`.
+
+-   `` is equality `==` or inequality `!=`, `T` is shared, and `T` is the least type such that `` and `` have type `T`.
+
+-   Ihe category O (Ordered) is a category of `T` and ``.
+
+The binary operator expression `  ` evaluates `` to a result `r1`. If `r1` is `trap`, the expression results in `trap`.
+
+Otherwise, `exp2` is evaluated to a result `r2`. If `r2` is `trap`, the expression results in `trap`.
+
+Otherwise, `r1` and `r2` are values `v1` and `v2` and the expression returns the Boolean result of `v1  v2`.
+
+For equality and inequality, the meaning of `v1  v2` depends on the compile-time, static choice of `T`. This means that only the static types of `` and `` are considered for equality, and not the run-time types of `v1` and `v2`, which, due to subtyping, may be more precise than the static types.
+
+### Pipe operators and placeholder expressions
+
+The pipe expression ` |> ` binds the value of `` to the special placeholder expression `_`, that can be referenced in `` and recursively in ``.
+Referencing the placeholder expression outside of a pipe operation is a compile-time error.
+
+The pipe expression ` |> ` is just syntactic sugar for a `let` binding to a placeholder identifier, `p`:
+
+``` bnf
+do { let p = ;  }
+```
+
+The placeholder expression `_` is just syntactic sugar for the expression referencing the placeholder identifier:
+
+``` bnf
+p
+```
+
+The placeholder identifier, `p`, is a fixed, reserved identifier that cannot be bound by any other expression or pattern other than a pipe operation, and can only be referenced using the placeholder expression `_`.
+
+`|>` has lowest precedence amongst all operators except `:` and associates to the left.
+
+Judicious use of the pipe operator allows one to express a more complicated nested expression by piping arguments of that expression into their nested positions within that expression.
+
+For example:
+
+``` motoko no-repl
+Iter.range(0, 10) |>
+  Iter.toList _ |>
+    List.filter(_, func n { n % 3 == 0 }) |>
+      { multiples = _ };
+```
+
+This may be a more readable rendition of:
+
+``` motoko no-repl
+{ multiples =
+   List.filter(
+     Iter.toList(Iter.range(0, 10)),
+     func n { n % 3 == 0 }) };
+```
+
+Above, each occurrence of `_` refers to the value of the left-hand-size of the nearest enclosing pipe operation, after associating nested pipes to the left.
+
+Note that the evaluation order of the two examples is different, but consistently left-to-right.
+
+:::note
+
+Although syntactically identical, the placeholder expression is semantically distinct from, and should not be confused with, the wildcard pattern `_`.
+
+Occurrences of the forms can be distinguished by their syntactic role as pattern or expression.
+
+:::
+
+### Tuples
+
+Tuple expression `(, …​, )` has tuple type `(T1, …​, Tn)`, provided ``, …​, `` have types `T1`, …​, `Tn`.
+
+The tuple expression `(, …​, )` evaluates the expressions `exp1` …​ `expn` in order, trapping as soon as some expression `` traps. If no evaluation traps and `exp1`, …​, `` evaluate to values `v1`,…​,`vn` then the tuple expression returns the tuple value `(v1, …​ , vn)`.
+
+The tuple projection ` . ` has type `Ti` provided `` has tuple type `(T1, …​, Ti, …​, Tn)`, `` == `i` and `1 <= i <= n`.
+
+The projection ` . ` evaluates `` to a result `r`. If `r` is `trap`, then the result is `trap`. Otherwise, `r` must be a tuple `(v1,…​,vi,…​,vn)` and the result of the projection is the value `vi`.
+
+The empty tuple expression `()` is called the **unit value**.
+
+### Option expressions
+
+The option expression `? ` has type `? T` provided `` has type `T`.
+
+The literal `null` has type `Null`. Since `Null <: ? T` for any `T`, literal `null` also has type `? T` and signifies the "missing" value at type `? T`.
+
+### Variant injection
+
+The variant injection `#  ` has variant type `{# id T}` provided:
+
+-   `` has type `T`.
+
+The variant injection `# ` is just syntactic sugar for `#  ()`.
+
+The variant injection `#  ` evaluates `` to a result `r`. If `r` is `trap`, then the result is `trap`. Otherwise, `r` must be a value `v` and the result of the injection is the tagged value `#  v`.
+
+The tag and contents of a variant value can be tested and accessed using a [variant pattern](#variant-pattern).
+
+### Objects
+
+Objects can be written in literal form `{ ;* }`, consisting of a list of expression fields:
+
+``` bnf
+ ::=                                Object expression fields
+  var?  (: ) =                     Field
+  var?  (: )                            Punned field
+```
+
+Such an object literal, sometimes called a record, is equivalent to the object declaration `object { ;* }` where the declaration fields are obtained from the expression fields by prefixing each of them with `public let`, or just `public` in case of `var` fields. However, unlike declarations, the field list does not bind each `` as a local name within the literal, i.e., the field names are not in scope in the field expressions.
+
+Object expressions support **punning** for concision. A punned field `` is shorthand for ` = `; Similarly, a typed, punned field ` : ` is short-hand for ` =  : `. Both associate the field named `` with the value of the identifier ``.
+
+### Object combination/extension
+
+Objects can be combined and/or extended using the `and` and `with` keywords.
+
+A record expression `{  (and )* (with ;+)? }` merges the objects or module) specified as base expressions, and augments the result to also contain the specified fields. The `with ;+` clause can be omitted when at least two bases appear and none have common field labels.
+Thus the field list serves to:
+
+-   Disambiguate field labels occurring more than once in the bases.
+-   Define new fields.
+-   Override existing fields and their types.
+-   Add new `var` fields.
+-   Redefine existing `var` fields from some base to prevent aliasing.
+
+The resulting type is determined by the bases' and explicitly given fields' static type.
+
+Any `var` field from some base must be overwritten in the explicit field list. This prevents introducing aliases of `var` fields.
+
+The record expression `{  and ...  with ; ... ; }` has type `T` provided:
+
+-  The record `{ ; ... ; }` has record type `{ field_tys } == { var?  : U1; ... var?  : Um }`.
+
+-  Let `newfields == {  , ...,  }` be the set of new field names.
+
+-   Considering value fields:
+
+    -   Base expression `` has object or module type `sorti { field_tysi } == sorti { var?  : Ti1, …​, var?  : Tik }` where `sorti <> Actor`.
+
+    Let `fields(i) == { , ...,  }` be the set of static field names of base `i`. Then:
+
+    -   `fields(i)` is disjoint from `newfields` (possibly by applying subtyping to the type of ``).
+
+    -   No field in `field_tysi` is a `var` field.
+
+    -  `fields(i)` is disjoint from `fields(j)` for `j < i`.
+
+-   Considering type fields:
+
+    -   Base expression `` has object or module type `sorti { typ_fieldsi } == sorti { type  = … , …, type  = … }` where `sorti <> Actor`.
+
+    -   `typ_fieldsi` _agrees_ with `typ_fieldsj` for `j < i`.
+
+-   `T` is `{ typ_fieldsi fields_tys1 ... typ_fieldsm fields_tysm field_tys }`.
+
+Here, two sequences of type fields agree only when any two type fields of the same name in each sequence have equivalent definitions.
+
+
+
+The record expression `{  and ...  with ; ... ; }` evaluates records `` through `` and `{ exp-field1; ... ) = fi()` if `` is in `fields(i)`, for some `i`, or `f()` if `` is in `newfields`.
+
+### Object projection (member access)
+
+The object projection ` . ` has type `var? T` provided `` has object type `sort { var1?  : T1, …​, var?  : T, …​, var?  : Tn }` for some sort `sort`.
+
+The object projection ` . ` evaluates `` to a result `r`. If `r` is `trap`, then the result is `trap`. Otherwise, `r` must be an object value `{  = v1,…​, id = v, …​,  = vm }` and the result of the projection is the value `w` obtained from value or location `v` in field `id`.
+
+If `var` is absent from `var? T` then the value `w` is just the value `v` of immutable field ``, otherwise:
+
+-   If the projection occurs as the target of an assignment expression then `w` is just `v`, the mutable location in field ``.
+
+-   Otherwise, `w` (of type `T`) is the value currently stored at the mutable location `v` in field ``.
+
+### Special member access
+
+The iterator access ` . ` has type `T` provided `` has type `U`, and `U`,`` and `T` are related by a row of the following table:
+
+|            |                 |                         |                                                 |
+| ---------- | --------------- | ----------------------- | ----------------------------------------------- |
+| U          | ``          | T                       | Description                                     |
+| [`Text`](https://mops.one/core/docs/Text)    | `size`  | [`Nat`](https://mops.one/core/docs/Nat) | Size (or length) in characters        |
+| [`Text`](https://mops.one/core/docs/Text)    | `chars` | `{ next: () -> Char? }` | Character iterator, first to last     |
+|            |                 |                         |                                                 |
+| [`Blob`](https://mops.one/core/docs/Blob)    | `size`  | [`Nat`](https://mops.one/core/docs/Nat) | Size in bytes                         |
+| [`Blob`](https://mops.one/core/docs/Blob)    | `get`   | `Nat -> Nat8`           | Indexed read function                 |
+| [`Blob`](https://mops.one/core/docs/Blob)    | `keys`  | `{ next: () -> Nat? }`  | Index iterator, by ascending index    |
+| [`Blob`](https://mops.one/core/docs/Blob)    | `vals`, `values` | `{ next: () -> Nat8? }` | Byte iterator, first to last |
+|            |                 |                         |                                                 |
+| `[var? T]` | `size`          | [`Nat`](https://mops.one/core/docs/Nat) | Number of elements                              |
+| `[var? T]` | `get`           | `Nat -> T`              | Indexed read function                           |
+| `[var? T]` | `keys`          | `{ next: () -> Nat? }`  | Index iterator, by ascending index              |
+| `[var? T]` | `vals`, `values`| `{ next: () -> T? }`    | Value iterator, by ascending index              |
+| `[var T]`  | `put`           | `(Nat, T) -> ()`        | Indexed write function (mutable arrays only)    |
+
+The projection ` . ` evaluates `` to a result `r`. If `r` is `trap`, then the result is `trap`. Otherwise, `r` must be a value of type `U` and the result of the projection is a value of type `T` whose semantics is given by the Description column of the previous table.
+
+:::note
+
+the `chars`, `vals`, `keys` and `vals` members produce stateful iterator objects than can be consumed by `for` expressions (see [for](#for)).
+
+:::
+
+
+### Assignment
+
+The assignment ` := ` has type `()` provided:
+
+-   `` has type `var T`.
+
+-   `` has type `T`.
+
+The assignment expression ` := ` evaluates `` to a result `r1`. If `r1` is `trap`, the expression results in `trap`.
+
+Otherwise, `exp2` is evaluated to a result `r2`. If `r2` is `trap`, the expression results in `trap`.
+
+Otherwise `r1` and `r2` are respectively a location `v1`, a mutable identifier, an item of a mutable array or a mutable field of an object, and a value `v2`. The expression updates the current value stored in `v1` with the new value `v2` and returns the empty tuple `()`.
+
+### Unary compound assignment
+
+The unary compound assignment `= ` has type `()` provided:
+
+-   `` has type `var T`.
+
+-   ``'s category is a category of `T`.
+
+The unary compound assignment `= ` evaluates `` to a result `r`. If `r` is `trap` the evaluation traps, otherwise `r` is a location storing value `v` and `r` is updated to contain the value ` v`.
+
+### Binary compound assignment
+
+The binary compound assignment ` = ` has type `()` provided:
+
+-   `` has type `var T`.
+
+-   `` has type `T`.
+
+-   ``'s category is a category of `T`.
+
+For binary operator ``, the compound assignment expression ` = ` evaluates `` to a result `r1`. If `r1` is `trap`, the expression results in `trap`. Otherwise, `exp2` is evaluated to a result `r2`. If `r2` is `trap`, the expression results in `trap`.
+
+Otherwise `r1` and `r2` are respectively a location `v1`, a mutable identifier, an item of a mutable array or a mutable field of object, and a value `v2`. The expression updates the current value, `w` stored in `v1` with the new value `w  v2` and returns the empty tuple `()`.
+
+### Arrays
+
+The expression `[ var? ,* ]` has type `[var? T]` provided each expression `` in the sequence `,*` has type T.
+
+The array expression `[ var , …​,  ]` evaluates the expressions `exp0` …​ `expn` in order, trapping as soon as some expression `` traps. If no evaluation traps and `exp0`, …​, `` evaluate to values `v0`,…​,`vn` then the array expression returns the array value `[var? v0, …​ , vn]` of size `n+1`.
+
+### Array indexing
+
+The array indexing expression ` [  ]` has type `var? T` provided:
+
+-   `` has mutable or immutable array type `[var? T1]`.
+
+The expression ` [  ]` evaluates `exp1` to a result `r1`. If `r1` is `trap`, then the result is `trap`.
+
+Otherwise, `exp2` is evaluated to a result `r2`. If `r2` is `trap`, the expression results in `trap`.
+
+Otherwise, `r1` is an array value, `var? [v0, …​, vn]`, and `r2` is a natural integer `i`. If `i > n` the index expression returns `trap`.
+
+Otherwise, the index expression returns the value `v`, obtained as follows:
+
+- If `var` is absent from `var? T` then the value `v` is the constant value `vi`.
+
+Otherwise,
+
+-   If the indexing occurs as the target of an assignment expression then `v` is the `i`-th mutable location in the array.
+
+-   Otherwise, `v` is `vi`, the value currently stored in the `i`-th location of the array.
+
+
+### Dotted function calls
+
+The dotted function call expression `? . ? ` has type `T` provided
+the expanded function call expression `?  ? ` has type `T`,
+where
+
+  * If the projection `.` has some function type then ` = .` and ` = `.
+
+  * Otherwise, the module environment is used to determine an appropriate function `` and argument `` by
+    constructing a set of candidates Cs and disambiguation Ds:
+
+      * If the receiver `` has type `R` and
+      * Cs = { `(, V1[Ts/Xs], a)` | `` has type `module {}` and `.` has type `(self : V1, ..., Va) -> V` and `R <: V1[Ts/Xs]` for `Ts` } and
+      * Ds = { `(, V, a)`  in Cs | for all `(_, W, _)` in Cs, `V <: W` } and
+      * { `(, _, _)` } = Ds and
+
+    Then ` = .` and ` = extend_args(, , a)`.
+
+    Here:
+
+    * `R` is the type of the receiver expression ``.
+    *  Cs is the set of candidate functions `.` in modules named ``, with explicitly name `self` parameter that matches the receiver type `R`.
+    *  Ds is the disambiguated set of candidates, filtered by specifity.
+    * `` is the name of the unique disambiguation, if one exists (that is, when Ds is a singleton set).
+    *  Finally `extend_args` is the following auxilliary function that inserts the receiver into arguments ``, using the candidate's arity `a`:
+
+    ```
+    extend_args( : exp,  : exp, arity : Nat) : exp
+    extend_args(, , 2) = (, )
+    extend_args(, (), arity) = 
+    extend_args(, , ... ), a) = (, , , ..., )
+    ```
+
+The dotted function call expression `? . ? ` evaluates
+as its expanded function call expression `?  ? `.
+
+### Function calls
+
+
+Function types can specify `implicit` parameters.
+The _arity_ of a function is its number of parameters.
+The _implicit arity_ of a function is its number of `implicit` parameters.
+
+An argument expression has arity n if it is a parenthesized sequence of `n` arguments, and arity 1 otherwise.
+
+A function call can either supply a tuple for all parameters, one argument per parameter, or one argument per non-implicit parameter, omitting arguments for all implicit parameters.
+The values of omitted arguments are inferred statically from the context.
+
+The function call expression `?  ? ` has type `T` provided the
+the expanded function call expression `?  ? ` has type `T` where:
+
+-   The function `` has function type `F = ? < X0 <: V0, ..., Xn <: Vn > U1 -> U2`.
+
+-   If `F` has implicit arity 0 then ` = `, otherwise:
+
+    * ` = ( exp21, ..., exp2a )`; and
+    * `a = arity(F) - implicit_arity(F)`; and
+    * ` = ( insert_holes(0 ; U1 ; (exp21,...,exp2a)) )`;
+
+    where `insert_holes` extends the actual arguments list with placeholders `hole(i, , U)` for missing implicit parameters:
+
+    ```
+    insert_holes(n ;  ; ) =
+      
+    insert_holes(n ; ( ( : (implicit : ( : U))), Us) ; ) =
+      hole(n, , U), insert_holes(n + 1 ; Us ; exps)
+    insert_holes(n ; ( ( : (implicit : U)), Us) ; ) =
+      hole(n, , U), insert_holes(n + 1 ; Us ; exps)
+    insert_holes(n ; (U, Us);  (, )) =
+      , insert_holes(n ; Us ; )
+    ```
+
+    (These equations are applied in order; semicolon is just as argument separator.)
+
+-   If `?` is absent but `n > 0` then there exists minimal `T0, …​, Tn` inferred by the compiler such that:
+
+-   Each type argument satisfies the corresponding type parameter's bounds: for each `1 <= i <= n`, `Ti <: [T0/X0, …​, Tn/Xn]Vi`.
+
+-   The argument `` has type `[T0/X0, …​, Tn/Xn]U1`, and
+
+-   `T == [T0/X0, …​, Tn/Xn]U2`.
+
+-   For each `i` in `(0..implicit_arity(F)]`:
+
+      * ` : [T0/X0, …​, Tn/Xn]Ui`; and
+      * `hole(i, , Ui) = `; and
+
+      Otherwise:
+
+      * Cs = { `(, V)` | `` has type `module {}` and `.` has type `V` and `V <: [T0/X0, …​, Tn/Xn]U1` }; and
+      * Ds = { `(, V)`  in Cs | for all `(_, W)` in Cs, `W <: V` }; and
+      * { `(, _)` } = Ds; and
+      * `hole(i, , Ui) = .`.
+
+    Here:
+
+    * `hole(i, , Ui)` is the description of the `ith` hole, a placeholder for an expression `` or `.`.
+    *  `` is the resolution of the hole from the local context, if any;
+    *  Cs is the set of candidate module `` named ``, with type `V` whose field `.` matches hole type `Ui` (after type instantiation).
+    *  Ds is the disambiguated set of candidates, filtered by generality.
+    * `.` is the name of the unique disambiguation, if one exists (that is, when Ds is a singleton set).
+
+The call expression ` ? ` evaluates `` to a result `r1`. If `r1` is `trap`, then the result is `trap`.
+
+Otherwise, `` (the hole expansion of ``) is evaluated to a result `r2`. If `r2` is `trap`, the expression results in `trap`.
+
+Otherwise, `r1` is a function value, `? func   {  }` (for some implicit environment), and `r2` is a value `v2`. If `` is present and of the form `shared ? ` then evaluation continues by matching the record value `{caller = p}` against ``, where `p` is the [`Principal`](https://mops.one/core/docs/Principal) invoking the function, typically a user or canister. Matching continues by matching `v1` against ``. If pattern matching succeeds with some bindings, then evaluation returns the result of `` in the environment of the function value not shown extended with those bindings. Otherwise, some pattern match has failed and the call results in `trap`.
+
+A ``, when present, modifies dynamic attributes of the message send (provided that the return type `T` is of form `async U`, i.e. a future). The recognized attributes are
+- `cycles : Nat` to attach cycles
+- `timeout : Nat32` to introduce a timeout for best-effort message execution.
+
+:::note
+
+The exhaustiveness side condition on `shared` function expressions ensures that argument pattern matching cannot fail (see [functions](#functions)).
+
+:::
+
+:::note
+
+Calls to local functions with `async` return type and `shared` functions can fail due to a lack of canister resources.
+Such failures will result in the call immediately throwing an error with  `code` `#call_error { err_code = n }`, where `n` is the non-zero `err_code` value returned by ICP.
+
+Earlier versions of Motoko would trap in such situations, making it difficult for the calling canister to mitigate such failures.
+Now, a caller can handle these errors using enclosing `try ... catch ...` expressions, if desired.
+
+:::
+
+### Functions
+
+The function expression `? func < X0 <: T0, …​, Xn <: Tn >  (: U2)? =? ` has type `? < X0 <: T0, ..., Xn <: Tn > U1-> U2` if, under the assumption that `X0 <: T0, …​, Xn <: Tn`:
+
+-   `?` is of the form `shared ? ` if and only if `?` is `shared ?` (the `` modifiers must agree, i.e. are either both absent, both `query`, or both `composite query`).
+
+-   All the types in `T0, …​, Tn` and `U2` are well-formed and well-constrained.
+
+-   Pattern `` has *context type* `{ caller : Principal }`.
+
+-   Pattern `` has type `U1`.
+
+-   If the function is `shared` then `` and `` must be exhaustive.
+
+-   Expression `` has type return type `U2` under the assumption that `` has type `U1`.
+
+`? func ?  (: )? =? ` evaluates to a function value denoted `? func ?  = `, that stores the code of the function together with the bindings from the current evaluation environment needed to evaluate calls to the function value.
+
+Note that a `` function may itself be `shared ` or `shared query ` or  `shared composite query `.
+
+-   A `shared ` function may be invoked from a remote caller. Unless causing a trap, the effects on the callee persist beyond completion of the call.
+
+-   A `shared query ` function may be also be invoked from a remote caller, but the effects on the callee are transient and discarded once the call has completed with a result (whether a value or error).
+
+-   A `shared composite query ` function may only be invoked as an ingress message, not from a remote caller.
+    Like a query, the effects on the callee are transient and discarded once the call has completed with a result, whether a value or error.
+    In addition, intermediate state changes made by the call are not observable by any of its own `query`  or `composite query` callees.
+
+
+In either case, `` provides access to a context value identifying the *caller* of the shared function.
+
+:::note
+
+The context type is a record to allow extension with further fields in future releases.
+
+:::
+
+Shared functions have different capabilities dependent on their qualification as `shared`, `shared query` or `shared composite query`.
+
+A `shared` function may call any `shared` or `shared query` function, but no `shared composite query` function.
+A `shared query` function may not call any `shared`, `shared query` or `shared composite query` function.
+A `shared composite query` function may call any `shared query` or `shared composite query` function, but no `shared` function.
+
+All varieties of shared functions may call unshared functions.
+
+Composite queries, though composable, can only be called externally such as from a frontend and cannot be initiated from an actor.
+
+
+### Blocks
+
+The block expression `{ ;* }` has type `T` provided the last declaration in the sequence `;*` has type `T`. All identifiers declared in block must be distinct type identifiers or distinct value identifiers and are in scope in the definition of all other declarations in the block.
+
+The bindings of identifiers declared in `{ dec;* }` are local to the block.
+
+The type system ensures that a value identifier cannot be evaluated before its declaration has been evaluated, precluding run-time errors at the cost of rejection some well-behaved programs.
+
+Identifiers whose types cannot be inferred from their declaration, but are used in a forward reference, may require an additional type annotation (see [annotated pattern](#annotated-pattern)) to satisfy the type checker.
+
+The block expression `{ ;* }` evaluates each declaration in `;*` in sequence (program order). The first declaration in `;*` that results in a trap causes the block to result in `trap`, without evaluating subsequent declarations.
+
+### Do
+
+The do expression `do ` allows the use of a block as an expression, in positions where the syntax would not directly allow a block.
+
+The expression `do ` has type `T` provided `` has type `T`.
+
+The `do` expression evaluates by evaluating `` and returning its result.
+
+### Option block
+
+The option block `do ? ` introduces scoped handling of null values.
+
+The expression `do ? ` has type `?T` provided `` has type `T`.
+
+The `do ? ` expression evaluates `` and returns its result as an optional value.
+
+Within `` the null break expression ` !` exits the nearest enclosing `do ?` block with value `null` whenever `` has value `null`, or continues evaluation with the contents of ``'s option value. (See [Null break](#null-break).)
+
+Option blocks nest with the target of a null break determined by the nearest enclosing option block.
+
+### Null break
+
+The null break expression ` !` invokes scoped handling of null values and returns the contents of an option value or changes control-flow when the value is `null`.
+
+It has type `T` provided:
+
+-   The expression appears in the body, ``, of an enclosing option block of the form `do ? ` (see [option block](#do-opt)).
+
+-   `` has option type `? T`.
+
+The expression ` !` evaluates `` to a result `r`. If `r` is `trap`, then the result is `trap`; if `r` is `null`, execution breaks with value `null` from the nearest enclosing option block of form `do ? `; otherwise, `r` is `? v` and execution continues with value `v`.
+
+### Not
+
+The not expression `not ` has type [`Bool`](https://mops.one/core/docs/Bool) provided `` has type [`Bool`](https://mops.one/core/docs/Bool).
+
+If `` evaluates to `trap`, the expression returns `trap`. Otherwise, `` evaluates to a Boolean value `v` and the expression returns `not v`, the Boolean negation of `v`.
+
+### And
+
+The and expression ` and ` has type [`Bool`](https://mops.one/core/docs/Bool) provided `` and `` have type [`Bool`](https://mops.one/core/docs/Bool).
+
+The expression ` and ` evaluates `exp1` to a result `r1`. If `r1` is `trap`, the expression results in `trap`. Otherwise `r1` is a Boolean value `v`. If `v == false` the expression returns the value `false` (without evaluating ``). Otherwise, the expression returns the result of evaluating ``.
+
+### Or
+
+The or expression ` or ` has type [`Bool`](https://mops.one/core/docs/Bool) provided `` and `` have type [`Bool`](https://mops.one/core/docs/Bool).
+
+The expression ` and ` evaluates `exp1` to a result `r1`. If `r1` is `trap`, the expression results in `trap`. Otherwise `r1` is a Boolean value `v`. If `v == true` the expression returns the value `true` without evaluating ``. Otherwise, the expression returns the result of evaluating ``.
+
+### If
+
+The expression `if   (else )?` has type `T` provided:
+
+-   `` has type [`Bool`](https://mops.one/core/docs/Bool).
+
+-   `` has type `T`.
+
+-   `` is absent and `() <: T`.
+
+-   `` is present and has type `T`.
+
+The expression evaluates `` to a result `r1`. If `r1` is `trap`, the result is `trap`. Otherwise, `r1` is the value `true` or `false`. If `r1` is `true`, the result is the result of evaluating ``. Otherwise, `r1` is `false` and the result is `()` (if `` is absent) or the result of `` (if `` is present).
+
+### Switch
+
+The switch expression `switch  { (case  ;)+ }` has type `T` provided:
+
+-   `exp` has type `U`.
+
+-   For each case `case  ` in the sequence `(case  ;)+`.
+
+-   Pattern `` has type `U`.
+
+-   Expression `` has type `T`.
+
+The expression evaluates `` to a result `r`. If `r` is `trap`, the result is `trap`. Otherwise, `r` is some value `v`. Let `case  ;` be the first case in `(case  ;)+` such that `` matches `v` for some binding of identifiers to values. Then result of the `switch` is the result of evaluating `` under that binding. If no case has a pattern that matches `v`, the result of the switch is `trap`.
+
+### While
+
+The expression `while  ` has type `()` provided:
+
+-   `` has type [`Bool`](https://mops.one/core/docs/Bool).
+
+-   `` has type `()`.
+
+The expression evaluates `` to a result `r1`. If `r1` is `trap`, the result is `trap`. Otherwise, `r1` is the value `true` or `false`. If `r1` is `true`, the result is the result of re-evaluating `while  `. Otherwise, the result is `()`.
+
+### Loop
+
+The expression `loop ` has type `None` provided `` has type `()`.
+
+The expression evaluates `` to a result `r1`. If `r1` is `trap`, the result is `trap`. Otherwise, the result is the result of re-evaluating `loop `.
+
+### Loop-while
+
+The expression `loop  while ` has type `()` provided:
+
+-   `` has type `()`.
+
+-   `` has type [`Bool`](https://mops.one/core/docs/Bool).
+
+The expression evaluates `` to a result `r1`. If `r1` is `trap`, the result is `trap`. Otherwise, evaluation continues with ``, producing result `r2`. If `r2` is `trap` the result is `trap`. Otherwise, if `r2` is `true`, the result is the result of re-evaluating `loop  while `. Otherwise, `r2` is false and the result is `()`.
+
+### For
+
+The iterator expression `for (  in  ) ` has type `()` provided:
+
+-   `` has type `{ next : () → ?T }`.
+
+-   pattern `` has type `T`.
+
+-   expression `` has type `()` (in the environment extended with the bindings of ``).
+
+The `for`-expression is syntactic sugar for the following, where `x` and `l` are fresh identifiers:
+
+``` bnf
+for (  in  )  :=
+  {
+    let x = ;
+    label l loop {
+      switch (x.next()) {
+        case (? ) ;
+        case (null) break l;
+      }
+    }
+  }
+```
+
+In particular, the `for` loop will trap if evaluation of `` traps; as soon as `x.next()` traps, or the value of `x.next()` does not match pattern ``, or when `` traps.
+
+:::note
+
+Although general purpose, `for` loops are commonly used to consume iterators produced by [special member access](#special-member-access) to, for example, loop over the indices (`a.keys()`) or values (`a.values()`) of some array, `a`.
+
+:::
+
+### Label
+
+The label-expression `label  (: )? ` has type `T` provided:
+
+-   `(: )?` is absent and `T` is unit; or `(: )?` is present and `T == `.
+
+-   `` has type `T` in the static environment extended with `label l : T`.
+
+The result of evaluating `label  (: )? ` is the result of evaluating ``.
+
+### Labeled loops
+
+If `` in `label  (: )? ` is a looping construct:
+
+-   `while (exp2) `.
+
+-   `loop  (while ())?`.
+
+-   `for ( in ) `.
+
+The body, ``, of the loop is implicitly enclosed in `label  (…​)` allowing early continuation of the loop by the evaluation of expression `continue `.
+
+`` is a fresh identifier that can only be referenced by `continue `, through its implicit expansion to `break `.
+
+### Break
+
+The expression `break` (without an identifier) is equivalent to `break `, where `` is the implicitly declared label around the innermost loop.
+
+The expression `break ` is equivalent to `break  ()`.
+
+The expression `break  ` has type `None` provided:
+
+-   The label `` is declared with type `label  : T`.
+
+-   `` has type `T`.
+
+The evaluation of `break  ` evaluates `` to some result `r`. If `r` is `trap`, the result is `trap`. If `r` is a value `v`, the evaluation abandons the current computation up to the dynamically enclosing declaration `label  …​` using the value `v` as the result of that labelled expression.
+
+### Continue
+
+The expression `continue` is equivalent to `continue `, where `` is the implicitly declared label around the body of the innermost loop.
+
+The expression `continue ` is equivalent to `break `, where `` is implicitly declared around the bodies of ``-labelled looping constructs (see [labeled loops](#labeled-loops)).
+
+### Return
+
+The expression `return` is equivalent to `return ()`.
+
+The expression `return ` has type `None` provided:
+
+-   `` has type `T`.
+
+-  and either one of:
+
+   -  `T` is the return type of the nearest enclosing function with no intervening `async` expression.
+
+   -  `async T` is the type of the nearest enclosing, perhaps implicit, `async` expression with no intervening function declaration.
+
+
+The `return` expression exits the corresponding dynamic function invocation or completes the corresponding dynamic `async` or `async*` expression with the result of ``.
+
+### Async
+
+The async expression `? async ` has type `async T` provided:
+
+-   `` has type `T`.
+
+-   `T` is shared.
+
+Any control-flow label in scope for `async ` is not in scope for ``. However, `` may declare and use its own, local, labels.
+
+The implicit return type in `` is `T`. That is, the return expression, ``, implicit or explicit, to any enclosed `return ?` expression, must have type `T`.
+
+Evaluation of `async ` queues a message to evaluate `` in the nearest enclosing or top-level actor. It immediately returns a future of type `async T` that can be used to `await` the result of the pending evaluation of ``.
+
+The presence of `` modifies the semantics of the async expression to
+- attach cycles with attribute `cycles : Nat`
+- impose a timeout (observed when awaiting the result) with attribute `timeout : Nat32`.
+
+:::note
+
+Because it involves messaging, evaluating an `async` expression can fail due to a lack of canister resources.
+
+Such failures will result in the call immediately throwing an error with  `code` `#call_error { err_code = n }`, where `n` is the non-zero `err_code` value returned by ICP.
+
+Earlier version of Motoko would trap in such situations, making it difficult for the producer of the async expression to mitigate such failures. Now, the producer can handle these errors using an enclosing `try ... catch ...` expression, if desired.
+
+:::
+
+
+### Await
+
+The `await` expression `await ` has type `T` provided:
+
+-   `` has type `async T`.
+
+-   `T` is shared.
+
+-   The `await` is explicitly enclosed by an `async`-expression or appears in the body of a `shared` function.
+
+Expression `await ` evaluates `` to a result `r`. If `r` is `trap`, evaluation returns `trap`. Otherwise `r` is a future. If the `future` is incomplete, that is, its evaluation is still pending, `await ` suspends evaluation of the neared enclosing `async` or `shared`-function, adding the suspension to the wait-queue of the `future`. Execution of the suspension is resumed once the future is completed, if ever. If the future is complete with value `v`, then `await ` suspends evaluation and schedules resumption of execution with value `v`. If the future is complete with thrown error value `e`, then `await ` suspends evaluation and schedules resumption of execution by re-throwing the error `e`.
+
+Suspending computation on `await`, regardless of the dynamic status of the future, ensures that all tentative state changes and message sends prior to the `await` are committed and irrevocable.
+
+:::danger
+
+Between suspension and resumption of a computation, the state of the enclosing actor may change due to concurrent processing of other incoming actor messages. It is the programmer’s responsibility to guard against non-synchronized state changes.
+
+Using `await` signals that the computation will commit its current state and suspend execution.
+
+:::
+
+:::note
+
+Because it involves additional messaging, an `await` on a completed future can, in rare circumstances, fail due to a lack of canister resources.
+Such failures will result in the call immediately throwing an error with `code` `#call_error { err_code = n }`, where `n` is the non-zero `err_code` value returned by ICP.
+
+The error is produced eagerly, without suspending nor committing state.
+Earlier versions of Motoko would trap in such situations, making it difficult for the consumer of the `await` to mitigate such failures. Now, the consumer can handle these errors by using an enclosing `try ... catch ...` expression, if desired.
+
+:::
+
+### Await?
+
+Similar to `await`, the `await?` expression `await? ` has type `T` provided:
+
+-   `` has type `async T`.
+
+-   `T` is shared.
+
+-   The `await?` is explicitly enclosed by an `async` expression or appears in the body of a `shared` function.
+
+Expression `await? ` evaluates `` to a result `r`. If `r` is `trap`, evaluation returns `trap`. Otherwise `r` is a future. If the `future` is incomplete, that is, its evaluation is still pending, `await? ` suspends evaluation of the neared enclosing `async` or `shared` function, adding the suspension to the wait-queue of the `future`. Execution of the suspension is resumed once the future is completed, if ever.
+If the future is complete with value `v`, then `await? ` immediately continues execution with the value `v`.
+If the future is complete with thrown error value `e`, then `await? ` immediately continues execution by re-throwing the error `e`.
+
+Thus `await?` behaves like `await` on an incomplete future, but does not suspend execution and simply continues when the future is already complete.
+
+This conditional suspension, dependent on the state of the future, enables performance optimization in cases where a definite commit point is not required.
+
+:::danger
+
+As with `await`, between suspension and resumption of a computation, the state of the enclosing actor may change due to concurrent processing of other incoming actor messages. It is the programmer’s responsibility to guard against non-synchronized state changes.
+
+Using `await?` signals that the computation may commit its current state and suspend execution, potentially allowing concurrent modification of state.
+
+:::
+
+
+### Async*
+
+The async expression `async* ` has type `async* T` provided:
+
+-   `` has type `T`.
+
+-   `T` is shared.
+
+Any control-flow label in scope for `async* ` is not in scope for ``. However, `` may declare and use its own, local, labels.
+
+The implicit return type in `` is `T`. That is, the return expression, ``, implicit or explicit, to any enclosed `return ?` expression, must have type `T`.
+
+Evaluation of `async* ` produces a delayed computation to evaluate ``. It immediately returns a value of type `async* T`.
+The delayed computation can be executed using `await*`, producing one evaluation of the computation ``.
+
+:::danger
+
+Note that `async ` has the effect of scheduling a single asynchronous computation of ``, regardless of whether its result, a future, is consumed with an `await`.
+Moreover, each additional consumption by an `await` just returns the previous result, without repeating the computation.
+
+In comparison, `async* `, has no effect until its value is consumed by an `await*`.
+Moreover, each additional consumption by an `await*` will trigger a new evaluation of ``, including repeated effects.
+
+Be careful of this distinction, and other differences, when refactoring code.
+
+:::
+
+:::note
+
+The `async*` and corresponding `await*` constructs are useful for efficiently abstracting asynchronous code into re-useable functions.
+In comparison, calling a local function that returns a proper `async` type requires committing state and suspending execution with each `await` of its result, which can be undesirable.
+
+:::
+
+
+### Await*
+
+The `await*` expression `await* ` has type `T` provided:
+
+-   `` has type `async* T`.
+
+-   `T` is shared.
+
+-   the `await*` is explicitly enclosed by an `async`-expression or appears in the body of a `shared` function.
+
+Expression `await* ` evaluates `` to a result `r`. If `r` is `trap`, evaluation returns `trap`. Otherwise `r` is a delayed computation ``. The evaluation of `await* ` proceeds with the evaluation of ``, executing the delayed computation.
+
+:::danger
+
+During the evaluation of ``, the state of the enclosing actor may change due to concurrent processing of other incoming actor messages. It is the programmer’s responsibility to guard against non-synchronized state changes.
+
+:::
+
+:::note
+
+Unlike `await`, which, regardless of the dynamic status of the future, ensures that all tentative state changes and message sends prior to the `await` are committed and irrevocable, `await*` does not, in itself, commit any state changes, nor does it suspend computation.
+Instead, evaluation proceeds immediately according to ``, the value of ``, committing state and suspending execution whenever `` does, but not otherwise.
+
+:::
+
+:::note
+
+Evaluation of a delayed `async*` block is synchronous while possible, switching to asynchronous when necessary due to a proper `await`.
+
+Using `await*` signals that the computation *may* commit state and suspend execution during the evaluation of ``, that is, that evaluation of `` may perform zero or more proper `await`s and may be interleaved with the execution of other, concurrent messages.
+
+:::
+
+### Throw
+
+The `throw` expression `throw ` has type `None` provided:
+
+-   `` has type [`Error`](https://mops.one/core/docs/Error).
+
+-   The `throw` is explicitly enclosed by an `async`-expression or appears in the body of a `shared` function.
+
+Expression `throw ` evaluates `` to a result `r`. If `r` is `trap`, evaluation returns `trap`. Otherwise `r` is an error value `e`. Execution proceeds from the `catch` clause of the nearest enclosing `try  catch  ` whose pattern `` matches value `e`. If there is no such `try` expression, `e` is stored as the erroneous result of the `async` value of the nearest enclosing `async`, `async*` expression or `shared` function invocation.
+
+### Try
+
+The `try` expression `try  catch  ` has type `T` provided:
+
+-   `` has type `T`.
+
+-   `` has type [`Error`](https://mops.one/core/docs/Error) and `` has type `T` in the context extended with ``.
+
+-   The `try` is explicitly enclosed by an `async`-expression or appears in the body of a `shared` function.
+
+Expression `try  catch  ` evaluates `` to a result `r`. If evaluation of `` throws an uncaught error value `e`, the result of the `try` is the result of evaluating `` under the bindings determined by the match of `e` against `pat`.
+
+:::note
+
+Because the [`Error`](https://mops.one/core/docs/Error) type is opaque, the pattern match cannot fail. Typing ensures that `` is an irrefutable wildcard or identifier pattern.
+
+:::
+
+The `try` expression can be provided with a `finally` cleanup clause to facilitate structured rollback of temporary state changes (e.g. to release a lock).
+The preceding `catch` clause may be omitted in the presence of a `finally` clause.
+
+This form is `try  (catch  )? finally `, and evaluation proceeds as above with the crucial addition that every control-flow path leaving `` or `` will execute the unit-valued `` before the entire `try` expression produces its result. The cleanup expression will additionally also be executed when the processing after an intervening `await` (directly, or indirectly as `await*`) traps.
+
+:::danger
+
+The code within a `finally` block should terminate promptly and not trap.
+A trapping finally block will fail to free its callback table slot which
+can prevent a future upgrade.
+In this situation, the canister should be explicitly stopped before re-attempting the upgrade.
+In addition, care should be taken to release any resources that may have remained acquired due to the trap.
+The canister may be re-started after the upgrade.
+
+:::
+
+
+See [Error type](#error-type).
+
+### Assert
+
+The assert expression `assert ` has type `()` provided `` has type [`Bool`](https://mops.one/core/docs/Bool).
+
+Expression `assert ` evaluates `` to a result `r`. If `r` is `trap` evaluation returns `trap`. Otherwise `r` is a Boolean value `v`. The result of `assert ` is:
+
+-   The value `()`, when `v` is `true`.
+
+-   `trap`, when `v` is `false`.
+
+### Type annotation
+
+The type annotation expression ` : ` has type `T` provided:
+
+-   `` is `T`.
+
+-   `` has type `U` where `U <: T`.
+
+Type annotation may be used to aid the type-checker when it cannot otherwise determine the type of `` or when one wants to constrain the inferred type, `U` of `` to a less-informative super-type `T` provided `U <: T`.
+
+The result of evaluating ` : ` is the result of evaluating ``.
+
+:::note
+
+Type annotations have no-runtime cost and cannot be used to perform the checked or unchecked `down-casts` available in other object-oriented languages.
+
+:::
+
+### Candid serialization
+
+The Candid serialization expression `to_candid ( ,*)` has type [`Blob`](https://mops.one/core/docs/Blob) provided:
+
+-   `(,*)` has type `(T1,…​,Tn)`, and each `Ti` is shared.
+
+Expression `to_candid ( ,* )` evaluates the expression sequence `( ,* )` to a result `r`. If `r` is `trap`, evaluation returns `trap`. Otherwise, `r` is a sequence of Motoko values `vs`. The result of evaluating `to_candid ( ,* )` is some Candid blob `b = encode((T1,...,Tn))(vs)`, encoding `vs`.
+
+The Candid deserialization expression `from_candid ` has type `?(T1,…​,Tn)` provided:
+
+-   `?(T1,…​,Tn)` is the expected type from the context.
+
+-   `` has type [`Blob`](https://mops.one/core/docs/Blob).
+
+-   `?(T1,…​,Tn)` is shared.
+
+Expression `from_candid ` evaluates `` to a result `r`. If `r` is `trap`, evaluation returns `trap`. Otherwise `r` is a binary blob `b`. If `b` Candid-decodes to Candid value sequence `Vs` of type `ea((T1,...,Tn))` then the result of `from_candid` is `?v` where `v = decode((T1,...,Tn))(Vs)`. If `b` Candid-decodes to a Candid value sequence `Vs` that is not of Candid type `ea((T1,...,Tn))` (but well-formed at some other type) then the result is `null`. If `b` is not the encoding of any well-typed Candid value, but some arbitrary binary blob, then the result of `from_candid` is a trap.
+
+Informally, here `ea(_)` is the Motoko-to-Candid type sequence translation and `encode/decode((T1,...,Tn))(_)` are type-directed Motoko-Candid value translations.
+
+
+
+:::note
+
+Operation `from_candid` returns `null` when the argument is a valid Candid encoding of the wrong type. It traps if the blob is not a valid Candid encoding at all.
+
+:::
+
+:::note
+
+Operations `to_candid` and `from_candid` are syntactic operators, not first-class functions, and must be fully applied in the syntax.
+
+:::
+
+:::danger
+
+The Candid encoding of a value as a blob is not unique and the same value may have many different Candid representations as a blob. For this reason, blobs should never be used to, for instance, compute hashes of values or determine equality, whether across compiler versions or even just different programs.
+
+:::
+
+### Declaration
+
+The declaration expression `` has type `T` provided the declaration `` has type `T`.
+
+Evaluating the expression `` proceeds by evaluating ``, returning the result of `` but discarding the bindings introduced by ``, if any.
+
+The expression `` is actually shorthand for the block expression `do {  }`.
+
+### Ignore
+
+The expression `ignore ` has type `()` provided the expression `` has type `Any` .
+
+The expression `ignore ` evaluates ``, typically for some side-effect, but discards its value.
+
+The `ignore` declaration is useful for evaluating an expression within a sequence of declarations when that expression has non-`unit` type, and the simpler `` declaration would be ill-typed. Then the semantics is equivalent to `let _ =  : Any`.
+
+### Debug
+
+The debug expression `debug ` has type `()` provided the expression `` has type `()`.
+
+When the program is compiled or interpreted with (default) flag `--debug`, evaluating the expression `debug ` proceeds by evaluating ``, returning the result of ``.
+
+When the program is compiled or interpreted with flag `--release`, evaluating the expression `debug ` immediately returns the unit value `()`. The code for `` is never executed, nor is its code included in the compiled binary.
+
+### Actor references
+
+The actor reference `actor ` has expected type `T` provided:
+
+-   The expression is used in a context expecting an expression of type `T`, typically as the subject of a type annotation, typed declaration or function argument.
+
+-   `T` is an some actor type `actor { …​ }`.
+
+-   `` has type [`Text`](https://mops.one/core/docs/Text).
+
+The argument `` must be, or evaluate to, the textual format of a canister identifier, specified elsewhere, otherwise the expression traps. The result of the expression is an actor value representing that canister.
+
+The validity of the canister identifier and its asserted type `T` are promises and taken on trust.
+
+An invalid canister identifier or type may manifest itself, if at all, as a later dynamic failure when calling a function on the actor’s proclaimed interface, which will either fail or be rejected.
+
+:::note
+
+The argument to `actor` should not include the `ic:` resource locator used to specify an `import`. For example, use `actor "lg264-qjkae"`, not `actor "ic:lg264-qjkae"`.
+
+:::
+
+:::danger
+
+Although they do not compromise type safety, actor references can easily introduce latent, dynamic errors. Accordingly, actor references should be used sparingly and only when needed.
+
+:::
+
+### Parentheses
+
+The parenthesized expression `(  )` has type `T` provided `` has type `T`.
+
+The result of evaluating `(  )` is the result of evaluating ``.
+
+### Subsumption
+
+Whenever `` has type `T` and `T <: U`, with `T` subtypes `U`, then by virtue of implicit subsumption, `` also has type `U` without extra syntax.
+
+In general, this means that an expression of a more specific type may appear wherever an expression of a more general type is expected, provided the specific and general types are related by subtyping. This static change of type has no runtime cost.
+
+## References
+
+-   **IEEE Standard for Floating-Point Arithmetic**, in IEEE Std 754-2019 (Revision of IEEE 754-2008), vol., no., pp.1-84, 22 July 2019, doi: 10.1109/IEEESTD.2019.8766229.
diff --git a/docs/languages/motoko/reference/motoko-grammar.md b/docs/languages/motoko/reference/motoko-grammar.md
index 919f636f..c9d530e7 100644
--- a/docs/languages/motoko/reference/motoko-grammar.md
+++ b/docs/languages/motoko/reference/motoko-grammar.md
@@ -6,380 +6,6 @@ title: "Motoko grammar"
 
 This section describes the concrete syntax, or grammar, of Motoko. The specification is auto-generated with a tool.
 
-```bnf
- ::= 
-    
-    X
-    X SEP 
-
- ::= 
-    X
-    X SEP 
-
- ::= 
-    'implicit'
-
- ::= 
-    'object'
-    'actor'
-    'module'
-
- ::= 
-    'object'
-    'persistent'? 'actor'
-    'module'
-
- ::= 
-    'query'
-    'composite' 'query'
-
- ::= 
-    
-    'shared' ?
-    
-
- ::= 
-    
-    'shared' ? ?
-     ?
-
- ::= 
-    
-     ('.' )* '.' 
-
- ::= 
-    '{' , ';')> '}'
-
- ::= 
-    '{' '#' '}'
-    '{' , ';')> '}'
-
- ::= 
-    '(' , ',')> ')'
-     ?
-    '[' 'var'?  ']'
-    
-    
-
- ::= 
-    
-    '?' 
-    '??' 
-    'weak' 
-
- ::= 
-    
-    'async' 
-    'async*' 
-     
-
- ::= 
-    
-       '->' 
-
- ::= 
-    
-     'and' 
-     'or' 
-
- ::= 
-     ':' 
-     ':' 
-    
-
- ::= 
-    '<' , ',')> '>'
-
- ::= 
-    
-    '<' , ',')> '>'
-    '<' 'system' (',' )* '>'
-
- ::= 
-    ('<' , ',')> '>')?
-    '<' 'system' (',' )* '>'
-
- ::= 
-    'type'  ('<' , ',')> '>')? '=' 
-    'var'?  ':' 
-       ':' 
-
- ::= 
-    '#'  (':' )?
-
- ::= 
-     '<:' 
-    
-
- ::= 
-    'null'
-    
-    
-    
-    
-    
-
- ::= 
-    '+'
-    '-'
-    '^'
-
- ::= 
-    '+'
-    '-'
-    '*'
-    '/'
-    '%'
-    '**'
-    '+%'
-    '-%'
-    '*%'
-    '**%'
-    '&'
-    '|'
-    '^'
-    '<<'
-    ' >>'
-    '<<>'
-    '<>>'
-    '#'
-
- ::= 
-    '=='
-    '!='
-    ' < '
-    '<='
-    ' > '
-    '>='
-
- ::= 
-    '+='
-    '-='
-    '^='
-
- ::= 
-    '+='
-    '-='
-    '*='
-    '/='
-    '%='
-    '**-'
-    '+%='
-    '-%='
-    '*%='
-    '**%='
-    '&='
-    '|='
-    '^='
-    '<<='
-    '>>='
-    '<<>='
-    '<>>='
-    '@='
-
- ::= 
-    '(' ? 'with' , ';')> ')'
-
- ::= 
-    '{' , ';')> '}'
-    '{'  'and'  ('and' )* '}'
-    '{'  ('and' )* 'with' , ';')> '}'
-
- ::= 
-    
-    '(' , ',')> ')'
-
- ::= 
-    
-    
-    
-    '_'
-
- ::= 
-    
-    
-    '(' , ',')> ')'
-    
-    '_'
-
- ::= 
-    
-    '[' 'var'? , ',')> ']'
-     '['  ']'
-     '.'
-     '.' 
-      
-     '!'
-    '(' 'system'  '.'  ')'
-
- ::= 
-    
-       
-    '#' 
-    '#'  
-    '?' 
-    '??' 
-     
-     
-    'actor' 
-    'not' 
-    'debug_show' 
-    'to_candid' '(' , ',')> ')'
-    'from_candid' 
-
- ::= 
-    
-      
-      
-     'and' 
-     'or' 
-     ':' 
-     '|>' 
-
- ::= 
-    
-     ':=' 
-     '??' 
-      
-    'return' ?
-    ? 'async' 
-    'async*' 
-    'await' 
-    'await?' 
-    'await*' 
-    'assert' 
-    'label'  (':' )? 
-    'break'  ?
-    'break'
-    'continue' ?
-    'debug' 
-    'if'  
-    'if'   'else' 
-    'try'  
-    'try'   'finally' 
-    'try'  'finally' 
-    'throw' 
-    'switch'  '{' , ';')> '}'
-    'while'  
-    'loop' 
-    'loop'  'while' 
-    'for' '('  'in'  ')' 
-    'ignore' 
-    'do' 
-    'do' '?' 
-
- ::= 
-    
-    
-
- ::= 
-    
-    
-
- ::= 
-    
-    
-
- ::= 
-    '{' , ';')> '}'
-
- ::= 
-    'case'  
-
- ::= 
-    'catch'  
-
- ::= 
-    'var'?  (':' )?
-    'var'?  (':' )? '=' 
-
- ::= 
-      
-
- ::= 
-    
-    'private'
-    'public'
-    'system'
-
- ::= 
-    
-    'flexible'
-    'stable'
-    'transient'
-
- ::= 
-    '_'
-    
-    
-    '(' , ',')> ')'
-
- ::= 
-    
-    '{' , ';')> '}'
-
- ::= 
-    
-    '#' 
-    '#'  
-    '?' 
-    '??' 
-     
-
- ::= 
-    
-     'or' 
-     ':' 
-
- ::= 
-    
-
- ::= 
-     (':' )?
-     (':' )? '=' 
-    'type' 
-
- ::= 
-    ?  
-
- ::= 
-    'var'  (':' )? '=' 
-    'var'  ':' 
-
- ::= 
-    'let'  '=' 
-    'let' 
-    'type'  ('<' , ',')> '>')? '=' 
-     'func'  (':' )? 
-    ? 
-    'mixin'  
-    'include'  
-
- ::= 
-     ? (':' )? '='? 
-     ? 'class'  (':' )? 
-
- ::= 
-    
-    
-    
-    'let'  '='  'else' 
-
- ::= 
-    '=' 
-    
-
- ::= 
-    '{' , ';')> '}'
-
- ::= 
-    '=' ? 
-    
-
- ::= 
-    'import'  '='? 
-
- ::= 
-    , ';')> , ';')>
+```bnf file=/grammar.txt
 ```
 
diff --git a/docs/languages/motoko/reference/style-guide.md b/docs/languages/motoko/reference/style-guide.md
new file mode 100644
index 00000000..62fdc274
--- /dev/null
+++ b/docs/languages/motoko/reference/style-guide.md
@@ -0,0 +1,897 @@
+---
+sidebar_position: 14
+description: "Motoko language documentation"
+title: "Motoko style guidelines"
+---
+
+To increase readability and uniformity of Motoko source code, the style guide provides suggestions for formatting Motoko sources and other basic conventions.
+
+## Layout
+
+### Spacing
+
+-   Put spaces around arithmetic operators, except to visually group sub-expressions of more tightly binding operators.
+
+    ``` motoko no-repl
+    let z = - 2*x + 3*y + 4*(x*x + y*y);
+    ```
+
+-   Put spaces around comparison operators, Boolean operators, and assignment operators.
+
+    ``` motoko no-repl
+    4 + 5 <= 5 + 4;
+    not (a or b and not c);
+    v := 0;
+    v += 1;
+    ```
+
+-   Put spaces around '='.
+
+    ``` motoko no-repl
+    var v = 0;
+    let r = { a = 1; b = 2 };
+    ```
+
+-   Analogously, put spaces around `:`.
+
+    ``` motoko no-repl
+    var v : Nat = 0;
+    func foo(x : Nat, y : Nat) : Nat { x + y }
+    func bar((x, y) : (Nat, Nat)) : Nat { x + y }
+    let w = 1 ^ 0xff : Nat16;
+    ```
+
+    Rationale: ':' is to declarations what '=' is to definitions. Moreover, the left-hand of a type annotation may generally be an arbitrary complex expression or pattern.
+
+-   Put a space after a comma or semicolon, but not before.
+
+    ``` motoko no-repl
+    let tuple = (1, 2, 3);
+    let record = { a = 1; b = 2; c = 3 };
+    ```
+
+-   Put spaces inside braces, unless they are a simple variant or record.
+
+    ``` motoko no-repl
+    func f() { 0 };
+    f({ a = 1; b = 2; c = 3 });
+    f({a = 1; b = 2});  // okay as well
+
+    type Vec3D = { x : Float; y : Float; y : Float };
+    type Order = { #less; #equal; #more };
+
+    type Order = {#less; #equal; #more};  // okay as well
+    type Proc = {h : Nat; w : Nat} -> {#ok; #fail};
+    ```
+
+-   Put spaces inside brackets if they stretch multiple lines.
+
+    ``` motoko no-repl
+    foo(
+      firstArgument,
+      ( longTupleComponent, anotherLongExpression,
+        moreLongExpression
+      ),
+      [ 1, 2, 3,
+        4, 5, 6,
+      ],
+      { field1 = 4; field2 = 5;
+        field3 = 6;
+      }
+    );
+    ```
+
+-   Put a space between statement keywords and their operands.
+
+    ``` motoko no-repl
+    if (f()) A else B;
+    for (x in xs.values()) { ... };
+    switch (compare(x, y)) {
+      case (#less) { A };
+      case (_) { B };
+    }
+
+    assert (x < 100);
+    await (async (0));
+    ```
+
+-   Do not put a space between a function or variant tag and its argument tuple or around a generic type parameter list.
+
+    ``` motoko no-repl
+    type Pair = (X, X);
+    type Id = (X) -> X;
+
+    let ok = #ok(5);
+
+    func id(x : X) : X { x };
+    id(5);
+    ```
+
+-   Put a space between a function and its argument if it is not a tuple or parenthesized expression (see [parentheses](#parentheses)) or a record used as a named parameter list (see [picking types](#picking-types)).
+
+    ``` motoko no-repl
+    sin 0.0;
+    g [1, 2, 3];
+    f{arg1 = 0; arg2 = 0};
+    ```
+
+Rationale: `g[1]` in particular will be misparsed as an indexing operation.
+
+-   Do not put a space around access operators like `.`, `?`, `!`, or index brackets.
+
+    ``` motoko no-repl
+    foo(bar).baz[5]().boo;
+    foom(?(bam()! + 1));
+    ```
+
+### Line breaks
+
+-   Pick a fixed right margin for lines and break definitions or expressions. 80 still is considered a good limit by many.
+
+    ``` motoko no-repl
+    let sum = a + b + 2*c + d +
+      e + f + g + h + i + k +
+      l + m + n + o + p;
+
+    // Or:
+    let sum =
+      a + b + 2*c + d + e +
+      f + g + h + i + k + l +
+      m + n + o + p;
+    ```
+
+    Rationale: Among other reasons, this style of formatting:
+
+    1.  Avoids code being hidden to the right in a window.
+
+    2.  Avoids random line breaks in side-by-side diffs. For example, as shown by GitHub or similar code review tools.
+
+    3.  Allows prettier display on paper, web sites, or other media.
+
+-   Break lines after an operator.
+
+    ``` motoko no-repl
+    a + b + c +
+      d + f;
+
+    foo(bar, baz).
+      boo();
+    ```
+
+-   When breaking function definitions or calls with long argument lists, put each argument on a separate line.
+
+    Also, consider using records for long parameter lists, see [picking types](#picking-types).
+
+    ``` motoko no-repl
+    func someFunction(
+      arg1 : FirstType,
+      arg2 : SecondType,
+      anotherArg : Nat,
+      yetAnother : [Type],
+      func : Nat -> Nat,
+    ) : Nat {
+      ...
+    };
+
+    someFunction(
+      veryLongArgumentExpression,
+      anotherVeryLongArgumentExpression,
+      3,
+      aNestedFunctionCall(
+        alsoWithLongArguments,
+        andMoreSuchArguments,
+      ),
+      moreLongishArgument,
+    );
+    ```
+
+    Rationale: This prevents overlooking an argument when reading code and avoids re-breaking lines when changing one of the expressions.
+
+### Indentation
+
+-   Each level of indentation should be 2 spaces.
+
+    ``` motoko no-repl
+    actor A {
+      public func f() {
+        return;
+      }
+    }
+    ```
+
+    Rationale: There may be a lot of nesting. Using only 2 spaces avoids wasting screen estate.
+
+-   Indentation should not depend on the lexical contents of previous lines.
+
+    In particular, do not vertically align indentation with inner characters from previous lines.
+
+    ``` motoko no-repl
+    let x = someFunction(
+      arg1, arg2, arg3, arg4, arg5);               // Do this.
+
+    let x = someFunction(arg1, arg2, arg3,
+      arg4, arg5);                                 // Or this.
+
+    let x =
+      someFunction(arg1, arg2, arg3, arg4, arg5);  // Or this.
+
+    let x = someFunction(                          // Or this.
+      longArg1,
+      longArg2,
+      longArg3,
+      longArg4,
+      longArg5,
+    );
+
+    // COUNTER EXAMPLE!
+    let x = someFunction(arg1, arg2, arg3,
+                         arg4, arg5);              // DO NOT DO THIS!
+    ```
+
+    Rationale: There are many problems with vertical alignment, for example:
+
+    1.  It wastes a lot of horizontal space.
+
+    2.  It creates wildly inconsistent indentation levels that obfuscate the structure of the code.
+
+    3.  It can produce realignment churn when changing a line, which, even when automated by editors, inflates and obfuscates diffs.
+
+    4.  It completely breaks with variable-width fonts.
+
+    Rule of thumb: there should be no indentation that is not a multiple of 2.
+
+-   Do not use tabs.
+
+    Rationale: The interpretation of tabs varies wildly across tools and they get lost or are displayed incorrectly in many contexts, such as web pages, diffs, etc.
+
+### Grouping
+
+-   Separate complex multi-line definitions with empty lines. One-liners can be put on consecutive lines.
+
+    ``` motoko no-repl
+    func foo() {
+      // This function does a lot of interesting stuff.
+      // It's definition takes multiple lines.
+    }
+
+    func boo() {
+      // This is another complicated function.
+      // It's definition also takes multiple lines.
+    }
+
+    func add(x : Nat, y : Nat) { return x + y };
+    func mul(x : Nat, y : Nat) { return x * y };
+    ```
+
+-   Separate logic groups of definitions with two empty lines. Add a one-line comment as a "section header" for each group.
+
+    ``` motoko no-repl
+    // A very large class
+    class MuffleMiff(n : Nat) {
+
+      // Accessors
+
+      public func miffMuff() : Text {
+        ...
+      }
+
+      public func sniffMiff() : Nat {
+        ...
+      }
+
+      // Mutators
+
+      public func clearMurk() {
+        ...
+      }
+
+      public func addMuff(name : Text) {
+        ...
+      }
+
+      // Processing
+
+      public func murkMuffle(param : List) {
+        ...
+      }
+
+      public func transformSneezler() {
+        ...
+      }
+
+      // Internal State
+
+      var miffCount = 0;
+      var mabbleMap = Map();
+
+    }
+    ```
+
+### Comments
+
+-   Use line comments (`//…​`). Use block comments (`/* …​ */`) only when commenting in the middle of a line or for commenting out pieces of code during development.
+
+    ``` motoko no-repl
+    // The following function runs the current
+    // pallaboom on a given snibble. It returns
+    // suitable plexus if it can.
+    func paBoom(s : Snibble) : Handle {
+      let puglet = initPugs(s.crick, 0 /* size */, #local);
+    /* Don't do the odd stuff yet...
+      ...
+      ...
+    */
+      return polyfillNexus(puglet);  // for now
+    }
+    ```
+
+    Rationale: Line comments make it easier to insert, remove or swap individual lines.
+
+-   Put short comments explaining a single line at the end of the line, separated by at least 2 spaces.
+
+    ``` motoko no-repl
+    paBoom(getSnibble()));  // create new snibble
+    ```
+
+-   Put multi-line comments before a line of code, with the same indentation as the code it is describing.
+
+    ``` motoko no-repl
+    func f() {
+      // Try to invoke the current pallaboom with
+      // the previous snibble. If that succeeds,
+      // we have the new plexus; if not, complain.
+      let plexusHandle = paBoom(getSnibble()));
+    }
+    ```
+
+-   Capitalize comments that are on separate lines. Use a proper full stop for sentences.
+
+## Punctuation
+
+### Semicolons
+
+-   Motoko uniformly requires a semicolon to separate expressions or local declarations in a block, regardless of whether the preceding declaration ends in a closing '}'.
+
+    Rationale: This is unlike other C-style languages, which tend to have rather ad-hoc rules.
+
+-   Put a semicolon after the last expression in a block, unless the whole block is written on a single line.
+
+    Similarly for types.
+
+    ``` motoko no-repl
+    // No ; needed before closing } on same line
+
+    type Vec3D = {x : Float; y : Float; z : Float};
+    type Result = {#ok : A; #error : Text};
+
+    func add(x : Nat, y : Nat) : Nat { return x + y };
+
+    // End last case with ;
+
+    type Address = {
+      first : Text;
+      last : Text;
+      street : Text;
+      nr : Nat;
+      zip : Nat;
+      city : Text;
+    };
+
+    type Expr = {
+      #const : Float;
+      #add : (Expr, Expr);
+      #mul : (Expr, Expr);
+    };
+
+    func eval(e : Expr) : Float {
+      switch (e) {
+        case (#const(x)) { x };
+        case (#add(e1, e2)) { eval(e1) + eval(e2) };
+        case (#mul(e1, e2)) { eval(e1) * eval(e2) };
+      };
+    }
+    ```
+
+    Rationale: Consistently ending lines with semicolon simplifies adding, removing, or swapping lines.
+
+### Braces
+
+-   Put braces around function bodies, `if` or `case` branches, and loop bodies, unless they appear nested as an expression and only contain a single expression.
+
+    ``` motoko no-repl
+    func f(x) { f1(x); f2(x) };
+
+    let abs = if (v >= 0) v else -v;
+    let val = switch (f()) { case (#ok(x)) x; case (_) 0 };
+    func succ(x : Nat) : Nat = x + 1;
+    ```
+
+-   Use "C-style" layout for braced sub-expressions stretching multiple lines.
+
+    ``` motoko no-repl
+    func f() {
+      return;
+    };
+
+    if (cond) {
+      foo();
+    } else {
+      bar();
+    };
+
+    switch (opt) {
+      case (?x) {
+        f(x);
+      };
+      case (null) {};
+    };
+    ```
+
+### Parentheses
+
+-   Motoko supports "parenless" style, meaning that parentheses are optional in most places, such as function parameter lists, or statement operands, when they enclose an expression that either is bracketed already. For example, a tuple, object, or array, or a simple constant or identifier.
+
+    ``` motoko no-repl
+    type Op = Nat -> Nat;
+    let a2 = Array.map(func x { x + 1 }, a);
+
+    let y = f x;
+    let z = f {};
+    let choice = if flag { f1() } else { f2() };
+
+    switch opt {
+      case null { tryAgain() };
+      case _ { proceed() };
+    };
+    ```
+
+-   Avoid overuse of parenless style.
+
+    In particular, do not omit parentheses and braces on statements at the same time.
+
+    ``` motoko no-repl
+    // COUNTER EXAMPLES!
+    let choice = if flag x + y else z;  // DO NOT DO THIS!
+
+    switch val {
+      case 0 f();    // DO NOT DO THIS!
+      case n n + 1;  // OR THIS!
+    };
+    ```
+
+    Rationale: Omitting both at the same time makes the code harder to read, since there is less visual clue how it groups.
+
+-   Similarly, do not omit parentheses around function parameters if the function also has type parameters.
+
+    ``` motoko no-repl
+    // COUNTER EXAMPLE!
+    foo 0;   // DO NOT DO THIS!
+    ```
+
+-   Omit parentheses around argument types of a function type with a single argument and no type parameters.
+
+    But do not omit them around when functions or classes also have type parameters.
+
+    ``` motoko no-repl
+    type Inv = Nat -> Nat;
+    type Id = (T) -> T;
+    type Get = (C) -> X;
+
+    // COUNTER EXAMPLE!
+    type Get = C -> X;   // DO NOT DO THIS!
+    ```
+
+### Miscellaneous
+
+-   Use `_` to group digits in numbers.
+
+    Group by 3 digits in decimal numbers and by 4 in hexadecimal notation.
+
+    ``` motoko no-repl
+    let billion = 1_000_000_000;
+    let pi = 3.141_592_653_589_793_12;
+    let mask : Nat32 = 0xff00_ff0f;
+    ```
+
+## Naming
+
+### Style
+
+-   Use `UpperCamelCase` for type names (including classes or type parameters), module names, and actor names.
+
+-   Use `lowerCamelCase` for all other names, including constants and variant fields.
+
+    ``` motoko no-repl
+    module MoreMuff {
+      type FileSize = Nat;
+      type Weekday = {#monday; #tuesday; #wednesday};
+      type Pair = (X, X);
+
+      class Container() { ... };
+
+      func getValue(name : Name) : Pair { ... };
+
+      let zero = 0;
+      let pair = getValue("opus");
+      var nifty : Nat = 0;
+
+      object obj { ... };
+
+      actor ServerProxy { ... };
+    };
+    ```
+
+    Rationale: The general convention is upper case for "static" entities like types and lower case for "dynamic" values. Modules and actors are fairly static and can export types. Objects usually don’t export types and tend to be used mostly as dynamic values.
+
+-   Spell acronyms as regular words.
+
+    ``` motoko no-repl
+    type HttpHeader = ...;
+    func getUrl() { ... };
+    let urlDigest = ...;
+    ```
+
+-   Do not use identifier names that start with an underscore `_`, except to document that a variable in a pattern is intentionally unused.
+
+    ``` motoko no-repl
+    let (width, _color, name) = rumpler();
+    ...  // _color is not used here
+
+    func foo(x : Nat, _futureFlag : Bool) { ... };
+    ```
+
+    Rationale: A type checker can warn about unused identifiers, which can be suppressed by explicitly prepending `_` to its name to document intention.
+
+    This aligns with the use of the keyword `_` for pattern wildcards.
+
+### Conventions
+
+-   The name of functions returning a value should describe that value.
+
+    Avoid redundant `get` prefixes.
+
+    ``` motoko no-repl
+    dict.size();
+    list.first();
+    sum(array);
+    ```
+
+-   The name of functions performing side effects or complex operations should describe that operation.
+
+    ``` motoko no-repl
+    dict.clear();
+    dict.set(key, value);
+    let result = traverse(graph);
+    ```
+
+-   The name of predicate functions returning [`Bool`](https://mops.one/core/docs/Bool) should use an `is` or `has` prefix or a similar description of the tested property.
+
+    ``` motoko no-repl
+    class Set() {
+      public func size() : Nat { ... };
+
+      public func add(x : X) { ... };
+      public func remove(x : X) { ... };
+
+      public func isEmpty() : Bool { ... };
+      public func contains(x : X) : Bool { ... };
+    };
+    ```
+
+-   Functions converting to or from a type `X` are named `toX` and `fromX`, respectively, if the source, resp. target, is either the object the function is a method of, or the primary type of the module this function appears in.
+
+-   In classes or objects, use a name ending with `_` to distinguish private variables from getters.
+
+    ``` motoko no-repl
+    class Cart(length_ : Nat) {
+      var width_ = 0;
+
+      public func length() : Nat { return length_ };
+      public func width() : Nat { return width_ };
+    }
+    ```
+
+    Rationale: In Motoko, functions are first-class values, so functions and other value identifiers share the same name space.
+
+    Identifiers with a leading `_` should *not* be used for private state, since that indicates an unused name (see [style](#style)).
+
+-   Use longer, more descriptive names for global or public identifier or ones with large scope, and short names for local ones with small scope.
+
+    It is fine to use single character identifiers when there is nothing interesting to say, especially when using the same naming scheme consistently.
+
+    ``` motoko no-repl
+    func map(x : Nat, y : Nat) : Nat { x + y };
+
+    func eval(e : Expr) : Nat {
+      let n =
+        switch (e) {
+          case (#neg(e1)) { - eval(e1) };
+          case (#add(e1, e2)) { eval(e1) + eval(e2) };
+          case (#mul(e1, e2)) { eval(e1) * eval(e2) };
+        };
+      Debug.print(n);
+      return n;
+    };
+    ```
+
+    Rationale: Contrary to popular belief, overly chatty local names can decrease readability instead of increasing it, by increasing the noise level.
+
+-   In suitable cases, use plural form for describing a collection of items, such as a list or array.
+
+    This also works for short names.
+
+    ``` motoko no-repl
+    func foreach(xs : [X], f : X -> ()) {
+      for (x in xs.values()) { f(x) }
+    }
+    ```
+
+## Types
+
+### Type annotations
+
+-   Put type annotations on definitions that involve fixed-width numeric types, to disambiguate the type of overloaded arithmetic operators and constants.
+
+    ``` motoko no-repl
+    let mask : Nat32 = 0xfc03_ff00;
+    let pivot : Nat32 = (size + 1)/2;
+    let vec : [Int16] = [1, 3, -4, 0];
+    ```
+
+    :::note
+
+    Use floating point constants to enforce type `Float` without an extra annotation. Similarly, use an explicit `+` sign to produce a positive value of type [`Int`](https://mops.one/core/docs/Int) instead of [`Nat`](https://mops.one/core/docs/Nat), if desired.
+
+    :::
+
+    ``` motoko no-repl
+    let zero = 1.0;    // type Float
+    let offset = +1;   // type Int
+    ```
+
+-   Similarly, put inline type annotations on arithmetic expressions with types other than [`Nat`](https://mops.one/core/docs/Nat) or [`Int`](https://mops.one/core/docs/Int).
+
+    ``` motoko no-repl
+    if (x & mask == (1 : Nat32)) { ... };
+    ```
+
+    :::note
+
+    The need to annotate constants in cases like this is a short-coming of Motoko’s type system that we hope to address soon.
+
+    :::
+
+    An annotation is not needed on function arguments, since their type is usually inferred from the function. The only exception is when that argument has generic type and the type arguments have been omitted.
+
+    ``` motoko no-repl
+    func foo(len : Nat32, vec : [Nat16]) { ... };
+    func bar(x : X) { ... };
+
+    foo(3, [0, 1, 2]);
+    bar(0);
+    bar(0 : Nat16);
+    ```
+
+-   Put type annotations on mutable variables, unless their type is obvious.
+
+    ``` motoko no-repl
+    var name = "Motoko";
+    var balance = 0;
+
+    func f(i : Int) {
+      var j = i;
+    };
+
+    var balance : Int = 0;
+    var obj : Class = foo();
+    ```
+
+    Rationale: Due to subtyping, inferring the type from the initialization would not necessarily deduce the intended type. For example, `balance` would have type [`Nat`](https://mops.one/core/docs/Nat) without the annotation, ruling out assignments of integers.
+
+-   Put type annotations on all public fields in a class.
+
+    ``` motoko no-repl
+    class C(init_ : Nat) {
+      public let init : Nat = init_;
+      public var count : Nat = 0;
+    }
+    ```
+
+-   Omit return type annotations of functions when the type is `()`.
+
+    ``` motoko no-repl
+    func twiceF() { f(); f() };  // no need to write ": ()"
+    ```
+
+-   Omit type annotations on functions when they are passed as arguments.
+
+    ``` motoko no-repl
+    Array.map(func n {n + 1}, a);
+    ```
+
+-   Put type annotations on definitions that involve numeric types other than [`Nat`](https://mops.one/core/docs/Nat) or [`Int`](https://mops.one/core/docs/Int), to resolve the overloading between arithmetic operators and constants.
+
+    ``` motoko no-repl
+    let mask : Nat32 = 0xfc03_ff00;
+    let offset : Nat32 = size + 1;
+    ```
+
+### Picking types
+
+-   Use [`Nat`](https://mops.one/core/docs/Nat) for any integral value that cannot be negative.
+
+-   Use fixed-width `NatN` or `IntN` only when storing many values and space usage matters, when bit-fiddling requires the low-level interpretation of a number as a vector of bits or when matching types imposed by external requirements, such as other canisters.
+
+-   Avoid proliferation of option types, and therefore `null`.
+
+    Limit their use to as small a scope as possible. Rule out the `null` case and use non-option types wherever possible.
+
+-   Consider using records instead of tuples when there are more than 2 or 3 components. Records are just simple objects with named fields.
+
+    Note that record types need not be declared but can be used in place.
+
+    ``` motoko no-repl
+      func nodeInfo(node : Node) : {parent : Node; left : Node; right : Node} { ... }
+    ```
+
+-   Consider using variants instead of [`Bool`](https://mops.one/core/docs/Bool) to represent binary choices.
+
+    Note that variant types need not be declared but can be used in place.
+
+    ``` motoko no-repl
+    func capitalization(word : Text) : {#upper; #lower} { ... }
+    ```
+
+-   Where possible, use return type `()` for functions whose primary purpose is to mutate state or cause other side effects.
+
+    ``` motoko no-repl
+    class Set() {
+      public func add(x : X) { ... };
+      public func remove(x : X) { ... };
+      ...
+    };
+    ```
+
+-   Consider using a record (an object with just data) as argument for long parameter lists.
+
+    ``` motoko no-repl
+    func process({seed : Float; delta : Float; data : [Record]; config : Config}) : Thing {
+      ...
+    };
+
+    process{config = Config(); data = read(); delta = 0.01; seed = 1.0};
+    ```
+
+    Rationale: This expresses named parameters. This way, arguments can be freely reordered at the call site and callers are prevented from accidentally passing them in the wrong order.
+
+-   Higher-order functions, such as functions that take a callback argument, should put the function parameter last.
+
+    Rationale: Makes call sites more readable, and in the absence of currying, there is no point in putting the function first, like you often would in functional languages.
+
+-   Do not use sentinel values, such as `-1`, to represent invalid values.
+
+    Use the option type instead.
+
+    ``` motoko no-repl
+    func lookup(x : key) : ?Nat { ... }
+    ```
+
+-   Data is immutable in Motoko unless explicitly stated otherwise.
+
+    Use mutability types and definitions (`var`) with care and only where needed.
+
+    Rationale: Mutable data cannot be communicated or share across actors. It is more error-prone and much more difficult to formally reason about, especially when concurrency is involved.
+
+## Features
+
+### Statements
+
+-   Use `for` loops instead of `while` loops for iterating over a numeric range or a container.
+
+    ``` motoko no-repl
+    for (i in Iter.range(1, 10)) { ... };
+    for (x in array.values()) { ... };
+    ```
+
+    Rationale: For loops are less error-prone and easier to read.
+
+-   Use `if` or `switch` as expressions where appropriate.
+
+    ``` motoko no-repl
+    func abs(i : Int) : Int { if (i < 0) -i else i };
+
+    let delta = switch mode { case (#up) +1; case (#dn) -1 };
+    ```
+
+-   Motoko requires that all expressions in a block have type `()`, in order to prevent accidentally dropped results.
+
+    Use `ignore` to explicitly drop results. Do *not* use `ignore` when it’s not needed.
+
+    ``` motoko no-repl
+    ignore async f();  // fire of a computation
+    ```
+
+-   Motoko allows to omit the `return` at the end of a function, because a block evaluates to its last expression.
+
+    Use this when a function is short and in "functional" style, that is, the function does not contain complex control flow or side effects.
+
+    Use explicit `return` at the end when the function contains other `return` statements or imperative control flow.
+
+    ``` motoko no-repl
+    func add(i : Nat, j : Nat) : Nat { i + j };
+
+    func foo(a : Float, b : Float) : Float {
+      let c = a*a + b*b;
+      c + 2*c*c;
+    };
+
+    func gcd(i : Nat, j : Nat) : Nat {
+      if (j == 0) i else gcd(j, i % j);
+    };
+
+    func gcd2(i : Nat, j : Nat) : Nat {
+      var a = i;
+      var b = j;
+      while (b > 0) {
+        let c = a;
+        a := b;
+        b := c % b;
+      };
+      return a;
+    };
+    ```
+
+### Objects and records
+
+-   Use the short-hand object syntax `{x1 = e1; …​ ; xN = eN}` when using objects as simple records, i.e., data structures with no private state and no methods.
+
+-   Use `object` when creating singleton objects.
+
+-   Limit the use of objects to records where possible.
+
+    Rationale: Only records can be sent as message parameters or results and can be stored in stable variables. Objects with methods are also more expensive to create and represent in memory.
+
+-   Use full objects only as a means for encapsulating state or behavior.
+
+### Classes
+
+-   Use `class` to create multiple objects of the same shape.
+
+-   Name classes after their conceptual functionality, not their implementation, except when having to distinguish multiple different implementations of the same concept. For example, `OrderedMap` vs `HashMap`).
+
+-   Classes are both type definitions and factory functions for objects.
+
+    Do not use classes unless both these roles are intended; use plain type aliases or functions returning an object in other cases.
+
+-   Do not overuse classes.
+
+    Use a module defining a plain type and functions on it where appropriate. Use classes only as a means for encapsulating state or behavior.
+
+    Rationale: Objects with methods have disadvantages over simple record types with separate functions (see above).
+
+-   If values of a class are meant to be sendable (shared), the class needs to provide a pair of `share`/`unshare` methods that convert to/from a sharable representation, for example, as a record.
+
+    :::note
+
+    For immutable classes it may seem more natural to make `unshare` a kind of static function. However, even for immutable ones it may depend on constructor arguments (such as an ordering function), so that the a pattern like `Map(compareInt).unshare(x)` seems appropriate.
+
+    :::
+
+-   For the time being, avoid overloading classes with too many methods, since that is currently expensive.
+
+    Restrict to a sufficiently small set of canonical methods and make less essential ones that can be implemented on top of those into functions in the enclosing module.
+
+-   Use modules for "static" classes or methods.
+
+### Modules
+
+-   Use `module` to group definitions, including types, and create a name spae for them.
+
+-   Where applicable, name modules after the main type or class they implement or provide functions for.
+
+-   Limit each module to a single main concept/type/class or closely entangled family of concepts/types/classes.
+
+
+
diff --git a/docs/references/message-execution-properties.md b/docs/references/message-execution-properties.md
index ee482a36..b8906e50 100644
--- a/docs/references/message-execution-properties.md
+++ b/docs/references/message-execution-properties.md
@@ -36,7 +36,7 @@ For example, consider the following Motoko code:
 The first message execution spans the lines 2-3, until the inter-canister call is made using the `await` syntax (orange box). The second message execution spans lines 3-5 when the inter-canister call returns (blue box). This part is called the _callback_ of the inter-canister call. The two message executions involved in this example will always be scheduled sequentially.
 
 :::note
-An `await` in the code does not necessarily mean that an inter-canister call is made and thus a message execution ends and the code after the `await` is executed as a separate message execution (callback). Async code with the `await` syntax (e.g. in Rust or Motoko) can also be used "internally" in the canister, without issuing an inter-canister call. In that case, the code part including the `await` will be processed within a single message execution. For Rust, both cases are possible if `await` is used. An inter-canister call is only made if the system API `ic0.call_perform` is called, e.g. when awaiting result of the CDK's `call` method. In Motoko, `await` always commits the current state and triggers a new message send, while `await*` does not necessarily commit the current state or trigger new message sends. See [Motoko actors and async programming](../languages/motoko/fundamentals/actors-async.md) for details on `await` vs. `await*`.
+An `await` in the code does not necessarily mean that an inter-canister call is made and thus a message execution ends and the code after the `await` is executed as a separate message execution (callback). Async code with the `await` syntax (e.g. in Rust or Motoko) can also be used "internally" in the canister, without issuing an inter-canister call. In that case, the code part including the `await` will be processed within a single message execution. For Rust, both cases are possible if `await` is used. An inter-canister call is only made if the system API `ic0.call_perform` is called, e.g. when awaiting result of the CDK's `call` method. In Motoko, `await` always commits the current state and triggers a new message send, while `await*` does not necessarily commit the current state or trigger new message sends. See [Motoko actors and async programming](../languages/motoko/fundamentals/actors/actors-async.md) for details on `await` vs. `await*`.
 :::
 
 :::note
diff --git a/plugins/remark-include-file.mjs b/plugins/remark-include-file.mjs
index 0c3f6211..3694a742 100644
--- a/plugins/remark-include-file.mjs
+++ b/plugins/remark-include-file.mjs
@@ -6,29 +6,68 @@
  *   ```candid file=/public/references/ic.did
  *   ```
  *
- * The plugin resolves  to the project root and reads the file
- * synchronously at build time, replacing the empty code block body with the
- * file's contents.
+ *   ```motoko file=/counter.mo
+ *   ```
+ *
+ *   ```motoko file=/todo-error.mo#L49-L58
+ *   ```
+ *
+ * Inline markdown inclusion (renders the file as prose, not a code block):
+ *
+ *   ```md file=/Changelog.md
+ *   ```
+ *
+ * Placeholders:
+ *           — project root
+ *    — .sources/motoko/doc/md/examples/
+ *        — .sources/motoko/ (root of the motoko submodule)
+ *
+ * An optional #L-L suffix slices specific lines (1-based, inclusive).
+ * Line ranges are not supported with the `md` inline inclusion form.
  *
- * A missing file causes a build error.
+ * A missing file or out-of-range line slice causes a build error.
  */
-import { visit } from "unist-util-visit";
+import { visit, SKIP } from "unist-util-visit";
 import { readFileSync, existsSync } from "node:fs";
-import { resolve } from "node:path";
-import { dirname, join } from "node:path";
+import { resolve, join, dirname } from "node:path";
 import { fileURLToPath } from "node:url";
 
 const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..");
 
+const PLACEHOLDERS = {
+  "": ROOT,
+  "": join(ROOT, ".sources", "motoko", "doc", "md", "examples"),
+  "": join(ROOT, ".sources", "motoko"),
+};
+
 export default function remarkIncludeFile() {
-  return (tree, file) => {
-    visit(tree, "code", (node) => {
+  return function (tree, file) {
+    visit(tree, "code", (node, index, parent) => {
       const fileMeta = (node.meta || "")
         .split(" ")
         .find((m) => m.startsWith("file="));
       if (!fileMeta) return;
 
-      const rawPath = fileMeta.slice("file=".length).replace(/^/, ROOT);
+      let rawPath = fileMeta.slice("file=".length);
+
+      // Extract optional #L-L line range before resolving the path
+      let lineStart = null;
+      let lineEnd = null;
+      const rangeMatch = rawPath.match(/#L(\d+)-L(\d+)$/);
+      if (rangeMatch) {
+        lineStart = parseInt(rangeMatch[1], 10);
+        lineEnd = parseInt(rangeMatch[2], 10);
+        rawPath = rawPath.slice(0, -rangeMatch[0].length);
+      }
+
+      // Expand placeholders
+      for (const [placeholder, expansion] of Object.entries(PLACEHOLDERS)) {
+        if (rawPath.startsWith(placeholder)) {
+          rawPath = expansion + rawPath.slice(placeholder.length);
+          break;
+        }
+      }
+
       const absPath = resolve(file.dirname || ROOT, rawPath);
 
       if (!existsSync(absPath)) {
@@ -37,7 +76,30 @@ export default function remarkIncludeFile() {
         );
       }
 
-      node.value = readFileSync(absPath, "utf-8").trimEnd();
+      let content = readFileSync(absPath, "utf-8");
+
+      if (lineStart !== null) {
+        const lines = content.split("\n");
+        if (lineStart < 1 || lineEnd > lines.length) {
+          throw new Error(
+            `remark-include-file: line range L${lineStart}-L${lineEnd} out of bounds ` +
+            `(file has ${lines.length} lines): ${absPath}`,
+          );
+        }
+        content = lines.slice(lineStart - 1, lineEnd).join("\n");
+      }
+
+      // Inline markdown inclusion: parse the file and replace the code node with
+      // the resulting AST children so content renders as prose, not a code block.
+      // `this` is the unified processor; its parse() method is used so the same
+      // remark plugins apply to the included content.
+      if (node.lang === "md") {
+        const parsed = this.parse(content.trimEnd());
+        parent.children.splice(index, 1, ...parsed.children);
+        return [SKIP, index + parsed.children.length];
+      }
+
+      node.value = content.trimEnd();
     });
   };
 }
diff --git a/scripts/postprocess-motoko.mjs b/scripts/postprocess-motoko.mjs
index ad1b71bc..93af4683 100644
--- a/scripts/postprocess-motoko.mjs
+++ b/scripts/postprocess-motoko.mjs
@@ -2,37 +2,44 @@
 /**
  * Post-process synced Motoko docs:
  * 1. Remove duplicate H1 headings (Starlight renders title from frontmatter)
- * 2. Rewrite relative links to match the flattened directory structure
- * 3. Redirect core library links to mops.one
- * 4. Remove _category_.yml and sub-section index.md files
- * 5. Expand Docusaurus file-embed blocks (```lang file=[#L-L])
- * 6. Convert Docusaurus remote-reference blocks (```md reference) to links
- * 7. Normalize Starlight aside syntax
+ * 2. Rewrite relative links to match the new directory structure
+ * 3. Rewrite external internetcomputer.org/docs links to internal paths
+ * 4. Redirect core library links to mops.one
+ * 5. Redirect motoko-tooling and docs.motoko.org links to /developer-tools/#mo-doc
+ * 6. Remove _category_.yml and sub-section index.md files
+ * 7. Rewrite Docusaurus file-embed paths to use  placeholder
+ *    (remark-include-file resolves these at build time from the pinned submodule)
+ * 8. Convert Docusaurus remote-reference blocks (```md reference) to links
+ * 9. Normalize Starlight aside syntax
  *
- * Docusaurus patterns handled vs. left as-is:
- *   file=        EXPANDED — inline file content (step 5). Supports extra attrs
- *                      (no-repl, title=) and #L-L line ranges.
- *   title=""     LEFT — Starlight renders code block titles natively.
- *   name=