Phase 8.3: Fix spawn to use bux_task_spawn for non-async functions
- Added exprSpawnAsync flag to AST ekSpawn - Sema checks if callee is async and sets the flag - HIR hSpawn carries spawnAsync flag - C backend uses bux_task_spawn for non-async (OS threads) and bux_async_spawn for async (coroutines) - Added concurrency example to test suite
This commit is contained in:
@@ -3,7 +3,7 @@ SRC := src/main.nim
|
||||
OUT := buxc
|
||||
BUILD_DIR := build
|
||||
|
||||
EXAMPLES := hello fibonacci factorial structs enums methods algebraic_enums generics generics_struct generic_infer generic_infer2 extend_generic pattern_matching strings strings2 map result_option try_operator ownership ctfe async
|
||||
EXAMPLES := hello fibonacci factorial structs enums methods algebraic_enums generics generics_struct generic_infer generic_infer2 extend_generic pattern_matching strings strings2 map result_option try_operator ownership ctfe async concurrency
|
||||
|
||||
.PHONY: all build dev test clean test-examples
|
||||
|
||||
|
||||
@@ -207,6 +207,7 @@ type
|
||||
of ekSpawn:
|
||||
exprSpawnCallee*: Expr
|
||||
exprSpawnArgs*: seq[Expr]
|
||||
exprSpawnAsync*: bool
|
||||
of ekAwait:
|
||||
exprAwaitOperand*: Expr
|
||||
of ekBlock:
|
||||
|
||||
+8
-7
@@ -294,14 +294,15 @@ proc emitExpr(be: var CBackend, node: HirNode): string =
|
||||
return &"sizeof({typ})"
|
||||
|
||||
of hSpawn:
|
||||
if node.spawnArgs.len > 0:
|
||||
# Fallback to OS thread spawn for functions with arguments
|
||||
var argsStr = ""
|
||||
let arg = be.emitExpr(node.spawnArgs[0])
|
||||
argsStr = &"(void*){arg}"
|
||||
return &"bux_task_spawn({node.spawnCallee}, {argsStr})"
|
||||
else:
|
||||
if node.spawnAsync:
|
||||
# Async coroutine spawn
|
||||
return &"bux_async_spawn({node.spawnCallee})"
|
||||
else:
|
||||
# OS thread spawn
|
||||
var argsStr = "NULL"
|
||||
if node.spawnArgs.len > 0:
|
||||
argsStr = &"(void*){be.emitExpr(node.spawnArgs[0])}"
|
||||
return &"bux_task_spawn((void* (*)(void*)){node.spawnCallee}, {argsStr})"
|
||||
|
||||
of hDynRef:
|
||||
let data = be.emitExpr(node.dynRefData)
|
||||
|
||||
@@ -118,6 +118,7 @@ type
|
||||
of hSpawn:
|
||||
spawnCallee*: string
|
||||
spawnArgs*: seq[HirNode]
|
||||
spawnAsync*: bool
|
||||
of hEmit:
|
||||
emitCode*: string
|
||||
of hDynRef:
|
||||
|
||||
@@ -832,6 +832,7 @@ proc lowerExpr(ctx: var LowerCtx, expr: Expr): HirNode =
|
||||
for arg in expr.exprSpawnArgs:
|
||||
args.add(ctx.lowerExpr(arg))
|
||||
return HirNode(kind: hSpawn, spawnCallee: calleeName, spawnArgs: args,
|
||||
spawnAsync: expr.exprSpawnAsync,
|
||||
typ: makePointer(makeVoid()), loc: loc)
|
||||
|
||||
of ekAwait:
|
||||
|
||||
+1
-1
@@ -465,7 +465,7 @@ proc parsePrimary(p: var Parser): Expr =
|
||||
if p.check(tkComma):
|
||||
discard p.advance()
|
||||
discard p.expect(tkRParen, "expected ')' after spawn arguments")
|
||||
return Expr(kind: ekSpawn, loc: loc, exprSpawnCallee: callee, exprSpawnArgs: args)
|
||||
return Expr(kind: ekSpawn, loc: loc, exprSpawnCallee: callee, exprSpawnArgs: args, exprSpawnAsync: false)
|
||||
of tkHashLine:
|
||||
discard p.advance()
|
||||
return Expr(kind: ekIntrinsic, loc: loc, exprIntrinsic: ikLine)
|
||||
|
||||
@@ -1143,6 +1143,18 @@ proc checkExpr(sema: var Sema, expr: Expr, scope: Scope): Type =
|
||||
discard sema.checkExpr(expr.exprSpawnCallee, scope)
|
||||
for arg in expr.exprSpawnArgs:
|
||||
discard sema.checkExpr(arg, scope)
|
||||
# Determine if callee is async
|
||||
var calleeName = ""
|
||||
case expr.exprSpawnCallee.kind
|
||||
of ekIdent:
|
||||
calleeName = expr.exprSpawnCallee.exprIdent
|
||||
of ekPath:
|
||||
calleeName = expr.exprSpawnCallee.exprPath.join("_")
|
||||
else: discard
|
||||
if calleeName != "":
|
||||
let sym = sema.globalScope.lookup(calleeName)
|
||||
if sym != nil and sym.decl != nil and sym.decl.kind == dkFunc and sym.decl.declFuncIsAsync:
|
||||
expr.exprSpawnAsync = true
|
||||
return makePointer(makeVoid())
|
||||
of ekAwait:
|
||||
let operand = sema.checkExpr(expr.exprAwaitOperand, scope)
|
||||
|
||||
Reference in New Issue
Block a user