Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
8603f73
fix(lsp): keep completion scoped once a prefix is typed
shockwave-bot[bot] Jun 1, 2026
f2bdd97
docs: record the two independent completion engines
shockwave-bot[bot] Jun 1, 2026
200e54a
feat(ide): source completion from the shared LSP engine
shockwave-bot[bot] Jun 1, 2026
5580723
feat(ide): align highlighting + folding to the LSP; add test suite
shockwave-bot[bot] Jun 1, 2026
04fc538
ci: run rust + web-ide tests (vitest, e2e, storybook) on PRs
shockwave-bot[bot] Jun 1, 2026
bd42da3
ci: set git identity so the dep-install tests can commit
shockwave-bot[bot] Jun 1, 2026
19dde54
refactor: extract pseudoscript-lsp-core; wasm = LSP-over-wasm
shockwave-bot[bot] Jun 1, 2026
024fa10
fix(fold): start folds at the declaration, not its doc comment
shockwave-bot[bot] Jun 1, 2026
5272a0e
fix(fold): fold a nested block flush to its brace, no trailing space
shockwave-bot[bot] Jun 1, 2026
61c07b2
fix(landing): drop the redundant orange dot from the brand lockup
shockwave-bot[bot] Jun 1, 2026
c356555
fix(complete): members of a ::-qualified node in another module
shockwave-bot[bot] Jun 1, 2026
f83c5bd
fix(ide): nav-history origin, theme selector, light-mode highlight, u…
shockwave-bot[bot] Jun 1, 2026
39abadf
fix(semantic): colour a whole macro invocation as one decorator
shockwave-bot[bot] Jun 1, 2026
0fb8cc4
fix(ide): multi-page doc preview navigation; hover card no longer ste…
shockwave-bot[bot] Jun 1, 2026
1897728
fix(ide): unify the project dialog's left column
shockwave-bot[bot] Jun 1, 2026
f17858a
fix(ide): examples out of recents; session save indicator; restore li…
shockwave-bot[bot] Jun 1, 2026
3f88b9a
feat(doc): generated docs render the web IDE's sequence diagram
shockwave-bot[bot] Jun 1, 2026
9edc182
refactor(web): migrate web-ide and landing to strict TypeScript
shockwave-bot[bot] Jun 1, 2026
6c0a359
fix(complete): suggest other workspace modules at the root
shockwave-bot[bot] Jun 1, 2026
a8835b9
fix(complete): member completion on local bindings; Option; macro args
shockwave-bot[bot] Jun 1, 2026
c9e7ed5
fix(complete): type chained receivers (G2) and offer nodes after `for…
shockwave-bot[bot] Jun 1, 2026
b80e79b
feat(ide): init a new workspace on disk from the project launcher
shockwave-bot[bot] Jun 1, 2026
e5314ae
feat(lang): bindings state their type — `x: Type = Expr` (ADR-027)
shockwave-bot[bot] Jun 1, 2026
edd22eb
docs(skill): align pseudocode skill with typed bindings (ADR-027)
shockwave-bot[bot] Jun 1, 2026
60488c1
feat(semantic): colour `//` and `/* */` comments
shockwave-bot[bot] Jun 1, 2026
4e4ac8c
feat(ide): download the authoring skill folder from the toolbar
shockwave-bot[bot] Jun 1, 2026
8bde2ba
feat(ide): disk-only workspaces — template new-project flow + externa…
shockwave-bot[bot] Jun 1, 2026
ff2c75f
fix(parser): localize from source-set errors and add fix-oriented hints
JonathanTurnock Jun 1, 2026
505e2c6
feat(ide): bundle LANG.md into the downloadable skill
shockwave-bot[bot] Jun 1, 2026
0ba9aa5
build(wasm): regenerate pds-wasm so the IDE gets the localized from/v…
JonathanTurnock Jun 1, 2026
e61ca1b
fix(semantic): colour feature/BDD keywords and Some/None
shockwave-bot[bot] Jun 1, 2026
81d3be3
fix(ide): single-lifeline fallback emits a valid sequence scene
JonathanTurnock Jun 1, 2026
923796b
feat(ide): installable PWA — manifest, icons, service worker
shockwave-bot[bot] Jun 1, 2026
520cae2
copy(landing): agentic coding; "one practice" (pseudo programming)
shockwave-bot[bot] Jun 1, 2026
d79bc0f
feat(ide): coded error reporting + fix go-to-definition on members
JonathanTurnock Jun 1, 2026
457672c
copy(landing): name the practice at the convergence core
shockwave-bot[bot] Jun 1, 2026
0583ccb
copy(landing): drop the corner ticks on the hero terminal
shockwave-bot[bot] Jun 1, 2026
61b04fe
feat(checker): reject method calls whose member does not exist (§6)
JonathanTurnock Jun 1, 2026
01949c5
style(checker): rustfmt the call-member check
JonathanTurnock Jun 1, 2026
f0c33c2
fix(ide): valid new-file template + go-to-definition across modules
JonathanTurnock Jun 1, 2026
44626de
test(ide): update e2e to the valid starter template
JonathanTurnock Jun 1, 2026
0b58ae3
refactor(ide): extract shared types into framework-agnostic core (Wav…
JonathanTurnock Jun 1, 2026
f539188
refactor(ide): extract navigation, diagnostics, naming/validation to …
JonathanTurnock Jun 1, 2026
e865103
refactor(ide): extract dirty, share, docs to core (Wave 1b)
JonathanTurnock Jun 1, 2026
a62ee2d
refactor(ide): extract model index + canvas projection to core (Wave 2)
JonathanTurnock Jun 1, 2026
fc1fd14
refactor(ide): notifications + wasm rune stores (Wave 3a)
JonathanTurnock Jun 1, 2026
207473a
refactor(ide): navigation rune store (Wave 3b)
JonathanTurnock Jun 1, 2026
9abdb4d
feat(web-landing): follow system theme, slim Tweaks to theme+motion, …
seekers-fd Jun 1, 2026
c8b826c
refactor(ide): workspace + selection rune stores (Wave 3c)
JonathanTurnock Jun 1, 2026
e3fbd98
refactor(ide): save + diagnostics rune stores (Wave 3d)
JonathanTurnock Jun 1, 2026
2084716
refactor(ide): ui + share rune stores — Wave 3 complete (Wave 3e)
JonathanTurnock Jun 1, 2026
76611cc
feat(ide): adopt shadcn-svelte + Tailwind v4, align theme to brand to…
JonathanTurnock Jun 1, 2026
e226609
feat(ide): add core shadcn-svelte primitives from the registry
JonathanTurnock Jun 1, 2026
d315c7d
feat(ide): Fleet/VS-Code island shell — activity bar, file menu, panels
JonathanTurnock Jun 1, 2026
d2e45ba
feat(ide): right-click context menus + Fleet island styling
JonathanTurnock Jun 1, 2026
8f3ab44
feat(ide): ⌘K command palette — go to file or symbol
JonathanTurnock Jun 1, 2026
663ea40
feat(ide): centre go-to search pill + menu shortcut hints
JonathanTurnock Jun 1, 2026
b81ad35
feat(ide): relocate chrome — problems/save→footer, nav→header, theme/…
JonathanTurnock Jun 1, 2026
4802ae5
feat(ide): web IDE overhaul — JetBrains/Fleet shell, canvas, LSP, export
JonathanTurnock Jun 2, 2026
b9b7224
fix(ide): align header search button with the right rail below it
JonathanTurnock Jun 2, 2026
16bd57e
fix(ide): size header icon buttons to match the activity bar / rail
JonathanTurnock Jun 2, 2026
dd5d203
fix(ide): make the top header 42px, in line with the nav rails
JonathanTurnock Jun 2, 2026
1cde188
feat(ide): right-click context menu on the sequence diagram
JonathanTurnock Jun 2, 2026
d61d2f9
feat: reimagine landing on model-driven theme; add `pds eval`
JonathanTurnock Jun 2, 2026
bb85516
feat(seo): metadata, Open Graph/Twitter, JSON-LD, sitemap, og image
JonathanTurnock Jun 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
28 changes: 15 additions & 13 deletions .claude/skills/pseudocode/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ data provenance are written as high-level pseudocode, infrastructure is declared
the whole thing compiles to C4 diagrams, sequence diagrams, and a doc site (`pds doc`).

This skill is the **method**, not the grammar. For any syntax question — keywords, `Result`
handling, `from` composition, macros, modules, visibility, the EBNF — read **`references/LANG.md`**
(the language specification) and follow it exactly. Do **not** invent syntax; if the spec doesn't
support a form (e.g. comparison operators in conditions — see its Open Questions), model around it
with a call that returns a `Result` or `bool` instead.
handling, `from` composition, macros, modules, visibility, the EBNF — run **`pds lang`** to print
the full language reference (spec + patterns + the conformance/grammar suite) and follow it exactly.
Do **not** invent syntax; if the spec doesn't support a form (e.g. comparison operators in
conditions — see its Open Questions), model around it with a call that returns a `Result` or `bool`
instead.

