feat: lifetime elision, tooling CI, registry, and LSP locals

Ship the QUALITY_PLAN stretch from ownership through ecosystem: C.1
lifetime elision (bootstrap + selfhost), bux fmt/test/doc CI hooks,
stdlib goldens, package registry (bux search/add), and LSP 0.4
position-sensitive locals with inferred let types. Full-tree format
pass plus Map/Set remove double-free fix.
This commit is contained in:
2026-07-19 16:35:08 +03:00
parent 3eb1ad3a82
commit 53b43b0f79
130 changed files with 20494 additions and 16738 deletions
+7
View File
@@ -0,0 +1,7 @@
[Package]
Name = "stdlib_array"
Version = "0.1.0"
Type = "bin"
[Build]
Output = "Bin"
+3
View File
@@ -0,0 +1,3 @@
stdlib_array: ok
PASS:
stdlib_array
+50
View File
@@ -0,0 +1,50 @@
// Stdlib golden: Array helpers + Contains/IndexOf/Extend
import Std::Io::{PrintLine};
import Std::Array::{
Array, Array_New, Array_Push, Array_Pop, Array_Clear, Array_IsEmpty,
Array_First, Array_Last, Array_Cap, Array_Reserve, Array_Len, Array_Get,
Array_Contains, Array_IndexOf, Array_Extend, Array_Free
};
import Std::Test::{
Test_AssertTrue, Test_AssertFalse, Test_AssertEqInt, Test_Pass
};
func Main() -> int {
var arr: Array<int> = Array_New<int>(2);
Array_Reserve<int>(&arr, 8);
Test_AssertTrue(Array_Cap<int>(&arr) >= 8);
Test_AssertTrue(Array_IsEmpty<int>(&arr));
Array_Push<int>(&arr, 10);
Array_Push<int>(&arr, 20);
Array_Push<int>(&arr, 30);
Test_AssertFalse(Array_IsEmpty<int>(&arr));
Test_AssertEqInt(Array_Len<int>(&arr) as int, 3);
Test_AssertEqInt(Array_First<int>(&arr), 10);
Test_AssertEqInt(Array_Last<int>(&arr), 30);
Test_AssertTrue(Array_Contains<int>(&arr, 20));
Test_AssertFalse(Array_Contains<int>(&arr, 99));
Test_AssertEqInt(Array_IndexOf<int>(&arr, 30), 2);
let popped: int = Array_Pop<int>(&arr);
Test_AssertEqInt(popped, 30);
Test_AssertEqInt(Array_Len<int>(&arr) as int, 2);
var extra: Array<int> = Array_New<int>(2);
Array_Push<int>(&extra, 40);
Array_Push<int>(&extra, 50);
Array_Extend<int>(&arr, &extra);
Test_AssertEqInt(Array_Len<int>(&arr) as int, 4);
Test_AssertEqInt(Array_Get<int>(&arr, 3), 50);
Array_Clear<int>(&arr);
Test_AssertTrue(Array_IsEmpty<int>(&arr));
Test_AssertTrue(Array_Cap<int>(&arr) >= 8);
Array_Free<int>(&arr);
Array_Free<int>(&extra);
PrintLine("stdlib_array: ok");
Test_Pass("stdlib_array");
return 0;
}
+7
View File
@@ -0,0 +1,7 @@
[Package]
Name = "stdlib_collections"
Version = "0.1.0"
Type = "bin"
[Build]
Output = "Bin"
@@ -0,0 +1,3 @@
stdlib_collections: ok
PASS:
stdlib_collections
@@ -0,0 +1,67 @@
// Stdlib golden: Map / Set / Result / Option helpers
import Std::Io::{PrintLine};
import Std::Map::{
Map, Map_New, Map_Set, Map_Get, Map_Has, Map_Remove, Map_Clear,
Map_Len, Map_IsEmpty, Map_Free
};
import Std::Set::{
Set, Set_New, Set_Add, Set_Has, Set_Remove, Set_Len, Set_IsEmpty, Set_Free
};
import Std::Result::{
Result, Result_NewOk, Result_NewErr, Result_IsOk, Result_IsErr,
Result_UnwrapOr, Result_Or, Result_UnwrapErr
};
import Std::Option::{
Option, Option_NewSome, Option_NewNone, Option_IsSome, Option_Or, Option_UnwrapOr
};
import Std::String::{String_Eq};
import Std::Test::{
Test_AssertTrue, Test_AssertFalse, Test_AssertEqInt, Test_Pass
};
func Main() -> int {
var m: Map<int, int> = Map_New<int, int>(16);
Map_Set<int, int>(&m, 1, 100);
Map_Set<int, int>(&m, 2, 200);
Map_Set<int, int>(&m, 3, 300);
Test_AssertEqInt(Map_Len<int, int>(&m) as int, 3);
Test_AssertTrue(Map_Has<int, int>(&m, 2));
Test_AssertTrue(Map_Remove<int, int>(&m, 2));
Test_AssertFalse(Map_Has<int, int>(&m, 2));
Test_AssertEqInt(Map_Get<int, int>(&m, 1), 100);
Test_AssertFalse(Map_Remove<int, int>(&m, 99));
Map_Clear<int, int>(&m);
Test_AssertTrue(Map_IsEmpty<int, int>(&m));
Map_Free<int, int>(&m);
var s: Set<int> = Set_New<int>(16);
Set_Add<int>(&s, 10);
Set_Add<int>(&s, 20);
Set_Add<int>(&s, 30);
Test_AssertTrue(Set_Remove<int>(&s, 20));
Test_AssertFalse(Set_Has<int>(&s, 20));
Test_AssertTrue(Set_Has<int>(&s, 10));
Test_AssertEqInt(Set_Len<int>(&s) as int, 2);
Test_AssertFalse(Set_IsEmpty<int>(&s));
Set_Free<int>(&s);
let ok: Result = Result_NewOk(42);
let err: Result = Result_NewErr("boom");
Test_AssertTrue(Result_IsOk(ok));
Test_AssertTrue(Result_IsErr(err));
Test_AssertEqInt(Result_UnwrapOr(err, -1), -1);
let recovered: Result = Result_Or(err, Result_NewOk(7));
Test_AssertEqInt(Result_UnwrapOr(recovered, 0), 7);
Test_AssertTrue(String_Eq(Result_UnwrapErr(err), "boom"));
let some: Option = Option_NewSome(5);
let none: Option = Option_NewNone();
Test_AssertTrue(Option_IsSome(some));
Test_AssertEqInt(Option_UnwrapOr(none, 9), 9);
let filled: Option = Option_Or(none, Option_NewSome(3));
Test_AssertEqInt(Option_UnwrapOr(filled, 0), 3);
PrintLine("stdlib_collections: ok");
Test_Pass("stdlib_collections");
return 0;
}
+103
View File
@@ -0,0 +1,103 @@
#!/usr/bin/env bash
# Golden behavioral tests for stdlib modules.
# Usage: from repo root: tests/stdlib_golden/run.sh [path/to/buxc]
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
BUXC_ARG="${1:-$ROOT/buxc}"
DIR="$(cd "$(dirname "$0")" && pwd)"
# Resolve to absolute path so `cd` into test packages still finds the binary.
if [[ "$BUXC_ARG" = /* ]]; then
BUXC="$BUXC_ARG"
else
BUXC="$(cd "$(dirname "$BUXC_ARG")" && pwd)/$(basename "$BUXC_ARG")"
fi
if [[ ! -x "$BUXC" && ! -f "$BUXC" ]]; then
echo "error: buxc not found at $BUXC (run make build first)"
exit 1
fi
passed=0
failed=0
skipped=0
normalize_out() {
# Drop absolute paths; trim trailing whitespace/blank lines
sed -E \
-e "s|$ROOT|ROOT|g" \
-e "s|$DIR|DIR|g" \
-e 's/[[:space:]]+$//' \
| sed -e :a -e '/^\n*$/{$d;N;ba' -e '}'
}
for case_dir in "$DIR"/*/; do
name="$(basename "$case_dir")"
[[ -f "$case_dir/bux.toml" ]] || continue
[[ -f "$case_dir/src/Main.bux" ]] || continue
if [[ ! -f "$case_dir/expected.out" ]]; then
echo " SKIP $name (no expected.out)"
skipped=$((skipped + 1))
continue
fi
# Build + run; capture stdout+stderr
out=""
if ! out="$(cd "$case_dir" && "$BUXC" run . 2>&1)"; then
echo " FAIL $name (build/run non-zero)"
printf '%s\n' "$out" | head -40
failed=$((failed + 1))
continue
fi
got="$(printf '%s\n' "$out" | normalize_out)"
exp="$(cat "$case_dir/expected.out" | normalize_out)"
# Match on key status lines (tests may also print build noise)
if printf '%s\n' "$got" | grep -Fqx "$(printf '%s' "$exp" | head -1)" 2>/dev/null; then
# Prefer full expected lines all present
all_ok=1
while IFS= read -r line; do
[[ -z "$line" ]] && continue
if ! printf '%s\n' "$got" | grep -Fqx "$line"; then
all_ok=0
break
fi
done <<< "$exp"
if [[ $all_ok -eq 1 ]]; then
echo " PASS $name"
passed=$((passed + 1))
continue
fi
fi
# Fallback: every non-empty expected line appears as substring
all_ok=1
while IFS= read -r line; do
[[ -z "$line" ]] && continue
if ! printf '%s\n' "$got" | grep -Fq "$line"; then
all_ok=0
break
fi
done <<< "$exp"
if [[ $all_ok -eq 1 ]]; then
echo " PASS $name"
passed=$((passed + 1))
else
echo " FAIL $name"
echo "---- expected lines ----"
printf '%s\n' "$exp"
echo "---- got (tail) ----"
printf '%s\n' "$got" | tail -20
echo "--------------"
failed=$((failed + 1))
fi
done
echo "Stdlib golden tests: $passed passed, $failed failed, $skipped skipped"
if [[ $failed -gt 0 ]]; then
exit 1
fi
+7
View File
@@ -0,0 +1,7 @@
[Package]
Name = "stdlib_string"
Version = "0.1.0"
Type = "bin"
[Build]
Output = "Bin"
+3
View File
@@ -0,0 +1,3 @@
stdlib_string: ok
PASS:
stdlib_string
+35
View File
@@ -0,0 +1,35 @@
// Stdlib golden: String_IsEmpty / IsBlank / Repeat / ReplaceAll
import Std::Io::{PrintLine};
import Std::String::{
String_IsEmpty, String_IsBlank, String_Repeat, String_ReplaceAll,
String_Eq, String_Len, String_Contains, String_StartsWith, String_EndsWith
};
import Std::Test::{
Test_AssertTrue, Test_AssertFalse, Test_AssertEqInt, Test_AssertEqString, Test_Pass
};
func Main() -> int {
Test_AssertTrue(String_IsEmpty(""));
Test_AssertFalse(String_IsEmpty("x"));
Test_AssertTrue(String_IsBlank(""));
Test_AssertTrue(String_IsBlank(" \t\n"));
Test_AssertFalse(String_IsBlank(" x "));
Test_AssertEqString(String_Repeat(".", 5), ".....");
Test_AssertEqInt(String_Len(String_Repeat("ab", 3)) as int, 6);
Test_AssertEqString(String_Repeat("x", 0), "");
Test_AssertEqString(String_Repeat("ok", 1), "ok");
let multi: String = String_ReplaceAll("a-b-a-b-a", "a", "X");
Test_AssertEqString(multi, "X-b-X-b-X");
let safe: String = String_ReplaceAll("..", ".", "x.");
Test_AssertEqString(safe, "x.x.");
Test_AssertTrue(String_Contains("hello", "ell"));
Test_AssertTrue(String_StartsWith("hello", "he"));
Test_AssertTrue(String_EndsWith("hello", "lo"));
PrintLine("stdlib_string: ok");
Test_Pass("stdlib_string");
return 0;
}