Skip to content

Releases

v0.12.1

Choose a tag to compare

@github-actions github-actions released this 12 Nov 04:09

Changed

  • Every example in “Learn Wavelet in Y minutes” can be edited and run directly
    on the page, including the two-file component example.
  • Compiled components omit Unicode case-conversion tables when they do not use
    upper or lower, reducing their size.

Full Changelog: v0.12.0...v0.12.1

v0.12.0

Choose a tag to compare

@github-actions github-actions released this 11 Nov 20:07

Added

  • A pure in-memory compiler API and a compiler component with a WIT interface.
    Callers supply source files, WIT dependencies, and macro capabilities explicitly.
    GitHub releases include the standalone wavelet-compiler.wasm component.
  • Compiled browser playgrounds and a dedicated REPL, with worker isolation,
    cancellation, timeouts, and recovery after compiler or runtime errors.
  • A code-led “Learn Wavelet in Y minutes” tour and rewritten documentation
    describing the current language, component interfaces, and embedding APIs.
  • Pinned Code Maat history analysis with revision, churn, and coupling reports,
    available through the local check suite and as downloadable CI artifacts.

Changed

  • Native builds, the native REPL, and the compiler component share the compiler
    pipeline and snippet wrapper. Documentation generation verifies every example
    through compiled execution against the independent interpreter oracle.
  • Macro preparation returns explicitly supplied or generated component artifacts
    for host instantiation, then resumes with synchronous macro capabilities.
  • REPL value declarations execute during submission and report initializer errors
    immediately.

Fixed

  • Compiled string concatenation handles characters and sequence payloads.
    String length counts Unicode scalars, matching the interpreter.
  • Compiled upper and lower match the interpreter's Unicode casing, including
    multi-character mappings and context-sensitive Greek sigma.
  • Generated WIT escapes reserved words in public identifiers so components keep
    the names declared in Wavelet.
  • Tuple length and statically typed tuple indexing agree with the interpreter.
  • Statically resolved builtin callbacks work in collection operations while
    preserving local shadowing.
  • Form printing preserves uppercase flag names through reading and printing.
  • Browser resource bindings avoid a JavaScript intrinsic-name collision for
    the built-in set resource.

Removed

  • Placeholder Derive implementations that returned constant answers. Unsupported
    derivation now reports an error; operations can be defined explicitly.

What's Changed

  • docs: correct stale phase status in check.rs header by @logaan in #33
  • Reorganise the work plan vault into eight ordered goals by @logaan in #34
  • docs: stop pointing CLAUDE.md at the deleted dev-notes/design.md by @logaan in #35
  • test(differential): F4 execution harness — docs examples, interpreter vs compiled by @logaan in #36
  • refactor(emit): split the 14.6k-line emit.rs into a module tree by @logaan in #39
  • refactor(emit): split Emitter::builtin into per-group helpers by @logaan in #38
  • fix: run extensionless shebang scripts, not just .wlt files by @logaan in #37
  • Add fixed-arity tuple constructors tuple0..tuple16; values callee passes (decision 0.1) by @logaan in #41
  • to-string: float and char arms in the wasm backend (0.2) by @logaan in #40

Full Changelog: v0.10.0...v0.12.0

v0.11.0

Choose a tag to compare

@github-actions github-actions released this 11 Nov 19:12

Added

  • A working WASI 0.2 HTTP example in examples/http, with vendored interfaces,
    a smoke-test script, and provider-neutral deployment guidance. The HTTP scaffold
    sets content type, escapes reflected text, and releases request/body resources.
  • A complete symmetric Component Model round-trip component and automated
    matrix against two independent Rust seeds, in both directions and against
    itself. Coverage includes stable WIT values, nested compounds, owned/borrowed
    resources, constructors, methods, statics, and zero/multiple parameters.
  • User-defined DefFunctor templates with named type parameters and concrete
    Instantiate expansion, including resource and compound-result templates.
  • Dual-role imports using roles: {runtime macro} to share one alias between
    compile-time macros and runtime functions.
  • User-declared DefResource resources; compiled cells; persistent resource
    state; resource methods, statics, constructors, and destructors.
  • Tuple constructors tuple0 through tuple16, tuple argument bundling,
    payloadless results, bound variant/enum constructors, and constructor aliases.
  • Compiled numeric conversions, f32, flags, collections, string operations,
    statically resolved map/filter/fold, and compound-value printing.
  • Cross-package signature types, dependency aliases, named functor application,
    typed macro trees, pattern exhaustiveness, and cross-component type checking.
  • Contextual callback typing and inference for recursive functions, cells,
    imported resource methods, and exported parameter/result annotations.
  • An independent execution regression corpus, output comparison, and official
    WAVE-parser checks for documented values and backend float/character output.
  • Shared private build staging with automatic cleanup, explicit path errors,
    duplicate filename rejection, and copied WIT/macro dependencies.
  • Formatting, Clippy, Lizard complexity, module/function-size, and measured
    LLVM coverage gates in scripts/check.sh and CI. Existing complexity debt
    has checked-in ratchets; functions cannot reach 1,000 code lines.
  • Pinned copy/paste detection for implementation Rust and JavaScript/TypeScript,
    with a content-based baseline that rejects new clones and extra copies.
  • Interactive line editing, persistent REPL history, and executable .wlt or
    extensionless scripts using a leading shebang.

