ci: selfhost smoke for move_field and multi-file #line
Add tools/smoke_selfhost.sh and make test-selfhost-smoke (via make selfhost) to the default make test suite, covering field-move ownership and per-file #line paths under buxc2.
This commit is contained in:
@@ -5,7 +5,7 @@ BUILD_DIR := build
|
||||
|
||||
EXAMPLES := hello fibonacci factorial structs enums methods algebraic_enums generics generics_struct generic_infer generic_infer2 extend_generic pattern_matching strings strings2 map result_option try_operator ownership ownership_checked drop_early_return lifetime_elision ctfe async concurrency os_time process json iter trait_bounds channel sync jwt stdlib_ergonomics tuples func_ptr map_remove array_iter_extra string_extra multi_closure iter_hof closure_control match_let string_interp iter_generic generic_infer_hof struct_tuple_pat match_block nested_patterns match_guards pattern_shadow move_field
|
||||
|
||||
.PHONY: all build dev debug test clean clean-all test-examples selfhost test-golden test-errors test-stdlib selfhost-loop lsp fmt-check docs bench test-apps test-dwarf
|
||||
.PHONY: all build dev debug test clean clean-all test-examples selfhost test-golden test-errors test-stdlib selfhost-loop lsp fmt-check docs bench test-apps test-dwarf test-selfhost-smoke
|
||||
|
||||
all: build
|
||||
|
||||
@@ -19,7 +19,7 @@ dev:
|
||||
debug: dev
|
||||
@echo "Debug binary: buxc_debug"
|
||||
|
||||
test: build fmt-check test-examples test-errors test-stdlib test-registry test-dwarf test-apps
|
||||
test: build fmt-check test-examples test-errors test-stdlib test-registry test-dwarf test-apps test-selfhost-smoke
|
||||
@echo "Running lexer tests..."
|
||||
$(NIM) c -r tests/lexer_test.nim
|
||||
@echo "Running parser tests..."
|
||||
@@ -234,3 +234,10 @@ test-dwarf: build
|
||||
@echo "=== DWARF / #line smoke (E.4) ==="
|
||||
@chmod +x tools/smoke_dwarf.sh
|
||||
@tools/smoke_dwarf.sh
|
||||
|
||||
# Selfhost (buxc2): move_field ownership + multi-file #line (session 41/42)
|
||||
.PHONY: test-selfhost-smoke
|
||||
test-selfhost-smoke: selfhost
|
||||
@echo "=== Selfhost smoke (move_field + multi-file #line) ==="
|
||||
@chmod +x tools/smoke_selfhost.sh
|
||||
@tools/smoke_selfhost.sh
|
||||
|
||||
@@ -138,7 +138,8 @@ make test-registry # package registry (local + HTTP index)
|
||||
make test-apps # showcase apps build + simpledb/jwt CLI smoke (in `make test`)
|
||||
make test-dwarf # #line maps + .debug_info + --release (in `make test`)
|
||||
make test-registry # package registry local + HTTP (in `make test`)
|
||||
make test-lsp # hover + references/rename smokes
|
||||
make test-selfhost-smoke # buxc2: move_field + multi-file #line (in `make test`)
|
||||
make test-lsp # hover + references/rename + call hierarchy
|
||||
make bench # micro-benchmarks (Bux + C/Nim/Zig twins)
|
||||
make bench-nexus # wrk throughput vs apps/nexus /api/health
|
||||
```
|
||||
|
||||
+31
-5
@@ -1,7 +1,7 @@
|
||||
# Bux — План към „добър“ език (v0.5 → v1.0)
|
||||
|
||||
> **Дата:** 2026-07-19
|
||||
> **Текущо:** v0.5.x — field-move, **multi-file #line**, Nexus KA, LSP 0.8 call hierarchy
|
||||
> **Текущо:** v0.5.x — multi-file #line, **selfhost CI smoke**, LSP 0.8, Nexus KA
|
||||
> **Цел:** Език, с който се пишат реални проекти комфортно, безопасно (по избор) и с надежден toolchain.
|
||||
|
||||
---
|
||||
@@ -656,9 +656,35 @@ A (stdlib ergonomics) → B (compiler holes) → C (ownership depth)
|
||||
|
||||
---
|
||||
|
||||
## Сесия 41 (selfhost multi-file #line paths)
|
||||
|
||||
1. **`Decl.sourceFile`** stamped when parsing/merging each `.bux` file
|
||||
(`Cli_StampSourceFile` / `Cli_MergeFileInto` / project `src/` loop)
|
||||
2. **`HirFunc.sourceFile`** copied in `Lcx_LowerFunc`
|
||||
3. **C backend:** before each function, set `currentFile` from `sourceFile`
|
||||
and emit `#line 1 "path"` + per-stmt `#line N "path"`
|
||||
4. **No env required** — stdlib + user multi-file paths appear automatically
|
||||
(`lib/Fs.bux`, `./src/Util.bux`, `./src/Main.bux`, …)
|
||||
5. Overrides: `BUX_DEBUG_FILE` (force one path), `BUX_NO_LINE=1` (disable)
|
||||
6. Verified: multi-file project runs; `#line` paths distinct per source
|
||||
|
||||
---
|
||||
|
||||
## Сесия 42 (selfhost CI smoke)
|
||||
|
||||
1. **`tools/smoke_selfhost.sh`:**
|
||||
- build/use `buxc2` (`make selfhost`)
|
||||
- **move_field**: run PASS + no `Array_Drop(&items)` after field move
|
||||
- **multi-file #line**: Util.bux + Main.bux + `lib/*.bux` paths in `main.c`
|
||||
2. **`make test-selfhost-smoke`** depends on `selfhost`
|
||||
3. Wired into default **`make test`**
|
||||
4. Verified: smoke script PASS
|
||||
|
||||
---
|
||||
|
||||
## Следващи стъпки
|
||||
|
||||
1. Selfhost multi-file `#line` paths without BUX_DEBUG_FILE
|
||||
2. Wire selfhost smoke for move_field into CI
|
||||
3. Method call hierarchy (receiver methods / interface dispatch)
|
||||
4. Rename of method receivers / qualified module paths (edge cases)
|
||||
1. Method call hierarchy (receiver methods / interface dispatch)
|
||||
2. Rename of method receivers / qualified module paths (edge cases)
|
||||
3. HirNode-level file for statements spanning multiple files (rare)
|
||||
4. Optional: selfhost-loop as optional CI job (slow)
|
||||
|
||||
Executable
+111
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env bash
|
||||
# Smoke: selfhost compiler (buxc2) — move_field ownership + multi-file #line
|
||||
set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
BUXC2="$ROOT/build/selfhost/build/buxc2"
|
||||
export BUX_STDLIB="$ROOT/lib"
|
||||
unset BUX_DEBUG_FILE || true
|
||||
unset BUX_NO_LINE || true
|
||||
|
||||
if [[ ! -x "$BUXC2" ]]; then
|
||||
echo "=== building selfhost (buxc2) ==="
|
||||
(cd "$ROOT" && make selfhost)
|
||||
fi
|
||||
if [[ ! -x "$BUXC2" ]]; then
|
||||
echo "error: buxc2 not found at $BUXC2" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TMP=$(mktemp -d)
|
||||
trap 'rm -rf "$TMP"' EXIT
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 1) move_field — Array moved into struct must not UAF; program runs
|
||||
# ---------------------------------------------------------------------------
|
||||
echo "=== selfhost: move_field ==="
|
||||
MF="$TMP/move_field"
|
||||
mkdir -p "$MF/src"
|
||||
cp -a "$ROOT/rt" "$MF/"
|
||||
cat > "$MF/bux.toml" <<'EOF'
|
||||
[Package]
|
||||
Name = "move_field"
|
||||
Version = "0.1.0"
|
||||
Type = "bin"
|
||||
|
||||
[Build]
|
||||
Output = "Bin"
|
||||
EOF
|
||||
cp "$ROOT/examples/move_field.bux" "$MF/src/Main.bux"
|
||||
|
||||
(cd "$MF" && "$BUXC2" project .)
|
||||
out=$("$MF/build/move_field")
|
||||
echo "$out" | tee "$TMP/mf.out"
|
||||
grep -q 'sum=30' "$TMP/mf.out"
|
||||
grep -q 'PASS' "$TMP/mf.out" || grep -q 'move_field' "$TMP/mf.out"
|
||||
# No Drop of moved local in MakeBox
|
||||
if grep -A20 'MakeBox' "$MF/build/main.c" | grep -q 'Array_Drop_int(&items)'; then
|
||||
echo "error: MakeBox still drops moved 'items'" >&2
|
||||
grep -n 'MakeBox\|Array_Drop_int' "$MF/build/main.c" | head -30
|
||||
exit 1
|
||||
fi
|
||||
echo " move_field: PASS (run + no Drop of moved Array)"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 2) multi-file #line — Util.bux + Main.bux + stdlib paths, no BUX_DEBUG_FILE
|
||||
# ---------------------------------------------------------------------------
|
||||
echo "=== selfhost: multi-file #line ==="
|
||||
MF2="$TMP/mfline"
|
||||
mkdir -p "$MF2/src"
|
||||
cp -a "$ROOT/rt" "$MF2/"
|
||||
cat > "$MF2/bux.toml" <<'EOF'
|
||||
[Package]
|
||||
Name = "mfline"
|
||||
Version = "0.1.0"
|
||||
Type = "bin"
|
||||
|
||||
[Build]
|
||||
Output = "Bin"
|
||||
EOF
|
||||
cat > "$MF2/src/Util.bux" <<'EOF'
|
||||
module Util {
|
||||
pub func Util_Double(n: int) -> int {
|
||||
return n * 2;
|
||||
}
|
||||
}
|
||||
EOF
|
||||
cat > "$MF2/src/Main.bux" <<'EOF'
|
||||
import Std::Io::{PrintLine};
|
||||
import Std::String::{String_FromInt};
|
||||
|
||||
func Main() -> int {
|
||||
let v: int = Util_Double(21);
|
||||
PrintLine(String_FromInt(v as int64));
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
|
||||
(cd "$MF2" && "$BUXC2" project .)
|
||||
run_out=$("$MF2/build/mfline")
|
||||
echo "$run_out" | tee "$TMP/mf2.out"
|
||||
grep -q '42' "$TMP/mf2.out"
|
||||
|
||||
MAIN_C="$MF2/build/main.c"
|
||||
test -f "$MAIN_C"
|
||||
# Distinct source paths in #line
|
||||
if ! grep -qE '#line [0-9]+ ".*Util\.bux"' "$MAIN_C"; then
|
||||
echo "error: no #line for Util.bux" >&2
|
||||
grep -E '^#line ' "$MAIN_C" | tail -20
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -qE '#line [0-9]+ ".*Main\.bux"' "$MAIN_C"; then
|
||||
echo "error: no #line for Main.bux" >&2
|
||||
exit 1
|
||||
fi
|
||||
# Stdlib also stamped
|
||||
if ! grep -qE '#line [0-9]+ ".*lib/.*\.bux"' "$MAIN_C"; then
|
||||
echo "error: no #line for stdlib lib/*.bux" >&2
|
||||
exit 1
|
||||
fi
|
||||
echo " multi-file #line: PASS (Util + Main + lib)"
|
||||
|
||||
echo "PASS: selfhost smoke (move_field + multi-file #line)"
|
||||
Reference in New Issue
Block a user