release: Bux v1.0.0 language freeze
ci / build (ubuntu) (push) Has been cancelled
ci / unit + fmt (push) Has been cancelled
ci / examples (push) Has been cancelled
ci / goldens + tools (push) Has been cancelled
ci / apps (push) Has been cancelled
ci / selfhost smoke (push) Has been cancelled
ci / macos smoke (push) Has been cancelled
ci / windows smoke (push) Has been cancelled
ci / CI gate (push) Has been cancelled
selfhost-loop / bootstrap determinism (push) Has been cancelled

Bump compiler banners and package version to 1.0.0, activate SEMVER policy,
and add RELEASE_v1.0.0 notes. Fix closure auto-Drop leaking outer Array
drops into nested capture bodies (iter_hof). Fmt-clean examples/src for CI.
This commit is contained in:
2026-07-27 21:49:12 +03:00
parent d60ce2bc3f
commit a23860be3e
16 changed files with 384 additions and 308 deletions
+2 -1
View File
@@ -2,13 +2,14 @@
![Bux Language](bux-lang-01.jpeg) ![Bux Language](bux-lang-01.jpeg)
> **Status:** v0.5.x — Bootstrap (`buxc`, Nim) and self-hosted (`buxc2`, Bux) both compile `.bux` → C → native binary. > **Status:** **v1.0.0** — language freeze. Bootstrap (`buxc`, Nim) and self-hosted (`buxc2`, Bux) both compile `.bux` → C → native binary.
> **Selfhost loop:** deterministic C codegen + ELF verified. > **Selfhost loop:** deterministic C codegen + ELF verified.
> **Gradual Ownership:** `@[Checked]` borrow checker, `@[Release]` zero-cost mode, `borrow &mut` expressions. > **Gradual Ownership:** `@[Checked]` borrow checker, `@[Release]` zero-cost mode, `borrow &mut` expressions.
> **Closures:** multi-instance capturing closures via fat function pointers (`BuxFn { code, env }`) in both compilers. > **Closures:** multi-instance capturing closures via fat function pointers (`BuxFn { code, env }`) in both compilers.
> **Tuples:** `(T, U)` types and `.0`/`.1` field access (bootstrap + selfhost). > **Tuples:** `(T, U)` types and `.0`/`.1` field access (bootstrap + selfhost).
> **Green Threads:** M:N scheduler with channels (Go-style goroutines without GC). > **Green Threads:** M:N scheduler with channels (Go-style goroutines without GC).
> **Examples:** 40+ programs pass (`make test-examples`). Apps: `boko-framework`, `jwt-pitbul`, `nexus`, `simpledb`. > **Examples:** 40+ programs pass (`make test-examples`). Apps: `boko-framework`, `jwt-pitbul`, `nexus`, `simpledb`.
> **Semver:** after 1.0, breaking changes require MAJOR (`docs/SEMVER.md`).
Bux is a fast, compiled, strongly-typed systems programming language. Features a C backend for native code generation, raw multi-line strings, gradual ownership (opt-in borrow checking), multi-instance closures, async/await, generics, algebraic enums, and a package manager. Bux is a fast, compiled, strongly-typed systems programming language. Features a C backend for native code generation, raw multi-line strings, gradual ownership (opt-in borrow checking), multi-instance closures, async/await, generics, algebraic enums, and a package manager.
+1 -1
View File
@@ -1345,7 +1345,7 @@ proc cmdDoc*(args: seq[string], opts: GlobalOptions): int =
return 0 return 0
proc cmdVersion*(args: seq[string], opts: GlobalOptions): int = proc cmdVersion*(args: seq[string], opts: GlobalOptions): int =
echo "bux 0.1.0 (bootstrap)" echo "bux 1.0.0 (bootstrap)"
return 0 return 0
proc runCli*(args: seq[string]): int = proc runCli*(args: seq[string]): int =
+20 -1
View File
@@ -2734,18 +2734,37 @@ proc lowerClosureFunc(ctx: var LowerCtx, expr: Expr): HirFunc =
f.retType = ctx.resolveTypeExpr(expr.exprClosureReturnType) f.retType = ctx.resolveTypeExpr(expr.exprClosureReturnType)
else: else:
f.retType = makeVoid() f.retType = makeVoid()
# Body with closure rewriting # Body with closure rewriting — isolate Drop/defer stack like lowerFunc.
# Nested closure lowering previously kept the outer function's deferStmts,
# so `return` inside a capture emitted Array_Drop for outer locals (session 88).
let savedDepth = ctx.closureDepth let savedDepth = ctx.closureDepth
let savedExpr = ctx.currentClosureExpr let savedExpr = ctx.currentClosureExpr
let savedEnv = ctx.envInstanceName let savedEnv = ctx.envInstanceName
let oldDefers = ctx.deferStmts
let oldMovedOut = ctx.movedOutLocals
let oldPartialMoved = ctx.partialMovedFields
ctx.deferStmts = @[]
ctx.movedOutLocals = initHashSet[string]()
ctx.partialMovedFields = initTable[string, HashSet[string]]()
ctx.closureDepth = ctx.closureDepth + 1 ctx.closureDepth = ctx.closureDepth + 1
ctx.currentClosureExpr = expr ctx.currentClosureExpr = expr
ctx.envInstanceName = f.envInstanceName ctx.envInstanceName = f.envInstanceName
if expr.exprClosureBody != nil: if expr.exprClosureBody != nil:
f.body = ctx.lowerBlock(expr.exprClosureBody) f.body = ctx.lowerBlock(expr.exprClosureBody)
# Emit pending auto-drops for locals allocated *inside* the closure body only
if ctx.deferStmts.len > 0 and f.body != nil and f.body.kind == hBlock:
var lastIsReturn = false
if f.body.blockStmts.len > 0 and f.body.blockStmts[^1].kind == hReturn:
lastIsReturn = true
if not lastIsReturn:
for i in countdown(ctx.deferStmts.len - 1, 0):
ctx.emitDropOrPartial(f.body.blockStmts, ctx.deferStmts[i], "")
ctx.closureDepth = savedDepth ctx.closureDepth = savedDepth
ctx.currentClosureExpr = savedExpr ctx.currentClosureExpr = savedExpr
ctx.envInstanceName = savedEnv ctx.envInstanceName = savedEnv
ctx.deferStmts = oldDefers
ctx.movedOutLocals = oldMovedOut
ctx.partialMovedFields = oldPartialMoved
ctx.extraFuncs.add(f) ctx.extraFuncs.add(f)
return f return f
+1 -1
View File
@@ -1,6 +1,6 @@
[Package] [Package]
Name = "buxc" Name = "buxc"
Version = "0.3.0" Version = "1.0.0"
Type = "bin" Type = "bin"
[Build] [Build]
+16 -18
View File
@@ -1,10 +1,11 @@
# Bux — План към „добър“ език (v0.5 → v1.0) # Bux — План към „добър“ език (v0.5 → **v1.0.0** ✅)
> **Дата:** 2026-07-23 > **Дата:** 2026-07-27
> **Текущо:** v0.5.x — `:type` macros + Array_Reverse (session 87) > **Текущо:** **v1.0.0** — language freeze (session 88 / release)
> **Цел:** Език, с който се пишат реални проекти комфортно, безопасно (по избор) и с надежден toolchain. > **Цел:** Език, с който се пишат реални проекти комфортно, безопасно (по избор) и с надежден toolchain.
> **Платформен фокус:** **Linux** (primary) · **cloud-native** (servers, containers, HTTP) · **embedded** (cross, freestanding-ish, CTFE). > **Платформен фокус:** **Linux** (primary) · **cloud-native** (servers, containers, HTTP) · **embedded** (cross, freestanding-ish, CTFE).
> **Не-цел:** MS Windows като product platform (исторически CI/hello smoke остават; няма roadmap investment). > **Не-цел:** MS Windows като product platform (исторически CI/hello smoke остават; няма roadmap investment).
> **Release notes:** `docs/RELEASE_v1.0.0.md` · **Semver:** `docs/SEMVER.md` (active).
--- ---
@@ -113,7 +114,7 @@ A (stdlib ergonomics) → B (compiler holes) → C (ownership depth)
--- ---
## Acceptance criteria за „добър v1.0“ ## Acceptance criteria за „добър v1.0“ — **met; tagged v1.0.0**
- [x] Всички examples + apps + selfhost smoke на CI (`make test` via `.github/workflows/ci.yml`); selfhost-loop optional - [x] Всички examples + apps + selfhost smoke на CI (`make test` via `.github/workflows/ci.yml`); selfhost-loop optional
- [x] Array/Map/String/Test API покрива 90% от ежедневните нужди (+ Insert/Remove/Clone/case/GetOr) - [x] Array/Map/String/Test API покрива 90% от ежедневните нужди (+ Insert/Remove/Clone/case/GetOr)
@@ -121,6 +122,7 @@ A (stdlib ergonomics) → B (compiler holes) → C (ownership depth)
- [x] `bux test` + `bux fmt` + `bux check` са default developer loop (`--filter` / `--check` shipped) - [x] `bux test` + `bux fmt` + `bux check` са default developer loop (`--filter` / `--check` shipped)
- [x] LanguageRef синхронизиран с компилатора (incl. C.1 elision) - [x] LanguageRef синхронизиран с компилатора (incl. C.1 elision)
- [x] Поне един външен/temp проект build-ва с registry dep (`tools/smoke_registry.sh` + HTTP) - [x] Поне един външен/temp проект build-ва с registry dep (`tools/smoke_registry.sh` + HTTP)
- [x] Version strings + SEMVER active + `docs/RELEASE_v1.0.0.md` (session 88)
--- ---
@@ -1461,22 +1463,18 @@ bootstrap + **buxc2** `macro_tt_raw` (incl. slice) PASS.
--- ---
## Следващи стъпки ## Сесия 88 (v1.0.0 language freeze)
### P0 — Compiler / language 1. Version banners: bootstrap + selfhost CLI → **1.0.0**; root `bux.toml` → 1.0.0
2. `docs/SEMVER.md` — **Active** (post-1.0 MAJOR = breaking)
3. `docs/RELEASE_v1.0.0.md` — freeze notes + verify commands
4. README / QUALITY_PLAN / ROADMAP status → v1.0.0
5. Tag `v1.0.0` after `make test` gate
1. ~~… through session 86~~ ✅ **Post-1.0 backlog (MINOR, not freeze blockers):**
2. ~~**`:type` macro fragments**~~ ✅ session 87 - Generics in `:type` (`Array<int>`); operators-only tt paste
3. Optional: richer free-form (operators-only tt); generics in `:type` (`Array<int>`) - `runtime_freestanding.c` + Cortex-M research
- LSP / IDE versioning independent of language MAJOR
### P1 — Linux / cloud-native
4. ~~(sessions 7581)~~ ✅
### P2 — Embedded / cross
5. ~~riscv64 smoke + freestanding notes~~ ✅ session 85
6. Optional: real `runtime_freestanding.c` + Cortex-M qemu — not v1.0
### Изрично **не** правим ### Изрично **не** правим
+55
View File
@@ -0,0 +1,55 @@
# Bux v1.0.0 — Language Freeze
**Date:** 2026-07-27
**Tag:** `v1.0.0`
## What 1.0 means
- **Language freeze** for public surface: syntax, stdlib APIs, and CLI that
scripts depend on follow `docs/SEMVER.md`.
- **Normative spec:** `docs/LanguageRef.md`.
- **Compilers:** bootstrap (`buxc`, Nim) and selfhost (`buxc2`, Bux) both target
the same language for the shipped feature set.
- **Platform focus:** Linux primary; cloud/containers; cross/static/minimal
runtime. Windows is not a product platform.
## Shipped surface (summary)
| Area | Highlights |
|------|------------|
| Frontend | Pratt parser, recovery, macros (`macro!`, fragments, juxta/`tt`/`type`) |
| Types | Generics (mono), tuples, fat `func` ABI, algebraic enums |
| Ownership | `@[Checked]`, `@[Release]`, Drop/RAII, field-move + remaining Drop |
| Concurrency | M:N tasks, channels, async |
| Stdlib | Array/Map/Set/String/Iter HOF, Net/TLS, registry, Test |
| Tooling | `fmt`, `test`, `doc`, `check`, LSP (separate versioning), DWARF `#line` |
| Ecosystem | path/git/HTTP registry, lock + `--locked`, 4 apps, benches |
## Explicitly *not* 1.0 blockers
- True freestanding / bare-metal (`runtime_freestanding.c`, Cortex-M)
- Operators-only token paste; full `Array<int>` in `:type` fragments
- Windows product investment
- LLVM / non-C backends
## Upgrade notes from 0.5.x
No mandatory source migration for projects that already build on late 0.5.x.
New package scaffolds still default to package version `0.1.0` (package semver,
not language version).
### Fix included in 1.0.0
- **Closure Drop isolation:** lowering a nested closure no longer emits
outer-function `Array_Drop` / auto-Drop on the closures return path
(broke `iter_hof` and any capturing HOF over droppable locals).
## Verify
```bash
make build
./buxc --version # bux 1.0.0 (bootstrap)
make test # full gate
make selfhost # buxc2
# optional: make selfhost-loop
```
+2 -2
View File
@@ -1,7 +1,7 @@
# Bux Language Roadmap — New Constructs # Bux Language Roadmap — New Constructs
> **Updated:** 2026-07-15 | **Status:** In Progress > **Updated:** 2026-07-27 | **Status:** ✅ Constructs for v1.0 shipped (language freeze)
> Recent: multi-instance closures (fat `BuxFn`), tuples in selfhost, Iter map/filter/fold, Rust-style diagnostics. > Recent: macros (`tt`/`type`/juxta), stdlib daily APIs, Linux/riscv smoke; see `docs/RELEASE_v1.0.0.md`.
This document tracks planned language constructs beyond Phase 8 strategy. This document tracks planned language constructs beyond Phase 8 strategy.
+18 -15
View File
@@ -1,6 +1,6 @@
# Bux Semantic Versioning Policy # Bux Semantic Versioning Policy
> Status: Draft for v0.x → v1.0 freeze (E.3) > Status: **Active** as of **v1.0.0** (language freeze)
Bux follows [Semantic Versioning 2.0.0](https://semver.org/) with the Bux follows [Semantic Versioning 2.0.0](https://semver.org/) with the
clarifications below. clarifications below.
@@ -19,18 +19,18 @@ MAJOR.MINOR.PATCH[-prerelease]
| **MINOR** | Backward-compatible features | | **MINOR** | Backward-compatible features |
| **PATCH** | Backward-compatible bug fixes | | **PATCH** | Backward-compatible bug fixes |
During **0.x** (pre-1.0): ### Before 1.0 (historical 0.x)
- `0.MINOR.PATCH` MINOR may still introduce breaking changes (documented in During **0.x**, MINOR could still introduce breaking changes (documented in
the release notes and `MIGRATION_*.sh` when needed). release notes and `MIGRATION_*.sh` when needed).
- Prefer deprecation warnings for at least one MINOR before removal when
practical.
After **1.0.0** (language freeze): ### From **1.0.0** (language freeze)
- Breaking changes require a MAJOR bump and a migration guide. - Breaking changes require a **MAJOR** bump and a migration guide.
- The Language Reference is the normative spec; compiler bugs that contradict - The **Language Reference** (`docs/LanguageRef.md`) is the normative spec;
the ref are fixed without a MAJOR bump. compiler bugs that contradict the ref are fixed without a MAJOR bump.
- New diagnostics and stricter `@[Checked]` are allowed in MINOR when
documented; prefer gating with attributes when practical.
--- ---
@@ -48,12 +48,14 @@ After **1.0.0** (language freeze):
(prefer contextual keywords) (prefer contextual keywords)
- New diagnostics / stricter `@[Checked]` (document; may be gated) - New diagnostics / stricter `@[Checked]` (document; may be gated)
- Formatter whitespace-only changes - Formatter whitespace-only changes
- New optional CLI flags and commands
--- ---
## Package versions (registry) ## Package versions (registry)
Registry packages use the same MAJOR.MINOR.PATCH scheme. Registry packages use the same MAJOR.MINOR.PATCH scheme (independent of the
compiler version).
`bux add foo` / `bux add foo 0.1` resolution: `bux add foo` / `bux add foo 0.1` resolution:
@@ -70,7 +72,8 @@ Lockfiles pin the **resolved** version and source path/URL.
## Release checklist (maintainers) ## Release checklist (maintainers)
1. Update `docs/LanguageRef.md` if behaviour changed 1. Update `docs/LanguageRef.md` if behaviour changed
2. Update `docs/QUALITY_PLAN.md` / changelog notes 2. Update `docs/QUALITY_PLAN.md` / release notes
3. Run `make test` (includes `fmt-check`, examples, goldens) 3. Bump compiler version strings (`bootstrap/cli.nim`, `src/cli.bux`, root `bux.toml`)
4. Run `make selfhost-loop` 4. Run `make test` (includes `fmt-check`, examples, goldens)
5. Tag `vMAJOR.MINOR.PATCH` 5. Run `make selfhost` and preferably `make selfhost-loop`
6. Tag `vMAJOR.MINOR.PATCH` and push the tag
+3 -3
View File
@@ -2254,7 +2254,7 @@ func Cli_Run(args: *String, argCount: int) -> int {
} }
if argCount < 2 { if argCount < 2 {
PrintLine("Bux Self-Hosting Compiler v0.2.0"); PrintLine("Bux Self-Hosting Compiler v1.0.0");
PrintLine("Usage: buxc <command> [args]"); PrintLine("Usage: buxc <command> [args]");
PrintLine("Commands: build, check, new, init, add, remove, fetch, install, search, fmt, doc, test, run, project, help, version"); PrintLine("Commands: build, check, new, init, add, remove, fetch, install, search, fmt, doc, test, run, project, help, version");
PrintLine(" test --filter <name> Only run tests/*.bux whose name contains <name>"); PrintLine(" test --filter <name> Only run tests/*.bux whose name contains <name>");
@@ -2272,12 +2272,12 @@ func Cli_Run(args: *String, argCount: int) -> int {
let cmd: String = args[1]; let cmd: String = args[1];
if String_Eq(cmd, "version") || String_Eq(cmd, "--version") || String_Eq(cmd, "-v") { if String_Eq(cmd, "version") || String_Eq(cmd, "--version") || String_Eq(cmd, "-v") {
PrintLine("Bux 0.2.0 (self-hosting bootstrap)"); PrintLine("Bux 1.0.0 (self-hosting)");
return 0; return 0;
} }
if String_Eq(cmd, "help") || String_Eq(cmd, "--help") || String_Eq(cmd, "-h") { if String_Eq(cmd, "help") || String_Eq(cmd, "--help") || String_Eq(cmd, "-h") {
PrintLine("Bux Self-Hosting Compiler v0.2.0"); PrintLine("Bux Self-Hosting Compiler v1.0.0");
PrintLine("Usage: buxc <command> [args]"); PrintLine("Usage: buxc <command> [args]");
PrintLine("Commands: build, check, new, init, add, remove, fetch, install, search, fmt, doc, test, run, project, help, version"); PrintLine("Commands: build, check, new, init, add, remove, fetch, install, search, fmt, doc, test, run, project, help, version");
PrintLine(" test --filter <name> Only run tests/*.bux whose name contains <name>"); PrintLine(" test --filter <name> Only run tests/*.bux whose name contains <name>");
+16 -16
View File
@@ -152,9 +152,9 @@ module Registry {
return p; return p;
} }
return bux_path_join(indexDir, p); return bux_path_join(indexDir, p);
} }
func Reg_SetPkg(reg: *Registry, idx: int, pkg: RegistryPackage) { func Reg_SetPkg(reg: *Registry, idx: int, pkg: RegistryPackage) {
if idx == 0 { reg.p0 = pkg; } if idx == 0 { reg.p0 = pkg; }
else if idx == 1 { reg.p1 = pkg; } else if idx == 1 { reg.p1 = pkg; }
else if idx == 2 { reg.p2 = pkg; } else if idx == 2 { reg.p2 = pkg; }
@@ -171,9 +171,9 @@ module Registry {
else if idx == 13 { reg.p13 = pkg; } else if idx == 13 { reg.p13 = pkg; }
else if idx == 14 { reg.p14 = pkg; } else if idx == 14 { reg.p14 = pkg; }
else if idx == 15 { reg.p15 = pkg; } else if idx == 15 { reg.p15 = pkg; }
} }
func Reg_GetPkg(reg: Registry, idx: int) -> RegistryPackage { func Reg_GetPkg(reg: Registry, idx: int) -> RegistryPackage {
if idx == 0 { return reg.p0; } if idx == 0 { return reg.p0; }
if idx == 1 { return reg.p1; } if idx == 1 { return reg.p1; }
if idx == 2 { return reg.p2; } if idx == 2 { return reg.p2; }
@@ -190,9 +190,9 @@ module Registry {
if idx == 13 { return reg.p13; } if idx == 13 { return reg.p13; }
if idx == 14 { return reg.p14; } if idx == 14 { return reg.p14; }
return reg.p15; return reg.p15;
} }
func Reg_ParseContent(content: String, indexPath: String) -> Registry { func Reg_ParseContent(content: String, indexPath: String) -> Registry {
var reg: Registry; var reg: Registry;
reg.path = indexPath; reg.path = indexPath;
reg.sourceUrl = ""; reg.sourceUrl = "";
@@ -252,9 +252,9 @@ module Registry {
i = i + 1; i = i + 1;
} }
return reg; return reg;
} }
func Reg_FindIndex() -> Registry { func Reg_FindIndex() -> Registry {
var reg: Registry; var reg: Registry;
reg.path = ""; reg.path = "";
reg.sourceUrl = ""; reg.sourceUrl = "";
@@ -314,15 +314,15 @@ module Registry {
return reg; return reg;
} }
return reg; return reg;
} }
func Reg_VersionOk(have: String, req: String) -> bool { func Reg_VersionOk(have: String, req: String) -> bool {
if String_Eq(req, "") || String_Eq(req, "*") { return true; } if String_Eq(req, "") || String_Eq(req, "*") { return true; }
return String_Eq(have, req); return String_Eq(have, req);
} }
// Lookup by name; versionReq "*" = last matching entry (highest listed last). // Lookup by name; versionReq "*" = last matching entry (highest listed last).
func Reg_Lookup(reg: Registry, name: String, versionReq: String) -> RegistryPackage { func Reg_Lookup(reg: Registry, name: String, versionReq: String) -> RegistryPackage {
var found: RegistryPackage; var found: RegistryPackage;
found.name = ""; found.name = "";
var i: int = 0; var i: int = 0;
@@ -334,9 +334,9 @@ module Registry {
i = i + 1; i = i + 1;
} }
return found; return found;
} }
func Reg_Search(reg: Registry, query: String) -> int { func Reg_Search(reg: Registry, query: String) -> int {
// print hits; return count // print hits; return count
var hits: int = 0; var hits: int = 0;
// Dedupe by name: keep last version // Dedupe by name: keep last version
@@ -376,5 +376,5 @@ module Registry {
i = i + 1; i = i + 1;
} }
return hits; return hits;
} }
} }