Changed

  • Static typing is now the default language behavior. Unknown runtime types,
    heterogeneous lists, function-valued runtime storage/returns, and dynamic
    callback selection are rejected. Statically resolved functions and macros
    remain supported. --strict is accepted for compatibility.
  • / in a name normalizes to -; qualified-symbol AST and macro-wire variants
    have been removed. Rebuild macro components against the updated meta ABI.
    The docs, language server, and all editor grammars follow the new spelling.
  • wavelet run and the REPL execute compiled components and surface build
    errors or traps directly. The interpreter remains the reference oracle.
  • Repeated REPL expressions reuse a bounded cache of compiled instances;
    definitions invalidate it, and value redefinitions replace older bindings.
  • Local resource calls use borrowed arguments. Owned transfers are supported
    at Component Model import/export boundaries; unsupported local owned
    transfers are rejected rather than silently diverging between engines.
  • Resource state is restricted to plain data or one outer cell containing
    plain data. Nested/shared cell graphs and function-bearing state are rejected
    before persistence.
  • Per-call arenas reset between exported calls while resource state persists.
    Runtime helper emission is split into smaller modules and functions.
  • If and Do are standard-library macros. The is a static ascription;
    conditions must be bool; integer literals must fit their contextual type;
    float literals are not Match patterns. A list argument binds to one parameter.
  • Floats print indicatively to six significant digits. Empty tuples and unit
    retain their documented diagnostic spellings; the WAVE check records its
    single empty-tuple syntax exception explicitly.
  • Source comments have been removed; agent guidance requires explanations in
    documentation and preserves executable/tool directives. Work happens in the
    shared checkout with local commits.
  • The official source extension is .wlt.

