feat(ast): 支持 volatile 调用前缀与注解位置 __attribute__(...) 修饰符
- Call 新增 IsVolatile 字段(末尾追加,既有字段偏移不变),承载值位置 volatile f() / volatile S() 前缀标记。 - parser 新增 _IsVolatileCallPrefix + _parse_test 消费点:吃掉 volatile 后对解析出的 Call 置 IsVolatile=1。 - parser 注解位置新增 _IsMagicAttributeCall:描述符收集循环扩为 _IsDescriptorKeyword or _IsMagicAttributeCall,把 __attribute__(...) 的实参经 _MakeTAttrMarker 合成为 t.attr.<name> 标记贴到类型联合最左,与 const/volatile 同族语义。
This commit is contained in:
1 parent
622ae03c9f
commit
c392390e0d
2 files changed
+72
-1
No files matched your search
@@ -284,6 +284,10 @@ class Call(ExprNode):
|
||||
func: rawptr[AST]
|
||||
args: rawptr[list[rawptr[AST]]]
|
||||
keywords: rawptr[list[rawptr[AST]]]
|
||||
# 值位置 `volatile f()` / `volatile S()` 前缀标记(见 parser.vp _IsVolatileCallPrefix):
|
||||
# 1=本次调用的结果槽(赋值目标/临时槽)按 volatile 存取,结构体构造的写入亦带
|
||||
# LLVM volatile。追加在末尾:既有字段偏移不变,__sizeof__() 自动纳入。
|
||||
IsVolatile: int
|
||||
|
||||
def __new__(self, pool: rawptr[memhub.MemManager],
|
||||
func: rawptr[AST],
|
||||
@@ -301,6 +305,7 @@ class Call(ExprNode):
|
||||
self.func = func
|
||||
self.args = args
|
||||
self.keywords = keywords
|
||||
self.IsVolatile = 0
|
||||
_set_parent_list(args, self)
|
||||
_set_parent_list(keywords, self)
|
||||
|
||||
|
||||
+67
-1
@@ -375,6 +375,24 @@ def _IsDescriptorKeyword(ps: rawptr[Parser]) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
def _IsMagicAttributeCall(ps: rawptr[Parser]) -> int:
|
||||
"""注解位置的 `__attribute__(...)` 前缀判定,1=是 / 0=否
|
||||
|
||||
`__attribute__` 是软关键字(不进关键字表):只在**注解位置**、且紧跟 '(' 时
|
||||
由本处消费;作普通标识符/装饰器名(`@__attribute__(...)` 走装饰器通道)都不受影响。
|
||||
语义与 const / volatile 描述符同族:顺序自由、可混写。
|
||||
"""
|
||||
if _cur_type(ps) != TokenType.Name:
|
||||
return 0
|
||||
s: str = _cur_str(ps)
|
||||
if s is None or string.strcmp(s, "__attribute__") != 0:
|
||||
return 0
|
||||
nxt: rawptr[Token] = ps.cur.next
|
||||
if nxt is None or nxt.type != TokenType.Op or nxt.op_subtype != TokOp.LPar:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
def _MakeDescriptorMarker(ps: rawptr[Parser]) -> rawptr[AST]:
|
||||
"""由当前描述符关键字构造标记节点 Attribute(Name('t'), 'CConst'/'CVolatile')。
|
||||
|
||||
@@ -980,10 +998,37 @@ def _parse_namedexpr(ps: rawptr[Parser]) -> rawptr[AST]:
|
||||
return left
|
||||
|
||||
|
||||
def _IsVolatileCallPrefix(ps: rawptr[Parser]) -> int:
|
||||
"""值位置的 `volatile 函数()` / `volatile 结构体()` 前缀判定,1=是 / 0=否
|
||||
|
||||
`volatile` 是软关键字:只在"值位置 + 紧跟 调用(Name 后随 '(')"时消费,
|
||||
作注解描述符(`a: volatile int`)与作标识符的写法都不受影响。
|
||||
"""
|
||||
if _cur_kw(ps) != Keyword.Volatile:
|
||||
return 0
|
||||
nxt: rawptr[Token] = ps.cur.next
|
||||
if nxt is None or nxt.type != TokenType.Name:
|
||||
return 0
|
||||
nxt2: rawptr[Token] = nxt.next
|
||||
if nxt2 is None or nxt2.type != TokenType.Op or nxt2.op_subtype != TokOp.LPar:
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
def _parse_test(ps: rawptr[Parser]) -> rawptr[AST]:
|
||||
"""test: or_test ['if' or_test 'else' test] | lambdef"""
|
||||
if _cur_kw(ps) == Keyword.Lambda:
|
||||
return _parse_lambda(ps)
|
||||
# 值位置 volatile 调用前缀:`a: int = volatile f()` / `volatile S()`
|
||||
# ⇒ 消费 volatile 并把调用节点标记为 volatile(结果槽按 volatile 存取;
|
||||
# 结构体构造的写入亦带 LLVM volatile)。LLVM 的 call 无 volatile 限定符,
|
||||
# 故语义只落在内存存取上(见 Call.IsVolatile 注释)。
|
||||
if _IsVolatileCallPrefix(ps) != 0:
|
||||
_advance(ps) # 消费 volatile
|
||||
vinner: rawptr[AST] = _parse_test(ps)
|
||||
if vinner is not None and vinner.kind() == ast.ASTKind.Call:
|
||||
(ast.Call*(vinner)).IsVolatile = 1
|
||||
return vinner
|
||||
left: rawptr[AST] = _parse_or_test(ps)
|
||||
if left is None: return None
|
||||
if _cur_kw(ps) == Keyword.If:
|
||||
@@ -2371,11 +2416,32 @@ def _parse_type_ann(ps: rawptr[Parser]) -> rawptr[AST]:
|
||||
mod_count: int = 0
|
||||
mod_lineno: int = _cur_lineno(ps)
|
||||
mod_col: int = _cur_col(ps)
|
||||
while _IsDescriptorKeyword(ps) != 0:
|
||||
while _IsDescriptorKeyword(ps) != 0 or _IsMagicAttributeCall(ps) != 0:
|
||||
if mods is None:
|
||||
# 元素大小显式传 8:list[T](pool, elem_size) 按字节步长寻址,传 4 会让
|
||||
# 两个及以上描述符(如 `const volatile`)的第 2 个 8 字节指针越位写入。
|
||||
mods = list[rawptr[AST]](ps.pool, 8)
|
||||
if _IsMagicAttributeCall(ps) != 0:
|
||||
# C 风格 `a: __attribute__(section(".text.wo"), aligned(16)) const int = ...`:
|
||||
# 与 const / volatile 同位置、同顺序自由、可混写;每个实参 desugar 成
|
||||
# `t.attr.<name>`(带调用则保留实参)后并入同一 markers 列表,由
|
||||
# _PrependDescriptorMarkers 贴到类型联合最左(与 TPC 文本展开同形)。
|
||||
ac_node: rawptr[AST] = _parse_test(ps)
|
||||
if ac_node is None:
|
||||
break
|
||||
if ac_node.kind() != ast.ASTKind.Call:
|
||||
break
|
||||
ac: ast.Call* = ast.Call*(ac_node)
|
||||
if ac.args is not None:
|
||||
acn: sizet = len(ac.args)
|
||||
aci: sizet = 0
|
||||
while aci < acn:
|
||||
mk: rawptr[AST] = _MakeTAttrMarker(ps, ac.args.get(aci))
|
||||
if mk is not None:
|
||||
mods.append(mk)
|
||||
mod_count += 1
|
||||
aci += 1
|
||||
continue
|
||||
mods.append(_MakeDescriptorMarker(ps))
|
||||
mod_count += 1
|
||||
_advance(ps)
|
||||
|
||||
Reference in new issue
Block a user