feat: try/unwrap payload types, LSP format, macro paste, freestanding runtime
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
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
- Type `?`/`!` as Result/Option Ok payload (not always int); fix unwrap C types - LSP 0.18 document formatting (bux fmt) + VS Code format-on-save - Macro `:type` generics (Array_New<$t>) and operators-only tt paste - Ship runtime_freestanding.c + BUX_RUNTIME=freestanding + smokes/examples
This commit is contained in:
+18
-6
@@ -181,13 +181,25 @@ no-libc freestanding firmware.
|
||||
| Thin runtime (no pthread/OpenSSL) | ✅ | `rt/runtime_minimal.c` |
|
||||
| Static musl / distroless | ✅ | `make test-musl-static`, Dockerfiles |
|
||||
| Linux multi-arch cross | ✅ | aarch64 + riscv64 smokes (SKIP without gcc) |
|
||||
| True freestanding (`-ffreestanding`, no libc) | 🔬 spike | Needs custom alloc, panic, and I/O stubs |
|
||||
| Cortex-M / qemu-system | 🔬 spike | Same; plus linker scripts and startup |
|
||||
| True freestanding (`-ffreestanding`, no libc) | ✅ spike shipped | `rt/runtime_freestanding.c` + `BUX_RUNTIME=freestanding` |
|
||||
| Cortex-M / qemu-system | 🔬 research | Needs linker scripts, startup, board UART — not in tree |
|
||||
|
||||
**Practical path today:** build with `BUX_RUNTIME=minimal --static --target …` for
|
||||
Linux userspace on foreign ISAs; treat bare-metal as a research project that
|
||||
starts from a custom `runtime_freestanding.c` (not shipped) and does **not**
|
||||
import `Std::Net` / `Std::Task` / OpenSSL.
|
||||
**Freestanding runtime** (`rt/runtime_freestanding.c`):
|
||||
|
||||
- No hosted libc: bump heap (default 256 KiB), freestanding string/arith helpers
|
||||
- Weak hooks `bux_fs_write` / `bux_fs_halt` for board BSP or host overrides
|
||||
- Net / Task / TLS / FS return failure stubs
|
||||
- Optional `_start` when compiled with `-DBUX_FS_PROVIDE_START` (nostdlib experiments)
|
||||
|
||||
```bash
|
||||
make test-freestanding # -ffreestanding -c + package build exit 42
|
||||
BUX_RUNTIME=freestanding buxc build .
|
||||
# Still uses host crt0 unless you pass -nostdlib / custom start via BUX_CFLAGS
|
||||
```
|
||||
|
||||
**Practical path for cloud/cross:** `BUX_RUNTIME=minimal --static --target …` for
|
||||
Linux userspace. Use `freestanding` only for no-libc research; do **not** import
|
||||
`Std::Net` / `Std::Task` / OpenSSL on that path.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+26
-1
@@ -1,7 +1,32 @@
|
||||
# Bux — План за подобрения (post-v1.0.0)
|
||||
|
||||
> **Дата:** 2026-07-28
|
||||
> **Статус:** Всички приоритетни задачи изпълнени ✅
|
||||
> **Статус:** Всички приоритетни задачи изпълнени ✅ · follow-up DX/correctness shipped
|
||||
|
||||
---
|
||||
|
||||
## Сесия 4 — Try payload type + LSP formatting (2026-07-28)
|
||||
|
||||
| # | Задача | Файлове |
|
||||
|---|--------|---------|
|
||||
| F.5 | `?` / `!` вече връщат **Ok/Some payload type** (не винаги `int`) | `bootstrap/sema.nim`, `bootstrap/hir_lower.nim` |
|
||||
| F.6 | Example `try_generic` — `Result<String, String>` + `?` | `examples/try_generic.bux` |
|
||||
| D.6 | LSP **v0.18** `textDocument/formatting` (+ range) = `bux fmt` | `tools/lsp_server.nim`, `tools/smoke_lsp_formatting.sh` |
|
||||
| D.7 | VS Code format-on-save default; docs | `vscode/package.json`, `docs/LSP.md` |
|
||||
|
||||
**Verified:** `try_generic` prints `hello` / `empty name`; `try_operator` still OK; formatting smoke PASS.
|
||||
|
||||
## Сесия 5 — Post-1.0 backlog: macros + freestanding (2026-07-28)
|
||||
|
||||
| # | Задача | Файлове |
|
||||
|---|--------|---------|
|
||||
| M.1 | Generics in `$t:type` + `$t` in `Array_New<$t>` | `bootstrap/macroexpand.nim`, `src/macroexpand.bux` |
|
||||
| M.2 | Operators-only `:tt` paste (`$op($a,$b)` + juxta binary split) | `bootstrap/parser.nim`, `bootstrap/macroexpand.nim` |
|
||||
| M.3 | Examples `macro_type_generic`, `macro_op_paste` | `examples/` |
|
||||
| R.1 | `rt/runtime_freestanding.c` + `BUX_RUNTIME=freestanding` | `rt/`, `bootstrap/cli.nim`, `src/cli.bux` |
|
||||
| R.2 | `make test-freestanding` smoke | `tools/smoke_freestanding.sh` |
|
||||
|
||||
**Verified:** both macro examples PASS; freestanding `-ffreestanding -c` + package exit 42.
|
||||
|
||||
---
|
||||
|
||||
|
||||
+23
-7
@@ -1,13 +1,14 @@
|
||||
# Bux Language Server (`bux-lsp`)
|
||||
|
||||
> **Status:** **v0.17.0** — stdio JSON-RPC 2.0 language server
|
||||
> **Status:** **v0.18.0** — stdio JSON-RPC 2.0 language server
|
||||
> **Binary:** `tools/bux-lsp` (`make lsp`)
|
||||
> **Editors:** VS Code extension in [`vscode/`](../vscode/README.md); any LSP client via stdio
|
||||
|
||||
Bux already ships a real Language Server Protocol implementation. It is **not**
|
||||
syntax-only: hover and outline use bootstrap semantic analysis when available,
|
||||
and **error underlines (red squiggles)** come from **in-process** lex / parse / type-check
|
||||
of the **live editor buffer** on every open, edit, and save.
|
||||
**error underlines (red squiggles)** come from **in-process** lex / parse / type-check
|
||||
of the **live editor buffer** on every open, edit, and save, and **Format Document**
|
||||
uses the same indentation engine as `bux fmt`.
|
||||
|
||||
---
|
||||
|
||||
@@ -33,13 +34,15 @@ Protocol framing: standard `Content-Length` headers + JSON-RPC 2.0 body.
|
||||
|
||||
---
|
||||
|
||||
## Capabilities (v0.16)
|
||||
## Capabilities (v0.18)
|
||||
|
||||
| Method | Support | Notes |
|
||||
|--------|---------|--------|
|
||||
| `initialize` / `shutdown` / `exit` | ✅ | `serverInfo`: `bux-lsp` 0.17.0 |
|
||||
| `initialize` / `shutdown` / `exit` | ✅ | `serverInfo`: `bux-lsp` 0.18.0 |
|
||||
| `textDocument/didOpen` / `didChange` / `didSave` | ✅ | Full text sync (`textDocumentSync: 1`) |
|
||||
| `textDocument/publishDiagnostics` | ✅ | **Live underlines** on open/change/save (in-process); optional `buxc` merge on open/save |
|
||||
| `textDocument/formatting` | ✅ | Full document — same rules as `bux fmt` (4-space brace indent) |
|
||||
| `textDocument/rangeFormatting` | ✅ | Applies full-file format (indent depends on whole brace structure) |
|
||||
| `textDocument/completion` | ✅ | Trigger: `.` `:` |
|
||||
| `textDocument/hover` | ✅ | Sema types for globals/stdlib; **scoped locals** + inferred `let` |
|
||||
| `textDocument/definition` | ✅ | Go to definition |
|
||||
@@ -123,15 +126,28 @@ make test-lsp
|
||||
|
||||
---
|
||||
|
||||
## Format Document / format-on-save
|
||||
|
||||
`textDocument/formatting` re-indents the buffer with **4 spaces × brace depth**
|
||||
(identical to `bux fmt` / `bootstrap/fmt.nim`). Idempotent: a clean file yields
|
||||
an empty edit list.
|
||||
|
||||
**VS Code:** the extension defaults `editor.formatOnSave` for `[bux]`. Disable
|
||||
with `"editor.formatOnSave": false` in workspace settings if you prefer manual
|
||||
only. Command palette: **Format Document**.
|
||||
|
||||
```bash
|
||||
make test-lsp # includes tools/smoke_lsp_formatting.sh
|
||||
```
|
||||
|
||||
## Limitations / not yet
|
||||
|
||||
Honest gaps (so Reddit / issue trackers stay accurate):
|
||||
|
||||
- **No format-on-save via LSP** yet (`bux fmt` exists as CLI; not `textDocument/formatting`)
|
||||
- **No semantic tokens** provider (TextMate grammar handles highlighting in VS Code)
|
||||
- **No code actions / lightbulbs** (quick-fixes)
|
||||
- **No inlay hints**
|
||||
- **didChange** uses a fast symbol path; full sema + diagnostics refresh mainly on open/save
|
||||
- **rangeFormatting** reformats the whole file (partial selection cannot get correct indent without full brace context)
|
||||
- Completion is useful but not a full IDE IntelliSense engine
|
||||
- Single-process stdio only (no TCP/socket mode)
|
||||
|
||||
|
||||
+49
-4
@@ -997,6 +997,25 @@ func Compute() -> Result {
|
||||
```
|
||||
|
||||
`?` can be used on `Result` and `Option` types in any expression context.
|
||||
The type of `expr?` is the **Ok / Some payload** (`T` in `Result<T,E>` or
|
||||
`Option<T>`), not always `int`. The enclosing function must return a compatible
|
||||
Result/Option so Err/None can propagate.
|
||||
|
||||
```bux
|
||||
// Generic Result — payload type is String
|
||||
func GetName() -> Result<String, String> {
|
||||
return Result_NewOk<String, String>("bux");
|
||||
}
|
||||
func Run() -> Result<String, String> {
|
||||
let n: String = GetName()?; // n: String
|
||||
return Result_NewOk<String, String>(n);
|
||||
}
|
||||
```
|
||||
|
||||
The postfix unwrap operator `expr!` extracts Ok/Some or panics (and exits) on
|
||||
Err/None; its type is likewise the payload type.
|
||||
|
||||
See also `examples/try_operator.bux` and `examples/try_generic.bux`.
|
||||
|
||||
---
|
||||
|
||||
@@ -1312,13 +1331,32 @@ macro! with_acc {
|
||||
between fragments) matches a **single call-site argument** that is a call
|
||||
expression: `apply_juxta!(Add(2, 5))` → binds `$f=Add`, `$args` = arg-list
|
||||
group, then `$f($args)` flattens to `Add(2, 5)`.
|
||||
- **Type fragments (session 87):**
|
||||
- **Type fragments (session 87+):** named, pointer, and **generic** types
|
||||
(`Array<int>`, `*int`); `$t` substitutes in `sizeof` / cast / let types and
|
||||
monomorph call type args (`Array_New<$t>`).
|
||||
```bux
|
||||
macro! size_of {
|
||||
( $t:type ) => { sizeof($t) as int }
|
||||
}
|
||||
macro! new_array {
|
||||
( $t:type, $cap:expr ) => { Array_New<$t>($cap) }
|
||||
}
|
||||
let n: int = size_of!(int);
|
||||
let p: int = size_of!(*int);
|
||||
let s: int = size_of!(Array<int>);
|
||||
var a: Array<int> = new_array!(int, 4);
|
||||
```
|
||||
- **Operators-only `:tt` paste:**
|
||||
```bux
|
||||
macro! apply_op {
|
||||
( $op:tt, $a:expr, $b:expr ) => { $op($a, $b) }
|
||||
}
|
||||
macro! flip_op {
|
||||
( $a:expr, $op:tt, $b:expr ) => { $op($b, $a) }
|
||||
}
|
||||
let x: int = apply_op!(+, 3, 4); // 7
|
||||
let y: int = apply_op!(*, 6, 7); // 42
|
||||
let z: int = flip_op!(10 - 3); // -7 (juxta binary split)
|
||||
```
|
||||
|
||||
### Invocation
|
||||
@@ -1415,8 +1453,15 @@ Examples: `examples/macro_hygiene.bux`, `examples/macro_unhygienic.bux`.
|
||||
templates (not as a free-standing primary expression).
|
||||
- Raw delimiter-balanced `tt` covers **tuple** `(a, b)` and **slice lit**
|
||||
`[a, b]` groups, plus **juxta call-split** for `$f:ident $args:tt` matching
|
||||
`F(a, b)`. Arbitrary free-form token pastes (operators-only, type-only
|
||||
without AST) remain out of scope.
|
||||
`F(a, b)`.
|
||||
- **Operators-only paste:** bare binary ops as `:tt` (`+`, `*`, `==`, …) and
|
||||
juxta binary split `$a:expr $op:tt $b:expr` on a single binary arg. Template
|
||||
form `$op($a, $b)` rebuilds `a OP b`. See `examples/macro_op_paste.bux`.
|
||||
- **`:type` generics:** `Array<int>`, `*int`, nested type args; `$t` splices
|
||||
into `sizeof($t)`, casts, and `Array_New<$t>(…)`. See
|
||||
`examples/macro_type.bux`, `examples/macro_type_generic.bux`.
|
||||
- Fully free-form token streams (unparsed soup) remain out of scope.
|
||||
|
||||
Examples: `examples/macro_tt.bux`, `examples/macro_tt_raw.bux`,
|
||||
`examples/macro_repeat.bux`, `examples/macro_nested.bux`.
|
||||
`examples/macro_repeat.bux`, `examples/macro_nested.bux`,
|
||||
`examples/macro_type_generic.bux`, `examples/macro_op_paste.bux`.
|
||||
|
||||
+14
-2
@@ -1472,10 +1472,22 @@ bootstrap + **buxc2** `macro_tt_raw` (incl. slice) PASS.
|
||||
5. Tag `v1.0.0` after `make test` gate
|
||||
|
||||
**Post-1.0 backlog (MINOR, not freeze blockers):**
|
||||
- Generics in `:type` (`Array<int>`); operators-only tt paste
|
||||
- `runtime_freestanding.c` + Cortex-M research
|
||||
- ~~Generics in `:type` (`Array<int>`); operators-only tt paste~~ ✅ session 5
|
||||
- ~~`runtime_freestanding.c`~~ ✅ session 5 (Cortex-M / board BSP still research)
|
||||
- LSP / IDE versioning independent of language MAJOR
|
||||
|
||||
### Follow-up (2026-07-28)
|
||||
|
||||
1. **`?` / `!` payload types** — bootstrap no longer hardcodes `int`; Ok/Some type
|
||||
from `Result<T,E>` / enum fields (`bootstrap/sema.nim`, `hir_lower.nim`).
|
||||
2. **Example** `try_generic` — String Result propagation.
|
||||
3. **LSP 0.18** — `textDocument/formatting` (+ range) via `formatSource` / `bux fmt`;
|
||||
VS Code format-on-save default; `tools/smoke_lsp_formatting.sh`.
|
||||
4. **Macros:** generic `:type` + `Array_New<$t>`; operators-only `$op($a,$b)` /
|
||||
juxta binary split (`examples/macro_type_generic`, `macro_op_paste`).
|
||||
5. **Freestanding:** `rt/runtime_freestanding.c`, `BUX_RUNTIME=freestanding`,
|
||||
`make test-freestanding`.
|
||||
|
||||
### Изрично **не** правим
|
||||
|
||||
- Повече Windows examples / Win OpenSSL / Win sockets
|
||||
|
||||
Reference in New Issue
Block a user