feat: async/await/spawn + fix else-if lowering bug
Self-hosted compiler (buxc2):
- Add async/await/spawn tokens, parsing, HIR, lowering, C emission
- Fix pointer type emission (*T -> T*) in C backend
- Fix sizeof(Type) parsing with parentheses
- Fix import ::{...} infinite loop guard
- Fix int64 emission by avoiding else-if chain workaround
- Add debug-free cli and hir_lower
Bootstrap compiler (Nim):
- Fix critical else-if lowering bug in hir_lower.nim:
when both elseIfs and else block exist, elseIfs were dropped
causing all else-if chains to collapse to if+else only
Runtime:
- Fix bux_async_await memory corruption (don't free in run)
- Add bux_remove_from_ready for safe cleanup
- Fix forward declaration and deduplicate bux_now_ms
Docs & examples:
- Update async.bux example with proper int64 params
- Update README, LanguageRef, Stdlib, PLAN for async features
- Mark Phase 7.10 bootstrap loop as completed
All 27 examples pass. buxc2 check/build work on all examples.
This commit is contained in:
+50
-13
@@ -127,15 +127,9 @@ func parserParseType(p: *Parser) -> *TypeExpr {
|
||||
te.line = line;
|
||||
te.column = col;
|
||||
te.pointerPointee = parserParseType(p);
|
||||
// Set typeName to "String*" for String pointer, else "int*"
|
||||
// Set typeName to "Pointee*"
|
||||
if te.pointerPointee != null as *TypeExpr {
|
||||
if String_Eq(te.pointerPointee.typeName, "String") {
|
||||
te.typeName = "String*";
|
||||
} else if String_Eq(te.pointerPointee.typeName, "int") {
|
||||
te.typeName = "int*";
|
||||
} else {
|
||||
te.typeName = "int*";
|
||||
}
|
||||
te.typeName = String_Concat(te.pointerPointee.typeName, "*");
|
||||
}
|
||||
return te;
|
||||
}
|
||||
@@ -241,8 +235,32 @@ func parserParsePrimary(p: *Parser) -> *Expr {
|
||||
// sizeof(Type)
|
||||
if kind == tkSizeOf {
|
||||
discard parserAdvance(p);
|
||||
discard parserExpect(p, tkLParen, "expected '(' after sizeof");
|
||||
let e: *Expr = parserMakeExpr(ekSizeOf, line, col);
|
||||
e.refType = parserParseType(p);
|
||||
discard parserExpect(p, tkRParen, "expected ')' after sizeof type");
|
||||
return e;
|
||||
}
|
||||
|
||||
// spawn Callee(args)
|
||||
if kind == tkSpawn {
|
||||
discard parserAdvance(p);
|
||||
let e: *Expr = parserMakeExpr(ekSpawn, line, col);
|
||||
e.child1 = parserParsePrimary(p);
|
||||
// Optional call arguments
|
||||
if parserCheck(p, tkLParen) {
|
||||
discard parserAdvance(p);
|
||||
if !parserCheck(p, tkRParen) {
|
||||
e.child2 = parserParseExpr(p);
|
||||
if parserMatch(p, tkComma) {
|
||||
e.child3 = parserParseExpr(p);
|
||||
while parserMatch(p, tkComma) {
|
||||
discard parserParseExpr(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
discard parserExpect(p, tkRParen, "expected ')' after spawn arguments");
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
@@ -322,6 +340,20 @@ func parserParsePostfix(p: *Parser) -> *Expr {
|
||||
continue;
|
||||
}
|
||||
|
||||
// .await
|
||||
if kind == tkDot {
|
||||
if parserPeek(p, 1) == tkAwait {
|
||||
discard parserAdvance(p); // .
|
||||
discard parserAdvance(p); // await
|
||||
let line: uint32 = parserCurToken(p).line;
|
||||
let col: uint32 = parserCurToken(p).column;
|
||||
let e: *Expr = parserMakeExpr(ekAwait, line, col);
|
||||
e.child1 = left;
|
||||
left = e;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Field: expr.name
|
||||
if kind == tkDot {
|
||||
discard parserAdvance(p);
|
||||
@@ -765,7 +797,7 @@ func parserParseParamList(p: *Parser) -> *Decl {
|
||||
// Declarations
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
func parserParseFuncDecl(p: *Parser, isPublic: bool, isExtern: bool) -> *Decl {
|
||||
func parserParseFuncDecl(p: *Parser, isPublic: bool, isExtern: bool, isAsync: bool) -> *Decl {
|
||||
let line: uint32 = parserCurToken(p).line;
|
||||
let col: uint32 = parserCurToken(p).column;
|
||||
discard parserExpect(p, tkFunc, "expected 'func'");
|
||||
@@ -776,6 +808,7 @@ func parserParseFuncDecl(p: *Parser, isPublic: bool, isExtern: bool) -> *Decl {
|
||||
d.line = line;
|
||||
d.column = col;
|
||||
d.isPublic = isPublic;
|
||||
d.isAsync = isAsync;
|
||||
d.strValue = nameTok.text;
|
||||
|
||||
// Type params <T, U>
|
||||
@@ -953,7 +986,7 @@ func parserParseImportDecl(p: *Parser, isPublic: bool) -> *Decl {
|
||||
// Parse path: Std::Io::PrintLine
|
||||
var pathStr: String = "";
|
||||
var segCount: int = 0;
|
||||
while parserCheck(p, tkIdent) || (segCount > 0 && parserCheck(p, tkColonColon)) {
|
||||
while parserCheck(p, tkIdent) || (segCount > 0 && parserCheck(p, tkColonColon) && parserPeek(p, 1) != tkLBrace) {
|
||||
if segCount > 0 {
|
||||
discard parserAdvance(p); // ::
|
||||
if String_Len(pathStr) > 0 {
|
||||
@@ -995,7 +1028,7 @@ func parserParseExternDecl(p: *Parser, isPublic: bool) -> *Decl {
|
||||
discard parserExpect(p, tkExtern, "expected 'extern'");
|
||||
|
||||
if parserCheck(p, tkFunc) {
|
||||
let d: *Decl = parserParseFuncDecl(p, isPublic, true);
|
||||
let d: *Decl = parserParseFuncDecl(p, isPublic, true, false);
|
||||
d.kind = dkExternFunc;
|
||||
return d;
|
||||
}
|
||||
@@ -1016,7 +1049,11 @@ func parserParseDecl(p: *Parser) -> *Decl {
|
||||
let isPublic: bool = parserMatch(p, tkPub);
|
||||
let kind: int = parserPeek(p, 0);
|
||||
|
||||
if kind == tkFunc { return parserParseFuncDecl(p, isPublic, false); }
|
||||
if kind == tkAsync && parserPeek(p, 1) == tkFunc {
|
||||
discard parserAdvance(p); // async
|
||||
return parserParseFuncDecl(p, isPublic, false, true);
|
||||
}
|
||||
if kind == tkFunc { return parserParseFuncDecl(p, isPublic, false, false); }
|
||||
if kind == tkStruct { return parserParseStructDecl(p, isPublic); }
|
||||
if kind == tkEnum { return parserParseEnumDecl(p, isPublic); }
|
||||
if kind == tkImport { return parserParseImportDecl(p, isPublic); }
|
||||
@@ -1048,7 +1085,7 @@ func parserParseDecl(p: *Parser) -> *Decl {
|
||||
while !parserCheck(p, tkRBrace) && parserPeek(p, 0) != tkEndOfFile {
|
||||
if parserCheck(p, tkNewLine) { discard parserAdvance(p); continue; }
|
||||
if parserCheck(p, tkFunc) {
|
||||
let m: *Decl = parserParseFuncDecl(p, false, false);
|
||||
let m: *Decl = parserParseFuncDecl(p, false, false, false);
|
||||
// Store method in linked list
|
||||
if d.methodCount == 0 {
|
||||
d.childDecl1 = m;
|
||||
|
||||
Reference in New Issue
Block a user