Conversation
Records the TIR-vs-MIR decision for ownership/borrow checking and the resolved move-vs-Copy semantics, seeding the next design session. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The bachelor's thesis now lives at github.com/MellKam/bachelor-thesis, independent of the wx language project. thesis/ is gitignored here so it can still be cloned into the same working directory for local convenience, without any git-level coupling between the two repos. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Primitives (i8..f64, bool, char, never) were resolved via a hardcoded
string match in resolve_type_identifier, bypassing the item/DefId
system entirely - so LSP go-to-definition, hover, and find-references
never worked on them. They're now declared as `#[intrinsic] pub type X;`
items in std/main.wx: Item::TypeAlias.ty becomes an optional `body`,
ensure_signature binds a bodiless #[intrinsic] alias directly to the
matching pre-interned primitive TypeIndex, and the old string-match
shortcut is gone.
Also fixes an unrelated wx-fmt bug found along the way: impl-block
`ImplItem::Constant` never printed pub_span/attributes at all, so
`impl f32 { pub const PI }` silently lost its `pub` on format - which
had already round-tripped through the real std/main.wx and broken
~100 compiler tests via a spurious "PI is never used" warning.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Records today's session: primitives turned into real intrinsic items, plus two bugs found but deliberately not fixed - root-level `use X::*;` is crate-wide rather than per-file (lookup_global_symbol's ancestor-walk conflates privacy-ancestry with import-lookup, confirmed via a multi-file probe), and duplicate inherent-impl members for non-generic targets are only ever caught at first use, or not at all if unused. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Replaces the `mutable: bool` flag on Type::Pointer/Slice/Array with an Ownership::Exclusive|Shared kind: `*T` is now an exclusive pointer, `&T` a shared read-only reference, dropping the old `*mut T`/bare-`*T` and `[]mut T`/`[]T` spellings. Slices and arrays follow the same split (`*[T]`/`&[T]`, `*[T; N]`/`&[T; N]`), and `.&mut` is removed — `.&` always yields a shared reference now, with the one real call site that needed the old mutable form (wasi_preview1_port's union-simulation workaround) rewritten using a null-pointer offsetof idiom instead of new syntax. Full pipeline touched: AST grammar (new `&` sigil, slice/array Rust-style size position), TIR Type/coercion/`as`-cast checks, diagnostics wording, and wx-fmt's printer. std/main.wx and every `.wx` file in the repo (doom/, examples/) are migrated, each verified with `wx check` individually — not a blind mechanical rename, since several call sites needed real judgment about whether a given pointer was actually written through. Also: - Adds `ptr::align_up<Mem: Memory>` to std/main.wx and migrates every hand-rolled bump-allocator alignment formula in the repo to use it. - Fixes two compiler bugs found while adding it: unary `^`/`-` on a typeset-bounded AssocTypeProjection (e.g. `Mem::Size`) crashed the compiler with a raw panic instead of a diagnostic, and the same shape failed to type-check under binary bitwise operators. Both fixed via one shared `is_typeset_bounded_assoc_type` check composed at all four operator-checking sites. - Fixes a real bug in examples/bump_allocator: the bump allocator could hand out address 0, colliding with `ptr::null()` and causing the demo to terminate one linked-list node early. - Refactors examples/bump_allocator's free functions into `impl Node` methods for readability. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ings Two entries: the design-only session that planned the exclusive/shared split before implementation (naming, AST/TIR shape, the .&mut removal and null-pointer offsetof resolution, the deferred variant-item idea for the union-simulation problem), and the implementation-session findings around ptr::align_up — the fixed unary-panic/bitwise-binary gap and the deferred bare-typeset-bounded-type-param gap. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…nd LSP wiring Add/Sub/Mul/Div/Rem/Neg become real #[tag]-resolved traits with #[inline] primitive impls in std/main.wx; arithmetic and unary `-` desugar through find_trait_impl (TIR::build_operator_dispatch), falling back to a plain Binary/Unary node in Comptime contexts so const-folding stays untouched. Generic (T: Add) and typeset-bounded (Mem::Size) operands defer dispatch to monomorphization via GenericMethodCall's existing abstract-method path. Compound assignment (`+=` etc.) is rebuilt as sugar over the same resolved dispatch (`x = x.add(y)`) via four new TIR nodes split on resolved-now vs. generic x plain-target vs. Place-target (Assign/CompoundAssign/ GenericCompoundAssign/CompoundStore/GenericCompoundStore), fixing a pre-existing double-evaluation bug in arr[i()] += 1 along the way. Also: primitives are real #[intrinsic] type-alias items (DefId, LSP go-to-def/hover) instead of a hardcoded string match; struct/trait-impl `pub` visibility fixes in wx-fmt; new tests covering struct (not just primitive) operator-trait impls end-to-end through TIR/MIR/codegen+wasmtime. Known follow-up, not fixed here: a chained-inlining flat-offset collision in opt::builder::compute_locals_offsets causes codegen::tests::test_lerp to trap — see devlog/2026-08-17-chained-inlining-offset-collision-investigation.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ng notes Records the design/implementation trail for the feature commit above: the compound-assignment node-shape design (rejected alternatives and why), the implementation session (deferred bugs found: chained-inlining collision, char arithmetic resolved as intentional "no impl"), the standalone chained-inlining root-cause investigation (two fix candidates designed, not implemented), and an unrelated pre-existing inline+intrinsic call-graph crash found and fixed along the way. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…nline] calls
compute_locals_offsets lets same-parent scopes share a flat local-offset
range, assuming they're mutually exclusive at runtime (true for if/else/match
arms, the only shape ordinary lowering produces). inline_call broke that
assumption by creating a new sibling scope per inlined call to hold its
arguments — two calls inlined at/under the same site (sibling arguments, or
separate sweeps substituting one after another) collided, silently
clobbering each other's staged values. Confirmed via wasmtime: test_lerp's
`a + (b-a)*t` traps, and calc(a,b,c,d){(a+b)+(c+d)} returned a wrong result.
Fixed by not creating that scope at all: an inlined call's parameters (and
any locals the callee declares in its own body) now get appended directly
to the caller's existing scope at the call site, so a second inlined call
there simply gets index ranges past the first's -- nothing to compare or
protect against, Vec::push can't collide with itself. The break-target
wrapper scope still exists unconditionally but never holds locals, so it's
always safe regardless of parent.
Also unified this with the pre-existing Rebaser (used by
MIR::build_start_function to combine globals' initializers) -- the old one
was a special case of the new one, removing a duplicate tree-walk. One
accepted, documented regression: opt::tests::test_simple_add now has one
extra dead SSA node per inlined call at a function's root (harmless, reused
via CSE). Verified build_start_function's globals-combining does not share
this bug (different, safe mechanism) with a new regression test.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…references Records the actual fix landed above -- a third, simpler design than either candidate the investigation entry worked out, arrived at by questioning whether inline_call needed a new per-call scope at all rather than how to protect one. Also documents the accepted test_simple_add regression and the empirical check ruling out the same bug shape in build_start_function's globals-combining. Updated the investigation and compound-assignment devlogs, plus the index, to stop describing this as deferred/open. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…/opt Ported the codegen/wasm-shaped-instruction cleanup out of the dwarf-debugging branch (which bundled it with DWARF debug-info support we're not adopting here) — codegen's Expression/ValueType/Local/BlockResult and opt::scheduler's near-identical Instruction/Local/ScalarType were two independent copies of the same wasm stack-machine shape. They now share one definition in the new wasm module, which codegen consumes for encoding and opt::scheduler produces from the sea-of-nodes graph. Along the way this deletes codegen's ~250-line Expression enum, which was already entirely dead except its four *Const variants (global-init encoding) now that function bodies lower through opt::scheduler::Instruction instead, and switches BrTable from one Box<[u32]> heap allocation per switch to indices into a shared br_table_depths arena. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Rewrite effect-system.md to the does(...)/does(*)/does() syntax settled on after comparing against Verse's effect system, and add effect-tracking-plan.md laying out the MVP implementation (trap-only EffectSet, resolution folded into existing TIR phases, trap as an #[intrinsic] reusing the existing unreachable lowering). Also replaces the stray examples/main.txt scratch file with main.wx, used to sketch the syntax proposals during the design discussion.
…nary dispatch
Extends operator-overload traits to bitwise ops (BitAnd/BitOr/BitXor/Shl/
Shr/BitNot), same native-fast-path-preserving shape as the existing
arithmetic traits. Comparison operators still deferred.
Widened integer literals from i64 to u64 (ExprKind::Int/ast::Expression::Int),
fixing two real bugs this exposed: i8::MIN-class negation boundary checks
using the wrong (positive) bound, and eval_const_expr's Div/Rem folding with
signed semantics unconditionally regardless of the operand type's actual
signedness.
Enum variants now require an explicit anchor value before auto-increment is
legal (new E1071) — closes a real silent-collision bug in the old
`Ordering { Less, Equal = 0, Greater = 1 }` shape, where `Less` implicitly
got 0 too.
Added the missing Type::TypeParam branch to build_unary_operator_dispatch,
closing a generic-bound dispatch gap for Neg/BitNot that the binary
dispatcher didn't have.
Fixed two related bugs surfaced by a new Hasher/Hash example
(examples/hashing/main.wx): a trait-impl method with its own type params
(distinct from the impl block's) lost them entirely during TIR signature
building (AstNodeRef::TraitImplFunction), and, once fixed, the identical
shape crashed codegen via a MIR abstract-dispatch bug that conflated "impl
block is generic" with "impl's own copy of the method is generic."
Removed several genuinely dead code paths found along the way: an
unreachable coercion arm (confirmed via eprintln instrumentation across the
full suite), five already-unused ast::BinaryOp predicate methods, and
collapsed 9 near-identical integer-range-check branches into one lookup.
Found and documented (not yet implemented, see devlog): memory-tag positions
(Mem::&T) never check that the base is actually bounded by Memory.
762 passed / 0 failed / 4 ignored. See devlog/2026-08-18-bitwise-operators-
enum-anchor-generic-trait-bugs.md for full details.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.