Fixed

  • GitHub releases include Windows x86-64 CLI and language server binaries and
    publish once checks and all platform builds pass.

  • Builds preserve authored wit/*.wit files and publish fetched dependencies only
    after all staged fetches succeed. Duplicate packages and colliding component
    filenames and package names that escape the output directory fail before output
    files are written; empty build/run/compose inputs
    return diagnostics.

  • Macro component caching distinguishes requested versions and explicit artifact
    paths. WIT dependencies accept binary and text-encoded WebAssembly packages.

  • Imported WIT types retain package and interface identity, including aliases;
    colliding record layouts and resource names no longer overwrite one another.
    Passing a handle to a different resource interface is rejected statically.

  • Imported single-field record results lift correctly through the canonical ABI.

  • The embedded runtime uses Wasmtime 50, which runs the composed resource and
    variant regression that failed in the previous runtime's adapter compiler.

  • Variant constructors shadow builtins consistently, including boxed calls;
    multi-field variant payloads use an explicit tuple type.

  • Checked neg/abs overflow agrees in the interpreter and both backend paths.

  • Speculative type inference cannot overwrite authoritative backend types.

  • Interpreter ownership transfer invalidates the source handle; borrowed handles
    remain borrowed, and destructors run once at teardown.

  • Tuple/record/variant pattern binding and coverage, canonical layout for narrow
    values and flags, dependency type aliases, resource compound results, and
    local overload resolution agree with their declared types.

  • Strings containing ASCII controls, including NUL, print valid WAVE escapes in
    both engines. Float/character formatting and compound printing agree.

  • wkg dependency fetching uses the current CLI directory syntax.

Removed

  • Runtime read and apply; use compiler-side reading and direct calls.
  • Interpreter fallback for failed CLI/REPL execution.
  • Qsym values and their macro ABI representation.

What's Changed

  • docs: correct stale phase status in check.rs header by @logaan in #33
  • Reorganise the work plan vault into eight ordered goals by @logaan in #34
  • docs: stop pointing CLAUDE.md at the deleted dev-notes/design.md by @logaan in #35
  • test(differential): F4 execution harness — docs examples, interpreter vs compiled by @logaan in #36
  • refactor(emit): split the 14.6k-line emit.rs into a module tree by @logaan in #39
  • refactor(emit): split Emitter::builtin into per-group helpers by @logaan in #38
  • fix: run extensionless shebang scripts, not just .wlt files by @logaan in #37
  • Add fixed-arity tuple constructors tuple0..tuple16; values callee passes (decision 0.1) by @logaan in #41
  • to-string: float and char arms in the wasm backend (0.2) by @logaan in #40

Full Changelog: v0.10.0...v0.11.0

v0.10.0

Choose a tag to compare

@github-actions github-actions released this 02 Jul 13:54
fcd6a31

Added

  • WIT round-trip conformance suite (conformance/). A roundtrip:suite
    WIT world that exercises every WIT feature (all primitives, strings, lists,
    tuples, records, options, results, variants, enums, flags, type aliases,
    and resources), with two independently seeded Rust reference components, a
    composition harness, and a Wavelet runner that drives the full check matrix
    against both Rust callees. The Wavelet callee counterpart is checked in as
    the acceptance target for the remaining backend gaps, which are tracked as
    individual follow-up tasks. The two fixes below are the first two items off
    that list.

  • to-char builtin, and char↔codepoint conversion. to-char(n) converts
    an int to the char with that codepoint (erroring on surrogates and values
    past 0x10FFFF; a char passes through unchanged), and the integer
    conversions (to-u8 … to-s64) now accept a char and yield its codepoint —
    so e.g. the next Unicode scalar of 'a' is
    to-char(add(to-u32('a') 1)).

Fixed

  • Chars no longer trap at the compiled component boundary. Compiled code
    lowered a char argument through the int unboxer, which traps on a char box,
    so calling any imported or exported function with a char hit a wasm
    unreachable; and a char lifted in arrived boxed as an int, so it stopped
    behaving as a char in-guest. Chars now lower from and lift to proper char
    values in every placement (arguments, results, list elements, option/result
    payloads), and the ordered comparisons (lt le gt ge) order chars by
    codepoint in compiled code, matching the interpreter.

  • Byte-width payloads no longer corrupt at the component boundary. The wasm
    backend gave every sub-4-byte integer (u8/s8/u16/s16) a 4-byte
    size/alignment and read/wrote it with full i32 accesses, so any such value
    the canonical ABI places in linear memory — list elements, record and tuple
    fields, option/result payloads — was lifted from (and lowered to) the wrong
    strides and offsets: the head of a list<u8> [1 2 3] lifted as 197121,
    some(7) as some(0). Compiled components now use the canonical byte-width
    layout with sign/zero-extending narrow loads, matching the interpreter.

What's Changed

  • docs(dev-notes): consolidate outstanding work into gaps.typ by @logaan in #25
  • conformance: WIT round-trip suite (stage 1 — Rust component + harness) by @logaan in #27
  • conformance: wavelet vs the roundtrip suite (stage 2 — matrix + shortcomings) by @logaan in #31
  • fix(emit): byte-width payloads use their canonical layout in linear memory by @logaan in #29
  • fix(emit)+feat(stdlib): chars at the compiled boundary, and to-char by @logaan in #30
  • release: 0.10.0 by @logaan in #32

Full Changelog: v0.9.2...v0.10.0

v0.9.2

Choose a tag to compare

@github-actions github-actions released this 27 Jun 07:54

Changed

  • The documentation site now uses the Wavelet wave brand mark as its favicon,
    replacing the default Docusaurus favicon.

What's Changed

  • docs: use the Wavelet logo as the favicon (release 0.9.2) by @logaan in #26

Full Changelog: v0.9.1...v0.9.2

v0.9.1

Choose a tag to compare

@github-actions github-actions released this 27 Jun 06:42

Changed

  • New project logo. The Docusaurus site navbar and the README now use the
    wave brand mark (brand/Logo.png) in place of the placeholder Docusaurus SVG.

Full Changelog: v0.9.0...v0.9.1

v0.9.0

Choose a tag to compare

@github-actions github-actions released this 27 Jun 05:45

Added

  • The set functor now runs and builds end to end. Instantiating
    wavelet:coll/set with Import {pkg: … elem: t as: …} binds the qualified ops
    alias/new, alias/add, alias/contains, and alias/size (with the
    signatures the synthesized resource promises — new() -> set,
    add(set, elem), contains(set, elem) -> bool, size(set) -> u32), so a
    functor program executes under wavelet run; membership uses the element
    type's Eq, so it agrees with eq/compare. The wasm backend now also
    builds set functor components: the synthesized per-element interface is
    emitted as a real exported WIT resource at parity with the interpreter — any
    element type (primitive, string, record, and compound list/tuple) and multiple
    instantiations per world, with the same structural-equality membership the
    interpreter uses. The one limitation is shaping, not semantics: an export that
    returns the set handle over a local-record element forms a WIT interface
    cycle (the element's api interface and the resource's interface would each
    use the other), which WIT cannot express, so it is rejected with a clear
    error. Exports that derive an ordinary result (e.g. -> u32), or that return a
    handle over a primitive/string element, build fine. The type-system guide's
    "A program you can build" section walks both buildable shapes with the WIT each
    emits.

Fixed

  • wavelet run now expands Derive (and any tree→tree stdlib macro). The
    run path skipped the expand_file pass that wavelet build/wavelet wit use,
    so a program that Derived a type died with unbound name derive-MACRO — even
    before any functor was involved. wavelet run now runs the expander first,
    matching the other paths, so derived programs (and functor programs, which lean
    on derived ops over their element type) execute.

What's Changed

  • feat(functor): build set functor components in the wasm backend by @logaan in #24
  • feat(functor): run the Set functor in the interpreter; fail build cleanly by @logaan in #22
  • docs(dev-notes): exhaustive language feature inventory by @logaan in #23

Full Changelog: v0.8.0...v0.9.0

v0.8.0

Choose a tag to compare

@github-actions github-actions released this 24 Jun 15:57
1996e18

Added

  • Monomorphic type system — total static type checking. Every Wavelet
    expression now has a WIT type, decided by a static checker pass (src/check.rs)
    that runs on every path — wavelet run, wavelet build, wavelet wit,
    and the playground — before any code runs or any component is emitted. Checking
    is total: an ill-typed definition is a compile error even when nothing calls
    it, so type errors surface at build/run/wit time rather than at the wasm
    boundary. Inference is bidirectional — types propagate inward from contexts
    (function signatures, Let bindings, Match results) and synthesize outward
    from atoms and applications.
  • Numeric-literal resolution + defaulting, and The ascription. A bare
    numeric literal takes its type from context and is range-checked against it
    (The u8 300 is a compile error); with no context it defaults to s64
    (integers) or f64 (fractionals). The The form ascribes a type to an
    expression (The s64 5), both to pin a literal and to drive resolution where
    arguments alone don't decide.
  • Ad-hoc overloading. Several monomorphic Defs sharing a name form an
    overload set. Each call site is resolved statically: first by the WIT types
    of its arguments, then — when arguments don't decide — by the expected return
    type supplied via The. An exported overload set is name-mangled at the
    component boundary
    so each concrete instance gets a distinct WIT export
    (e.g. an eq over point is exported as eq-point).
  • Derive {Eq Ord Show Hash} t. Derives the standard operations for a type,
    expanding to concrete monomorphic definitions (e.g. eq-point, show-point)
    whose WIT signatures are synthesized like any other export.
  • Functor instantiation via Import {pkg: … elem: t as: …}. A parameterized
    import specializes a generic interface to a concrete element type, synthesizing
    a per-element WIT interface (e.g. set instantiated at point yields a
    concrete point-set interface) — nothing generic survives into the emitted
    world.
  • Macro components — run macros defined in other components. Import {pkg: "…" macros: true} imports a macro library: a component exporting
    wavelet:meta/macros@0.1.0 (manifest() → (name, arity) pairs, expand(name, args) → result<tree, string>). Wavelet instantiates it at compile time,
    registers its macro arities with the reader (so foreign TitleCase macros read
    paren-free, top-to-bottom, like local DefMacros), and routes expansion
    through the component's expand to a fixpoint (design.md §6.2–§6.3). The
    library's .wasm is resolved from an explicit from: path or the conventional
    wit/macros/<ns>-<name>.wasm location. A macros: true import is
    compile-time-only: it is excluded from the synthesized runtime world, so the
    shipped component never imports wavelet:meta/macros. Because a macro library
    is an ordinary component, macros can be written in any language that compiles to
    one, and they run sandboxed by construction.
  • Qualified and aliased foreign macros. Imported macros are available both
    bare (Element) and qualified by the import alias (dsl/Element, with
    as:). A bare TitleCase name provided by two imports — or by an import and a
    local DefMacro — is ambiguous and errors only when used bare, with a
    message suggesting you alias or qualify; the qualified spelling always
    resolves.
  • Build-time component runtime. Running foreign macros at compile time needs
    a wasm runtime, so the compiler now depends on wasmtime (native targets
    only). It is gated out of the wasm32 build: the browser-playground bindings
    moved behind a new default-on playground cargo feature, so the
    wasm-compiled interpreter (and the macro-library guest) build without
    wasmtime or wasm-bindgen. The playground therefore has no component
    runtime — foreign-macro examples run only in native wavelet build, not in
    the browser.
  • Produce macro components from Wavelet (wavelet build). A .wvl file
    whose top level is a Package declaration plus DefMacros only (no Export,
    no runtime defs) now compiles into a component exporting wavelet:meta/macros,
    so a macro library can be written in Wavelet itself and imported with
    Import {… macros: true} like any other macro component (design.md §6.3). Each
    macro body is compiled to wasm (the compiler learned to emit
    Quote/Quasi/Unquote/Splice, gensym, and the form-introspection
    builtins), so the produced component carries no interpreter and is built
    in-process — no cargo, no wasm32-unknown-unknown target. The interpreter
    remains the differential oracle the compiled expansions are checked against.

Changed

  • Macro expansion is compiled, not interpreted (native build). A file's
    local DefMacros and produced macro libraries now expand through a compiled
    wavelet:meta/macros component rather than the tree-walking interpreter, so
    wavelet build/wavelet expand no longer interpret macros. Macro builds are
    faster and need no wasm32-unknown-unknown target. The browser playground
    keeps expanding local macros with the in-browser interpreter (it has no
    component runtime); the interpreter also stays as the differential oracle.

Fixed

  • The type checker now runs on wavelet run, wavelet build, and
    wavelet wit, not only the playground.
    Previously the checker (and, on the
    run path, overload resolution) was wired into the playground evaluator alone:
    wavelet run bound same-named Defs by last-wins shadowing — so an overloaded
    call reached whichever def was read last and failed or silently ran the wrong
    body — and wavelet build/wavelet wit emitted/synthesized ill-typed programs
    without complaint. Each of these paths now type-checks the (expanded, for
    build/wit) program first, so an ill-typed program is rejected everywhere and an
    overloaded call dispatched through wavelet run resolves to the correct member.
  • Compiled add/sub/mul/div/rem/neg and lt/le/gt/ge now
    match the interpreter on floats and strings.
    The wasm backend previously
    unboxed every operand as an integer, so a compiled component that did f64
    arithmetic or compared strings built cleanly but trapped at runtime. These
    builtins now dispatch on the operand at runtime: arithmetic does f64 math
    when an operand is a decimal (widening integers in mixed operands), and the
    comparisons order strings lexicographically and numbers as f64 — the same
    results the interpreter (the semantics oracle) produces.
  • Compiled arithmetic is strictly binary. add/sub/mul/div/rem in a
    compiled component now require exactly two arguments, as the interpreter
    already did, instead of silently folding three or more.
  • Compiled integer overflow is checked. add/sub/mul overflow and the
    div/rem edge cases (divide-by-zero, INT_MIN / -1, INT_MIN % -1) now
    trap in a compiled component, matching the interpreter's checked-arithmetic
    errors instead of wrapping.
  • -inf is matched as a whole word. The lexer no longer splits a longer
    token beginning with -inf (e.g. -info, -infinity) into -inf plus a
    trailing fragment, mirroring the whole-word match the positive inf/nan
    literals already used.
  • wavelet run reports a missing entry point. Running a file with no
    no-argument run closure now prints an actionable error instead of silently
    doing nothing.
  • u64 parameters reject negatives. The interpreter's dynamic type check for
    a u64 parameter now rejects negative integers, consistent with the to-u64
    builtin.
  • Overload name-mangling at the WIT boundary is no longer over-broad and emits
    legal WIT.
    Exporting an ordinary library-named function defined once (e.g.
    get, head, map, concat, to-string) is no longer treated as a
    one-member overload set and name-mangled; only a genuine ≥2-member overload set
    or one of the curated overloadable operations (the derivable eq/compare/
    show/hash and the comparison/arithmetic operators) triggers mangling. The
    mangled suffix is also now an identifier-safe WIT label: a constructor-typed
    first parameter such as list(s32) produces eq-list-s32 rather than the
    illegal eq-list<s32>.
  • Overload mangling no longer collides on members that differ only past the
    first parameter.
    The mangled WIT label was derived from the first parameter
    type alone, so two members like eq {a: point b: string} and
    eq {a: point b: s32} both became eq-point — two functions of the same name
    in one interface (invalid WIT). When the first-parameter labels are all
    distinct they are kept unchanged (so eq over point/string stays
    eq-point/eq-string); when any collide, the whole set is disambiguated over
    all parameter types (eq-point-string, eq-point-s32). A genuine duplicate
    (two members with identical parameter type lists) is now a clear compile error
    naming the export instead of emitting invalid WIT.
  • A Derived op's auto-export no longer collides with an explicit
    re-export.
    Derive auto-emits a bare Export {op}-{t} for each derived
    operation, so writing that same Export eq-point yourself (a derived op is an
    ordinary exportable function) declared it twice and synthesized a duplicate
    eq-point WIT function. Identical export declarations — same exported name and
    same explicit signature — are now collapsed to one before WIT synthesis;
    declarations that share a name but differ in interface or signature are kept.
  • An ordinary Import carrying an elem: field is no longer hijacked as a
    functor.
    Functor instantiation is now classified by the import's package
    identity, not by the presence of an elem: field: only an Import whose pkg:
    is a known functor package (currently `wavelet:col...
Read more

v0.7.0

Choose a tag to compare

@github-actions github-actions released this 16 Jun 13:28

Added

  • Call chaining recv.name(args). A . attached to a form, then a name and
    an attached (, rewrites the receiver into the call's first argument:
    1.increment() reads as (increment, 1), and
    foo(1 2 3).bar(4 5 6).baz(7 8 9) as
    (baz, (bar, (foo, 1, 2, 3), 4, 5, 6), 7, 8, 9). Chains fold left-to-right.
    This is pure reader rewriting, not method dispatch — 1.increment() is
    exactly increment(1). Like the attachment rule it is whitespace-sensitive:
    the ., name, and ( must each abut the token before them. (1.5 is still a
    decimal — a . is only a chain dot when no digit follows.)

Changed

  • TitleCase macro sugar no longer spreads internal capitals. A TitleCase
    head is now lower-cased whole before gaining its -MACRO suffix, instead of
    inserting a hyphen at each interior capital: DefMacro ↦ defmacro-MACRO and
    DefType ↦ deftype-MACRO (previously def-macro-MACRO / def-type-MACRO),
    while single-word heads like If ↦ if-MACRO are unchanged. A multi-word
    user macro must now be defined under the single lower-case word it is invoked
    as — e.g. define DefMacro trylet … and invoke it as TryLet … (previously
    DefMacro try-let …). Detection is unchanged: a token is a macro head when it
    starts with a capital and contains at least one lower-case letter.
  • Function calls are now WAVE tuples with the head first. foo(1 "baz")
    reads and prints as (foo, 1, "baz") (previously the variant case foo
    carrying a payload). Special forms and macros share the shape: If c t e is
    (if-MACRO, c, t, e), and If(c t e) reads identically. Evaluating any
    parenthesized form is a call — its head is resolved and applied to the bundled
    arguments (0 ⇒ the empty tuple, 1 ⇒ that value, ≥2 ⇒ a tuple) — so a literal
    tuple value now comes only from Quote or a builtin. (foo) is a
    zero-argument call (parenthesized grouping is gone), and () is the empty
    tuple (an error if evaluated). form-kind reports tup for a quoted call;
    call is now only a runtime variant carrying a payload (ok(1)).
  • wavelet read now defaults to stdin when given no file argument. echo '...' | wavelet read reads the program from standard input; passing a path
    still reads that file. Previously stdin required an explicit /dev/stdin.

Removed

  • List and record call sugar foo[a b] and foo{k: v}. Write foo([a b])
    and foo({k: v}) instead. Only ( attaches to a name now; attaching [ or
    { to a name is a read error that points at the new spelling. (Free-standing
    […] list and {…} record/flag values are unaffected.)
  • /// doc comments. A /// line is now an ordinary // comment: its text
    is discarded by the reader instead of attaching to the following form, and it
    no longer appears as a WIT doc comment in wavelet wit output or on LSP hover.

What's Changed

  • Collect small wins into dev-notes/blueberries.md by @logaan in #4
  • Plan: switch canonical call form from variants to tuples by @logaan in #3
  • Make wavelet read default to stdin by @logaan in #6
  • Investigation: dropping the interpreter for the compiler by @logaan in #2
  • docs: plan for running macros defined in other components by @logaan in #1
  • Calls are tuples, not variants by @logaan in #8
  • docs: dedicated, numbered Reader sugar page by @logaan in #7
  • docs+refactor: scripts/README.md and a scripts/ci/ split by @logaan in #5
  • Drop /// doc comments from the language by @logaan in #11
  • feat(reader): call-chaining sugar recv.name(args) by @logaan in #10
  • Drop internal-capital spreading from TitleCase macro sugar by @logaan in #9

New Contributors

  • @logaan made their first contribution in #4

Full Changelog: v0.6.0...v0.7.0

v0.6.0

Choose a tag to compare

@github-actions github-actions released this 15 Jun 10:23

WASI decoupling: Wavelet no longer special-cases any WASI interface. The
compiler vendors no WASI WIT and has no built-in wasi:cli/wasi:http
knowledge; a component declares the host interfaces it imports and exports
explicitly, and their WIT is fetched into the project by wkg. These are
breaking changes.

Added

  • wkg and wac are now runtime dependencies of wavelet build/wavelet new. wkg (the WebAssembly package tooling) fetches host WIT, and wac
    (the WebAssembly composition tool) composes components. Both must be on
    PATH (the Homebrew formula declares them; or cargo install wkg wac-cli).
    The interpreter (wavelet run) and cargo test do not need them.
  • Project layout with a wit/ directory. A project now carries its WIT
    package and fetched dependencies on disk: wit/ holds the synthesized world,
    wit/deps/ holds the host/dependency WIT that wkg fetched, and wkg.lock
    pins the dependency versions. wavelet new scaffolds wit/ and runs wkg wit fetch to populate wit/deps/ and write wkg.lock.
  • wavelet build now composes into a single artifact. It generates a
    .wac describing how the project's components wire together and runs wac compose to produce one composed out/app.wasm, with host (wasi:*) imports
    left unsatisfied for the runtime to provide. wavelet compose remains as the
    manual/explicit alternative.
  • Output and arguments now go through explicitly-imported WASI interfaces.
    A program that wants stdout/args imports wasi:cli/stdout,
    wasi:cli/environment, and wasi:io/streams (as ordinary Import forms)
    and drives them through the generic canonical-ABI bridge, exactly as the
    http template imports wasi:http/types + wasi:io/streams. The cli
    template was migrated to this shape.
  • The generic canonical-ABI bridge now lowers/lifts every non-resource WIT
    value kind and resource handles/methods/drop driven by a parsed WIT
    signature, so an arbitrary host or third-party interface can be imported and
    exported without compiler-side special-casing.

Removed

  • The Target special form is gone. A file no longer adopts a host world
    with Target "wasi:cli/command"; instead it exports that world's interface
    directly, e.g. Export {iface: "wasi:cli/run" name: run result: result}.
    A source file using Target now fails to read.
  • The print, println, args, read-line, and env builtins are gone.
    There is no built-in I/O path; output and argument access happen by importing
    and calling the relevant WASI interfaces (see Added). wavelet run
    interprets pure cross-component logic only and produces no program output.
  • The vendored WASI WIT (src/wasi-http.wit) and all the hand-coded WASI
    magic (the http/* intrinsics, the wasi:cli/command target translation,
    the forced wasi:io/streams import) were removed; host WIT now comes from
    wit/deps.

Full Changelog: v0.5.0...v0.6.0