fix: selfhost CLI run command, lexer char literal, parser test path, calloc in runtime
- Fix lexer unterminated char error test (was treating 'a as lifetime) - Fix parser test sample.bux path for root-dir execution - Add bux_system() to runtime.c and run command to selfhost CLI - Switch bux_alloc from malloc to calloc for zero-init - Fix module flattening in Cli_Check/Cli_Compile to scan full decl list - Make test passes fully, selfhost builds successfully
This commit is contained in:
+42
-5
@@ -12,6 +12,7 @@ extern func bux_path_join(a: String, b: String) -> String;
|
||||
extern func bux_mkdir_if_needed(path: String) -> int;
|
||||
extern func bux_run_nim(nim_file: String, out_bin: String) -> int;
|
||||
extern func bux_list_dir(dir: String, ext: String, out_count: *int) -> *String;
|
||||
extern func bux_system(cmd: String) -> int;
|
||||
|
||||
func ReadFile(path: String) -> String {
|
||||
return bux_read_file(path);
|
||||
@@ -61,9 +62,14 @@ func Cli_Compile(source: String, sourceName: String) -> String {
|
||||
}
|
||||
PrintLine(" Parse done");
|
||||
|
||||
// Flatten module wrappers: if the only item is a module decl, hoist its children
|
||||
if mod.firstItem != null as *Decl && mod.firstItem.kind == dkModule && mod.firstItem.childDecl1 != null as *Decl {
|
||||
mod.firstItem = mod.firstItem.childDecl1;
|
||||
// Flatten module wrappers: find module decl and hoist its children
|
||||
var decl: *Decl = mod.firstItem;
|
||||
while decl != null as *Decl {
|
||||
if decl.kind == dkModule && decl.childDecl1 != null as *Decl {
|
||||
mod.firstItem = decl.childDecl1;
|
||||
break;
|
||||
}
|
||||
decl = decl.childDecl2;
|
||||
}
|
||||
|
||||
// Phase 3: Semantic analysis
|
||||
@@ -167,8 +173,13 @@ func Cli_Check(srcPath: String) -> int {
|
||||
}
|
||||
|
||||
// Flatten module wrappers
|
||||
if mod.firstItem != null as *Decl && mod.firstItem.kind == dkModule && mod.firstItem.childDecl1 != null as *Decl {
|
||||
mod.firstItem = mod.firstItem.childDecl1;
|
||||
var decl2: *Decl = mod.firstItem;
|
||||
while decl2 != null as *Decl {
|
||||
if decl2.kind == dkModule && decl2.childDecl1 != null as *Decl {
|
||||
mod.firstItem = decl2.childDecl1;
|
||||
break;
|
||||
}
|
||||
decl2 = decl2.childDecl2;
|
||||
}
|
||||
|
||||
// Phase 3: Sema
|
||||
@@ -348,6 +359,26 @@ func Cli_BuildProject(projectDir: String) -> int {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Run command — build project and execute
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Cli_RunProject(projectDir: String) -> int {
|
||||
let rc: int = Cli_BuildProject(projectDir);
|
||||
if rc != 0 {
|
||||
return rc;
|
||||
}
|
||||
let man: Manifest = Manifest_Load(bux_path_join(projectDir, "bux.toml"));
|
||||
var outName: String = man.name;
|
||||
if String_Eq(outName, "") {
|
||||
outName = "bux_out";
|
||||
}
|
||||
let outBin: String = bux_path_join(bux_path_join(projectDir, "build"), outName);
|
||||
Print("Running: ");
|
||||
PrintLine(outBin);
|
||||
return bux_system(outBin);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Main entry — dispatch based on args
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -401,6 +432,12 @@ func Cli_Run(args: *String, argCount: int) -> int {
|
||||
return Cli_BuildProject(dir);
|
||||
}
|
||||
|
||||
if String_Eq(cmd, "run") {
|
||||
let dir: String = ".";
|
||||
if argCount >= 3 { dir = args[2]; }
|
||||
return Cli_RunProject(dir);
|
||||
}
|
||||
|
||||
Print("Unknown command: ");
|
||||
PrintLine(cmd);
|
||||
return 1;
|
||||
|
||||
@@ -553,6 +553,8 @@ proc nextToken(lex: var Lexer): Token =
|
||||
# Simple heuristic: if peek(2) is ', it's a char literal; else lifetime
|
||||
if lex.peek(2) == '\'':
|
||||
return lex.scanChar(startLoc, 0)
|
||||
elif lex.peek(2) == '\0':
|
||||
return lex.scanChar(startLoc, 0)
|
||||
else:
|
||||
# Lifetime: consume ' and then identifier chars
|
||||
discard lex.advance() # '
|
||||
|
||||
+42
-5
@@ -12,6 +12,7 @@ extern func bux_path_join(a: String, b: String) -> String;
|
||||
extern func bux_mkdir_if_needed(path: String) -> int;
|
||||
extern func bux_run_nim(nim_file: String, out_bin: String) -> int;
|
||||
extern func bux_list_dir(dir: String, ext: String, out_count: *int) -> *String;
|
||||
extern func bux_system(cmd: String) -> int;
|
||||
|
||||
func ReadFile(path: String) -> String {
|
||||
return bux_read_file(path);
|
||||
@@ -61,9 +62,14 @@ func Cli_Compile(source: String, sourceName: String) -> String {
|
||||
}
|
||||
PrintLine(" Parse done");
|
||||
|
||||
// Flatten module wrappers: if the only item is a module decl, hoist its children
|
||||
if mod.firstItem != null as *Decl && mod.firstItem.kind == dkModule && mod.firstItem.childDecl1 != null as *Decl {
|
||||
mod.firstItem = mod.firstItem.childDecl1;
|
||||
// Flatten module wrappers: find module decl and hoist its children
|
||||
var decl: *Decl = mod.firstItem;
|
||||
while decl != null as *Decl {
|
||||
if decl.kind == dkModule && decl.childDecl1 != null as *Decl {
|
||||
mod.firstItem = decl.childDecl1;
|
||||
break;
|
||||
}
|
||||
decl = decl.childDecl2;
|
||||
}
|
||||
|
||||
// Phase 3: Semantic analysis
|
||||
@@ -167,8 +173,13 @@ func Cli_Check(srcPath: String) -> int {
|
||||
}
|
||||
|
||||
// Flatten module wrappers
|
||||
if mod.firstItem != null as *Decl && mod.firstItem.kind == dkModule && mod.firstItem.childDecl1 != null as *Decl {
|
||||
mod.firstItem = mod.firstItem.childDecl1;
|
||||
var decl2: *Decl = mod.firstItem;
|
||||
while decl2 != null as *Decl {
|
||||
if decl2.kind == dkModule && decl2.childDecl1 != null as *Decl {
|
||||
mod.firstItem = decl2.childDecl1;
|
||||
break;
|
||||
}
|
||||
decl2 = decl2.childDecl2;
|
||||
}
|
||||
|
||||
// Phase 3: Sema
|
||||
@@ -348,6 +359,26 @@ func Cli_BuildProject(projectDir: String) -> int {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Run command — build project and execute
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Cli_RunProject(projectDir: String) -> int {
|
||||
let rc: int = Cli_BuildProject(projectDir);
|
||||
if rc != 0 {
|
||||
return rc;
|
||||
}
|
||||
let man: Manifest = Manifest_Load(bux_path_join(projectDir, "bux.toml"));
|
||||
var outName: String = man.name;
|
||||
if String_Eq(outName, "") {
|
||||
outName = "bux_out";
|
||||
}
|
||||
let outBin: String = bux_path_join(bux_path_join(projectDir, "build"), outName);
|
||||
Print("Running: ");
|
||||
PrintLine(outBin);
|
||||
return bux_system(outBin);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Main entry — dispatch based on args
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -401,6 +432,12 @@ func Cli_Run(args: *String, argCount: int) -> int {
|
||||
return Cli_BuildProject(dir);
|
||||
}
|
||||
|
||||
if String_Eq(cmd, "run") {
|
||||
let dir: String = ".";
|
||||
if argCount >= 3 { dir = args[2]; }
|
||||
return Cli_RunProject(dir);
|
||||
}
|
||||
|
||||
Print("Unknown command: ");
|
||||
PrintLine(cmd);
|
||||
return 1;
|
||||
|
||||
+6
-1
@@ -22,7 +22,7 @@ char* bux_argv(int index) {
|
||||
|
||||
/* Memory allocation */
|
||||
void* bux_alloc(size_t size) {
|
||||
void* ptr = malloc(size);
|
||||
void* ptr = calloc(1, size);
|
||||
if (ptr == NULL) {
|
||||
fprintf(stderr, "bux runtime: out of memory (alloc %zu bytes)\n", size);
|
||||
abort();
|
||||
@@ -75,6 +75,11 @@ int bux_run_nim(const char* nim_file, const char* out_bin) {
|
||||
return system(cmd);
|
||||
}
|
||||
|
||||
int bux_system(const char* cmd) {
|
||||
if (cmd == NULL) return -1;
|
||||
return system(cmd);
|
||||
}
|
||||
|
||||
int bux_strlen_c(const char* s) {
|
||||
if (s == NULL) return 0;
|
||||
const char* p = s;
|
||||
|
||||
@@ -111,7 +111,7 @@ suite "Parser":
|
||||
check ret.stmtReturnValue.exprCallCallee.kind == ekIdent
|
||||
|
||||
test "full sample file":
|
||||
let source = readFile("tests/testdata/sample.bux")
|
||||
let source = readFile(currentSourcePath.parentDir / "testdata" / "sample.bux")
|
||||
let lexRes = tokenize(source, "sample.bux")
|
||||
check not lexRes.hasErrors
|
||||
let parseRes = parse(lexRes.tokens, "sample.bux")
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user