fix(v1.0.2): Array grow from 0, Map/Set rehash, checked div/mod
ci / build (ubuntu) (push) Has been cancelled
ci / macos smoke (push) Has been cancelled
ci / windows smoke (push) Has been cancelled
selfhost-loop / bootstrap determinism (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 / CI gate (push) Has been cancelled

- Array_Push grows from cap 0 (same min as Insert) to avoid segfault
- Map/StringMap/Set: default min cap 8 and auto-rehash at ~50% load
- Integer / and % emit bux_div_i64 / bux_mod_i64 (panic instead of SIGFPE)
- Bump version to 1.0.2; stdlib golden regressions; fmt clean
This commit is contained in:
2026-07-29 00:03:22 +03:00
parent f21002d258
commit d8c21609fd
16 changed files with 296 additions and 37 deletions
+19
View File
@@ -996,7 +996,24 @@ module CBackend {
// Binary — always parenthesize so C precedence cannot rewrite the AST.
// Without parens, Mul(Add(a,b), c) emits `a + b * c` (= a+(b*c)) instead of (a+b)*c.
// Integer / and % use checked runtime helpers (panic on zero divisor).
if kind == hBinary {
if node.intValue == tkSlash {
StringBuilder_Append(&cbe.sb, "bux_div_i64((int64_t)(");
CBE_EmitExpr(cbe, node.child1);
StringBuilder_Append(&cbe.sb, "), (int64_t)(");
CBE_EmitExpr(cbe, node.child2);
StringBuilder_Append(&cbe.sb, "))");
return;
}
if node.intValue == tkPercent {
StringBuilder_Append(&cbe.sb, "bux_mod_i64((int64_t)(");
CBE_EmitExpr(cbe, node.child1);
StringBuilder_Append(&cbe.sb, "), (int64_t)(");
CBE_EmitExpr(cbe, node.child2);
StringBuilder_Append(&cbe.sb, "))");
return;
}
StringBuilder_Append(&cbe.sb, "(");
CBE_EmitExpr(cbe, node.child1);
StringBuilder_Append(&cbe.sb, " ");
@@ -2108,6 +2125,8 @@ module CBackend {
StringBuilder_Append(&cbe.sb, "#include <string.h>\n");
StringBuilder_Append(&cbe.sb, "#include <stdio.h>\n");
StringBuilder_Append(&cbe.sb, "#include <stdlib.h>\n\n");
StringBuilder_Append(&cbe.sb, "extern int64_t bux_div_i64(int64_t a, int64_t b);\n");
StringBuilder_Append(&cbe.sb, "extern int64_t bux_mod_i64(int64_t a, int64_t b);\n\n");
// Type aliases
StringBuilder_Append(&cbe.sb, "typedef const char* String;\n");
StringBuilder_Append(&cbe.sb, "typedef unsigned char uint8;\n");
+3 -3
View File
@@ -2337,7 +2337,7 @@ func Cli_Run(args: *String, argCount: int) -> int {
}
if argCount < 2 {
PrintLine("Bux Self-Hosting Compiler v1.0.0");
PrintLine("Bux Self-Hosting Compiler v1.0.2");
PrintLine("Usage: buxc <command> [args]");
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>");
@@ -2355,12 +2355,12 @@ func Cli_Run(args: *String, argCount: int) -> int {
let cmd: String = args[1];
if String_Eq(cmd, "version") || String_Eq(cmd, "--version") || String_Eq(cmd, "-v") {
PrintLine("Bux 1.0.0 (self-hosting)");
PrintLine("Bux 1.0.2 (self-hosting)");
return 0;
}
if String_Eq(cmd, "help") || String_Eq(cmd, "--help") || String_Eq(cmd, "-h") {
PrintLine("Bux Self-Hosting Compiler v1.0.0");
PrintLine("Bux Self-Hosting Compiler v1.0.2");
PrintLine("Usage: buxc <command> [args]");
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>");
+1 -1
View File
@@ -2579,7 +2579,7 @@ module HirLower {
}
// Fallback: type annotation on the is-expression operand
if String_Eq(enumName, "") && expr.child1 != null as *Expr &&
expr.child1.refType != null as *TypeExpr {
expr.child1.refType != null as *TypeExpr {
let te: *TypeExpr = Lcx_SubstituteType(ctx, expr.child1.refType);
if te != null as *TypeExpr && !String_Eq(te.typeName, "") {
enumName = te.typeName;
+7 -7
View File
@@ -358,7 +358,7 @@ module Sema {
}
if !foundName {
Sema_EmitError(sema, expr.line, expr.column,
String_Concat("unknown argument name '", String_Concat(checkArg.argName, "'")));
String_Concat("unknown argument name '", String_Concat(checkArg.argName, "'")));
}
}
checkArg = checkArg.next;
@@ -1079,8 +1079,8 @@ module Sema {
// Arity check (runs after Sema_ResolveCallArgs so defaults/named args align)
if callDecl != null as *Decl && expr.callArgCount != callDecl.paramCount && sema.diagCount == diagsBeforeCallArgs {
Sema_EmitError(sema, expr.line, expr.column,
String_Concat("expected ", String_Concat(bux_int_to_str(callDecl.paramCount as int64),
String_Concat(" arguments, got ", bux_int_to_str(expr.callArgCount as int64)))));
String_Concat("expected ", String_Concat(bux_int_to_str(callDecl.paramCount as int64),
String_Concat(" arguments, got ", bux_int_to_str(expr.callArgCount as int64)))));
callDecl = null as *Decl;
}
var argIdx: int = 0;
@@ -1109,9 +1109,9 @@ module Sema {
let wantName: String = Sema_TypeNameForDiag(cp.refParamType, Sema_ResolveType(sema, cp.refParamType));
let gotName: String = Sema_TypeNameForDiag(arg.expr.refType, argKind);
Sema_EmitError(sema, arg.expr.line, arg.expr.column,
String_Concat("argument ", String_Concat(bux_int_to_str((argIdx + 1) as int64),
String_Concat(": expected ", String_Concat(wantName,
String_Concat(", got ", gotName))))));
String_Concat("argument ", String_Concat(bux_int_to_str((argIdx + 1) as int64),
String_Concat(": expected ", String_Concat(wantName,
String_Concat(", got ", gotName))))));
}
}
}
@@ -1565,7 +1565,7 @@ module Sema {
let gotName: String = Sema_TypeNameForDiag(stmt.child1.refType, initType);
let wantName: String = Sema_TypeNameForDiag(stmt.refStmtType, Sema_ResolveType(sema, stmt.refStmtType));
let msg: String = String_Concat("cannot assign ",
String_Concat(gotName, String_Concat(" to ", wantName)));
String_Concat(gotName, String_Concat(" to ", wantName)));
Sema_EmitError(sema, stmt.line, stmt.column, msg);
}
}