Repository navigation
Releases
v0.12.1
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
upperorlower, reducing their size.
Full Changelog: v0.12.0...v0.12.1
v0.12.0
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 standalonewavelet-compiler.wasmcomponent. - 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
upperandlowermatch 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
Deriveimplementations 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
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
DefFunctortemplates with named type parameters and concrete
Instantiateexpansion, 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
DefResourceresources; compiled cells; persistent resource
state; resource methods, statics, constructors, and destructors. - Tuple constructors
tuple0throughtuple16, tuple argument bundling,
payloadless results, bound variant/enum constructors, and constructor aliases. - Compiled numeric conversions, f32, flags, collections, string operations,
statically resolvedmap/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 inscripts/check.shand 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
.wltor
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.--strictis 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 runand 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. IfandDoare standard-library macros.Theis 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/*.witfiles 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/absoverflow 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. -
wkgdependency fetching uses the current CLI directory syntax.
Removed
- Runtime
readandapply; 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
Added
-
WIT round-trip conformance suite (
conformance/). Aroundtrip: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-charbuiltin, and char↔codepoint conversion.to-char(n)converts
an int to the char with that codepoint (erroring on surrogates and values
past0x10FFFF; 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 acharhit 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 (ltlegtge) 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 fulli32accesses, 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 alist<u8>[1 2 3]lifted as 197121,
some(7)assome(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
Changed
- The documentation site now uses the Wavelet wave brand mark as its favicon,
replacing the default Docusaurus favicon.
What's Changed
Full Changelog: v0.9.1...v0.9.2
v0.9.1
Changed
- New project logo. The Docusaurus site navbar and the
READMEnow 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
Added
- The
setfunctor now runs and builds end to end. Instantiating
wavelet:coll/setwithImport {pkg: … elem: t as: …}binds the qualified ops
alias/new,alias/add,alias/contains, andalias/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 underwavelet run; membership uses the element
type'sEq, so it agrees witheq/compare. The wasm backend now also
buildssetfunctor 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 thesethandle over a local-record element forms a WIT interface
cycle (the element'sapiinterface and the resource's interface would each
usethe 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 runnow expandsDerive(and any tree→tree stdlib macro). The
run path skipped theexpand_filepass thatwavelet build/wavelet wituse,
so a program thatDerived a type died withunbound name derive-MACRO— even
before any functor was involved.wavelet runnow 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
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,Letbindings,Matchresults) and synthesize outward
from atoms and applications. - Numeric-literal resolution + defaulting, and
Theascription. A bare
numeric literal takes its type from context and is range-checked against it
(The u8 300is a compile error); with no context it defaults tos64
(integers) orf64(fractionals). TheTheform 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 viaThe. An exported overload set is name-mangled at the
component boundary so each concrete instance gets a distinct WIT export
(e.g. aneqoverpointis exported aseq-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.setinstantiated atpointyields a
concretepoint-setinterface) — 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 localDefMacros), and routes expansion
through the component'sexpandto a fixpoint (design.md §6.2–§6.3). The
library's.wasmis resolved from an explicitfrom:path or the conventional
wit/macros/<ns>-<name>.wasmlocation. Amacros: trueimport is
compile-time-only: it is excluded from the synthesized runtime world, so the
shipped component never importswavelet: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
localDefMacro— 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 onwasmtime(native targets
only). It is gated out of thewasm32build: the browser-playground bindings
moved behind a new default-onplaygroundcargo feature, so the
wasm-compiled interpreter (and the macro-library guest) build without
wasmtimeorwasm-bindgen. The playground therefore has no component
runtime — foreign-macro examples run only in nativewavelet build, not in
the browser. - Produce macro components from Wavelet (
wavelet build). A.wvlfile
whose top level is aPackagedeclaration plusDefMacros only (noExport,
no runtime defs) now compiles into a component exportingwavelet: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 — nocargo, nowasm32-unknown-unknowntarget. The interpreter
remains the differential oracle the compiled expansions are checked against.
Changed
- Macro expansion is compiled, not interpreted (native build). A file's
localDefMacros and produced macro libraries now expand through a compiled
wavelet:meta/macroscomponent rather than the tree-walking interpreter, so
wavelet build/wavelet expandno longer interpret macros. Macro builds are
faster and need nowasm32-unknown-unknowntarget. 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 runbound same-namedDefs by last-wins shadowing — so an overloaded
call reached whichever def was read last and failed or silently ran the wrong
body — andwavelet build/wavelet witemitted/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 throughwavelet runresolves to the correct member. - Compiled
add/sub/mul/div/rem/negandlt/le/gt/genow
match the interpreter on floats and strings. The wasm backend previously
unboxed every operand as an integer, so a compiled component that didf64
arithmetic or comparedstrings built cleanly but trapped at runtime. These
builtins now dispatch on the operand at runtime: arithmetic doesf64math
when an operand is a decimal (widening integers in mixed operands), and the
comparisons order strings lexicographically and numbers asf64— the same
results the interpreter (the semantics oracle) produces. - Compiled arithmetic is strictly binary.
add/sub/mul/div/remin 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/muloverflow and the
div/remedge 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. -infis matched as a whole word. The lexer no longer splits a longer
token beginning with-inf(e.g.-info,-infinity) into-infplus a
trailing fragment, mirroring the whole-word match the positiveinf/nan
literals already used.wavelet runreports a missing entry point. Running a file with no
no-argumentrunclosure now prints an actionable error instead of silently
doing nothing.u64parameters reject negatives. The interpreter's dynamic type check for
au64parameter now rejects negative integers, consistent with theto-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 derivableeq/compare/
show/hashand the comparison/arithmetic operators) triggers mangling. The
mangled suffix is also now an identifier-safe WIT label: a constructor-typed
first parameter such aslist(s32)produceseq-list-s32rather than the
illegaleq-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 likeeq {a: point b: string}and
eq {a: point b: s32}both becameeq-point— two functions of the same name
in one interface (invalid WIT). When the first-parameter labels are all
distinct they are kept unchanged (soeqoverpoint/stringstays
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.Deriveauto-emits a bareExport {op}-{t}for each derived
operation, so writing that sameExport eq-pointyourself (a derived op is an
ordinary exportable function) declared it twice and synthesized a duplicate
eq-pointWIT 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
Importcarrying anelem:field is no longer hijacked as a
functor. Functor instantiation is now classified by the import's package
identity, not by the presence of anelem:field: only anImportwhosepkg:
is a known functor package (currently `wavelet:col...
v0.7.0
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
exactlyincrement(1). Like the attachment rule it is whitespace-sensitive:
the., name, and(must each abut the token before them. (1.5is 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-MACROsuffix, instead of
inserting a hyphen at each interior capital:DefMacro↦defmacro-MACROand
DefType↦deftype-MACRO(previouslydef-macro-MACRO/def-type-MACRO),
while single-word heads likeIf↦if-MACROare unchanged. A multi-word
user macro must now be defined under the single lower-case word it is invoked
as — e.g. defineDefMacro trylet …and invoke it asTryLet …(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 casefoo
carrying a payload). Special forms and macros share the shape:If c t eis
(if-MACRO, c, t, e), andIf(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 fromQuoteor a builtin.(foo)is a
zero-argument call (parenthesized grouping is gone), and()is the empty
tuple (an error if evaluated).form-kindreportstupfor a quoted call;
callis now only a runtime variant carrying a payload (ok(1)). wavelet readnow defaults to stdin when given no file argument.echo '...' | wavelet readreads 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]andfoo{k: v}. Writefoo([a b])
andfoo({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 inwavelet witoutput 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 readdefault 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
Full Changelog: v0.6.0...v0.7.0
v0.6.0
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
wkgandwacare now runtime dependencies ofwavelet build/wavelet new.wkg(the WebAssembly package tooling) fetches host WIT, andwac
(the WebAssembly composition tool) composes components. Both must be on
PATH(the Homebrew formula declares them; orcargo install wkg wac-cli).
The interpreter (wavelet run) andcargo testdo 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 thatwkgfetched, andwkg.lock
pins the dependency versions.wavelet newscaffoldswit/and runswkg wit fetchto populatewit/deps/and writewkg.lock. wavelet buildnow composes into a single artifact. It generates a
.wacdescribing how the project's components wire together and runswac composeto produce one composedout/app.wasm, with host (wasi:*) imports
left unsatisfied for the runtime to provide.wavelet composeremains as the
manual/explicit alternative.- Output and arguments now go through explicitly-imported WASI interfaces.
A program that wants stdout/args importswasi:cli/stdout,
wasi:cli/environment, andwasi:io/streams(as ordinaryImportforms)
and drives them through the generic canonical-ABI bridge, exactly as the
httptemplate importswasi: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
Targetspecial form is gone. A file no longer adopts a host world
withTarget "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 usingTargetnow fails to read. - The
print,println,args,read-line, andenvbuiltins 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 (thehttp/*intrinsics, thewasi:cli/commandtarget translation,
the forcedwasi:io/streamsimport) were removed; host WIT now comes from
wit/deps.
Full Changelog: v0.5.0...v0.6.0