snapshot before regression test

This commit is contained in:
t
2026-07-18 19:25:40 +08:00
commit 796222a300
2295 changed files with 206453 additions and 0 deletions

1
lib/includes/__init__.py Normal file
View File

@@ -0,0 +1 @@
"""类型系统与 C 语法定义 (t.py / c.py)"""

721
lib/includes/c.py Normal file
View File

@@ -0,0 +1,721 @@
# C语法定义模块
from __future__ import annotations
import ast
import logging
from typing import Any, Optional
from . import t
from lib.constants.config import mode as _config_mode
def _to_str(node: Any) -> str:
if node is None:
return ''
if isinstance(node, str):
return node
if isinstance(node, list):
return ' && '.join([_to_str(n) for n in node])
NodeType: str = type(node).__name__
if NodeType == 'Constant':
return node.value
elif NodeType == 'ID':
return node.name
elif NodeType == 'BinaryOp':
left: str = _to_str(node.left)
right: str = _to_str(node.right)
return f'{left} {node.op} {right}'
elif NodeType == 'UnaryOp':
expr: str = _to_str(node.expr)
return f'{node.op}{expr}'
else:
return repr(node)
class Asm:
@staticmethod
def _parse_asm_descr(expr: ast.AST) -> str:
"""递归解析AST节点确保获取t.ASM_DESCR的实际值支持|组合
处理场景:
1. t.ASM_DESCR.XXX → 取属性值
2. t.ASM_DESCR.XXX | t.ASM_DESCR.YYY → 拼接两个值
3. 常量字符串 → 直接返回
"""
# 场景1位或组合XXX | YYY
if isinstance(expr, ast.BinOp):
left_val: str = Asm._parse_asm_descr(expr.left)
right_val: str = Asm._parse_asm_descr(expr.right)
return left_val + right_val
# 场景2t.ASM_DESCR.XXX 多层属性访问
elif isinstance(expr, ast.Attribute):
# 第一步:判断是否是 t.ASM_DESCR 的属性
if isinstance(expr.value, ast.Attribute):
# 内层是 t.ASM_DESCR
if (isinstance(expr.value.value, ast.Name) and
expr.value.value.id == 't' and
expr.value.attr == 'ASM_DESCR'):
# 取 t.ASM_DESCR.XXX 的实际值
AttrName: str = expr.attr
if hasattr(t.ASM_DESCR, AttrName):
return getattr(t.ASM_DESCR, AttrName, "")
# 兼容 t.XXX 简化写法(如果有的话)
elif isinstance(expr.value, ast.Name) and expr.value.id == 't':
AttrName: str = expr.attr
if hasattr(t.ASM_DESCR, AttrName):
return getattr(t.ASM_DESCR, AttrName, "")
# 场景3直接传常量如 "r"、"cc"
elif isinstance(expr, ast.Constant):
return expr.value
# 其他场景返回空
return ""
@staticmethod
def _extract_val_expr(translator: Any, expr_node: ast.AST) -> str:
"""从AST表达式节点提取值表达式的字符串形式"""
val_ExprNode: Any = translator.HandleExpr(expr_node)[0]
if isinstance(val_ExprNode, str):
return val_ExprNode
try:
return str(val_ExprNode)
except Exception as _e:
if _config_mode == "strict":
logging.warning(f"异常被忽略: {_e}")
return ''
@staticmethod
def _parse_asm_template(translator: Any, args: list[ast.AST]) -> tuple[str, list[tuple[str, str]], list[tuple[str, str]], int]:
"""解析f-string或常量模板字符串返回(asm_code, output_ops, input_ops, operand_seq)"""
output_ops: list[tuple[str, str]] = []
input_ops: list[tuple[str, str]] = []
operand_seq: int = 0
asm_code: str = ""
first_arg: ast.AST = args[0]
if isinstance(first_arg, ast.JoinedStr):
asm_parts: list[str] = []
for part in first_arg.values:
if isinstance(part, ast.Constant):
asm_parts.append(part.value)
elif isinstance(part, ast.FormattedValue):
expr: ast.AST = part.value
if isinstance(expr, ast.Call) and isinstance(expr.func, ast.Attribute) and expr.func.value.id == 'c':
# 解析内联的AsmInp/AsmOut
call_node: ast.Call = expr
val_expr: str = Asm._extract_val_expr(translator, call_node.args[0]) if len(call_node.args)>=1 else ""
constraint: str = Asm._parse_asm_descr(call_node.args[1]) if len(call_node.args)>=2 else ""
if call_node.func.attr == 'AsmOut':
output_ops.append((val_expr, constraint))
asm_parts.append(f"%{operand_seq}")
operand_seq += 1
elif call_node.func.attr == 'AsmInp':
input_ops.append((val_expr, constraint))
asm_parts.append(f"%{operand_seq}")
operand_seq += 1
else:
asm_parts.append(translator.HandleExpr(expr)[0])
asm_code = ''.join(asm_parts)
elif isinstance(first_arg, ast.Constant):
asm_code = first_arg.value
return asm_code, output_ops, input_ops, operand_seq
@staticmethod
def _parse_asm_operands(translator: Any, args: list[ast.AST], keywords: list[ast.keyword], output_ops: list[tuple[str, str]], input_ops: list[tuple[str, str]], operand_seq: int) -> tuple[list[tuple[str, str]], list[tuple[str, str]], int]:
"""解析位置参数和关键字参数中的输出/输入操作数"""
def parse_operand(arg: ast.AST) -> Optional[tuple[str, str, str]]:
"""解析 AsmInp/AsmOut 参数"""
if isinstance(arg, ast.Call) and isinstance(arg.func, ast.Attribute) and arg.func.value.id == 'c':
call_node: ast.Call = arg
val_expr: str = Asm._extract_val_expr(translator, call_node.args[0]) if len(call_node.args)>=1 else ""
constraint: str = Asm._parse_asm_descr(call_node.args[1]) if len(call_node.args)>=2 else ""
if call_node.func.attr == 'AsmOut':
return ('out', val_expr, constraint)
elif call_node.func.attr == 'AsmInp':
return ('in', val_expr, constraint)
return None
# 处理位置参数中的操作数
for arg in args[1:]:
result: Optional[tuple[str, str, str]] = parse_operand(arg)
if result:
direction, val_expr, constraint = result
if direction == 'out':
output_ops.append((val_expr, constraint))
operand_seq += 1
elif direction == 'in':
input_ops.append((val_expr, constraint))
operand_seq += 1
# 处理关键字参数中的操作数
for kw in keywords:
if kw.arg == 'out':
# 处理 out 关键字参数 (输出操作数)
if isinstance(kw.value, ast.List):
for elt in kw.value.elts:
result = parse_operand(elt)
if result and result[0] == 'out':
output_ops.append((result[1], result[2]))
operand_seq += 1
elif isinstance(kw.value, ast.Call):
result = parse_operand(kw.value)
if result and result[0] == 'out':
output_ops.append((result[1], result[2]))
operand_seq += 1
elif kw.arg == 'inp' or kw.arg == 'inputs':
# 处理 inp/inputs 关键字参数 (输入操作数追加到f-string中已有输入之后)
if isinstance(kw.value, ast.List):
for elt in kw.value.elts:
if isinstance(elt, ast.Tuple):
# 处理列表中的 (value, constraint) 元组格式
if len(elt.elts) >= 2:
val_expr: str = Asm._extract_val_expr(translator, elt.elts[0]) if len(elt.elts) >= 1 else ""
constraint: str = Asm._parse_asm_descr(elt.elts[1])
input_ops.append((val_expr, constraint))
operand_seq += 1
else:
result = parse_operand(elt)
if result and result[0] == 'in':
input_ops.append((result[1], result[2]))
operand_seq += 1
elif isinstance(kw.value, ast.Call):
result = parse_operand(kw.value)
if result and result[0] == 'in':
input_ops.append((result[1], result[2]))
operand_seq += 1
elif isinstance(kw.value, ast.Tuple):
# 处理 (value, constraint) 元组格式
if len(kw.value.elts) >= 2:
val_expr: str = Asm._extract_val_expr(translator, kw.value.elts[0]) if len(kw.value.elts) >= 1 else ""
constraint: str = Asm._parse_asm_descr(kw.value.elts[1])
input_ops.append((val_expr, constraint))
operand_seq += 1
return output_ops, input_ops, operand_seq
@staticmethod
def _parse_asm_clobbers(args: list[ast.AST], keywords: list[ast.keyword]) -> list[str]:
"""解析位置参数和关键字参数中的破坏列表"""
clobbers: list[str] = []
# 处理位置参数中的破坏列表
for arg in args[1:]:
if isinstance(arg, ast.List):
# 解析破坏列表(支持|组合)
for elt in arg.elts:
clobber_val: str = Asm._parse_asm_descr(elt)
if clobber_val:
clobbers.append(clobber_val)
# 处理关键字参数中的破坏列表
for kw in keywords:
if kw.arg == 'op':
# 处理 op 关键字参数 (clobber破坏列表)
if isinstance(kw.value, ast.List):
for elt in kw.value.elts:
clobber_val: str = Asm._parse_asm_descr(elt)
if clobber_val:
clobbers.append(clobber_val)
elif kw.arg == 'clobber':
# 处理 clobber 关键字参数
if isinstance(kw.value, ast.List):
for elt in kw.value.elts:
clobber_val: str = Asm._parse_asm_descr(elt)
if clobber_val:
clobbers.append(clobber_val)
return clobbers
@staticmethod
def _generate_asm_code(asm_code: str, output_ops: list[tuple[str, str]], input_ops: list[tuple[str, str]], clobbers: list[str], asm_format: str) -> list[str]:
"""格式化汇编代码并生成最终的__asm__代码字符串"""
# 格式化汇编代码
asm_lines: list[str] = [line.strip() for line in asm_code.split('\n') if line.strip()]
formatted_asm: str = '\n '.join([f'"{line}\\n"' for line in asm_lines])
# 拼接约束字符串
# 输出约束:如果约束已包含 = 或 +,直接使用;否则添加 =
def format_constraint(constraint: str, is_output: bool = True) -> str:
if not constraint:
return ""
# 如果约束已包含修饰符,直接返回
if '=' in constraint or '+' in constraint:
return constraint
# 否则添加适当的修饰符
return ('=' if is_output else '') + constraint
out_const: str = ', '.join([f'"{format_constraint(c, True)}"({v})' for v, c in output_ops]) if output_ops else ""
in_const: str = ', '.join([f'"{format_constraint(c, False)}"({v})' for v, c in input_ops]) if input_ops else ""
clobber_const: str = ', '.join([f'"{x}"' for x in clobbers]) if clobbers else ""
# 构建约束部分:确保冒号格式正确
constraint_parts: list[str] = []
# 输出约束
if output_ops:
constraint_parts.append(f': {out_const}')
elif input_ops or clobbers:
constraint_parts.append(':')
# 输入约束
if input_ops:
constraint_parts.append(f': {in_const}')
elif clobbers:
constraint_parts.append(':')
# 破坏列表
if clobbers:
constraint_parts.append(f': {clobber_const}')
constraint_str: str = ' '.join(constraint_parts)
# 生成最终代码
if asm_format == 'ARM':
# ARM 使用 .arch 指令和不同的内联汇编语法
final_asm: str = f'__asm__ __volatile__ (\n {formatted_asm} {constraint_str});'
elif asm_format == 'AT&T':
# AT&T 语法不需要额外标记GCC 默认就是 AT&T
final_asm = f'__asm__ __volatile__ (\n {formatted_asm} {constraint_str});'
else:
# Intel 语法需要 .intel_syntax 指令
final_asm = f'__asm__ __volatile__ (".intel_syntax noprefix\\n\\t"\n {formatted_asm} ".att_syntax prefix" {constraint_str});'
return [final_asm]
@staticmethod
def HandleCall(translator: Any, args: list[ast.AST], keywords: list[ast.keyword]) -> list[str]:
if not args:
return ['__asm__ volatile ("nop");']
# 解析模板
asm_code: str
output_ops: list[tuple[str, str]]
input_ops: list[tuple[str, str]]
operand_seq: int
asm_code, output_ops, input_ops, operand_seq = Asm._parse_asm_template(translator, args)
# 解析操作数
output_ops, input_ops, operand_seq = Asm._parse_asm_operands(
translator, args, keywords, output_ops, input_ops, operand_seq)
# 解析破坏列表
clobbers: list[str] = Asm._parse_asm_clobbers(args, keywords)
# 解析汇编格式
asm_format: str = 'Intel'
for kw in keywords:
if kw.arg == 'format':
if isinstance(kw.value, ast.Constant) and isinstance(kw.value.value, str):
asm_format = kw.value.value
# 生成最终代码
return Asm._generate_asm_code(asm_code, output_ops, input_ops, clobbers, asm_format)
class AsmInp:
def __init__(self, value: Any, constraint: Any) -> None:
self.value: Any = value
self.constraint: Any = constraint
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]:
return []
class AsmOut:
def __init__(self, value: Any, constraint: Any) -> None:
self.value: Any = value
self.constraint: Any = constraint
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]:
return []
class NoBreak:
""" switch 分支无break """
pass
class Break:
""" switch 分支提前break """
pass
class Load:
"""解引用a写入b等价于 *b = *a无拷贝副作用"""
def __init__(self, src: Any, dst: Any) -> None:
self.src: Any = src
self.dst: Any = dst
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
if len(args) >= 2:
src: Any = translator.HandleExpr(args[0])[0]
dst: Any = translator.HandleExpr(args[1])[0]
return [f'*({dst}) = *({src})']
return []
class Addr:
"""取地址"""
def __init__(self, addr: Any) -> None:
self.addr: Any = addr
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.Addr() 调用"""
if args:
expr: Any = translator.HandleExpr(args[0])[0]
if isinstance(expr, str):
return [f'&{expr}']
return [f'&{_to_str(expr)}']
return ['0']
class Deref:
"""解引用"""
def __init__(self, ptr: Any) -> None:
self.ptr: Any = ptr
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.Deref() 调用"""
if args:
expr: Any = translator.HandleExpr(args[0])[0]
if hasattr(expr, 'op') and expr.op == '*':
return [expr]
return [f'*({_to_str(expr)})']
return ['0']
class DerefAs:
"""解引用写入,等价于 *ptr = value"""
def __init__(self, ptr: Any, value: Any) -> None:
self.ptr: Any = ptr
self.value: Any = value
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.DerefAs() 调用"""
if len(args) >= 2:
ptr: Any = translator.HandleExpr(args[0])[0]
val: Any = translator.HandleExpr(args[1])[0]
return [f'*({_to_str(ptr)}) = {_to_str(val)}']
return []
class Set:
"""设置值"""
def __init__(self, key: Any, value: Any) -> None:
self.key: Any = key
self.value: Any = value
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.Set() 调用"""
if len(args) >= 2:
target: Any = translator.HandleExpr(args[0])[0]
value: Any = translator.HandleExpr(args[1])[0]
return [f'{_to_str(target)} = {_to_str(value)}']
return []
class CReturn:
"""多返回值装饰器
用于实现函数多返回值,通过匿名结构体返回实现。
例如:@c.CReturn(t.CInt, t.CInt) 表示函数返回两个 int 值。
等价于 -> tuple[t.CInt, t.CInt] 返回类型注解。
规则:
1. CReturn 中有几个类型就说明要返回几个值
2. 函数返回类型为匿名结构体 { type1, type2, ... }
3. return 语句使用 insert_value 构建结构体
4. 调用处使用 extract_value 提取各字段
"""
def __init__(self, *ReturnTypes: Any) -> None:
self.ReturnTypes: tuple[Any, ...] = ReturnTypes
def __call__(self, func: Any) -> Any:
"""装饰器调用"""
# 将返回类型信息附加到函数上
func._CreturnTypes = self.ReturnTypes
return func
class CDefine:
"""#define 宏定义"""
def __init__(self, name: Any, value: Any) -> None:
self.name: Any = name
self.value: Any = value
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CDefine() 调用"""
if len(args) >= 1:
if isinstance(args[0], ast.Constant):
name: Any = args[0].value
else:
name = 'MACRO'
if len(args) >= 2:
value: Any = translator.HandleExpr(args[1])[0]
return ['#define ' + str(name) + ' ' + _to_str(value)]
return ['#define ' + str(name)]
return []
class CIfndef:
"""#ifndef 条件编译"""
def __init__(self, condition: Any) -> None:
self.condition: Any = condition
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CIfndef() 调用"""
if args:
condition: Any = translator.HandleExpr(args[0])[0]
return ['#ifndef ' + _to_str(condition)]
return ['#if 0']
class CIfdef:
"""#ifdef 条件编译"""
def __init__(self, condition: Any) -> None:
self.condition: Any = condition
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CIfdef() 调用"""
if args:
condition: Any = translator.HandleExpr(args[0])[0]
return ['#ifdef ' + _to_str(condition)]
return ['#if 0']
class CError:
"""#error 错误信息"""
def __init__(self, condition: Any) -> None:
self.condition: Any = condition
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CError() 调用"""
if args:
# 如果是字符串常量,保留引号
if isinstance(args[0], ast.Constant) and isinstance(args[0].value, str):
return ['#error "' + args[0].value + '"']
else:
condition: Any = translator.HandleExpr(args[0])[0]
return ['#error ' + _to_str(condition)]
return ['#error "Error: Condition is not met."']
class TokenPast:
"""## 连接符"""
def __init__(self, left: Any, right: Any) -> None:
self.left: Any = left
self.right: Any = right
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]:
"""处理 c.TokenPast() 调用"""
if len(args) >= 2:
# 处理左操作数 - 去掉引号
if isinstance(args[0], ast.Constant):
left: str = str(args[0].value)
elif isinstance(args[0], ast.Name):
left = args[0].id
else:
left = _to_str(translator.HandleExpr(args[0])[0])
# 处理右操作数 - 去掉引号
if isinstance(args[1], ast.Constant):
right: str = str(args[1].value)
elif isinstance(args[1], ast.Name):
right = args[1].id
else:
right = _to_str(translator.HandleExpr(args[1])[0])
# 返回字符串,但用特殊标记包装,让 _AstNodeToStr 能正确处理
result: str = left + ' ## ' + right
# 使用一个特殊的类来包装结果,让 _AstNodeToStr 直接返回其值
class TokenPastResult:
def __init__(self, value: str) -> None:
self.value: str = value
def __str__(self) -> str:
return self.value
return [TokenPastResult(result)]
return ['']
class CIf:
"""#if 条件编译"""
def __init__(self, condition: Any) -> None:
self.condition: Any = condition
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CIf() 调用"""
if args:
condition: Any = translator.HandleExpr(args[0])[0]
return ['#if ' + _to_str(condition)]
return ['#if 0']
class CElif:
"""#elif 条件编译"""
def __init__(self, condition: Any) -> None:
self.condition: Any = condition
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CElif() 调用"""
if args:
condition: Any = translator.HandleExpr(args[0])[0]
return ['#elif ' + _to_str(condition)]
return ['#else']
class CElse:
"""#else 条件编译"""
def __init__(self) -> None:
pass
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CElse() 调用"""
return ['#else']
class CEndif:
"""#endif 条件编译"""
def __init__(self) -> None:
pass
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CEndif() 调用"""
return ['#endif']
class CUndef:
"""#undef 取消宏定义"""
def __init__(self, name: Any) -> None:
self.name: Any = name
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CUndef(name) 调用"""
if args:
arg: Any = args[0]
if isinstance(arg, str):
name: str = arg
elif isinstance(arg, ast.Name):
name = arg.id
elif isinstance(arg, ast.Constant):
name = str(arg.value)
else:
name = str(arg)
return [f'#undef {name}']
return ['#undef']
class LLVMIR:
"""内联 LLVM IR
用法: c.LLVMIR(f"add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
或: c.LLVMIR(f"%{c.LOut(result)} = add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
c.LInp(expr) - 输入操作数,翻译后替换为对应的 LLVM 临时变量名
c.LOut(expr) - 输出操作数,翻译后替换为对应的 LLVM 临时变量名
"""
def __init__(self, ir_template: Any, ret_type: Any = None) -> None:
self.ir_template: Any = ir_template
self.ret_type: Any = ret_type
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
return ['/* LLVMIR */']
class LInp:
"""LLVM IR 输入操作数标记
用法: c.LInp(expr) - 标记 expr 为输入操作数
在 c.LLVMIR 的 f-string 中使用,翻译后替换为 %N 形式的操作数引用
"""
def __init__(self, value: Any) -> None:
self.value: Any = value
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]:
return []
class LOut:
"""LLVM IR 输出操作数标记
用法: c.LOut(expr) - 标记 expr 为输出操作数
在 c.LLVMIR 的 f-string 中使用,翻译后替换为 %N 形式的操作数引用
"""
def __init__(self, value: Any) -> None:
self.value: Any = value
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[Any]:
return []
class CPragma:
"""#pragma 指令
用于生成 C 语言的 #pragma 指令。
例如c.CPragma("GCC diagnostic push") 生成 #pragma GCC diagnostic push
"""
def __init__(self, directive: Any) -> None:
self.directive: Any = directive
@staticmethod
def HandleCall(translator: Any, args: Any, keywords: Any) -> list[str]:
"""处理 c.CPragma() 调用"""
if args:
arg: Any = args[0]
if isinstance(arg, ast.Constant):
directive: Any = arg.value
else:
expr: Any = translator.HandleExpr(arg)[0]
directive = _to_str(expr)
return [f'#pragma {directive}']
return ['#pragma']
# C 库类字典,用于 HandleCSpecialCall
Library_C = {
'Asm': Asm,
'Load': Load,
'Addr': Addr,
'Deref': Deref,
'Set': Set,
'AsmInp': AsmInp,
'AsmOut': AsmOut,
'CDefine': CDefine,
'CIfndef': CIfndef,
'CIfdef': CIfdef,
'CIf': CIf,
'CElif': CElif,
'CElse': CElse,
'CEndif': CEndif,
'CUndef': CUndef,
'CError': CError,
'TokenPast': TokenPast,
'CReturn': CReturn,
'CPragma': CPragma,
'LLVMIR': LLVMIR,
'LInp': LInp,
'LOut': LOut,
}
class Attribute:
"""函数/变量属性装饰器"""
def __init__(self, *attrs: Any) -> None:
self.attrs: tuple[Any, ...] = attrs
def __call__(self, func: Any) -> Any:
# 将属性附加到函数上
func._c_attributes = self.attrs
return func

1163
lib/includes/t.py Normal file

File diff suppressed because it is too large Load Diff