feat: add HIR, C backend, and end-to-end compilation
- Phase 3: High-Level IR (HIR) with lowering from AST - Method call desugaring (obj.method() → Type_method(obj)) - if/else, while, loop, break, continue lowering - struct, enum, function lowering - 8 HIR tests passing - Phase 5A: C backend code generation - Type mapping (Bux types → C11 types) - Expression and statement emission - Struct, enum, function generation - C main() wrapper for Bux Main() - Runtime shim (stdlib/runtime.c) - bux_alloc, bux_free, bux_print, bux_panic - BuxString, BuxSlice types - Bounds checking, division by zero - Build integration - bux build: lex → parse → sema → HIR → C → cc - bux run: build + execute - bux clean: remove build directory - Parser fixes - Newline handling in struct, enum, extend, interface blocks - self keyword as expression and parameter name - Sema improvements - Method resolution (extend blocks) - Interface conformance checking - collectGlobals made public - All 70 tests passing (25 lexer + 16 parser + 21 sema + 8 HIR) - End-to-end: Bux programs compile to native ELF64 binaries
This commit is contained in:
+39
-4
@@ -323,10 +323,11 @@ proc parsePrimary(p: var Parser): Expr =
|
||||
case p.peek()
|
||||
of tkIntLiteral, tkFloatLiteral, tkStringLiteral, tkCharLiteral, tkBoolLiteral:
|
||||
return newLiteralExpr(p.advance())
|
||||
of tkSelf:
|
||||
discard p.advance()
|
||||
return Expr(kind: ekSelf, loc: loc)
|
||||
of tkIdent:
|
||||
let name = p.advance().text
|
||||
if name == "self":
|
||||
return Expr(kind: ekSelf, loc: loc)
|
||||
# Path expression: a::b::c
|
||||
if p.check(tkColonColon):
|
||||
var segs = @[name]
|
||||
@@ -781,11 +782,25 @@ proc parseParamList(p: var Parser, allowVariadic: bool = false): seq[Param] =
|
||||
var isVar = false
|
||||
if allowVariadic and p.check(tkDotDotDot):
|
||||
discard p.advance()
|
||||
let name = p.expect(tkIdent, "expected parameter name after '...'").text
|
||||
let nameTok = p.at
|
||||
var name = ""
|
||||
if nameTok.kind == tkIdent:
|
||||
name = p.advance().text
|
||||
elif nameTok.kind == tkSelf:
|
||||
name = p.advance().text
|
||||
else:
|
||||
name = p.expect(tkIdent, "expected parameter name after '...'").text
|
||||
let ty = p.parseType()
|
||||
result.add(Param(loc: loc, name: name, ptype: ty, isVariadic: true))
|
||||
else:
|
||||
let name = p.expect(tkIdent, "expected parameter name").text
|
||||
let nameTok = p.at
|
||||
var name = ""
|
||||
if nameTok.kind == tkIdent:
|
||||
name = p.advance().text
|
||||
elif nameTok.kind == tkSelf:
|
||||
name = p.advance().text
|
||||
else:
|
||||
name = p.expect(tkIdent, "expected parameter name").text
|
||||
discard p.expect(tkColon, "expected ':' after parameter name")
|
||||
let ty = p.parseType()
|
||||
var defaultVal: Expr = nil
|
||||
@@ -826,6 +841,11 @@ proc parseStructDecl(p: var Parser, isPublic: bool): Decl =
|
||||
discard p.expect(tkLBrace, "expected '{' to start struct body")
|
||||
var fields: seq[StructField] = @[]
|
||||
while not p.check(tkRBrace) and not p.isAtEnd:
|
||||
# Skip newlines
|
||||
while p.check(tkNewLine):
|
||||
discard p.advance()
|
||||
if p.check(tkRBrace) or p.isAtEnd:
|
||||
break
|
||||
let fLoc = p.currentLoc
|
||||
var fPub = false
|
||||
if p.check(tkPub):
|
||||
@@ -853,6 +873,11 @@ proc parseEnumDecl(p: var Parser, isPublic: bool): Decl =
|
||||
discard p.expect(tkLBrace, "expected '{' to start enum body")
|
||||
var variants: seq[EnumVariant] = @[]
|
||||
while not p.check(tkRBrace) and not p.isAtEnd:
|
||||
# Skip newlines
|
||||
while p.check(tkNewLine):
|
||||
discard p.advance()
|
||||
if p.check(tkRBrace) or p.isAtEnd:
|
||||
break
|
||||
let vLoc = p.currentLoc
|
||||
let vName = p.expect(tkIdent, "expected variant name").text
|
||||
var fields: seq[TypeExpr] = @[]
|
||||
@@ -908,6 +933,11 @@ proc parseInterfaceDecl(p: var Parser, isPublic: bool): Decl =
|
||||
discard p.expect(tkLBrace, "expected '{' to start interface body")
|
||||
var methods: seq[Decl] = @[]
|
||||
while not p.check(tkRBrace) and not p.isAtEnd:
|
||||
# Skip newlines
|
||||
while p.check(tkNewLine):
|
||||
discard p.advance()
|
||||
if p.check(tkRBrace) or p.isAtEnd:
|
||||
break
|
||||
methods.add(p.parseFuncDecl(false, false, ParsedAttrs()))
|
||||
discard p.expect(tkRBrace, "expected '}' to close interface")
|
||||
return Decl(kind: dkInterface, loc: loc, isPublic: isPublic,
|
||||
@@ -924,6 +954,11 @@ proc parseImplDecl(p: var Parser): Decl =
|
||||
discard p.expect(tkLBrace, "expected '{' to start impl block")
|
||||
var methods: seq[Decl] = @[]
|
||||
while not p.check(tkRBrace) and not p.isAtEnd:
|
||||
# Skip newlines
|
||||
while p.check(tkNewLine):
|
||||
discard p.advance()
|
||||
if p.check(tkRBrace) or p.isAtEnd:
|
||||
break
|
||||
methods.add(p.parseFuncDecl(false, false, ParsedAttrs()))
|
||||
discard p.expect(tkRBrace, "expected '}' to close impl block")
|
||||
return Decl(kind: dkImpl, loc: loc, declImplTypeName: typeName,
|
||||
|
||||
Reference in New Issue
Block a user