l0n0lc 0.8.4__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- l0n0lc/Py/350/275/254Cpp/350/275/254/350/257/221/345/231/250.py +579 -0
- l0n0lc/__init__.py +75 -6
- l0n0lc/aot/347/274/226/350/257/221.py +679 -0
- l0n0lc/ast/350/256/277/351/227/256/350/200/205.py +599 -0
- l0n0lc/cpp/347/261/273/345/236/213.py +330 -0
- l0n0lc/cpp/347/274/226/350/257/221/345/231/250.py +317 -0
- l0n0lc/simd/344/274/230/345/214/226.py +260 -0
- l0n0lc/std_map.py +153 -0
- l0n0lc/std_set.py +185 -0
- l0n0lc/std_vector.py +96 -0
- l0n0lc//344/273/243/347/240/201/344/274/230/345/214/226.py +302 -0
- l0n0lc//344/273/243/347/240/201/347/224/237/346/210/220.py +546 -0
- l0n0lc//344/276/235/350/265/226/346/263/250/345/205/245.py +155 -0
- l0n0lc//345/215/263/346/227/266/347/274/226/350/257/221.py +192 -0
- l0n0lc//345/217/230/351/207/217/347/256/241/347/220/206/345/231/250.py +123 -0
- l0n0lc//345/237/272/347/241/200/346/230/240/345/260/204.py +103 -0
- l0n0lc//345/237/272/347/241/200/346/267/267/345/205/245.py +147 -0
- l0n0lc//345/256/271/345/231/250/346/236/204/345/273/272/345/231/250.py +214 -0
- l0n0lc//345/267/245/345/205/267.py +285 -0
- l0n0lc//345/271/266/350/241/214/347/274/226/350/257/221/345/231/250.py +412 -0
- l0n0lc//345/274/202/345/270/270.py +474 -0
- l0n0lc//346/225/260/347/273/204/345/257/271/350/261/241/346/261/240.py +248 -0
- l0n0lc//346/226/207/344/273/266/347/256/241/347/220/206/345/231/250.py +286 -0
- l0n0lc//346/227/245/345/277/227/345/267/245/345/205/267.py +152 -0
- l0n0lc//347/261/273/345/236/213/346/216/250/346/226/255/345/267/245/345/205/267.py +352 -0
- l0n0lc//347/261/273/345/236/213/350/275/254/346/215/242.py +210 -0
- l0n0lc//347/261/273/346/224/257/346/214/201.py +372 -0
- l0n0lc//347/274/226/350/257/221/344/270/212/344/270/213/346/226/207.py +132 -0
- l0n0lc//347/274/226/350/257/221/347/256/241/347/220/206/345/231/250.py +171 -0
- l0n0lc//350/241/250/350/276/276/345/274/217/345/244/204/347/220/206.py +462 -0
- l0n0lc//350/275/254/350/257/221/345/231/250/345/267/245/345/205/267.py +49 -0
- l0n0lc//350/277/220/350/241/214/346/227/266/345/212/240/350/275/275.py +217 -0
- l0n0lc//351/200/232/347/224/250/345/267/245/345/205/267.py +149 -0
- l0n0lc-1.0.0.dist-info/METADATA +363 -0
- l0n0lc-1.0.0.dist-info/RECORD +39 -0
- {l0n0lc-0.8.4.dist-info → l0n0lc-1.0.0.dist-info}/WHEEL +1 -1
- l0n0lc-1.0.0.dist-info/entry_points.txt +2 -0
- {l0n0lc-0.8.4.dist-info → l0n0lc-1.0.0.dist-info}/licenses/LICENSE +0 -0
- l0n0lc/StdList.py +0 -24
- l0n0lc/StdMap.py +0 -21
- l0n0lc/c/345/237/272/347/241/200/345/244/204/347/220/206.py +0 -207
- l0n0lc/jit.py +0 -604
- l0n0lc//347/274/226/350/257/221.py +0 -58
- l0n0lc//351/200/232/347/224/250.py +0 -134
- l0n0lc-0.8.4.dist-info/METADATA +0 -241
- l0n0lc-0.8.4.dist-info/RECORD +0 -12
- {l0n0lc-0.8.4.dist-info → l0n0lc-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,579 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import ast
|
|
3
|
+
import hashlib
|
|
4
|
+
import inspect
|
|
5
|
+
import ctypes
|
|
6
|
+
import io
|
|
7
|
+
import sys
|
|
8
|
+
import tempfile
|
|
9
|
+
from typing import Callable, Any, List, Dict, Set, Optional, Tuple, Union
|
|
10
|
+
from .cpp类型 import C变量, 代码块, C代码
|
|
11
|
+
from .异常 import Jit错误, 编译错误
|
|
12
|
+
from .工具 import 全局上下文, 含非ASCII字符
|
|
13
|
+
from .cpp编译器 import Cpp编译器
|
|
14
|
+
from .ast访问者 import 语句访问者
|
|
15
|
+
from .表达式处理 import 表达式访问者
|
|
16
|
+
from .类型转换 import 类型转换器
|
|
17
|
+
from .代码生成 import 代码生成器
|
|
18
|
+
from .类支持 import 类支持处理器
|
|
19
|
+
from .运行时加载 import 运行时加载器
|
|
20
|
+
from .基础混入 import 通用访问者混入
|
|
21
|
+
from .代码优化 import 代码优化器
|
|
22
|
+
from .文件管理器 import 文件管理器
|
|
23
|
+
from .编译上下文 import 编译上下文
|
|
24
|
+
from .变量管理器 import 变量管理器
|
|
25
|
+
from .编译管理器 import 编译管理器
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Py转Cpp转译器(通用访问者混入, ast.NodeVisitor):
|
|
29
|
+
"""
|
|
30
|
+
AST 访问者类,负责将 Python 函数 AST 转换为 C++ 代码并进行编译。
|
|
31
|
+
核心功能包括类型推断、代码生成、依赖管理和 C++ 编译器调用。
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(
|
|
35
|
+
self, 目标函数: Callable, 编译器: Cpp编译器, 可执行文件名: Optional[str] = None,
|
|
36
|
+
总是重编: bool = False, 启用并行编译: bool = True, 最大进程数: Optional[int] = None,
|
|
37
|
+
启用代码优化: bool = True
|
|
38
|
+
) -> None:
|
|
39
|
+
"""
|
|
40
|
+
初始化转译器。
|
|
41
|
+
|
|
42
|
+
:param 目标函数: 需要编译的 Python 函数对象
|
|
43
|
+
:param 编译器: CppCompiler 实例,用于处理后续的 C++ 编译工作
|
|
44
|
+
:param 可执行文件名: 如果提供,将编译为可执行文件而非动态库
|
|
45
|
+
:param 总是重编: 是否每次运行都强制重新编译
|
|
46
|
+
:param 启用并行编译: 是否启用并行编译依赖(默认 True)
|
|
47
|
+
:param 最大进程数: 并行编译的最大进程数(None 表示使用 CPU 核心数)
|
|
48
|
+
:param 启用代码优化: 是否启用代码优化(常量折叠、死代码消除等,默认 True)
|
|
49
|
+
"""
|
|
50
|
+
self.目标函数 = 目标函数
|
|
51
|
+
# 使用传入的编译器实例(已配置优化级别)
|
|
52
|
+
self.编译器 = 编译器
|
|
53
|
+
self.可执行文件名 = 可执行文件名
|
|
54
|
+
self.总是重编 = 总是重编
|
|
55
|
+
self.启用并行编译 = 启用并行编译
|
|
56
|
+
self.最大进程数 = 最大进程数
|
|
57
|
+
self.启用代码优化 = 启用代码优化
|
|
58
|
+
self.已编译 = False # 延迟编译标记
|
|
59
|
+
self.源代码 = inspect.getsource(目标函数)
|
|
60
|
+
# 计算源码哈希值,用于缓存文件名生成
|
|
61
|
+
self.代码哈希 = hashlib.blake2s(self.源代码.encode(), digest_size=8).hexdigest()
|
|
62
|
+
|
|
63
|
+
if inspect.isclass(目标函数):
|
|
64
|
+
import sys
|
|
65
|
+
|
|
66
|
+
module = sys.modules.get(目标函数.__module__)
|
|
67
|
+
self.全局变量 = module.__dict__ if module else {}
|
|
68
|
+
self.是否为类 = True
|
|
69
|
+
self.类成员变量: Dict[str, str] = {} # Python Name -> C Type
|
|
70
|
+
self.类成员默认值: Dict[str, Any] = {} # 成员变量默认值
|
|
71
|
+
self.类静态成员: Dict[str, Tuple[str, Any]] = (
|
|
72
|
+
{}
|
|
73
|
+
) # 静态成员: name -> (type, value)
|
|
74
|
+
self.类基类列表: List[Any] = [] # 基类列表
|
|
75
|
+
self.构造函数 = None
|
|
76
|
+
else:
|
|
77
|
+
self.全局变量 = 目标函数.__globals__
|
|
78
|
+
self.是否为类 = False
|
|
79
|
+
|
|
80
|
+
self.本地变量 = {}
|
|
81
|
+
self.参数变量 = {}
|
|
82
|
+
self.参数名称 = [] # 保存参数名称列表,用于类型推断
|
|
83
|
+
self.当前方法参数: Dict[str, C变量] = {} # 当前方法的参数(用于类方法)
|
|
84
|
+
self.ctypes参数类型 = [] # 保存参数的 ctypes 类型,用于 ctypes 调用
|
|
85
|
+
self.ctypes返回类型 = ctypes.c_voidp # 保存返回值的 ctypes 类型
|
|
86
|
+
self.类方法列表: List[Dict[str, Any]] = [] # 存储类方法信息
|
|
87
|
+
self.依赖函数: List["Py转Cpp转译器"] = [] # 递归依赖的其他 JIT 函数
|
|
88
|
+
self.代码缓冲区 = io.StringIO() # 使用 StringIO 代替列表,提升字符串拼接性能
|
|
89
|
+
self.代码块上下文 = 代码块(self) # 代码块上下文管理器
|
|
90
|
+
self.正在直接调用 = False # 标记是否正在进行直接 Python 调用
|
|
91
|
+
self.正在构建参数 = False # 标记是否正在处理函数参数
|
|
92
|
+
|
|
93
|
+
# 库缓存(每个转译器实例自己持有)
|
|
94
|
+
self.目标库 = None # ctypes.CDLL 对象
|
|
95
|
+
self.cpp函数 = None # 编译后的 C++ 函数
|
|
96
|
+
|
|
97
|
+
# 初始化变量管理器
|
|
98
|
+
self.变量管理器 = 变量管理器()
|
|
99
|
+
# 向后兼容:保留属性别名,指向变量管理器的字段
|
|
100
|
+
self.作用域变量 = self.变量管理器.作用域变量
|
|
101
|
+
self.当前作用域层级 = self.变量管理器.当前作用域层级
|
|
102
|
+
|
|
103
|
+
# 初始化编译上下文(替代部分全局状态)
|
|
104
|
+
self.编译上下文 = 编译上下文(全局上下文.工作目录)
|
|
105
|
+
# 添加默认头文件
|
|
106
|
+
self.编译上下文.添加包含头文件("<stdint.h>")
|
|
107
|
+
# 向后兼容:保留属性别名,指向编译上下文的字段
|
|
108
|
+
self.包含头文件 = self.编译上下文.包含头文件
|
|
109
|
+
self.链接库 = self.编译上下文.链接库
|
|
110
|
+
self.库搜索目录 = self.编译上下文.库搜索目录
|
|
111
|
+
|
|
112
|
+
# 记录 List 类型的参数,用于将其拆解为指针和长度两个参数传递
|
|
113
|
+
# 格式: 参数名 -> (指针变量, 长度变量)
|
|
114
|
+
self.列表参数映射: Dict[str, Tuple[C变量, C变量]] = {}
|
|
115
|
+
|
|
116
|
+
self.函数名 = 目标函数.__name__
|
|
117
|
+
|
|
118
|
+
if 可执行文件名:
|
|
119
|
+
self.C函数名 = "main" # 如果是可执行文件,入口函数为 main
|
|
120
|
+
else:
|
|
121
|
+
if 含非ASCII字符(self.函数名):
|
|
122
|
+
# 防止中文函数名导致的编码问题,使用 hex 编码
|
|
123
|
+
self.C函数名 = f"function_{self.函数名.encode().hex()}"
|
|
124
|
+
else:
|
|
125
|
+
self.C函数名 = self.函数名
|
|
126
|
+
|
|
127
|
+
file_path = inspect.getfile(目标函数)
|
|
128
|
+
file_name = os.path.split(file_path)[1]
|
|
129
|
+
file_name_hash = hashlib.blake2s(file_path.encode(), digest_size=8).hexdigest()
|
|
130
|
+
# 文件前缀,包含原文件名哈希、文件名、函数名,用于区分
|
|
131
|
+
self.文件前缀 = f"{file_name_hash}_{file_name}_{self.函数名}_@"
|
|
132
|
+
|
|
133
|
+
self.返回类型 = "void" # 默认 C++ 返回类型
|
|
134
|
+
self.目标库 = None # ctypes 加载的动态库对象
|
|
135
|
+
self.cpp函数 = None # 加载后的 C++ 函数对象, 如果是类,这里可能不需要或者指向构造函数包装器
|
|
136
|
+
|
|
137
|
+
# 初始化文件管理器
|
|
138
|
+
self.文件管理器 = 文件管理器(全局上下文.工作目录)
|
|
139
|
+
|
|
140
|
+
# 初始化编译管理器
|
|
141
|
+
self.编译管理器 = 编译管理器(
|
|
142
|
+
self.文件管理器,
|
|
143
|
+
self.编译器,
|
|
144
|
+
self.编译上下文
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
# 初始化各个处理器
|
|
148
|
+
self.表达式访问者 = 表达式访问者(self)
|
|
149
|
+
self.语句访问者 = 语句访问者(self)
|
|
150
|
+
# 类型转换器的所有方法都是静态方法,不需要实例化
|
|
151
|
+
self.代码生成器 = 代码生成器(self)
|
|
152
|
+
self.类支持处理器 = 类支持处理器(self) if self.是否为类 else None
|
|
153
|
+
self.运行时加载器 = 运行时加载器(self)
|
|
154
|
+
|
|
155
|
+
self.分析完成 = False
|
|
156
|
+
self.仅分析函数声明 = False
|
|
157
|
+
|
|
158
|
+
def 分析(self, 仅分析函数声明:bool = False):
|
|
159
|
+
"""
|
|
160
|
+
解析 Python 源码,遍历 AST 以分析类型和依赖,但不进行编译。
|
|
161
|
+
此步骤对于推断返回类型和参数类型至关重要。
|
|
162
|
+
"""
|
|
163
|
+
# 避免重复分析
|
|
164
|
+
if self.分析完成 and self.仅分析函数声明 == 仅分析函数声明:
|
|
165
|
+
return
|
|
166
|
+
self.仅分析函数声明 = 仅分析函数声明
|
|
167
|
+
# 清理源码缩进,防止因函数嵌套在类或其他块中导致的缩进错误
|
|
168
|
+
lines = self.源代码.split("\n")
|
|
169
|
+
cleaned_lines = []
|
|
170
|
+
first_non_whitespace = None
|
|
171
|
+
|
|
172
|
+
for line in lines:
|
|
173
|
+
stripped = line.lstrip()
|
|
174
|
+
if stripped:
|
|
175
|
+
first_non_whitespace = len(line) - len(stripped)
|
|
176
|
+
break
|
|
177
|
+
|
|
178
|
+
if first_non_whitespace is not None:
|
|
179
|
+
for line in lines:
|
|
180
|
+
stripped = line.lstrip()
|
|
181
|
+
if not stripped:
|
|
182
|
+
continue
|
|
183
|
+
cleaned_lines.append(line[first_non_whitespace:])
|
|
184
|
+
|
|
185
|
+
cleaned_source = "\n".join(cleaned_lines)
|
|
186
|
+
if not cleaned_source: # 处理空函数的情况
|
|
187
|
+
cleaned_source = "def dummy(): pass"
|
|
188
|
+
|
|
189
|
+
tree = ast.parse(cleaned_source, mode="exec")
|
|
190
|
+
|
|
191
|
+
# 应用代码优化
|
|
192
|
+
if self.启用代码优化:
|
|
193
|
+
优化器 = 代码优化器(self)
|
|
194
|
+
tree = 优化器.优化(tree)
|
|
195
|
+
|
|
196
|
+
self.visit(tree)
|
|
197
|
+
self.分析完成 = True
|
|
198
|
+
|
|
199
|
+
def 编译(self):
|
|
200
|
+
"""
|
|
201
|
+
执行完整的编译流程:分析 -> 生成 C++ 代码 -> 编译为动态库/可执行文件。
|
|
202
|
+
"""
|
|
203
|
+
try:
|
|
204
|
+
# 清除旧的库缓存,确保使用新编译的库
|
|
205
|
+
self.目标库 = None
|
|
206
|
+
self.cpp函数 = None
|
|
207
|
+
|
|
208
|
+
self.分析()
|
|
209
|
+
|
|
210
|
+
# 使用并行编译管理器编译依赖函数
|
|
211
|
+
if self.依赖函数:
|
|
212
|
+
from .并行编译器 import 并行编译管理器
|
|
213
|
+
|
|
214
|
+
并行管理器 = 并行编译管理器(self.最大进程数) # type: ignore
|
|
215
|
+
统计 = 并行管理器.并行编译依赖(
|
|
216
|
+
self.依赖函数,
|
|
217
|
+
启用并行=self.启用并行编译
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
# 检查是否有编译失败的依赖
|
|
221
|
+
if 统计['失败'] > 0:
|
|
222
|
+
from .日志工具 import 日志
|
|
223
|
+
失败列表 = [r['函数名'] for r in 统计['结果列表'] if r['状态'] == '编译失败']
|
|
224
|
+
日志.警告(f"部分依赖编译失败: {', '.join(失败列表)}")
|
|
225
|
+
|
|
226
|
+
# 加载所有依赖的库
|
|
227
|
+
for dep in self.依赖函数:
|
|
228
|
+
if dep.已编译 and dep.目标库 is None:
|
|
229
|
+
dep.加载库()
|
|
230
|
+
|
|
231
|
+
# 收集依赖文件,确保依赖文件在主文件之前
|
|
232
|
+
all_source_files = set()
|
|
233
|
+
all_lib_files = set()
|
|
234
|
+
processed_deps = set()
|
|
235
|
+
|
|
236
|
+
def 递归收集依赖(dep):
|
|
237
|
+
if dep in processed_deps:
|
|
238
|
+
return
|
|
239
|
+
processed_deps.add(dep)
|
|
240
|
+
|
|
241
|
+
# 递归收集依赖的依赖
|
|
242
|
+
for sub_dep in dep.依赖函数:
|
|
243
|
+
递归收集依赖(sub_dep)
|
|
244
|
+
|
|
245
|
+
# 添加当前依赖的头文件
|
|
246
|
+
self.包含头文件.add(f'"{dep.获取头文件名()}"')
|
|
247
|
+
# 添加依赖库
|
|
248
|
+
all_lib_files.add(dep.文件管理器.获取完整路径(dep.获取库文件名()))
|
|
249
|
+
|
|
250
|
+
for dep in self.依赖函数:
|
|
251
|
+
递归收集依赖(dep)
|
|
252
|
+
|
|
253
|
+
# 主文件放在最后
|
|
254
|
+
all_source_files.add(self.文件管理器.获取完整路径(self.获取cpp文件名()))
|
|
255
|
+
|
|
256
|
+
self.代码生成器.保存代码到文件()
|
|
257
|
+
|
|
258
|
+
# 配置编译器
|
|
259
|
+
# 添加工作目录到库搜索路径,以便找到编译好的类库
|
|
260
|
+
self.编译器.添加库目录(全局上下文.工作目录)
|
|
261
|
+
self.编译器.添加库目录(list(self.库搜索目录))
|
|
262
|
+
self.编译器.添加库(list(self.链接库))
|
|
263
|
+
|
|
264
|
+
output_path = self.文件管理器.获取完整路径(self.获取库文件名())
|
|
265
|
+
|
|
266
|
+
# 合并源文件和库文件
|
|
267
|
+
all_files = list(all_source_files) + list(all_lib_files)
|
|
268
|
+
|
|
269
|
+
if self.可执行文件名:
|
|
270
|
+
self.编译器.编译文件(all_files, output_path)
|
|
271
|
+
else:
|
|
272
|
+
self.编译器.编译共享库(all_files, output_path)
|
|
273
|
+
# 编译成功后标记为已编译(用于类和非延迟编译的场景)
|
|
274
|
+
self.已编译 = True
|
|
275
|
+
|
|
276
|
+
except Exception as e:
|
|
277
|
+
# 编译失败时清理临时文件
|
|
278
|
+
self.清理编译文件()
|
|
279
|
+
# 如果是编译错误,包装并重新抛出
|
|
280
|
+
if isinstance(e, (RuntimeError, OSError)):
|
|
281
|
+
raise 编译错误(
|
|
282
|
+
f"编译失败: {str(e)}",
|
|
283
|
+
compiler_output=str(e),
|
|
284
|
+
source_file=self.文件管理器.获取完整路径(self.获取cpp文件名()),
|
|
285
|
+
python_source=self.源代码
|
|
286
|
+
) from e
|
|
287
|
+
else:
|
|
288
|
+
raise
|
|
289
|
+
|
|
290
|
+
def 清理编译文件(self):
|
|
291
|
+
"""清理编译失败时产生的临时文件"""
|
|
292
|
+
files_to_clean = [
|
|
293
|
+
self.获取cpp文件名(),
|
|
294
|
+
self.获取头文件名(),
|
|
295
|
+
self.获取库文件名()
|
|
296
|
+
]
|
|
297
|
+
self.编译管理器.清理编译文件(files_to_clean)
|
|
298
|
+
|
|
299
|
+
def 清理所有缓存(self):
|
|
300
|
+
"""清理所有缓存文件(手动清理接口)"""
|
|
301
|
+
return self.编译管理器.清理所有缓存()
|
|
302
|
+
|
|
303
|
+
def 检查缓存完整性(self):
|
|
304
|
+
"""检查缓存文件的完整性"""
|
|
305
|
+
return self.编译管理器.检查缓存完整性(
|
|
306
|
+
lambda: (self.获取cpp文件名(), self.获取头文件名(), self.获取库文件名())
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
def 添加代码(self, code: str, lineno: Optional[int] = None):
|
|
310
|
+
"""添加一行 C++ 代码"""
|
|
311
|
+
# 使用 StringIO 而不是列表,提升性能
|
|
312
|
+
self.代码缓冲区.write(code)
|
|
313
|
+
self.代码缓冲区.write("\n")
|
|
314
|
+
|
|
315
|
+
def 添加代码带行号(self, code: str, node: Union[ast.stmt, ast.expr, ast.arg, ast.arguments]):
|
|
316
|
+
"""添加一行C++代码并自动获取行号"""
|
|
317
|
+
lineno = getattr(node, "lineno", None)
|
|
318
|
+
self.添加代码(code, lineno)
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def 进入作用域(self):
|
|
322
|
+
"""进入新的作用域(如 if/for 块内部)"""
|
|
323
|
+
self.变量管理器.进入作用域()
|
|
324
|
+
|
|
325
|
+
def 退出作用域(self):
|
|
326
|
+
"""退出当前作用域"""
|
|
327
|
+
self.变量管理器.退出作用域()
|
|
328
|
+
|
|
329
|
+
def 获取C变量(self, name: str) -> Optional[Any]:
|
|
330
|
+
"""从当前及上层作用域查找 C 变量"""
|
|
331
|
+
return self.变量管理器.获取C变量(name)
|
|
332
|
+
|
|
333
|
+
def 添加C变量(self, variable: C变量):
|
|
334
|
+
"""在当前作用域注册 C 变量"""
|
|
335
|
+
self.变量管理器.添加C变量(variable)
|
|
336
|
+
|
|
337
|
+
def 获取值(self, value, is_type_annotation=False):
|
|
338
|
+
"""
|
|
339
|
+
将 AST 节点转换为对应的值或 C++ 表达式字符串。
|
|
340
|
+
处理常量、变量名、属性访问、函数调用、运算表达式等。
|
|
341
|
+
"""
|
|
342
|
+
return self.表达式访问者.获取值(value, is_type_annotation)
|
|
343
|
+
|
|
344
|
+
# 文件操作相关方法
|
|
345
|
+
def 获取文件前缀(self):
|
|
346
|
+
return self.文件前缀
|
|
347
|
+
|
|
348
|
+
def 获取无扩展名文件名(self):
|
|
349
|
+
return f"{self.文件前缀}{self.代码哈希}"
|
|
350
|
+
|
|
351
|
+
def 获取头文件名(self):
|
|
352
|
+
return f"{self.获取无扩展名文件名()}.h"
|
|
353
|
+
|
|
354
|
+
def 获取cpp文件名(self):
|
|
355
|
+
return f"{self.获取无扩展名文件名()}.cpp"
|
|
356
|
+
|
|
357
|
+
def 获取库文件名(self):
|
|
358
|
+
if self.可执行文件名:
|
|
359
|
+
return self.可执行文件名
|
|
360
|
+
return f"{self.获取无扩展名文件名()}.so"
|
|
361
|
+
|
|
362
|
+
def 获取链接库名(self):
|
|
363
|
+
"""获取用于链接的库名(不带.so扩展名)"""
|
|
364
|
+
if self.可执行文件名:
|
|
365
|
+
return self.可执行文件名
|
|
366
|
+
return self.获取无扩展名文件名()
|
|
367
|
+
|
|
368
|
+
def 生成定义(self):
|
|
369
|
+
"""生成 C 函数定义/声明,或 C++ 类定义"""
|
|
370
|
+
return self.代码生成器.生成函数定义()
|
|
371
|
+
|
|
372
|
+
def 获取包含代码(self):
|
|
373
|
+
"""生成包含头文件的代码"""
|
|
374
|
+
return self.代码生成器.生成包含代码()
|
|
375
|
+
|
|
376
|
+
def 获取头文件代码(self):
|
|
377
|
+
"""生成头文件完整代码"""
|
|
378
|
+
return self.代码生成器.生成头文件代码()
|
|
379
|
+
|
|
380
|
+
def 获取cpp代码(self):
|
|
381
|
+
"""生成cpp文件完整代码"""
|
|
382
|
+
return self.代码生成器.生成cpp代码()
|
|
383
|
+
|
|
384
|
+
def 保存代码到文件(self):
|
|
385
|
+
"""保存代码到文件"""
|
|
386
|
+
self.代码生成器.保存代码到文件()
|
|
387
|
+
|
|
388
|
+
def 加载库(self):
|
|
389
|
+
"""加载编译好的动态库(仅首次调用时加载)"""
|
|
390
|
+
# 如果已经加载过,直接返回
|
|
391
|
+
if self.目标库 is not None and self.cpp函数 is not None:
|
|
392
|
+
return
|
|
393
|
+
|
|
394
|
+
# 首次加载
|
|
395
|
+
self.运行时加载器.加载库()
|
|
396
|
+
|
|
397
|
+
def __call__(self, *args, **kwargs):
|
|
398
|
+
"""调用编译后的函数(延迟编译:首次调用时才编译)"""
|
|
399
|
+
if self.可执行文件名 is None:
|
|
400
|
+
# 检查是否需要编译
|
|
401
|
+
if self.总是重编 or not self.文件管理器.文件是否存在(self.获取库文件名()):
|
|
402
|
+
self.编译()
|
|
403
|
+
else:
|
|
404
|
+
self.分析(True)
|
|
405
|
+
# 加载库(如果还没加载)
|
|
406
|
+
self.加载库()
|
|
407
|
+
return self.运行时加载器.调用函数(*args, **kwargs)
|
|
408
|
+
|
|
409
|
+
# AST访问方法重写
|
|
410
|
+
def visit_FunctionDef(self, node: ast.FunctionDef) -> Any:
|
|
411
|
+
if self.是否为类:
|
|
412
|
+
# 委托给类支持处理器
|
|
413
|
+
if self.类支持处理器 is None:
|
|
414
|
+
self.抛出错误("类支持处理器未初始化,但当前正在处理类", node)
|
|
415
|
+
else:
|
|
416
|
+
self.类支持处理器.访问方法节点(node)
|
|
417
|
+
else:
|
|
418
|
+
# 处理普通函数
|
|
419
|
+
with self.代码块上下文:
|
|
420
|
+
# 处理函数参数
|
|
421
|
+
self.语句访问者.visit_arguments(node.args)
|
|
422
|
+
|
|
423
|
+
# 在函数体开始处,使用指针和长度重建 std::vector (如果存在 List 参数)
|
|
424
|
+
for param_name, (ptr_var, len_var) in self.列表参数映射.items():
|
|
425
|
+
original_var = self.参数变量[param_name]
|
|
426
|
+
# 重建代码: std::vector<T> vec(ptr, ptr + len);
|
|
427
|
+
self.添加代码(
|
|
428
|
+
f"{original_var.类型名} {original_var.C名称}({ptr_var.C名称}, {ptr_var.C名称} + {len_var.C名称});"
|
|
429
|
+
)
|
|
430
|
+
if not self.仅分析函数声明:
|
|
431
|
+
for stmt in node.body:
|
|
432
|
+
self.visit(stmt)
|
|
433
|
+
|
|
434
|
+
# 分析返回类型(仅对非类方法)
|
|
435
|
+
if not self.是否为类:
|
|
436
|
+
self.推断函数返回类型(node)
|
|
437
|
+
|
|
438
|
+
def 推断函数返回类型(self, node: ast.FunctionDef):
|
|
439
|
+
"""推断普通函数的返回类型"""
|
|
440
|
+
if isinstance(node.returns, ast.Name):
|
|
441
|
+
ret_py_type = self.获取值(node.returns, is_type_annotation=True)
|
|
442
|
+
|
|
443
|
+
# 处理字符串类型注解(如 'Vector2D')
|
|
444
|
+
if isinstance(ret_py_type, str) and ret_py_type not in [
|
|
445
|
+
"int",
|
|
446
|
+
"float",
|
|
447
|
+
"str",
|
|
448
|
+
"bool",
|
|
449
|
+
"void",
|
|
450
|
+
]:
|
|
451
|
+
# 尝试从全局变量中查找对应的类
|
|
452
|
+
if ret_py_type in self.全局变量:
|
|
453
|
+
potential_class = self.全局变量[ret_py_type]
|
|
454
|
+
if inspect.isclass(potential_class):
|
|
455
|
+
ret_py_type = potential_class
|
|
456
|
+
|
|
457
|
+
# 处理自定义类类型
|
|
458
|
+
if inspect.isclass(ret_py_type):
|
|
459
|
+
# 首先检查是否有类型映射
|
|
460
|
+
mapped_type = 全局上下文.类型映射表.get(ret_py_type)
|
|
461
|
+
if mapped_type:
|
|
462
|
+
# 使用映射的类型
|
|
463
|
+
self.返回类型 = mapped_type.目标类型
|
|
464
|
+
# 添加需要包含的头文件
|
|
465
|
+
if mapped_type.包含目录:
|
|
466
|
+
self.包含头文件.update(mapped_type.包含目录)
|
|
467
|
+
if not self.可执行文件名:
|
|
468
|
+
# 使用映射的ctypes类型,如果没有则使用void指针
|
|
469
|
+
self.ctypes返回类型 = (
|
|
470
|
+
mapped_type.ctypes类型
|
|
471
|
+
if mapped_type.ctypes类型
|
|
472
|
+
else ctypes.c_voidp
|
|
473
|
+
)
|
|
474
|
+
elif ret_py_type.__module__ == "builtins":
|
|
475
|
+
self.返回类型 = self.解析类型(ret_py_type)
|
|
476
|
+
if not self.可执行文件名:
|
|
477
|
+
self.ctypes返回类型 = 类型转换器.Python类型转ctypes(
|
|
478
|
+
ret_py_type
|
|
479
|
+
)
|
|
480
|
+
else:
|
|
481
|
+
# 用户自定义类
|
|
482
|
+
self.返回类型 = ret_py_type.__name__
|
|
483
|
+
if not self.可执行文件名:
|
|
484
|
+
self.ctypes返回类型 = ctypes.c_voidp # 自定义类使用void指针
|
|
485
|
+
else:
|
|
486
|
+
# 处理非类类型(如基本类型的别名等)
|
|
487
|
+
self.返回类型 = self.解析类型(ret_py_type)
|
|
488
|
+
if not self.可执行文件名:
|
|
489
|
+
self.ctypes返回类型 = 类型转换器.Python类型转ctypes(
|
|
490
|
+
ret_py_type
|
|
491
|
+
)
|
|
492
|
+
elif node.returns is None:
|
|
493
|
+
# 没有类型注解,需要根据函数体推断返回类型
|
|
494
|
+
# 检查函数体中是否有返回语句
|
|
495
|
+
return_stmt = None
|
|
496
|
+
for stmt in node.body:
|
|
497
|
+
if isinstance(stmt, ast.Return):
|
|
498
|
+
return_stmt = stmt
|
|
499
|
+
break
|
|
500
|
+
|
|
501
|
+
if return_stmt and return_stmt.value is not None:
|
|
502
|
+
# 有返回语句但没有类型注解,尝试推断返回值类型
|
|
503
|
+
# 使用AST分析而不是实际求值,避免变量未定义的问题
|
|
504
|
+
if isinstance(return_stmt.value, ast.Call):
|
|
505
|
+
# 检查函数调用
|
|
506
|
+
call_node = return_stmt.value
|
|
507
|
+
if isinstance(call_node.func, ast.Attribute):
|
|
508
|
+
# 其他方法使用auto
|
|
509
|
+
self.返回类型 = "auto"
|
|
510
|
+
self.ctypes返回类型 = ctypes.c_voidp
|
|
511
|
+
elif isinstance(call_node.func, ast.Name):
|
|
512
|
+
# 函数调用,如 func()
|
|
513
|
+
func_name = call_node.func.id
|
|
514
|
+
# 检查是否是当前类的构造函数调用
|
|
515
|
+
if func_name == self.函数名 and self.是否为类:
|
|
516
|
+
# 构造函数调用返回当前类类型
|
|
517
|
+
self.返回类型 = self.函数名
|
|
518
|
+
self.ctypes返回类型 = ctypes.c_voidp # 自定义类使用void指针
|
|
519
|
+
else:
|
|
520
|
+
# 其他函数使用auto
|
|
521
|
+
self.返回类型 = "auto"
|
|
522
|
+
self.ctypes返回类型 = ctypes.c_voidp
|
|
523
|
+
else:
|
|
524
|
+
# 其他类型的调用使用auto
|
|
525
|
+
self.返回类型 = "auto"
|
|
526
|
+
self.ctypes返回类型 = ctypes.c_voidp
|
|
527
|
+
elif isinstance(return_stmt.value, ast.Constant):
|
|
528
|
+
# 常量返回值
|
|
529
|
+
if isinstance(return_stmt.value.value, str):
|
|
530
|
+
self.返回类型 = "auto"
|
|
531
|
+
self.ctypes返回类型 = ctypes.c_char_p
|
|
532
|
+
elif isinstance(return_stmt.value.value, bool):
|
|
533
|
+
self.返回类型 = "bool"
|
|
534
|
+
self.ctypes返回类型 = ctypes.c_bool
|
|
535
|
+
elif isinstance(return_stmt.value.value, int):
|
|
536
|
+
self.返回类型 = "int64_t"
|
|
537
|
+
self.ctypes返回类型 = ctypes.c_int64
|
|
538
|
+
elif isinstance(return_stmt.value.value, float):
|
|
539
|
+
self.返回类型 = "double"
|
|
540
|
+
self.ctypes返回类型 = ctypes.c_double
|
|
541
|
+
else:
|
|
542
|
+
self.返回类型 = "auto"
|
|
543
|
+
self.ctypes返回类型 = ctypes.c_voidp
|
|
544
|
+
else:
|
|
545
|
+
# 其他表达式使用auto
|
|
546
|
+
self.返回类型 = "auto"
|
|
547
|
+
self.ctypes返回类型 = ctypes.c_voidp
|
|
548
|
+
else:
|
|
549
|
+
# 没有返回语句或返回值为None,设为void
|
|
550
|
+
self.返回类型 = "void"
|
|
551
|
+
self.ctypes返回类型 = None
|
|
552
|
+
else:
|
|
553
|
+
self.返回类型 = "auto"
|
|
554
|
+
|
|
555
|
+
def visit_ClassDef(self, node: ast.ClassDef) -> Any:
|
|
556
|
+
# 委托给类支持处理器
|
|
557
|
+
if self.类支持处理器:
|
|
558
|
+
self.类支持处理器.处理类定义(node)
|
|
559
|
+
else:
|
|
560
|
+
if hasattr(self, "抛出错误"):
|
|
561
|
+
self.抛出错误(
|
|
562
|
+
"Class definition not supported in function context", node
|
|
563
|
+
)
|
|
564
|
+
else:
|
|
565
|
+
raise Jit错误("Class definition not supported in function context")
|
|
566
|
+
|
|
567
|
+
def generic_visit(self, node):
|
|
568
|
+
"""
|
|
569
|
+
通用的访问方法,将未处理的节点委托给相应的访问者
|
|
570
|
+
"""
|
|
571
|
+
# 优先委托给语句访问者
|
|
572
|
+
if hasattr(self.语句访问者, f'visit_{node.__class__.__name__}'):
|
|
573
|
+
return getattr(self.语句访问者, f'visit_{node.__class__.__name__}')(node)
|
|
574
|
+
# 其次委托给表达式访问者
|
|
575
|
+
elif hasattr(self.表达式访问者, f'visit_{node.__class__.__name__}'):
|
|
576
|
+
return getattr(self.表达式访问者, f'visit_{node.__class__.__name__}')(node)
|
|
577
|
+
# 最后调用父类的默认处理
|
|
578
|
+
else:
|
|
579
|
+
return super().generic_visit(node)
|
l0n0lc/__init__.py
CHANGED
|
@@ -1,6 +1,75 @@
|
|
|
1
|
-
from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
from .
|
|
6
|
-
from
|
|
1
|
+
from .工具 import (
|
|
2
|
+
映射函数, 映射类型, 可直接调用, 转C字符串,
|
|
3
|
+
映射函数到, 全局上下文
|
|
4
|
+
)
|
|
5
|
+
from .cpp编译器 import Cpp编译器
|
|
6
|
+
from .即时编译 import 即时编译, jit
|
|
7
|
+
from .Py转Cpp转译器 import Py转Cpp转译器
|
|
8
|
+
from .基础映射 import (
|
|
9
|
+
int8, int16, int32, int64,
|
|
10
|
+
uint8, uint16, uint32, uint64,
|
|
11
|
+
float32, float64
|
|
12
|
+
)
|
|
13
|
+
from .aot编译 import (
|
|
14
|
+
JIT函数信息,
|
|
15
|
+
包扫描器,
|
|
16
|
+
AOT编译器,
|
|
17
|
+
编译包,
|
|
18
|
+
编译函数列表
|
|
19
|
+
)
|
|
20
|
+
from .simd优化 import (
|
|
21
|
+
CPU特性,
|
|
22
|
+
获取CPU特性,
|
|
23
|
+
获取最佳SIMD指令集,
|
|
24
|
+
获取SIMD编译标志,
|
|
25
|
+
启用自动向量化标志,
|
|
26
|
+
获取向量化宏定义
|
|
27
|
+
)
|
|
28
|
+
from .数组对象池 import (
|
|
29
|
+
数组对象池,
|
|
30
|
+
数组对象池统计,
|
|
31
|
+
获取全局对象池,
|
|
32
|
+
重置全局对象池,
|
|
33
|
+
获取全局池统计,
|
|
34
|
+
清空全局对象池,
|
|
35
|
+
设置全局池启用
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
# 核心装饰器
|
|
40
|
+
"jit", "即时编译",
|
|
41
|
+
"映射函数", "可直接调用", "映射类型", "映射函数到",
|
|
42
|
+
"全局上下文", # 全局上下文管理(用于清理和重置)
|
|
43
|
+
|
|
44
|
+
# 类型
|
|
45
|
+
"int8", "int16", "int32", "int64",
|
|
46
|
+
"uint8", "uint16", "uint32", "uint64",
|
|
47
|
+
"float32", "float64",
|
|
48
|
+
|
|
49
|
+
# 编译器
|
|
50
|
+
"Cpp编译器", "Py转Cpp转译器",
|
|
51
|
+
|
|
52
|
+
# AOT 编译
|
|
53
|
+
"JIT函数信息",
|
|
54
|
+
"包扫描器",
|
|
55
|
+
"AOT编译器",
|
|
56
|
+
"编译包",
|
|
57
|
+
"编译函数列表",
|
|
58
|
+
|
|
59
|
+
# SIMD 优化
|
|
60
|
+
"CPU特性",
|
|
61
|
+
"获取CPU特性",
|
|
62
|
+
"获取最佳SIMD指令集",
|
|
63
|
+
"获取SIMD编译标志",
|
|
64
|
+
"启用自动向量化标志",
|
|
65
|
+
"获取向量化宏定义",
|
|
66
|
+
|
|
67
|
+
# 数组对象池
|
|
68
|
+
"数组对象池",
|
|
69
|
+
"数组对象池统计",
|
|
70
|
+
"获取全局对象池",
|
|
71
|
+
"重置全局对象池",
|
|
72
|
+
"获取全局池统计",
|
|
73
|
+
"清空全局对象池",
|
|
74
|
+
"设置全局池启用",
|
|
75
|
+
]
|