Two jobs only:
- **Map** an existing application into a `.pds` model (reverse).
Expand Down Expand Up @@ -57,14 +58,14 @@ disclose it as a branch. *How the JWT is parsed* is plumbing → omit it.
## Concern → construct map

Read it top-to-bottom when mapping an existing app; read it right-to-left when reconstituting code
from a model. (Constructs and call syntax are defined in `references/LANG.md`.)
from a model. (Constructs and call syntax are defined in the language reference — run `pds lang`.)

| App concern | PseudoScript | Disclosed? |
|---|---|---|
| HTTP route / controller / RPC handler | callable with `#[http("VERB /path")]` | body disclosed only for the orchestration that carries meaning; routing/serialization is the macro, not the body |
| Use case / application service / interactor | disclosed callable | **disclose** |
| Domain rule, validation, **authorization** decision | `if (r.isErr) { return Err(...) }` branches | **disclose** |
| Calculation / assembling a result from parts | `x = T from { a, b }` + the calls feeding it | **disclose** (provenance) |
| Calculation / assembling a result from parts | `x: T = T from { a, b }` + the calls feeding it | **disclose** (provenance) |
| Repository / DAO / ORM mapper | black-box `component` (or `container`) with `fetch`/`save`/… signatures | black box |
| Database / cache / queue infrastructure | black-box `container`, often tagged `#critical` | black box |
| DTO / entity / domain event / message | `data` record; events as a discriminated union | fields disclosed when they matter; `data X;` otherwise |
Expand All @@ -90,7 +91,8 @@ from a model. (Constructs and call syntax are defined in `references/LANG.md`.)
5. **Disclose the use cases.** Translate each service/interactor method into a disclosed callable,
tracing the **business logic line for line**: every guard becomes an `if (…isErr) { return Err }`,
every assembled value becomes `from { … }`, every dependency call becomes a `Target.method(args)`.
Keep bodies at flow-and-provenance level — never field-level arithmetic.
Every binding states its type (`x: T = …`). Keep bodies at flow-and-provenance level — never
field-level arithmetic.
6. **Mark the entry points.** Attach the trigger macro that matches how each callable is actually
initiated: `#[http]`, `#[onevent]`, `#[schedule]`, `#[manual]`. These become inbound edges and
sequence-diagram entry points.
Expand Down Expand Up @@ -188,18 +190,18 @@ public container Checkout for Shop {
/// Reserve stock, price it, charge, persist, announce.
#[http("POST /orders")]
public PlaceOrder(cmd: PlaceOrder): Result<Order, OrderError> {
reserved = Inventory::Reservations.reserve(cmd.sku, cmd.qty)
reserved: Result<void, OutOfStock> = Inventory::Reservations.reserve(cmd.sku, cmd.qty)
if (reserved.isErr) {
return Err(reserved.error)
}
quote = self.Quote(cmd.sku, cmd.qty)
order = Order from { cmd, quote }
paid = Payments.charge(order)
quote: number = self.Quote(cmd.sku, cmd.qty)
order: Order = Order from { cmd, quote }
paid: Result<void, Declined> = Payments.charge(order)
if (paid.isErr) {
return Err(paid.error)
}
OrderStore::Orders.save(order)
evt = OrderPlaced from { order }
evt: OrderPlaced = OrderPlaced from { order }
Bus.publish(evt)
return Ok(order)
}
Expand Down Expand Up @@ -264,4 +266,4 @@ Before declaring a model done, confirm:
- [ ] **Features cover the behaviour** — one `feature` per acceptance scenario, each `for` a real
node, given/when/then in order, steps phrased as observable behaviour.
- [ ] **Spec-faithful syntax** — names are fully qualified or aliased; visibility is correct; nothing
uses a form `references/LANG.md` doesn't define.
uses a form the language reference (`pds lang`) doesn't define.
72 changes: 72 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: test

on:
pull_request:
push:
branches: [main]

permissions:
contents: read

concurrency:
group: test-${{ github.ref }}
cancel-in-progress: true

jobs:
rust:
name: Rust (fmt, clippy, test)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy, rustfmt
- uses: Swatinem/rust-cache@v2
# The dependency-install tests shell out to `git commit`, which needs an
# author identity the bare runner lacks.
- name: Configure git identity for tests
run: |
git config --global user.email "ci@flying-dice.test"
git config --global user.name "pseudoscript CI"
- run: cargo fmt --all --check
- run: cargo clippy --workspace --all-targets -- -D warnings
- run: cargo test --workspace

web:
name: Web IDE (vitest, build, e2e, storybook)
runs-on: ubuntu-latest
defaults:
run:
working-directory: web-ide
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: web-ide/package-lock.json
- run: npm ci
# The wasm bundle is vendored under src/lib/pds-wasm, so no Rust build here.
- run: npm run check
- run: npm run test
- run: npm run build
- run: npx playwright install --with-deps chromium
- run: npm run test:e2e
- run: npm run build-storybook

landing:
name: Landing (svelte-check, build)
runs-on: ubuntu-latest
defaults:
run:
working-directory: web-landing
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: web-landing/package-lock.json
- run: npm ci
- run: npm run check
- run: npm run build
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ target/
.DS_Store
.idea/
.playwright-mcp/
node_modules/
13 changes: 11 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

## What this repository is

This is the specification for **PseudoScript** (file extension `.pds`), an architecture-modeling language where the model *is* the source: it reads like high-level pseudocode, expresses C4-style structure (system / container / component / person), and compiles to SVG diagrams. The deliverable right now is the **spec and its conformance suite**, not an implementation — the Rust crate is a stub (`crates/pseudoscript/src/main.rs` prints "Hello, world!"). Most work here is writing and refining spec prose, conformance cases, and decision records.
This is the specification for **PseudoScript** (file extension `.pds`), an architecture-modeling language where the model *is* the source: it reads like high-level pseudocode, expresses C4-style structure (system / container / component / person), and compiles to SVG diagrams. The **spec and its conformance suite lead**: `LANG.md` and the cases under `CONFORMANCE/` are the source of truth, and expected outputs are hand-written, never copied from the implementation. The toolchain is now implemented — a Cargo workspace under `crates/` (lexer/parser, model/checker, formatter, diagram emitter, doc-site generator, LSP) driven by the `pds` binary — but it follows the spec, not the other way round. Much of the work here is still writing and refining spec prose, conformance cases, and decision records.

## Source of truth and its layers

Expand Down Expand Up @@ -36,4 +36,13 @@ A `PreToolUse` hook in `.claude/settings.json` **denies any `git commit`** until

## Rust crate

A Cargo workspace (`resolver = "3"`, edition 2024) with one member, `crates/pseudoscript`, whose binary is named `pds`. Standard commands: `cargo build`, `cargo test`, `cargo run -p pseudoscript`, `cargo test <name>` for a single test. The implementation is not started; when writing Rust, the `idiomatic-rust` skill is required.
A Cargo workspace (`resolver = "3"`, edition 2024) with several members under `crates/` — `pseudoscript-syntax` (lexer/parser), `pseudoscript-model` (resolution + checks), `pseudoscript-format`, `pseudoscript-emit` (diagrams), `pseudoscript-doc`, `pseudoscript-lsp` / `pseudoscript-lsp-core`, `pseudoscript-wasm` — plus `crates/pseudoscript`, whose binary is `pds`. Standard commands: `cargo build`, `cargo test`, `cargo test -p pseudoscript <name>` for a single test. The `pds` binary wraps the libraries: `check`/`eval` (diagnostics — `eval` reads stdin so an agent can check a snippet without a file), `fmt`, `tokens`, `doc`, `outline`, `svg`, `lsp`, `lang`/`skill`, and the `add`/`install`/`update` dependency commands. When writing Rust, the `idiomatic-rust` skill is required.

## One LSP API, two transports — do not fork it

Language intelligence has a single source of truth: **`crates/pseudoscript-lsp-core`** — transport-neutral `text + position -> lsp_types value` handlers (completion, hover, definition, references, semantic tokens, folding, symbols, diagnostics, formatting). It depends on `pseudoscript-model` + the standalone `lsp-types` (pinned to tower-lsp 0.20's `=0.94.1`, WASM-safe), **not** `tower-lsp`. Two thin edges share it:

- **`crates/pseudoscript-lsp`** — the stdio server (`server.rs` + `workspace.rs`): tower-lsp transport over `lsp-core`. What native editors (e.g. `pseudoscript-jetbrains`) get.
- **`crates/pseudoscript-wasm`** — the browser bridge: each language export calls the same `lsp-core` handler and serialises its `lsp_types` result to JSON, so the WASM API is byte-for-byte the LSP API. The web IDE (`web-ide/src/lib/pds.js` + `pseudoscript-language.js`) is an LSP client — it decodes delta-encoded semantic tokens, integer `CompletionItemKind`, line-based `FoldingRange`, Markdown `Hover`. `definition`/`references` stay WASM-ergonomic (fqn-based, with previews) because LSP `Location` is URL-centric and the browser has no file URLs; they still route through `model::resolve`, so no logic forks. Diagram/doc exports (`emit_scene`, `symbol_scene`, …) are WASM-only — no LSP equivalent.

To change a language feature, edit it once in `lsp-core` (or its `model` primitive). After a *wasm-exported* surface changes, rebuild: `npm run build:wasm` in `web-ide`, then commit the regenerated `pds-wasm/` artifacts. Highlight **colours** and pure editor UX stay client-side.
2 changes: 1 addition & 1 deletion CONFORMANCE/generation/9-sequence.pds
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public container Inventory for Shop;
public container Orders for Shop {
#[manual]
public Place(order: Order): Result<Order, Rejected> {
r = Inventory.reserve(order)
r: Result<Order, Rejected> = Inventory.reserve(order)
if (r.isErr) {
return Err(r.error)
}
Expand Down
2 changes: 1 addition & 1 deletion CONFORMANCE/static/0-ok-worked-example.pds
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public system Banking;

public container Mainframe for Banking {
public GetBankingInfo(id: number): Result<BankingInfo, NotFound> {
r = AccountStore::Repository.fetch(id)
r: Result<BankingInfo, NotFound> = AccountStore::Repository.fetch(id)
if (r.isErr) {
return Err(r.error)
}
Expand Down
2 changes: 1 addition & 1 deletion CONFORMANCE/static/5-missing-return.pds
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public system Banking;

public container Mainframe for Banking {
Get(): Result<Info, Missing> {
r = self.Fetch()
r: Result<Info, Missing> = self.Fetch()
if (r.isErr) {
return Err(r.error)
}
Expand Down
1 change: 1 addition & 0 deletions CONFORMANCE/static/6-accessor-on-non-optional.diagnostics
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
no field `isSome` on `Ref`; `.isSome` is an `Option` accessor (§6.2) — type the value `Option<Ref>` to use it
18 changes: 18 additions & 0 deletions CONFORMANCE/static/6-accessor-on-non-optional.pds
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// LANG.md §6.2: `.isSome` is an `Option` accessor. `mv` is a plain record, not
// an `Option`, so the read names no field — the diagnostic points at typing the
// value `Option<...>`.

//! example

public data Ref { id: number }

public system S;

public container C for S {
pick(mv: Ref): number {
if (mv.isSome) {
return 1
}
return 0
}
}
1 change: 1 addition & 0 deletions CONFORMANCE/static/6-call-method-on-data-value.diagnostics
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
no method `doThing` on `Conv`
13 changes: 13 additions & 0 deletions CONFORMANCE/static/6-call-method-on-data-value.pds
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// LANG.md §6: a `.name(args)` call's member MUST exist on the receiver's type.
// `c` is a `Conv` record (fields only); a `data` value has no callables, so any
// method call on one is rejected.

//! example

public data Conv { id: uuid }

public system S;

public container C for S {
run(c: Conv): void { c.doThing() }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
no method `nope` on `Store`
16 changes: 16 additions & 0 deletions CONFORMANCE/static/6-call-unknown-method-on-node.pds
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// LANG.md §6: a `.name(args)` call's member MUST exist on the receiver's type.
// `Store` resolves to a component node; `nope` is not one of its callables.

//! example

public system S;

public container Db for S;

public component Store for Db {
get(): void;
}

public container C for S {
run(): void { Store.nope() }
}
2 changes: 1 addition & 1 deletion CONFORMANCE/static/6-option-value-on-none.pds
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public system Registry;

public container Directory for Registry {
public find(id: number): Option<Person> {
o = self.lookup(id)
o: Option<Person> = self.lookup(id)
if (o.isNone) {
return Some(o.value)
}
Expand Down
2 changes: 1 addition & 1 deletion CONFORMANCE/static/6-result-wrong-accessor.pds
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public system Banking;

public container Mainframe for Banking {
public GetBankingInfo(id: number): Result<BankingInfo, NotFound> {
r = AccountStore::Repository.fetch(id)
r: Result<BankingInfo, NotFound> = AccountStore::Repository.fetch(id)
if (r.isErr) {
return Err(r.value)
}
Expand Down
1 change: 1 addition & 0 deletions CONFORMANCE/static/6-void-as-value.diagnostics
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
unresolved reference `void`; `void` is a type, not a value — a void result returns bare `Ok` (§6.1)
15 changes: 15 additions & 0 deletions CONFORMANCE/static/6-void-as-value.pds
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// LANG.md §6.1: `void` is a type, not a value. A void-returning callable returns
// with a bare `Ok`; `Ok(void)` reads `void` as a value, which resolves to no
// parameter, binding, node, alias, or variant.

//! example

public data Failure { reason: string }

public system S;

public container C for S {
run(): Result<void, Failure> {
return Ok(void)
}
}
1 change: 1 addition & 0 deletions CONFORMANCE/static/7-1-binding-type-mismatch.diagnostics
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
binding `n` is annotated `number` but its value is `string`
12 changes: 12 additions & 0 deletions CONFORMANCE/static/7-1-binding-type-mismatch.pds
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// LANG.md §7.1 (ADR-027): a binding's annotation must match a determinable
// initialiser. A `number`-annotated binding initialised with a string literal
// is rejected.

//! example

public system S;
public container C for S {
run(): void {
n: number = ""
}
}
4 changes: 2 additions & 2 deletions CONFORMANCE/static/7-rebind-rejected.pds
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ public system Banking;

public container Mainframe for Banking {
Run(): void {
r = self.Make()
r = self.Make()
r: Info = self.Make()
r: Info = self.Make()
}
Make(): Info;
}
2 changes: 1 addition & 1 deletion CONFORMANCE/syntax/3-option.pds
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public system Registry;
public container Directory for Registry {
/// The optional person on file for an id.
public find(id: number): Option<Person> {
o = self.lookup(id)
o: Option<Person> = self.lookup(id)
if (o.isNone) {
return None
}
Expand Down
10 changes: 10 additions & 0 deletions CONFORMANCE/syntax/7-1-untyped-assignment-rejected.reject
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// LANG.md §7.1 (ADR-027): a binding states its type. An unannotated
// `x = Expr` no longer parses.

public system S;
public container C for S {
run(): void {
x = self.make()
}
make(): number;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
assignment requires a type annotation: write `name: Type = …`
4 changes: 2 additions & 2 deletions CONFORMANCE/syntax/7-chaining.pds
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ data Info { owner: string }

public container Mainframe for Banking {
Run(): void {
a = Store::Repo.fetch(1).value.owner
b = self.Pick().first().tag
a: string = Store::Repo.fetch(1).value.owner
b: string = self.Pick().first().tag
}
}
14 changes: 14 additions & 0 deletions CONFORMANCE/syntax/7-from-labelled-source.reject
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// LANG.md §7.2: a `from` source set holds bare references (bindings, field
// accesses, or calls), separated by `,` and closed by `}`. A `key: value`
// label is not a source — `data` is never constructed with field values
// (ADR-003) — so the `:` is rejected at the source set.

//! example

public data Thing { name: string }

public system S;

public container C for S {
make(): Thing { return Thing from { name: "x" } }
}
1 change: 1 addition & 0 deletions CONFORMANCE/syntax/7-from-labelled-source.reject.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
`from` takes bare references, not `field: value` — bind the value to a name and list the name (§7.2)
8 changes: 4 additions & 4 deletions CONFORMANCE/syntax/7-statements.pds
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ data BankingInfo { id: number }

public container Mainframe for Banking {
Run(): void {
a = Foo.getThing()
b = Bar.getOther()
c = BankingInfo from { a, b }
a: Result<BankingInfo, void> = Foo.getThing()
b: BankingInfo = Bar.getOther()
c: BankingInfo = BankingInfo from { a, b }
if (a.isErr) {
return
} else {
x = a.value
x: BankingInfo = a.value
}
while (cond) {
self.step()
Expand Down
Loading
Loading