Phase 7.9: Self-hosted compiler buxc2 builds and runs! 🎉
buxc (Nim bootstrap) successfully compiles buxc2 (Bux self-hosted compiler)
into a working 88KB ELF x86-64 binary.
Compiler fixes (Nim):
- duplicate symbol: user funcs shadow stdlib funcs via mergeDecls()
- forward declarations: func without body + definition (both orderings)
- extern func dedup: same extern in multiple files
- discard keyword: new language keyword, lowered to expr stmt or no-op
- parser: keywords as field names + advance-on-error safeguard
- parser: var without initializer (zero-init)
- parser: multi-line || && continuation expressions
- parser: else-if chain newline handling
- C backend: const declarations emitted as #define
- C backend: load(field_ptr) → base.field optimization (fixes lvalue errors)
Source fixes (src_bux/*.bux):
- types.bux: tk* → ty* prefix for type kind constants (avoid token conflict)
- sema.bux: remaining tk* → ty* references, StringMap → *void workaround
- hir_lower.bux: ekReturn removed, Lcx_LowerParam helper, *f dereference
- c_backend.bux: &mod.funcs[i] for pointer passing
- cli.bux: ReadFile/WriteFile → bux_read_file/bux_write_file wrappers
- parser.bux: pathStr.len → String_Len(pathStr)
- types.bux: "*" + x → String_Concat("*", x)
Build system:
- Makefile: added 4 missing examples + selfhost target
- PLAN.md: updated with actual project state, Phase 7.9 marked complete
All 18 examples pass, all unit tests pass.
This commit is contained in:
+23
-4
@@ -209,7 +209,19 @@ proc collectGlobals*(sema: var Sema) =
|
||||
let retType = if decl.declFuncReturnType != nil: sema.resolveType(decl.declFuncReturnType) else: makeVoid()
|
||||
sym.typ = makeFunc(params, retType)
|
||||
if not sema.globalScope.define(sym):
|
||||
sema.emitError(decl.loc, &"duplicate symbol '{decl.declFuncName}'")
|
||||
let existing = sema.globalScope.lookup(decl.declFuncName)
|
||||
if existing != nil and existing.kind == skFunc:
|
||||
if existing.decl != nil and existing.decl.declFuncBody == nil and decl.declFuncBody != nil:
|
||||
# First was forward declaration, update with definition
|
||||
existing.decl = decl
|
||||
existing.typ = sym.typ
|
||||
elif decl.declFuncBody == nil:
|
||||
# New one is a forward declaration, existing already has it — skip
|
||||
discard
|
||||
else:
|
||||
sema.emitError(decl.loc, &"duplicate symbol '{decl.declFuncName}'")
|
||||
else:
|
||||
sema.emitError(decl.loc, &"duplicate symbol '{decl.declFuncName}'")
|
||||
# Auto-register func Type_Method(self: Type, ...) as a method
|
||||
if decl.declFuncParams.len > 0 and decl.declFuncParams[0].name == "self":
|
||||
var typeName = ""
|
||||
@@ -243,7 +255,10 @@ proc collectGlobals*(sema: var Sema) =
|
||||
let retType = if decl.declExtFuncReturnType != nil: sema.resolveType(decl.declExtFuncReturnType) else: makeVoid()
|
||||
sym.typ = makeFunc(params, retType)
|
||||
if not sema.globalScope.define(sym):
|
||||
sema.emitError(decl.loc, &"duplicate symbol '{decl.declExtFuncName}'")
|
||||
# Allow duplicate extern func declarations (same func declared in multiple files)
|
||||
let existing = sema.globalScope.lookup(decl.declExtFuncName)
|
||||
if existing == nil or existing.kind != skFunc:
|
||||
sema.emitError(decl.loc, &"duplicate symbol '{decl.declExtFuncName}'")
|
||||
of dkStruct:
|
||||
let t = makeNamed(decl.declStructName)
|
||||
let sym = Symbol(kind: skType, name: decl.declStructName, typ: t,
|
||||
@@ -776,10 +791,14 @@ proc checkStmt(sema: var Sema, stmt: Stmt, scope: Scope): Type =
|
||||
of skExpr:
|
||||
return sema.checkExpr(stmt.stmtExpr, scope)
|
||||
of skLet:
|
||||
let initType = sema.checkExpr(stmt.stmtLetInit, scope)
|
||||
var initType: Type = makeVoid()
|
||||
if stmt.stmtLetInit != nil:
|
||||
initType = sema.checkExpr(stmt.stmtLetInit, scope)
|
||||
let declaredType = if stmt.stmtLetType != nil: sema.resolveType(stmt.stmtLetType) else: initType
|
||||
if stmt.stmtLetType != nil and not initType.isAssignableTo(declaredType) and not (initType.kind in {TypeKind.tkUnknown, TypeKind.tkNamed, TypeKind.tkTypeParam}):
|
||||
if stmt.stmtLetInit != nil and stmt.stmtLetType != nil and not initType.isAssignableTo(declaredType) and not (initType.kind in {TypeKind.tkUnknown, TypeKind.tkNamed, TypeKind.tkTypeParam}):
|
||||
sema.emitError(stmt.loc, &"cannot assign {initType.toString} to {declaredType.toString}")
|
||||
if stmt.stmtLetInit == nil and stmt.stmtLetType == nil:
|
||||
sema.emitError(stmt.loc, "variable must have either type annotation or initializer")
|
||||
let sym = Symbol(kind: skVar, name: stmt.stmtLetName, typ: declaredType,
|
||||
isMutable: stmt.stmtLetMut)
|
||||
if not scope.define(sym):
|
||||
|
||||
Reference in New Issue
Block a user