feat(tpv): 语言内协程 M1-M7 移植——async/await 状态机 + 异常传播 + 帧池
- M1: async def -> 帧结构体 + create_/resume_ 状态机 + coro.coro_run 内联 - M2: async 参数、嵌套 await 提升 __await_N、If/While 内 await - M3: For 内 await(range->While)、coro_sleep 轮询挂起、coro_destroy 回池 - M4: raise 存码、await 子帧异常传播、coro_exception、coro_gather - M5/M6: try/except 链式匹配 + as e 绑定 + 异常类型码 - M7: try/finally、异常消息 msg 槽、自定义异常类、帧池复用
This commit is contained in:
1 parent
f0a70748d7
commit
82a86761b9
11 files changed
+7722
-4575
No files matched your search
@@ -1352,6 +1352,17 @@ class AssignGenMixin:
|
||||
|
||||
# 如果有初始值,store
|
||||
if aa.value is not None:
|
||||
# 协程(TPV-M1):记录 async 函数调用赋值的变量名(coro.coro_run
|
||||
# 内联翻译反查帧类型用)。对齐 TPC HandlesAnnAssign.py L319-326:
|
||||
# value 是 Call 且 func 是 Name 且该名字是 async 函数时,
|
||||
# 登记 _coro_var_async[target] = callee。
|
||||
if aa.value.kind() == ast.ASTKind.Call:
|
||||
val_cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(aa.value)
|
||||
if val_cl.func is not None and val_cl.func.kind() == ast.ASTKind.Name:
|
||||
val_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(val_cl.func)
|
||||
if val_nm.id is not None:
|
||||
if self.Gen.AsyncGen.is_async_func(trans, val_nm.id) != 0:
|
||||
self.Gen.AsyncGen.register_coro_var(trans, nm.id, val_nm.id)
|
||||
# 局部数组:列表字面量 → 逐元素 GEP + store 初始化
|
||||
# 修复:此前局部 CArray[...] = [x, y] 会走 translate_list_literal,
|
||||
# 错误触发 list[T] 泛型特化(堆对象)导致崩溃(如 this.vp 的
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+1537
-1509
File diff suppressed because it is too large.
Load diff
+1202
-1151
File diff suppressed because it is too large.
Load diff
@@ -361,11 +361,11 @@ class ClassGenBase:
|
||||
nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(deco)
|
||||
if nm.id is not None:
|
||||
if string.strcmp(nm.id, "staticmethod") == 0:
|
||||
meta |= META_STATIC
|
||||
meta |= GenTypes.META_STATIC
|
||||
elif string.strcmp(nm.id, "property") == 0:
|
||||
meta |= META_PROP_GETTER
|
||||
meta |= GenTypes.META_PROP_GETTER
|
||||
elif string.strcmp(nm.id, "classmethod") == 0:
|
||||
meta |= META_CLASS
|
||||
meta |= GenTypes.META_CLASS
|
||||
elif string.strcmp(nm.id, "TLS") == 0:
|
||||
meta |= META_TLS
|
||||
elif k == ast.ASTKind.Attribute:
|
||||
@@ -385,11 +385,11 @@ class ClassGenBase:
|
||||
if is_prop_name != 0 or string.strcmp(at.attr, "setter") == 0 \
|
||||
or string.strcmp(at.attr, "getter") == 0 or string.strcmp(at.attr, "deleter") == 0:
|
||||
if string.strcmp(at.attr, "setter") == 0:
|
||||
meta |= META_PROP_SETTER
|
||||
meta |= GenTypes.META_PROP_SETTER
|
||||
elif string.strcmp(at.attr, "getter") == 0:
|
||||
meta |= META_PROP_GETTER
|
||||
meta |= GenTypes.META_PROP_GETTER
|
||||
elif string.strcmp(at.attr, "deleter") == 0:
|
||||
meta |= META_PROP_DELETER
|
||||
meta |= GenTypes.META_PROP_DELETER
|
||||
return meta
|
||||
def register_class_meta(self, pool: memhub.MemBuddy | t.CPtr,
|
||||
kind: int, cls: str, field: str) -> int:
|
||||
|
||||
+1297
-1310
File diff suppressed because it is too large.
Load diff
@@ -118,4 +118,20 @@ class ExprGenMixin(ExprGenBase.ExprGenBase):
|
||||
# 解析器对 f"{expr:spec}"(单 FormattedValue 无字面量)返回裸 FormattedValue
|
||||
# 而非 JoinedStr(见 ast/parser.vp _parse_fstring),需单独翻译
|
||||
return self.Gen.ExprGenFstr.translate_formatted_value(builder, pool, mod, node, trans)
|
||||
elif k == ast.ASTKind.Await:
|
||||
# 协程 await(TPV-M1):await 目标是 async 函数调用时内联翻译
|
||||
# (子帧创建 + resume 到 DONE + 取子帧 ret 存父帧 await 槽 + 父挂起),
|
||||
# 返回子协程 ret 值(i32)。顶层 await(AnnAssign/Assign 的 value 直接
|
||||
# 是 Await)由 AsyncGen 段翻译特判处理,本分支覆盖表达式上下文中的
|
||||
# await(M1 覆盖有限场景,详见 AsyncGenMixin._emit_await)。
|
||||
aw: ast.Await | t.CPtr = (ast.Await | t.CPtr)(node)
|
||||
if aw is not None and aw.value is not None and aw.value.kind() == ast.ASTKind.Call:
|
||||
aw_cl: ast.Call | t.CPtr = (ast.Call | t.CPtr)(aw.value)
|
||||
if aw_cl.func is not None and aw_cl.func.kind() == ast.ASTKind.Name:
|
||||
aw_nm: ast.Name | t.CPtr = (ast.Name | t.CPtr)(aw_cl.func)
|
||||
if aw_nm.id is not None and trans is not None:
|
||||
if self.Gen.AsyncGen.is_async_func(trans, aw_nm.id) != 0:
|
||||
return self.Gen.AsyncGen._emit_await(
|
||||
builder, pool, mod, trans, aw, aw_nm.id)
|
||||
return None
|
||||
return None
|
||||
@@ -224,6 +224,13 @@ class FuncGenDef(CallGenBase.CallGenBase):
|
||||
if fd is None or fd.name is None:
|
||||
return 0
|
||||
|
||||
# async def(TPV-M1 协程):FLAG_IS_ASYNC=1(includes/ast/stmts.vp L342-345,
|
||||
# 解析器把 async def 存为 FunctionDef 且 flags & 1)。
|
||||
# → 走 AsyncGenMixin 状态机翻译(create_<name>/resume_<name>),
|
||||
# 早返回不进普通函数路径(普通路径生成 ret 型普通函数,无法挂起/恢复)。
|
||||
if fd.flags is not None and (fd.flags & 1) != 0:
|
||||
return self.Gen.AsyncGen.translate_async_function(trans, node)
|
||||
|
||||
pool: memhub.MemBuddy | t.CPtr = trans.Pool
|
||||
mod: llvmlite.LLVMModule | t.CPtr = trans.Module
|
||||
imported_modules: str = trans._imported_modules
|
||||
|
||||
@@ -50,6 +50,7 @@ import lib.core.Gen.StmtGenDeclMixin as StmtGenDeclMixin
|
||||
import lib.core.Gen.StmtGenMixin as StmtGenMixin
|
||||
import lib.core.Gen.MatchGenMixin as MatchGenMixin
|
||||
import lib.core.Gen.AssignGenMixin as AssignGenMixin
|
||||
import lib.core.Gen.AsyncGenMixin as AsyncGenMixin
|
||||
import lib.core.Gen.VarGenMixin as VarGenMixin
|
||||
import lib.core.Gen.TranslatorGenMixin as TranslatorGenMixin
|
||||
|
||||
@@ -111,6 +112,7 @@ class Generator:
|
||||
StmtGen: StmtGenMixin.StmtGenMixin | t.CPtr
|
||||
MatchGen: MatchGenMixin.MatchGenMixin | t.CPtr
|
||||
AssignGen: AssignGenMixin.AssignGenMixin | t.CPtr
|
||||
AsyncGen: AsyncGenMixin.AsyncGenMixin | t.CPtr
|
||||
VarGen: VarGenMixin.VarGenMixin | t.CPtr
|
||||
TranslatorGen: TranslatorGenMixin.TranslatorGenMixin | t.CPtr
|
||||
|
||||
@@ -440,6 +442,13 @@ class Generator:
|
||||
string.memset(SubTranslatorGen, 0, TranslatorGenMixin.TranslatorGenMixin.__sizeof__())
|
||||
SubTranslatorGen.Gen = self
|
||||
self.TranslatorGen = SubTranslatorGen
|
||||
SubAsyncGen: AsyncGenMixin.AsyncGenMixin | t.CPtr = CompilerFactory.get_perm_pool().alloc(AsyncGenMixin.AsyncGenMixin.__sizeof__())
|
||||
if SubAsyncGen is None:
|
||||
stdio.printf("FAIL: AsyncGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubAsyncGen, 0, AsyncGenMixin.AsyncGenMixin.__sizeof__())
|
||||
SubAsyncGen.Gen = self
|
||||
self.AsyncGen = SubAsyncGen
|
||||
|
||||
# ---- 初始化各子对象字段(Init* 方法内联调用) ----
|
||||
SubBaseGen.InitBaseGen(pool)
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,58 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import stdio
|
||||
import coro
|
||||
|
||||
|
||||
# TPV-M3~M7 协程综合测试:
|
||||
# M3: For 内 await(range→While)、coro_sleep 挂起、coro_destroy 帧回池
|
||||
# M4: raise 存码、await 子帧异常传播、coro_exception 查询
|
||||
# M5/M6: try/except(链式匹配 + as e 绑定异常码 + 类型码)
|
||||
# M7: try/finally、异常消息 msg 槽、自定义异常类、帧池复用
|
||||
class MyError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
async def leaf(x: int) -> int:
|
||||
return x * 2
|
||||
|
||||
|
||||
async def task(n: int) -> int:
|
||||
s: int = 0
|
||||
for i in range(3): # M3:For 内 await
|
||||
s = s + await leaf(i)
|
||||
if s > 4:
|
||||
await coro.coro_sleep(5) # M3:coro_sleep 挂起(wake 槽 + 轮询)
|
||||
try:
|
||||
raise ValueError("boom") # M4/M6:raise 类型 + M7 消息
|
||||
except ValueError as e: # M5/M6:as e 绑定异常码
|
||||
s = s + e
|
||||
return s
|
||||
|
||||
|
||||
async def raiser() -> int:
|
||||
try:
|
||||
raise MyError("fin_msg") # M7:自定义异常类 + 消息
|
||||
finally:
|
||||
x: int = 99 # M7:finally 正常路径执行
|
||||
return 0
|
||||
|
||||
|
||||
def main() -> int:
|
||||
tt: t.CPtr = task(3)
|
||||
r: int = coro.coro_run(tt)
|
||||
e: int = coro.coro_exception(tt)
|
||||
stdio.printf("coro result = %d exc = %d\n", r, e)
|
||||
coro.coro_destroy(tt) # M3/M7:destroy 回池
|
||||
t1: t.CPtr = raiser()
|
||||
r1: int = coro.coro_run(t1)
|
||||
e1: int = coro.coro_exception(t1)
|
||||
m1: t.CPtr = coro.coro_exception_msg(t1)
|
||||
stdio.printf("coro result = %d exc = %d msg = %s\n", r1, e1, m1)
|
||||
coro.coro_destroy(t1)
|
||||
t2: t.CPtr = raiser() # 帧池复用
|
||||
r2: int = coro.coro_run(t2)
|
||||
e2: int = coro.coro_exception(t2)
|
||||
stdio.printf("coro result = %d exc = %d\n", r2, e2)
|
||||
coro.coro_destroy(t2)
|
||||
return 0
|
||||
Reference in new issue
Block a user