feat: keyword-as-identifier, hFieldPtr/hSizeOf handling, skip forward decl bodies

This commit is contained in:
2026-05-31 21:35:34 +03:00
parent 27b3db5091
commit 194d70173c
4 changed files with 86 additions and 22 deletions
+34 -11
View File
@@ -259,6 +259,26 @@ func CBE_EmitExpr(cbe: *CEmitter, node: *HirNode) {
return; return;
} }
// Field access: obj.field — emit as obj->field (since most are pointers)
if kind == hFieldPtr {
CBE_EmitExpr(cbe, node.child1);
StringBuilder_Append(&cbe.sb, "->");
StringBuilder_Append(&cbe.sb, node.strValue);
return;
}
// Sizeof: sizeof(Type) — emit as sizeof(Type)
if kind == hSizeOf {
StringBuilder_Append(&cbe.sb, "sizeof(");
if !String_Eq(node.typeName, "") {
StringBuilder_Append(&cbe.sb, node.typeName);
} else {
StringBuilder_Append(&cbe.sb, "int");
}
StringBuilder_Append(&cbe.sb, ")");
return;
}
// Index: arr[idx] — emit as arr[idx] // Index: arr[idx] — emit as arr[idx]
if kind == hIndexPtr { if kind == hIndexPtr {
CBE_EmitExpr(cbe, node.child1); CBE_EmitExpr(cbe, node.child1);
@@ -512,21 +532,24 @@ func CBackend_Generate(mod: *HirModule) -> String {
i = 0; i = 0;
while i < mod.funcCount { while i < mod.funcCount {
if String_Eq(mod.funcs[i].name, "Main") { hasMain = true; } if String_Eq(mod.funcs[i].name, "Main") { hasMain = true; }
// Skip forward declarations (functions without body)
let body: *HirNode = mod.funcs[i].body;
if body == null as *HirNode {
i = i + 1;
continue;
}
CBE_EmitFuncDecl(cbe, &mod.funcs[i]); CBE_EmitFuncDecl(cbe, &mod.funcs[i]);
StringBuilder_Append(&cbe.sb, " {\n"); StringBuilder_Append(&cbe.sb, " {\n");
// Body // Body
var hasReturn: bool = false; var hasReturn: bool = false;
let body: *HirNode = mod.funcs[i].body; cbe.indent = 1;
if body != null as *HirNode { CBE_EmitExpr(cbe, body);
cbe.indent = 1; cbe.indent = 0;
CBE_EmitExpr(cbe, body); // Check if body has a return statement
cbe.indent = 0; var stmt: *HirNode = body.child1;
// Check if body has a return statement while stmt != null as *HirNode {
var stmt: *HirNode = body.child1; if stmt.kind == hReturn { hasReturn = true; }
while stmt != null as *HirNode { stmt = stmt.child3;
if stmt.kind == hReturn { hasReturn = true; }
stmt = stmt.child3;
}
} }
// Add default return 0 only if function returns int and has no explicit return // Add default return 0 only if function returns int and has no explicit return
if String_Eq(mod.funcs[i].retTypeName, "int") && !hasReturn { if String_Eq(mod.funcs[i].retTypeName, "int") && !hasReturn {
+9
View File
@@ -105,6 +105,15 @@ func Lcx_LowerExpr(ctx: *LowerCtx, expr: *Expr) -> *HirNode {
return n; return n;
} }
// Sizeof
if kind == ekSizeOf {
n.kind = hSizeOf;
if expr.refType != null as *TypeExpr {
n.typeName = expr.refType.typeName;
}
return n;
}
// Field access // Field access
if kind == ekField { if kind == ekField {
n.kind = hFieldPtr; n.kind = hFieldPtr;
+34 -11
View File
@@ -259,6 +259,26 @@ func CBE_EmitExpr(cbe: *CEmitter, node: *HirNode) {
return; return;
} }
// Field access: obj.field — emit as obj->field (since most are pointers)
if kind == hFieldPtr {
CBE_EmitExpr(cbe, node.child1);
StringBuilder_Append(&cbe.sb, "->");
StringBuilder_Append(&cbe.sb, node.strValue);
return;
}
// Sizeof: sizeof(Type) — emit as sizeof(Type)
if kind == hSizeOf {
StringBuilder_Append(&cbe.sb, "sizeof(");
if !String_Eq(node.typeName, "") {
StringBuilder_Append(&cbe.sb, node.typeName);
} else {
StringBuilder_Append(&cbe.sb, "int");
}
StringBuilder_Append(&cbe.sb, ")");
return;
}
// Index: arr[idx] — emit as arr[idx] // Index: arr[idx] — emit as arr[idx]
if kind == hIndexPtr { if kind == hIndexPtr {
CBE_EmitExpr(cbe, node.child1); CBE_EmitExpr(cbe, node.child1);
@@ -512,21 +532,24 @@ func CBackend_Generate(mod: *HirModule) -> String {
i = 0; i = 0;
while i < mod.funcCount { while i < mod.funcCount {
if String_Eq(mod.funcs[i].name, "Main") { hasMain = true; } if String_Eq(mod.funcs[i].name, "Main") { hasMain = true; }
// Skip forward declarations (functions without body)
let body: *HirNode = mod.funcs[i].body;
if body == null as *HirNode {
i = i + 1;
continue;
}
CBE_EmitFuncDecl(cbe, &mod.funcs[i]); CBE_EmitFuncDecl(cbe, &mod.funcs[i]);
StringBuilder_Append(&cbe.sb, " {\n"); StringBuilder_Append(&cbe.sb, " {\n");
// Body // Body
var hasReturn: bool = false; var hasReturn: bool = false;
let body: *HirNode = mod.funcs[i].body; cbe.indent = 1;
if body != null as *HirNode { CBE_EmitExpr(cbe, body);
cbe.indent = 1; cbe.indent = 0;
CBE_EmitExpr(cbe, body); // Check if body has a return statement
cbe.indent = 0; var stmt: *HirNode = body.child1;
// Check if body has a return statement while stmt != null as *HirNode {
var stmt: *HirNode = body.child1; if stmt.kind == hReturn { hasReturn = true; }
while stmt != null as *HirNode { stmt = stmt.child3;
if stmt.kind == hReturn { hasReturn = true; }
stmt = stmt.child3;
}
} }
// Add default return 0 only if function returns int and has no explicit return // Add default return 0 only if function returns int and has no explicit return
if String_Eq(mod.funcs[i].retTypeName, "int") && !hasReturn { if String_Eq(mod.funcs[i].retTypeName, "int") && !hasReturn {
+9
View File
@@ -105,6 +105,15 @@ func Lcx_LowerExpr(ctx: *LowerCtx, expr: *Expr) -> *HirNode {
return n; return n;
} }
// Sizeof
if kind == ekSizeOf {
n.kind = hSizeOf;
if expr.refType != null as *TypeExpr {
n.typeName = expr.refType.typeName;
}
return n;
}
// Field access // Field access
if kind == ekField { if kind == ekField {
n.kind = hFieldPtr; n.kind = hFieldPtr;