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:
+25
-25
@@ -7,29 +7,29 @@ module CBackend {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func CBackend_TypeToC(kind: int) -> String {
|
||||
if kind == tkVoid { return "void"; }
|
||||
if kind == tkBool { return "bool"; }
|
||||
if kind == tkBool8 { return "bool"; }
|
||||
if kind == tkBool16 { return "bool"; }
|
||||
if kind == tkBool32 { return "bool"; }
|
||||
if kind == tkChar8 { return "char"; }
|
||||
if kind == tkChar16 { return "uint16_t"; }
|
||||
if kind == tkChar32 { return "uint32_t"; }
|
||||
if kind == tkStr { return "const char*"; }
|
||||
if kind == tkInt8 { return "int8_t"; }
|
||||
if kind == tkInt16 { return "int16_t"; }
|
||||
if kind == tkInt32 { return "int32_t"; }
|
||||
if kind == tkInt64 { return "int64_t"; }
|
||||
if kind == tkInt { return "int"; }
|
||||
if kind == tkUInt8 { return "uint8_t"; }
|
||||
if kind == tkUInt16 { return "uint16_t"; }
|
||||
if kind == tkUInt32 { return "uint32_t"; }
|
||||
if kind == tkUInt64 { return "uint64_t"; }
|
||||
if kind == tkUInt { return "unsigned int"; }
|
||||
if kind == tkFloat32 { return "float"; }
|
||||
if kind == tkFloat64 { return "double"; }
|
||||
if kind == tkPointer { return "void*"; }
|
||||
if kind == tkNamed { return "void*"; }
|
||||
if kind == tyVoid { return "void"; }
|
||||
if kind == tyBool { return "bool"; }
|
||||
if kind == tyBool8 { return "bool"; }
|
||||
if kind == tyBool16 { return "bool"; }
|
||||
if kind == tyBool32 { return "bool"; }
|
||||
if kind == tyChar8 { return "char"; }
|
||||
if kind == tyChar16 { return "uint16_t"; }
|
||||
if kind == tyChar32 { return "uint32_t"; }
|
||||
if kind == tyStr { return "const char*"; }
|
||||
if kind == tyInt8 { return "int8_t"; }
|
||||
if kind == tyInt16 { return "int16_t"; }
|
||||
if kind == tyInt32 { return "int32_t"; }
|
||||
if kind == tyInt64 { return "int64_t"; }
|
||||
if kind == tyInt{ return "int"; }
|
||||
if kind == tyUInt8 { return "uint8_t"; }
|
||||
if kind == tyUInt16 { return "uint16_t"; }
|
||||
if kind == tyUInt32 { return "uint32_t"; }
|
||||
if kind == tyUInt64 { return "uint64_t"; }
|
||||
if kind == tyUInt { return "unsigned int"; }
|
||||
if kind == tyFloat32 { return "float"; }
|
||||
if kind == tyFloat64 { return "double"; }
|
||||
if kind == tyPointer { return "void*"; }
|
||||
if kind == tyNamed { return "void*"; }
|
||||
return "int";
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ func CBE_EmitExpr(cbe: *CEmitter, node: *HirNode) {
|
||||
|
||||
// Alloca
|
||||
if kind == hAlloca {
|
||||
StringBuilder_Append(&cbe.sb, CBackend_TypeToC(tkInt)); // simplified type
|
||||
StringBuilder_Append(&cbe.sb, CBackend_TypeToC(tyInt)); // simplified type
|
||||
StringBuilder_Append(&cbe.sb, " ");
|
||||
StringBuilder_Append(&cbe.sb, node.strValue);
|
||||
StringBuilder_Append(&cbe.sb, ";\n");
|
||||
@@ -171,7 +171,7 @@ func CBE_EmitExpr(cbe: *CEmitter, node: *HirNode) {
|
||||
// Cast
|
||||
if kind == hCast {
|
||||
StringBuilder_Append(&cbe.sb, "((");
|
||||
StringBuilder_Append(&cbe.sb, CBackend_TypeToC(tkPointer));
|
||||
StringBuilder_Append(&cbe.sb, CBackend_TypeToC(tyPointer));
|
||||
StringBuilder_Append(&cbe.sb, ")");
|
||||
CBE_EmitExpr(cbe, node.child1);
|
||||
StringBuilder_Append(&cbe.sb, ")");
|
||||
|
||||
+10
-2
@@ -4,8 +4,16 @@ module Cli {
|
||||
|
||||
extern func PrintLine(s: String);
|
||||
extern func Print(s: String);
|
||||
extern func ReadFile(path: String) -> String;
|
||||
extern func WriteFile(path: String, content: String) -> bool;
|
||||
extern func bux_read_file(path: String) -> String;
|
||||
extern func bux_write_file(path: String, content: String) -> bool;
|
||||
|
||||
func ReadFile(path: String) -> String {
|
||||
return bux_read_file(path);
|
||||
}
|
||||
|
||||
func WriteFile(path: String, content: String) -> bool {
|
||||
return bux_write_file(path, content);
|
||||
}
|
||||
|
||||
// Import the compiler pipeline
|
||||
// In self-hosting mode, these are compiled together from src_bux/
|
||||
|
||||
+23
-15
@@ -106,13 +106,6 @@ func Lcx_LowerExpr(ctx: *LowerCtx, expr: *Expr) -> *HirNode {
|
||||
return n;
|
||||
}
|
||||
|
||||
// Return
|
||||
if kind == ekReturn {
|
||||
n.kind = hReturn;
|
||||
n.child1 = Lcx_LowerExpr(ctx, expr.child1);
|
||||
return n;
|
||||
}
|
||||
|
||||
// Cast
|
||||
if kind == ekCast {
|
||||
n.kind = hCast;
|
||||
@@ -222,6 +215,21 @@ func Lcx_LowerBlock(ctx: *LowerCtx, block: *Block, retTypeKind: int) -> *HirNode
|
||||
return n;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Param → HirParam conversion
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Lcx_LowerParam(out: *HirParam, p: *Param) {
|
||||
out.name = p.name;
|
||||
if p.refParamType != null as *TypeExpr {
|
||||
out.typeKind = p.refParamType.kind;
|
||||
out.typeName = p.refParamType.typeName;
|
||||
} else {
|
||||
out.typeKind = 0;
|
||||
out.typeName = "";
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Function lowering
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -231,12 +239,12 @@ func Lcx_LowerFunc(ctx: *LowerCtx, decl: *Decl) -> *HirFunc {
|
||||
f.name = decl.strValue;
|
||||
f.isPublic = decl.isPublic;
|
||||
f.paramCount = decl.paramCount;
|
||||
f.param0 = decl.param0;
|
||||
f.param1 = decl.param1;
|
||||
f.param2 = decl.param2;
|
||||
f.param3 = decl.param3;
|
||||
f.param4 = decl.param4;
|
||||
f.param5 = decl.param5;
|
||||
Lcx_LowerParam(&f.param0, &decl.param0);
|
||||
Lcx_LowerParam(&f.param1, &decl.param1);
|
||||
Lcx_LowerParam(&f.param2, &decl.param2);
|
||||
Lcx_LowerParam(&f.param3, &decl.param3);
|
||||
Lcx_LowerParam(&f.param4, &decl.param4);
|
||||
Lcx_LowerParam(&f.param5, &decl.param5);
|
||||
|
||||
if decl.retType != null as *TypeExpr {
|
||||
f.retTypeName = decl.retType.typeName;
|
||||
@@ -276,12 +284,12 @@ func HirLower_LowerModule(mod: *Module, sema: *Sema) -> *HirModule {
|
||||
while decl != null as *Decl {
|
||||
if decl.kind == dkFunc {
|
||||
let f: *HirFunc = Lcx_LowerFunc(ctx, decl);
|
||||
ctx.funcs[ctx.funcCount] = f;
|
||||
ctx.funcs[ctx.funcCount] = *f;
|
||||
ctx.funcCount = ctx.funcCount + 1;
|
||||
}
|
||||
if decl.kind == dkExternFunc {
|
||||
let f: *HirFunc = Lcx_LowerFunc(ctx, decl);
|
||||
ctx.externFuncs[ctx.externCount] = f;
|
||||
ctx.externFuncs[ctx.externCount] = *f;
|
||||
ctx.externCount = ctx.externCount + 1;
|
||||
}
|
||||
if decl.kind == dkStruct {
|
||||
|
||||
+1
-1
@@ -818,7 +818,7 @@ func parserParseImportDecl(p: *Parser, isPublic: bool) -> *Decl {
|
||||
while parserCheck(p, tkIdent) || (segCount > 0 && parserCheck(p, tkColonColon)) {
|
||||
if segCount > 0 {
|
||||
discard parserAdvance(p); // ::
|
||||
if pathStr.len > 0 {
|
||||
if String_Len(pathStr) > 0 {
|
||||
let tmp: *char8 = bux_alloc(256) as *char8;
|
||||
// Append to path string (simplified)
|
||||
pathStr = String_Concat(pathStr, "::");
|
||||
|
||||
+75
-78
@@ -8,8 +8,8 @@ module Sema {
|
||||
struct Sema {
|
||||
module: *Module,
|
||||
scope: *Scope,
|
||||
typeTable: *StringMap,
|
||||
methodTable: *StringMap,
|
||||
typeTable: *void,
|
||||
methodTable: *void,
|
||||
diagCount: int,
|
||||
diags: *SemaDiag,
|
||||
hasError: bool,
|
||||
@@ -38,44 +38,41 @@ func Sema_EmitError(sema: *Sema, line: uint32, col: uint32, msg: String) {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Sema_ResolveType(sema: *Sema, te: *TypeExpr) -> int {
|
||||
if te == null as *TypeExpr { return tkUnknown; }
|
||||
if te == null as *TypeExpr { return tyUnknown; }
|
||||
let name: String = te.typeName;
|
||||
|
||||
if te.kind == tekPointer {
|
||||
return tkPointer;
|
||||
return tyPointer;
|
||||
}
|
||||
|
||||
if String_Eq(name, "void") { return tkVoid; }
|
||||
if String_Eq(name, "bool") { return tkBool; }
|
||||
if String_Eq(name, "bool8") { return tkBool8; }
|
||||
if String_Eq(name, "bool16") { return tkBool16; }
|
||||
if String_Eq(name, "bool32") { return tkBool32; }
|
||||
if String_Eq(name, "char8") { return tkChar8; }
|
||||
if String_Eq(name, "char16") { return tkChar16; }
|
||||
if String_Eq(name, "char32") { return tkChar32; }
|
||||
if String_Eq(name, "String") { return tkStr; }
|
||||
if String_Eq(name, "str") { return tkStr; }
|
||||
if String_Eq(name, "int8") { return tkInt8; }
|
||||
if String_Eq(name, "int16") { return tkInt16; }
|
||||
if String_Eq(name, "int32") { return tkInt32; }
|
||||
if String_Eq(name, "int64") { return tkInt64; }
|
||||
if String_Eq(name, "int") { return tkInt; }
|
||||
if String_Eq(name, "uint8") { return tkUInt8; }
|
||||
if String_Eq(name, "uint16") { return tkUInt16; }
|
||||
if String_Eq(name, "uint32") { return tkUInt32; }
|
||||
if String_Eq(name, "uint64") { return tkUInt64; }
|
||||
if String_Eq(name, "uint") { return tkUInt; }
|
||||
if String_Eq(name, "float32") { return tkFloat32; }
|
||||
if String_Eq(name, "float64") { return tkFloat64; }
|
||||
if String_Eq(name, "float") { return tkFloat64; }
|
||||
if String_Eq(name, "void") { return tyVoid; }
|
||||
if String_Eq(name, "bool") { return tyBool; }
|
||||
if String_Eq(name, "bool8") { return tyBool8; }
|
||||
if String_Eq(name, "bool16") { return tyBool16; }
|
||||
if String_Eq(name, "bool32") { return tyBool32; }
|
||||
if String_Eq(name, "char8") { return tyChar8; }
|
||||
if String_Eq(name, "char16") { return tyChar16; }
|
||||
if String_Eq(name, "char32") { return tyChar32; }
|
||||
if String_Eq(name, "String") { return tyStr; }
|
||||
if String_Eq(name, "str") { return tyStr; }
|
||||
if String_Eq(name, "int8") { return tyInt8; }
|
||||
if String_Eq(name, "int16") { return tyInt16; }
|
||||
if String_Eq(name, "int32") { return tyInt32; }
|
||||
if String_Eq(name, "int64") { return tyInt64; }
|
||||
if String_Eq(name, "int") { return tyInt; }
|
||||
if String_Eq(name, "uint8") { return tyUInt8; }
|
||||
if String_Eq(name, "uint16") { return tyUInt16; }
|
||||
if String_Eq(name, "uint32") { return tyUInt32; }
|
||||
if String_Eq(name, "uint64") { return tyUInt64; }
|
||||
if String_Eq(name, "uint") { return tyUInt; }
|
||||
if String_Eq(name, "float32") { return tyFloat32; }
|
||||
if String_Eq(name, "float64") { return tyFloat64; }
|
||||
if String_Eq(name, "float") { return tyFloat64; }
|
||||
|
||||
// Check type table for user-defined types
|
||||
if sema.typeTable != null as *StringMap {
|
||||
if StringMap_Has(sema.typeTable, name) {
|
||||
return tkNamed;
|
||||
}
|
||||
}
|
||||
return tkNamed; // assume named type
|
||||
// Check type table for user-defined types (StringMap not yet supported)
|
||||
// TODO: re-enable when StringMap generic is available
|
||||
// if sema.typeTable != null as *void { ... }
|
||||
return tyNamed; // assume named type
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -83,26 +80,26 @@ func Sema_ResolveType(sema: *Sema, te: *TypeExpr) -> int {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Sema_IsNumeric(kind: int) -> bool {
|
||||
if kind == tkUnknown || kind == tkNamed || kind == tkTypeParam { return true; }
|
||||
return kind >= tkInt8 && kind <= tkUInt64;
|
||||
if kind == tyUnknown || kind == tyNamed || kind == tyTypeParam { return true; }
|
||||
return kind >= tyInt8 && kind <= tyUInt64;
|
||||
}
|
||||
|
||||
func Sema_IsBool(kind: int) -> bool {
|
||||
return kind == tkBool || kind == tkBool8 || kind == tkBool16 || kind == tkBool32;
|
||||
return kind == tyBool || kind == tyBool8 || kind == tyBool16 || kind == tyBool32;
|
||||
}
|
||||
|
||||
func Sema_TypeName(kind: int) -> String {
|
||||
if kind == tkUnknown { return "?"; }
|
||||
if kind == tkVoid { return "void"; }
|
||||
if kind == tkBool { return "bool"; }
|
||||
if kind == tkInt { return "int"; }
|
||||
if kind == tkInt64 { return "int64"; }
|
||||
if kind == tkUInt { return "uint"; }
|
||||
if kind == tkFloat64 { return "float64"; }
|
||||
if kind == tkStr { return "String"; }
|
||||
if kind == tkPointer { return "*ptr"; }
|
||||
if kind == tkNamed { return "user-type"; }
|
||||
if kind == tkTypeParam { return "type-param"; }
|
||||
if kind == tyUnknown { return "?"; }
|
||||
if kind == tyVoid { return "void"; }
|
||||
if kind == tyBool { return "bool"; }
|
||||
if kind == tyInt{ return "int"; }
|
||||
if kind == tyInt64 { return "int64"; }
|
||||
if kind == tyUInt { return "uint"; }
|
||||
if kind == tyFloat64 { return "float64"; }
|
||||
if kind == tyStr { return "String"; }
|
||||
if kind == tyPointer { return "*ptr"; }
|
||||
if kind == tyNamed { return "user-type"; }
|
||||
if kind == tyTypeParam { return "type-param"; }
|
||||
return "?";
|
||||
}
|
||||
|
||||
@@ -111,19 +108,19 @@ func Sema_TypeName(kind: int) -> String {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Sema_CheckExpr(sema: *Sema, expr: *Expr) -> int {
|
||||
if expr == null as *Expr { return tkUnknown; }
|
||||
if expr == null as *Expr { return tyUnknown; }
|
||||
let kind: int = expr.kind;
|
||||
|
||||
// Literal
|
||||
if kind == ekLiteral {
|
||||
let tk: int = expr.tokKind;
|
||||
if tk == tkIntLiteral { return tkInt; }
|
||||
if tk == tkFloatLiteral { return tkFloat64; }
|
||||
if tk == tkStringLiteral { return tkStr; }
|
||||
if tk == tkBoolLiteral { return tkBool; }
|
||||
if tk == tkCharLiteral { return tkChar32; }
|
||||
if tk == tkNull { return tkPointer; }
|
||||
return tkUnknown;
|
||||
if tk == tkIntLiteral { return tyInt; }
|
||||
if tk == tkFloatLiteral { return tyFloat64; }
|
||||
if tk == tkStringLiteral { return tyStr; }
|
||||
if tk == tkBoolLiteral { return tyBool; }
|
||||
if tk == tkCharLiteral { return tyChar32; }
|
||||
if tk == tkNull { return tyPointer; }
|
||||
return tyUnknown;
|
||||
}
|
||||
|
||||
// Identifier — look up in scope
|
||||
@@ -131,7 +128,7 @@ func Sema_CheckExpr(sema: *Sema, expr: *Expr) -> int {
|
||||
let sym: Symbol = Scope_Lookup(sema.scope, expr.strValue);
|
||||
if sym.kind == 0 && !String_Eq(sym.name, expr.strValue) {
|
||||
Sema_EmitError(sema, expr.line, expr.column, "undeclared identifier");
|
||||
return tkUnknown;
|
||||
return tyUnknown;
|
||||
}
|
||||
return sym.typeKind;
|
||||
}
|
||||
@@ -143,31 +140,31 @@ func Sema_CheckExpr(sema: *Sema, expr: *Expr) -> int {
|
||||
let op: int = expr.intValue;
|
||||
|
||||
// Comparison operators return bool
|
||||
if op >= tkEq && op <= tkGe { return tkBool; }
|
||||
if op >= tkEq && op <= tkGe { return tyBool; }
|
||||
// Logical operators return bool
|
||||
if op == tkAmpAmp || op == tkPipePipe || op == tkBang { return tkBool; }
|
||||
if op == tkAmpAmp || op == tkPipePipe || op == tkBang { return tyBool; }
|
||||
// Arithmetic returns wider type
|
||||
if !Sema_IsNumeric(left) || !Sema_IsNumeric(right) {
|
||||
Sema_EmitError(sema, expr.line, expr.column, "arithmetic requires numeric operands");
|
||||
}
|
||||
if left == tkFloat64 || right == tkFloat64 { return tkFloat64; }
|
||||
return tkInt;
|
||||
if left == tyFloat64 || right == tyFloat64 { return tyFloat64; }
|
||||
return tyInt;
|
||||
}
|
||||
|
||||
// Unary
|
||||
if kind == ekUnary {
|
||||
let operand: int = Sema_CheckExpr(sema, expr.child1);
|
||||
let op: int = expr.intValue;
|
||||
if op == tkBang { return tkBool; }
|
||||
if op == tkStar { return tkUnknown; } // dereference — resolve pointee
|
||||
if op == tkAmp { return tkPointer; }
|
||||
if op == tkBang { return tyBool; }
|
||||
if op == tkStar { return tyUnknown; } // dereference — resolve pointee
|
||||
if op == tkAmp { return tyPointer; }
|
||||
return operand;
|
||||
}
|
||||
|
||||
// Call
|
||||
if kind == ekCall {
|
||||
let callee: int = Sema_CheckExpr(sema, expr.child1);
|
||||
if callee == tkUnknown { return tkUnknown; }
|
||||
if callee == tyUnknown { return tyUnknown; }
|
||||
// Assume callee returns same type (simplified)
|
||||
return callee;
|
||||
}
|
||||
@@ -182,7 +179,7 @@ func Sema_CheckExpr(sema: *Sema, expr: *Expr) -> int {
|
||||
if expr.refType != null as *TypeExpr {
|
||||
return Sema_ResolveType(sema, expr.refType);
|
||||
}
|
||||
return tkUnknown;
|
||||
return tyUnknown;
|
||||
}
|
||||
|
||||
// Try (?)
|
||||
@@ -191,7 +188,7 @@ func Sema_CheckExpr(sema: *Sema, expr: *Expr) -> int {
|
||||
return inner; // simplified
|
||||
}
|
||||
|
||||
return tkUnknown;
|
||||
return tyUnknown;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -227,7 +224,7 @@ func Sema_CheckStmt(sema: *Sema, stmt: *Stmt) {
|
||||
// If
|
||||
if kind == skIf {
|
||||
let condType: int = Sema_CheckExpr(sema, stmt.child1);
|
||||
if !Sema_IsBool(condType) && condType != tkUnknown {
|
||||
if !Sema_IsBool(condType) && condType != tyUnknown {
|
||||
Sema_EmitError(sema, stmt.line, stmt.column, "if condition must be bool");
|
||||
}
|
||||
return;
|
||||
@@ -236,7 +233,7 @@ func Sema_CheckStmt(sema: *Sema, stmt: *Stmt) {
|
||||
// While
|
||||
if kind == skWhile {
|
||||
let condType: int = Sema_CheckExpr(sema, stmt.child1);
|
||||
if !Sema_IsBool(condType) && condType != tkUnknown {
|
||||
if !Sema_IsBool(condType) && condType != tyUnknown {
|
||||
Sema_EmitError(sema, stmt.line, stmt.column, "while condition must be bool");
|
||||
}
|
||||
return;
|
||||
@@ -263,7 +260,7 @@ func Sema_CollectGlobals(sema: *Sema) {
|
||||
var sym: Symbol;
|
||||
sym.kind = skFunc;
|
||||
sym.name = decl.strValue;
|
||||
sym.typeKind = tkFunc;
|
||||
sym.typeKind = tyFunc;
|
||||
sym.isPublic = decl.isPublic;
|
||||
discard Scope_Define(sema.scope, sym);
|
||||
}
|
||||
@@ -273,7 +270,7 @@ func Sema_CollectGlobals(sema: *Sema) {
|
||||
var sym: Symbol;
|
||||
sym.kind = skType;
|
||||
sym.name = decl.strValue;
|
||||
sym.typeKind = tkNamed;
|
||||
sym.typeKind = tyNamed;
|
||||
sym.isPublic = decl.isPublic;
|
||||
discard Scope_Define(sema.scope, sym);
|
||||
}
|
||||
@@ -283,7 +280,7 @@ func Sema_CollectGlobals(sema: *Sema) {
|
||||
var sym: Symbol;
|
||||
sym.kind = skType;
|
||||
sym.name = decl.strValue;
|
||||
sym.typeKind = tkNamed;
|
||||
sym.typeKind = tyNamed;
|
||||
sym.isPublic = decl.isPublic;
|
||||
discard Scope_Define(sema.scope, sym);
|
||||
}
|
||||
@@ -293,7 +290,7 @@ func Sema_CollectGlobals(sema: *Sema) {
|
||||
var sym: Symbol;
|
||||
sym.kind = skFunc;
|
||||
sym.name = decl.strValue;
|
||||
sym.typeKind = tkFunc;
|
||||
sym.typeKind = tyFunc;
|
||||
sym.isPublic = true;
|
||||
discard Scope_Define(sema.scope, sym);
|
||||
}
|
||||
@@ -316,8 +313,8 @@ func Sema_Analyze(mod: *Module) -> *Sema {
|
||||
s.hasError = false;
|
||||
s.diagCount = 0;
|
||||
s.diags = bux_alloc(256 as uint * sizeof(SemaDiag)) as *SemaDiag;
|
||||
s.typeTable = null as *StringMap;
|
||||
s.methodTable = null as *StringMap;
|
||||
s.typeTable = null as *void;
|
||||
s.methodTable = null as *void;
|
||||
|
||||
// First pass: collect globals
|
||||
Sema_CollectGlobals(s);
|
||||
@@ -334,14 +331,14 @@ func Sema_Analyze(mod: *Module) -> *Sema {
|
||||
var tpSym: Symbol;
|
||||
tpSym.kind = skType;
|
||||
tpSym.name = decl.typeParam0;
|
||||
tpSym.typeKind = tkTypeParam;
|
||||
tpSym.typeKind = tyTypeParam;
|
||||
discard Scope_Define(&funcScope, tpSym);
|
||||
}
|
||||
if decl.typeParamCount >= 2 {
|
||||
var tpSym2: Symbol;
|
||||
tpSym2.kind = skType;
|
||||
tpSym2.name = decl.typeParam1;
|
||||
tpSym2.typeKind = tkTypeParam;
|
||||
tpSym2.typeKind = tyTypeParam;
|
||||
discard Scope_Define(&funcScope, tpSym2);
|
||||
}
|
||||
|
||||
@@ -350,7 +347,7 @@ func Sema_Analyze(mod: *Module) -> *Sema {
|
||||
while i < decl.paramCount {
|
||||
var pSym: Symbol;
|
||||
pSym.kind = skVar;
|
||||
pSym.typeKind = tkInt; // simplified
|
||||
pSym.typeKind = tyInt; // simplified
|
||||
pSym.isMutable = false;
|
||||
if i == 0 { pSym.name = decl.param0.name; }
|
||||
else if i == 1 { pSym.name = decl.param1.name; }
|
||||
|
||||
+61
-61
@@ -5,35 +5,35 @@ module Types {
|
||||
// TypeKind constants
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
const tkUnknown: int = 0;
|
||||
const tkVoid: int = 1;
|
||||
const tkBool: int = 2;
|
||||
const tkBool8: int = 3;
|
||||
const tkBool16: int = 4;
|
||||
const tkBool32: int = 5;
|
||||
const tkChar8: int = 6;
|
||||
const tkChar16: int = 7;
|
||||
const tkChar32: int = 8;
|
||||
const tkStr: int = 9;
|
||||
const tkInt8: int = 10;
|
||||
const tkInt16: int = 11;
|
||||
const tkInt32: int = 12;
|
||||
const tkInt64: int = 13;
|
||||
const tkInt: int = 14;
|
||||
const tkUInt8: int = 15;
|
||||
const tkUInt16: int = 16;
|
||||
const tkUInt32: int = 17;
|
||||
const tkUInt64: int = 18;
|
||||
const tkUInt: int = 19;
|
||||
const tkFloat32: int = 20;
|
||||
const tkFloat64: int = 21;
|
||||
const tkPointer: int = 22;
|
||||
const tkSlice: int = 23;
|
||||
const tkRange: int = 24;
|
||||
const tkTuple: int = 25;
|
||||
const tkNamed: int = 26;
|
||||
const tkTypeParam: int = 27;
|
||||
const tkFunc: int = 28;
|
||||
const tyUnknown: int = 0;
|
||||
const tyVoid: int = 1;
|
||||
const tyBool: int = 2;
|
||||
const tyBool8: int = 3;
|
||||
const tyBool16: int = 4;
|
||||
const tyBool32: int = 5;
|
||||
const tyChar8: int = 6;
|
||||
const tyChar16: int = 7;
|
||||
const tyChar32: int = 8;
|
||||
const tyStr: int = 9;
|
||||
const tyInt8: int = 10;
|
||||
const tyInt16: int = 11;
|
||||
const tyInt32: int = 12;
|
||||
const tyInt64: int = 13;
|
||||
const tyInt: int = 14;
|
||||
const tyUInt8: int = 15;
|
||||
const tyUInt16: int = 16;
|
||||
const tyUInt32: int = 17;
|
||||
const tyUInt64: int = 18;
|
||||
const tyUInt: int = 19;
|
||||
const tyFloat32: int = 20;
|
||||
const tyFloat64: int = 21;
|
||||
const tyPointer: int = 22;
|
||||
const tySlice: int = 23;
|
||||
const tyRange: int = 24;
|
||||
const tyTuple: int = 25;
|
||||
const tyNamed: int = 26;
|
||||
const tyTypeParam: int = 27;
|
||||
const tyFunc: int = 28;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Type struct
|
||||
@@ -57,67 +57,67 @@ struct Type {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Type_MakeUnknown() -> Type {
|
||||
return Type { kind: tkUnknown, name: "", innerCount: 0,
|
||||
return Type { kind: tyUnknown, name: "", innerCount: 0,
|
||||
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
||||
innerKind3: 0, innerName3: "" };
|
||||
}
|
||||
|
||||
func Type_MakeVoid() -> Type {
|
||||
return Type { kind: tkVoid, name: "void", innerCount: 0,
|
||||
return Type { kind: tyVoid, name: "void", innerCount: 0,
|
||||
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
||||
innerKind3: 0, innerName3: "" };
|
||||
}
|
||||
|
||||
func Type_MakeBool() -> Type {
|
||||
return Type { kind: tkBool, name: "bool", innerCount: 0,
|
||||
return Type { kind: tyBool, name: "bool", innerCount: 0,
|
||||
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
||||
innerKind3: 0, innerName3: "" };
|
||||
}
|
||||
|
||||
func Type_MakeInt() -> Type {
|
||||
return Type { kind: tkInt, name: "int", innerCount: 0,
|
||||
return Type { kind: tyInt, name: "int", innerCount: 0,
|
||||
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
||||
innerKind3: 0, innerName3: "" };
|
||||
}
|
||||
|
||||
func Type_MakeInt64() -> Type {
|
||||
return Type { kind: tkInt64, name: "int64", innerCount: 0,
|
||||
return Type { kind: tyInt64, name: "int64", innerCount: 0,
|
||||
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
||||
innerKind3: 0, innerName3: "" };
|
||||
}
|
||||
|
||||
func Type_MakeUInt() -> Type {
|
||||
return Type { kind: tkUInt, name: "uint", innerCount: 0,
|
||||
return Type { kind: tyUInt, name: "uint", innerCount: 0,
|
||||
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
||||
innerKind3: 0, innerName3: "" };
|
||||
}
|
||||
|
||||
func Type_MakeFloat64() -> Type {
|
||||
return Type { kind: tkFloat64, name: "float64", innerCount: 0,
|
||||
return Type { kind: tyFloat64, name: "float64", innerCount: 0,
|
||||
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
||||
innerKind3: 0, innerName3: "" };
|
||||
}
|
||||
|
||||
func Type_MakeStr() -> Type {
|
||||
return Type { kind: tkStr, name: "String", innerCount: 0,
|
||||
return Type { kind: tyStr, name: "String", innerCount: 0,
|
||||
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
||||
innerKind3: 0, innerName3: "" };
|
||||
}
|
||||
|
||||
func Type_MakePointer(pointee: Type) -> Type {
|
||||
return Type { kind: tkPointer, name: "", innerCount: 1,
|
||||
return Type { kind: tyPointer, name: "", innerCount: 1,
|
||||
innerKind1: pointee.kind, innerName1: pointee.name,
|
||||
innerKind2: 0, innerName2: "", innerKind3: 0, innerName3: "" };
|
||||
}
|
||||
|
||||
func Type_MakeNamed(name: String) -> Type {
|
||||
return Type { kind: tkNamed, name: name, innerCount: 0,
|
||||
return Type { kind: tyNamed, name: name, innerCount: 0,
|
||||
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
||||
innerKind3: 0, innerName3: "" };
|
||||
}
|
||||
|
||||
func Type_MakeTypeParam(name: String) -> Type {
|
||||
return Type { kind: tkTypeParam, name: name, innerCount: 0,
|
||||
return Type { kind: tyTypeParam, name: name, innerCount: 0,
|
||||
innerKind1: 0, innerName1: "", innerKind2: 0, innerName2: "",
|
||||
innerKind3: 0, innerName3: "" };
|
||||
}
|
||||
@@ -128,32 +128,32 @@ func Type_MakeTypeParam(name: String) -> Type {
|
||||
|
||||
func Type_IsNumeric(t: Type) -> bool {
|
||||
let k: int = t.kind;
|
||||
if k == tkInt8 || k == tkInt16 || k == tkInt32 || k == tkInt64 || k == tkInt { return true; }
|
||||
if k == tkUInt8 || k == tkUInt16 || k == tkUInt32 || k == tkUInt64 || k == tkUInt { return true; }
|
||||
if k == tkFloat32 || k == tkFloat64 { return true; }
|
||||
if k == tkUnknown || k == tkNamed || k == tkTypeParam { return true; }
|
||||
if k == tyInt8 || k == tyInt16 || k == tyInt32 || k == tyInt64 || k == tyInt { return true; }
|
||||
if k == tyUInt8 || k == tyUInt16 || k == tyUInt32 || k == tyUInt64 || k == tyUInt { return true; }
|
||||
if k == tyFloat32 || k == tyFloat64 { return true; }
|
||||
if k == tyUnknown || k == tyNamed || k == tyTypeParam { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
func Type_IsInteger(t: Type) -> bool {
|
||||
let k: int = t.kind;
|
||||
if k == tkInt8 || k == tkInt16 || k == tkInt32 || k == tkInt64 || k == tkInt { return true; }
|
||||
if k == tkUInt8 || k == tkUInt16 || k == tkUInt32 || k == tkUInt64 || k == tkUInt { return true; }
|
||||
if k == tkUnknown || k == tkNamed || k == tkTypeParam { return true; }
|
||||
if k == tyInt8 || k == tyInt16 || k == tyInt32 || k == tyInt64 || k == tyInt { return true; }
|
||||
if k == tyUInt8 || k == tyUInt16 || k == tyUInt32 || k == tyUInt64 || k == tyUInt { return true; }
|
||||
if k == tyUnknown || k == tyNamed || k == tyTypeParam { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
func Type_IsBool(t: Type) -> bool {
|
||||
let k: int = t.kind;
|
||||
return k == tkBool || k == tkBool8 || k == tkBool16 || k == tkBool32;
|
||||
return k == tyBool || k == tyBool8 || k == tyBool16 || k == tyBool32;
|
||||
}
|
||||
|
||||
func Type_IsPointer(t: Type) -> bool {
|
||||
return t.kind == tkPointer;
|
||||
return t.kind == tyPointer;
|
||||
}
|
||||
|
||||
func Type_IsSlice(t: Type) -> bool {
|
||||
return t.kind == tkSlice;
|
||||
return t.kind == tySlice;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -162,7 +162,7 @@ func Type_IsSlice(t: Type) -> bool {
|
||||
|
||||
func Type_Eq(a: Type, b: Type) -> bool {
|
||||
if a.kind != b.kind { return false; }
|
||||
if a.kind == tkNamed || a.kind == tkTypeParam {
|
||||
if a.kind == tyNamed || a.kind == tyTypeParam {
|
||||
return String_Eq(a.name, b.name);
|
||||
}
|
||||
return true;
|
||||
@@ -173,16 +173,16 @@ func Type_Eq(a: Type, b: Type) -> bool {
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func Type_ToString(t: Type) -> String {
|
||||
if t.kind == tkVoid { return "void"; }
|
||||
if t.kind == tkBool { return "bool"; }
|
||||
if t.kind == tkStr { return "String"; }
|
||||
if t.kind == tkInt { return "int"; }
|
||||
if t.kind == tkInt64 { return "int64"; }
|
||||
if t.kind == tkUInt { return "uint"; }
|
||||
if t.kind == tkFloat64 { return "float64"; }
|
||||
if t.kind == tkNamed { return t.name; }
|
||||
if t.kind == tkTypeParam { return t.name; }
|
||||
if t.kind == tkPointer { return "*" + t.innerName1; }
|
||||
if t.kind == tyVoid { return "void"; }
|
||||
if t.kind == tyBool { return "bool"; }
|
||||
if t.kind == tyStr { return "String"; }
|
||||
if t.kind == tyInt { return "int"; }
|
||||
if t.kind == tyInt64 { return "int64"; }
|
||||
if t.kind == tyUInt { return "uint"; }
|
||||
if t.kind == tyFloat64 { return "float64"; }
|
||||
if t.kind == tyNamed { return t.name; }
|
||||
if t.kind == tyTypeParam { return t.name; }
|
||||
if t.kind == tyPointer { return String_Concat("*", t.innerName1); }
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user