gstaichi 0.1.18.dev1__cp310-cp310-win_amd64.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.
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools/cmake/SPIRV-ToolsConfig.cmake +5 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools/cmake/SPIRV-ToolsTarget-release.cmake +29 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools/cmake/SPIRV-ToolsTarget.cmake +113 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-diff/cmake/SPIRV-Tools-diffConfig.cmake +5 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-diff/cmake/SPIRV-Tools-diffTargets-release.cmake +19 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-diff/cmake/SPIRV-Tools-diffTargets.cmake +122 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-link/cmake/SPIRV-Tools-linkConfig.cmake +5 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-link/cmake/SPIRV-Tools-linkTargets-release.cmake +19 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-link/cmake/SPIRV-Tools-linkTargets.cmake +122 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-lint/cmake/SPIRV-Tools-lintConfig.cmake +5 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-lint/cmake/SPIRV-Tools-lintTargets-release.cmake +19 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-lint/cmake/SPIRV-Tools-lintTargets.cmake +122 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-opt/cmake/SPIRV-Tools-optConfig.cmake +5 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-opt/cmake/SPIRV-Tools-optTargets-release.cmake +19 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-opt/cmake/SPIRV-Tools-optTargets.cmake +122 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-reduce/cmake/SPIRV-Tools-reduceConfig.cmake +5 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-reduce/cmake/SPIRV-Tools-reduceTarget-release.cmake +19 -0
- gstaichi-0.1.18.dev1.data/data/SPIRV-Tools-reduce/cmake/SPIRV-Tools-reduceTarget.cmake +122 -0
- gstaichi-0.1.18.dev1.data/data/bin/SPIRV-Tools-shared.dll +0 -0
- gstaichi-0.1.18.dev1.data/data/include/GLFW/glfw3.h +6389 -0
- gstaichi-0.1.18.dev1.data/data/include/GLFW/glfw3native.h +594 -0
- gstaichi-0.1.18.dev1.data/data/include/spirv-tools/instrument.hpp +268 -0
- gstaichi-0.1.18.dev1.data/data/include/spirv-tools/libspirv.h +907 -0
- gstaichi-0.1.18.dev1.data/data/include/spirv-tools/libspirv.hpp +375 -0
- gstaichi-0.1.18.dev1.data/data/include/spirv-tools/linker.hpp +97 -0
- gstaichi-0.1.18.dev1.data/data/include/spirv-tools/optimizer.hpp +970 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools-diff.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools-link.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools-lint.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools-opt.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools-reduce.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools-shared.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/SPIRV-Tools.lib +0 -0
- gstaichi-0.1.18.dev1.data/data/lib/cmake/glfw3/glfw3Config.cmake +3 -0
- gstaichi-0.1.18.dev1.data/data/lib/cmake/glfw3/glfw3ConfigVersion.cmake +65 -0
- gstaichi-0.1.18.dev1.data/data/lib/cmake/glfw3/glfw3Targets-release.cmake +19 -0
- gstaichi-0.1.18.dev1.data/data/lib/cmake/glfw3/glfw3Targets.cmake +107 -0
- gstaichi-0.1.18.dev1.data/data/lib/glfw3.lib +0 -0
- gstaichi-0.1.18.dev1.dist-info/METADATA +108 -0
- gstaichi-0.1.18.dev1.dist-info/RECORD +198 -0
- gstaichi-0.1.18.dev1.dist-info/WHEEL +5 -0
- gstaichi-0.1.18.dev1.dist-info/entry_points.txt +2 -0
- gstaichi-0.1.18.dev1.dist-info/licenses/LICENSE +201 -0
- gstaichi-0.1.18.dev1.dist-info/top_level.txt +1 -0
- taichi/CHANGELOG.md +15 -0
- taichi/__init__.py +44 -0
- taichi/__main__.py +5 -0
- taichi/_funcs.py +706 -0
- taichi/_kernels.py +420 -0
- taichi/_lib/__init__.py +3 -0
- taichi/_lib/c_api/bin/taichi_c_api.dll +0 -0
- taichi/_lib/c_api/include/taichi/cpp/taichi.hpp +1401 -0
- taichi/_lib/c_api/include/taichi/taichi.h +29 -0
- taichi/_lib/c_api/include/taichi/taichi_core.h +1111 -0
- taichi/_lib/c_api/include/taichi/taichi_cpu.h +29 -0
- taichi/_lib/c_api/include/taichi/taichi_cuda.h +36 -0
- taichi/_lib/c_api/include/taichi/taichi_platform.h +55 -0
- taichi/_lib/c_api/include/taichi/taichi_unity.h +64 -0
- taichi/_lib/c_api/include/taichi/taichi_vulkan.h +151 -0
- taichi/_lib/c_api/lib/taichi_c_api.lib +0 -0
- taichi/_lib/c_api/runtime/runtime_cuda.bc +0 -0
- taichi/_lib/c_api/runtime/runtime_x64.bc +0 -0
- taichi/_lib/c_api/runtime/slim_libdevice.10.bc +0 -0
- taichi/_lib/c_api/taichi/lib/cmake/taichi/TaichiConfig.cmake +29 -0
- taichi/_lib/c_api/taichi/lib/cmake/taichi/TaichiConfigVersion.cmake +65 -0
- taichi/_lib/c_api/taichi/lib/cmake/taichi/TaichiTargets.cmake +121 -0
- taichi/_lib/core/__init__.py +0 -0
- taichi/_lib/core/py.typed +0 -0
- taichi/_lib/core/taichi_python.cp310-win_amd64.pyd +0 -0
- taichi/_lib/core/taichi_python.pyi +3077 -0
- taichi/_lib/runtime/runtime_cuda.bc +0 -0
- taichi/_lib/runtime/runtime_x64.bc +0 -0
- taichi/_lib/runtime/slim_libdevice.10.bc +0 -0
- taichi/_lib/utils.py +249 -0
- taichi/_logging.py +131 -0
- taichi/_main.py +552 -0
- taichi/_snode/__init__.py +5 -0
- taichi/_snode/fields_builder.py +189 -0
- taichi/_snode/snode_tree.py +34 -0
- taichi/_ti_module/__init__.py +3 -0
- taichi/_ti_module/cppgen.py +309 -0
- taichi/_ti_module/module.py +145 -0
- taichi/_version.py +1 -0
- taichi/_version_check.py +100 -0
- taichi/ad/__init__.py +3 -0
- taichi/ad/_ad.py +530 -0
- taichi/algorithms/__init__.py +3 -0
- taichi/algorithms/_algorithms.py +117 -0
- taichi/aot/__init__.py +12 -0
- taichi/aot/_export.py +28 -0
- taichi/aot/conventions/__init__.py +3 -0
- taichi/aot/conventions/gfxruntime140/__init__.py +38 -0
- taichi/aot/conventions/gfxruntime140/dr.py +244 -0
- taichi/aot/conventions/gfxruntime140/sr.py +613 -0
- taichi/aot/module.py +253 -0
- taichi/aot/utils.py +151 -0
- taichi/assets/.git +1 -0
- taichi/assets/Go-Regular.ttf +0 -0
- taichi/assets/static/imgs/ti_gallery.png +0 -0
- taichi/examples/minimal.py +28 -0
- taichi/experimental.py +16 -0
- taichi/graph/__init__.py +3 -0
- taichi/graph/_graph.py +292 -0
- taichi/lang/__init__.py +50 -0
- taichi/lang/_ndarray.py +348 -0
- taichi/lang/_ndrange.py +152 -0
- taichi/lang/_texture.py +172 -0
- taichi/lang/_wrap_inspect.py +189 -0
- taichi/lang/any_array.py +99 -0
- taichi/lang/argpack.py +411 -0
- taichi/lang/ast/__init__.py +5 -0
- taichi/lang/ast/ast_transformer.py +1806 -0
- taichi/lang/ast/ast_transformer_utils.py +328 -0
- taichi/lang/ast/checkers.py +106 -0
- taichi/lang/ast/symbol_resolver.py +57 -0
- taichi/lang/ast/transform.py +9 -0
- taichi/lang/common_ops.py +310 -0
- taichi/lang/exception.py +80 -0
- taichi/lang/expr.py +180 -0
- taichi/lang/field.py +464 -0
- taichi/lang/impl.py +1246 -0
- taichi/lang/kernel_arguments.py +157 -0
- taichi/lang/kernel_impl.py +1415 -0
- taichi/lang/matrix.py +1877 -0
- taichi/lang/matrix_ops.py +341 -0
- taichi/lang/matrix_ops_utils.py +190 -0
- taichi/lang/mesh.py +687 -0
- taichi/lang/misc.py +807 -0
- taichi/lang/ops.py +1489 -0
- taichi/lang/runtime_ops.py +13 -0
- taichi/lang/shell.py +35 -0
- taichi/lang/simt/__init__.py +5 -0
- taichi/lang/simt/block.py +94 -0
- taichi/lang/simt/grid.py +7 -0
- taichi/lang/simt/subgroup.py +191 -0
- taichi/lang/simt/warp.py +96 -0
- taichi/lang/snode.py +487 -0
- taichi/lang/source_builder.py +150 -0
- taichi/lang/struct.py +855 -0
- taichi/lang/util.py +381 -0
- taichi/linalg/__init__.py +8 -0
- taichi/linalg/matrixfree_cg.py +310 -0
- taichi/linalg/sparse_cg.py +59 -0
- taichi/linalg/sparse_matrix.py +303 -0
- taichi/linalg/sparse_solver.py +123 -0
- taichi/math/__init__.py +11 -0
- taichi/math/_complex.py +204 -0
- taichi/math/mathimpl.py +886 -0
- taichi/profiler/__init__.py +6 -0
- taichi/profiler/kernel_metrics.py +260 -0
- taichi/profiler/kernel_profiler.py +592 -0
- taichi/profiler/memory_profiler.py +15 -0
- taichi/profiler/scoped_profiler.py +36 -0
- taichi/shaders/Circles_vk.frag +29 -0
- taichi/shaders/Circles_vk.vert +45 -0
- taichi/shaders/Circles_vk_frag.spv +0 -0
- taichi/shaders/Circles_vk_vert.spv +0 -0
- taichi/shaders/Lines_vk.frag +9 -0
- taichi/shaders/Lines_vk.vert +11 -0
- taichi/shaders/Lines_vk_frag.spv +0 -0
- taichi/shaders/Lines_vk_vert.spv +0 -0
- taichi/shaders/Mesh_vk.frag +71 -0
- taichi/shaders/Mesh_vk.vert +68 -0
- taichi/shaders/Mesh_vk_frag.spv +0 -0
- taichi/shaders/Mesh_vk_vert.spv +0 -0
- taichi/shaders/Particles_vk.frag +95 -0
- taichi/shaders/Particles_vk.vert +73 -0
- taichi/shaders/Particles_vk_frag.spv +0 -0
- taichi/shaders/Particles_vk_vert.spv +0 -0
- taichi/shaders/SceneLines2quad_vk_comp.spv +0 -0
- taichi/shaders/SceneLines_vk.frag +9 -0
- taichi/shaders/SceneLines_vk.vert +12 -0
- taichi/shaders/SceneLines_vk_frag.spv +0 -0
- taichi/shaders/SceneLines_vk_vert.spv +0 -0
- taichi/shaders/SetImage_vk.frag +21 -0
- taichi/shaders/SetImage_vk.vert +15 -0
- taichi/shaders/SetImage_vk_frag.spv +0 -0
- taichi/shaders/SetImage_vk_vert.spv +0 -0
- taichi/shaders/Triangles_vk.frag +16 -0
- taichi/shaders/Triangles_vk.vert +29 -0
- taichi/shaders/Triangles_vk_frag.spv +0 -0
- taichi/shaders/Triangles_vk_vert.spv +0 -0
- taichi/shaders/lines2quad_vk_comp.spv +0 -0
- taichi/sparse/__init__.py +3 -0
- taichi/sparse/_sparse_grid.py +77 -0
- taichi/tools/__init__.py +12 -0
- taichi/tools/diagnose.py +124 -0
- taichi/tools/np2ply.py +364 -0
- taichi/tools/vtk.py +38 -0
- taichi/types/__init__.py +19 -0
- taichi/types/annotations.py +47 -0
- taichi/types/compound_types.py +90 -0
- taichi/types/enums.py +49 -0
- taichi/types/ndarray_type.py +147 -0
- taichi/types/primitive_types.py +203 -0
- taichi/types/quant.py +88 -0
- taichi/types/texture_type.py +85 -0
- taichi/types/utils.py +13 -0
@@ -0,0 +1,328 @@
|
|
1
|
+
# type: ignore
|
2
|
+
|
3
|
+
import ast
|
4
|
+
import builtins
|
5
|
+
import traceback
|
6
|
+
from enum import Enum
|
7
|
+
from sys import version_info
|
8
|
+
from textwrap import TextWrapper
|
9
|
+
from typing import TYPE_CHECKING, Any, List
|
10
|
+
|
11
|
+
from taichi._lib.core.taichi_python import ASTBuilder
|
12
|
+
from taichi.lang import impl
|
13
|
+
from taichi.lang.exception import (
|
14
|
+
TaichiCompilationError,
|
15
|
+
TaichiNameError,
|
16
|
+
TaichiSyntaxError,
|
17
|
+
handle_exception_from_cpp,
|
18
|
+
)
|
19
|
+
|
20
|
+
if TYPE_CHECKING:
|
21
|
+
from taichi.lang.kernel_impl import (
|
22
|
+
Func,
|
23
|
+
Kernel,
|
24
|
+
)
|
25
|
+
|
26
|
+
|
27
|
+
class Builder:
|
28
|
+
def __call__(self, ctx, node):
|
29
|
+
method = getattr(self, "build_" + node.__class__.__name__, None)
|
30
|
+
try:
|
31
|
+
if method is None:
|
32
|
+
error_msg = f'Unsupported node "{node.__class__.__name__}"'
|
33
|
+
raise TaichiSyntaxError(error_msg)
|
34
|
+
info = ctx.get_pos_info(node) if isinstance(node, (ast.stmt, ast.expr)) else ""
|
35
|
+
with impl.get_runtime().src_info_guard(info):
|
36
|
+
return method(ctx, node)
|
37
|
+
except Exception as e:
|
38
|
+
if impl.get_runtime().print_full_traceback:
|
39
|
+
raise e
|
40
|
+
if ctx.raised or not isinstance(node, (ast.stmt, ast.expr)):
|
41
|
+
raise e.with_traceback(None)
|
42
|
+
ctx.raised = True
|
43
|
+
e = handle_exception_from_cpp(e)
|
44
|
+
if not isinstance(e, TaichiCompilationError):
|
45
|
+
msg = ctx.get_pos_info(node) + traceback.format_exc()
|
46
|
+
raise TaichiCompilationError(msg) from None
|
47
|
+
msg = ctx.get_pos_info(node) + str(e)
|
48
|
+
raise type(e)(msg) from None
|
49
|
+
|
50
|
+
|
51
|
+
class VariableScopeGuard:
|
52
|
+
def __init__(self, scopes):
|
53
|
+
self.scopes = scopes
|
54
|
+
|
55
|
+
def __enter__(self):
|
56
|
+
self.scopes.append({})
|
57
|
+
|
58
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
59
|
+
self.scopes.pop()
|
60
|
+
|
61
|
+
|
62
|
+
class StaticScopeStatus:
|
63
|
+
def __init__(self):
|
64
|
+
self.is_in_static_scope = False
|
65
|
+
|
66
|
+
|
67
|
+
class StaticScopeGuard:
|
68
|
+
def __init__(self, status):
|
69
|
+
self.status = status
|
70
|
+
|
71
|
+
def __enter__(self):
|
72
|
+
self.prev = self.status.is_in_static_scope
|
73
|
+
self.status.is_in_static_scope = True
|
74
|
+
|
75
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
76
|
+
self.status.is_in_static_scope = self.prev
|
77
|
+
|
78
|
+
|
79
|
+
class NonStaticControlFlowStatus:
|
80
|
+
def __init__(self):
|
81
|
+
self.is_in_non_static_control_flow = False
|
82
|
+
|
83
|
+
|
84
|
+
class NonStaticControlFlowGuard:
|
85
|
+
def __init__(self, status: NonStaticControlFlowStatus):
|
86
|
+
self.status = status
|
87
|
+
|
88
|
+
def __enter__(self):
|
89
|
+
self.prev = self.status.is_in_non_static_control_flow
|
90
|
+
self.status.is_in_non_static_control_flow = True
|
91
|
+
|
92
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
93
|
+
self.status.is_in_non_static_control_flow = self.prev
|
94
|
+
|
95
|
+
|
96
|
+
class LoopStatus(Enum):
|
97
|
+
Normal = 0
|
98
|
+
Break = 1
|
99
|
+
Continue = 2
|
100
|
+
|
101
|
+
|
102
|
+
class LoopScopeAttribute:
|
103
|
+
def __init__(self, is_static: bool):
|
104
|
+
self.is_static = is_static
|
105
|
+
self.status: LoopStatus = LoopStatus.Normal
|
106
|
+
self.nearest_non_static_if: ast.If | None = None
|
107
|
+
|
108
|
+
|
109
|
+
class LoopScopeGuard:
|
110
|
+
def __init__(self, scopes, non_static_guard=None):
|
111
|
+
self.scopes = scopes
|
112
|
+
self.non_static_guard = non_static_guard
|
113
|
+
|
114
|
+
def __enter__(self):
|
115
|
+
self.scopes.append(LoopScopeAttribute(self.non_static_guard is None))
|
116
|
+
if self.non_static_guard:
|
117
|
+
self.non_static_guard.__enter__()
|
118
|
+
|
119
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
120
|
+
self.scopes.pop()
|
121
|
+
if self.non_static_guard:
|
122
|
+
self.non_static_guard.__exit__(exc_type, exc_val, exc_tb)
|
123
|
+
|
124
|
+
|
125
|
+
class NonStaticIfGuard:
|
126
|
+
def __init__(
|
127
|
+
self,
|
128
|
+
if_node: ast.If,
|
129
|
+
loop_attribute: LoopScopeAttribute,
|
130
|
+
non_static_status: NonStaticControlFlowStatus,
|
131
|
+
):
|
132
|
+
self.loop_attribute = loop_attribute
|
133
|
+
self.if_node = if_node
|
134
|
+
self.non_static_guard = NonStaticControlFlowGuard(non_static_status)
|
135
|
+
|
136
|
+
def __enter__(self):
|
137
|
+
if self.loop_attribute:
|
138
|
+
self.old_non_static_if = self.loop_attribute.nearest_non_static_if
|
139
|
+
self.loop_attribute.nearest_non_static_if = self.if_node
|
140
|
+
self.non_static_guard.__enter__()
|
141
|
+
|
142
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
143
|
+
if self.loop_attribute:
|
144
|
+
self.loop_attribute.nearest_non_static_if = self.old_non_static_if
|
145
|
+
self.non_static_guard.__exit__(exc_type, exc_val, exc_tb)
|
146
|
+
|
147
|
+
|
148
|
+
class ReturnStatus(Enum):
|
149
|
+
NoReturn = 0
|
150
|
+
ReturnedVoid = 1
|
151
|
+
ReturnedValue = 2
|
152
|
+
|
153
|
+
|
154
|
+
class ASTTransformerContext:
|
155
|
+
def __init__(
|
156
|
+
self,
|
157
|
+
excluded_parameters=(),
|
158
|
+
is_kernel: bool = True,
|
159
|
+
func: "Func | Kernel | None" = None,
|
160
|
+
arg_features=None,
|
161
|
+
global_vars: dict[str, Any] | None = None,
|
162
|
+
argument_data=None,
|
163
|
+
file: str | None = None,
|
164
|
+
src: list[str] | None = None,
|
165
|
+
start_lineno: int | None = None,
|
166
|
+
ast_builder: ASTBuilder | None = None,
|
167
|
+
is_real_function: bool = False,
|
168
|
+
):
|
169
|
+
self.func = func
|
170
|
+
self.local_scopes = []
|
171
|
+
self.loop_scopes: List[LoopScopeAttribute] = []
|
172
|
+
self.excluded_parameters = excluded_parameters
|
173
|
+
self.is_kernel = is_kernel
|
174
|
+
self.arg_features = arg_features
|
175
|
+
self.returns = None
|
176
|
+
self.global_vars = global_vars
|
177
|
+
self.argument_data = argument_data
|
178
|
+
self.return_data = None
|
179
|
+
self.file = file
|
180
|
+
self.src = src
|
181
|
+
self.indent = 0
|
182
|
+
for c in self.src[0]:
|
183
|
+
if c == " ":
|
184
|
+
self.indent += 1
|
185
|
+
else:
|
186
|
+
break
|
187
|
+
self.lineno_offset = start_lineno - 1
|
188
|
+
self.raised = False
|
189
|
+
self.non_static_control_flow_status = NonStaticControlFlowStatus()
|
190
|
+
self.static_scope_status = StaticScopeStatus()
|
191
|
+
self.returned = ReturnStatus.NoReturn
|
192
|
+
self.ast_builder = ast_builder
|
193
|
+
self.visited_funcdef = False
|
194
|
+
self.is_real_function = is_real_function
|
195
|
+
self.kernel_args = []
|
196
|
+
|
197
|
+
# e.g.: FunctionDef, Module, Global
|
198
|
+
def variable_scope_guard(self):
|
199
|
+
return VariableScopeGuard(self.local_scopes)
|
200
|
+
|
201
|
+
# e.g.: For, While
|
202
|
+
def loop_scope_guard(self, is_static=False):
|
203
|
+
if is_static:
|
204
|
+
return LoopScopeGuard(self.loop_scopes)
|
205
|
+
return LoopScopeGuard(self.loop_scopes, self.non_static_control_flow_guard())
|
206
|
+
|
207
|
+
def non_static_if_guard(self, if_node: ast.If):
|
208
|
+
return NonStaticIfGuard(
|
209
|
+
if_node,
|
210
|
+
self.current_loop_scope() if self.loop_scopes else None,
|
211
|
+
self.non_static_control_flow_status,
|
212
|
+
)
|
213
|
+
|
214
|
+
def non_static_control_flow_guard(self):
|
215
|
+
return NonStaticControlFlowGuard(self.non_static_control_flow_status)
|
216
|
+
|
217
|
+
def static_scope_guard(self):
|
218
|
+
return StaticScopeGuard(self.static_scope_status)
|
219
|
+
|
220
|
+
def current_scope(self):
|
221
|
+
return self.local_scopes[-1]
|
222
|
+
|
223
|
+
def current_loop_scope(self):
|
224
|
+
return self.loop_scopes[-1]
|
225
|
+
|
226
|
+
def loop_status(self):
|
227
|
+
if self.loop_scopes:
|
228
|
+
return self.loop_scopes[-1].status
|
229
|
+
return LoopStatus.Normal
|
230
|
+
|
231
|
+
def set_loop_status(self, status):
|
232
|
+
self.loop_scopes[-1].status = status
|
233
|
+
|
234
|
+
def is_in_static_for(self):
|
235
|
+
if self.loop_scopes:
|
236
|
+
return self.loop_scopes[-1].is_static
|
237
|
+
return False
|
238
|
+
|
239
|
+
def is_in_non_static_control_flow(self):
|
240
|
+
return self.non_static_control_flow_status.is_in_non_static_control_flow
|
241
|
+
|
242
|
+
def is_in_static_scope(self):
|
243
|
+
return self.static_scope_status.is_in_static_scope
|
244
|
+
|
245
|
+
def is_var_declared(self, name):
|
246
|
+
for s in self.local_scopes:
|
247
|
+
if name in s:
|
248
|
+
return True
|
249
|
+
return False
|
250
|
+
|
251
|
+
def create_variable(self, name, var):
|
252
|
+
if name in self.current_scope():
|
253
|
+
raise TaichiSyntaxError("Recreating variables is not allowed")
|
254
|
+
self.current_scope()[name] = var
|
255
|
+
|
256
|
+
def check_loop_var(self, loop_var):
|
257
|
+
if self.is_var_declared(loop_var):
|
258
|
+
raise TaichiSyntaxError(
|
259
|
+
f"Variable '{loop_var}' is already declared in the outer scope and cannot be used as loop variable"
|
260
|
+
)
|
261
|
+
|
262
|
+
def get_var_by_name(self, name: str):
|
263
|
+
for s in reversed(self.local_scopes):
|
264
|
+
if name in s:
|
265
|
+
return s[name]
|
266
|
+
if name in self.global_vars:
|
267
|
+
var = self.global_vars[name]
|
268
|
+
from taichi.lang.matrix import ( # pylint: disable-msg=C0415
|
269
|
+
Matrix,
|
270
|
+
make_matrix,
|
271
|
+
)
|
272
|
+
|
273
|
+
if isinstance(var, Matrix):
|
274
|
+
return make_matrix(var.to_list())
|
275
|
+
return var
|
276
|
+
try:
|
277
|
+
return getattr(builtins, name)
|
278
|
+
except AttributeError:
|
279
|
+
raise TaichiNameError(f'Name "{name}" is not defined')
|
280
|
+
|
281
|
+
def get_pos_info(self, node) -> str:
|
282
|
+
msg = f'File "{self.file}", line {node.lineno + self.lineno_offset}, in {self.func.func.__name__}:\n'
|
283
|
+
if version_info < (3, 8):
|
284
|
+
msg += self.src[node.lineno - 1] + "\n"
|
285
|
+
return msg
|
286
|
+
col_offset = self.indent + node.col_offset
|
287
|
+
end_col_offset = self.indent + node.end_col_offset
|
288
|
+
|
289
|
+
wrapper = TextWrapper(width=80)
|
290
|
+
|
291
|
+
def gen_line(code, hint):
|
292
|
+
hint += " " * (len(code) - len(hint))
|
293
|
+
code = wrapper.wrap(code)
|
294
|
+
hint = wrapper.wrap(hint)
|
295
|
+
if not len(code):
|
296
|
+
return "\n\n"
|
297
|
+
return "".join([c + "\n" + h + "\n" for c, h in zip(code, hint)])
|
298
|
+
|
299
|
+
if node.lineno == node.end_lineno:
|
300
|
+
hint = " " * col_offset + "^" * (end_col_offset - col_offset)
|
301
|
+
msg += gen_line(self.src[node.lineno - 1], hint)
|
302
|
+
else:
|
303
|
+
node_type = node.__class__.__name__
|
304
|
+
|
305
|
+
if node_type in ["For", "While", "FunctionDef", "If"]:
|
306
|
+
end_lineno = max(node.body[0].lineno - 1, node.lineno)
|
307
|
+
else:
|
308
|
+
end_lineno = node.end_lineno
|
309
|
+
|
310
|
+
for i in range(node.lineno - 1, end_lineno):
|
311
|
+
last = len(self.src[i])
|
312
|
+
while last > 0 and (self.src[i][last - 1].isspace() or not self.src[i][last - 1].isprintable()):
|
313
|
+
last -= 1
|
314
|
+
first = 0
|
315
|
+
while first < len(self.src[i]) and (
|
316
|
+
self.src[i][first].isspace() or not self.src[i][first].isprintable()
|
317
|
+
):
|
318
|
+
first += 1
|
319
|
+
if i == node.lineno - 1:
|
320
|
+
hint = " " * col_offset + "^" * (last - col_offset)
|
321
|
+
elif i == node.end_lineno - 1:
|
322
|
+
hint = " " * first + "^" * (end_col_offset - first)
|
323
|
+
elif first < last:
|
324
|
+
hint = " " * first + "^" * (last - first)
|
325
|
+
else:
|
326
|
+
hint = ""
|
327
|
+
msg += gen_line(self.src[i], hint)
|
328
|
+
return msg
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# type: ignore
|
2
|
+
|
3
|
+
import ast
|
4
|
+
|
5
|
+
from taichi.lang._wrap_inspect import getsourcefile, getsourcelines
|
6
|
+
from taichi.lang.exception import TaichiSyntaxError
|
7
|
+
|
8
|
+
|
9
|
+
class KernelSimplicityASTChecker(ast.NodeVisitor):
|
10
|
+
class ScopeGuard:
|
11
|
+
def __init__(self, checker):
|
12
|
+
self.c = checker
|
13
|
+
self._allows_for_loop = True
|
14
|
+
self._allows_more_stmt = True
|
15
|
+
|
16
|
+
@property
|
17
|
+
def allows_for_loop(self):
|
18
|
+
return self._allows_for_loop
|
19
|
+
|
20
|
+
@property
|
21
|
+
def allows_more_stmt(self):
|
22
|
+
return self._allows_more_stmt
|
23
|
+
|
24
|
+
def mark_no_more_for_loop(self):
|
25
|
+
self._allows_for_loop = False
|
26
|
+
|
27
|
+
def mark_no_more_stmt(self):
|
28
|
+
self._allows_for_loop = False
|
29
|
+
self._allows_more_stmt = False
|
30
|
+
|
31
|
+
def __enter__(self):
|
32
|
+
self.c._scope_guards.append(self)
|
33
|
+
|
34
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
35
|
+
self.c._scope_guards.pop()
|
36
|
+
|
37
|
+
def __init__(self, func):
|
38
|
+
super().__init__()
|
39
|
+
self._func_file = getsourcefile(func)
|
40
|
+
self._func_lineno = getsourcelines(func)[1]
|
41
|
+
self._func_name = func.__name__
|
42
|
+
self._scope_guards = []
|
43
|
+
|
44
|
+
def new_scope(self):
|
45
|
+
return KernelSimplicityASTChecker.ScopeGuard(self)
|
46
|
+
|
47
|
+
@property
|
48
|
+
def current_scope(self):
|
49
|
+
return self._scope_guards[-1]
|
50
|
+
|
51
|
+
@property
|
52
|
+
def top_level(self):
|
53
|
+
return len(self._scope_guards) == 0
|
54
|
+
|
55
|
+
def get_error_location(self, node):
|
56
|
+
# -1 because ast's lineno is 1-based.
|
57
|
+
lineno = self._func_lineno + node.lineno - 1
|
58
|
+
return f"file={self._func_file} kernel={self._func_name} line={lineno}"
|
59
|
+
|
60
|
+
@staticmethod
|
61
|
+
def should_check(node):
|
62
|
+
if not isinstance(node, ast.stmt):
|
63
|
+
return False
|
64
|
+
# TODO(#536): Frontend pass should help make sure |func| is a valid AST for
|
65
|
+
# Taichi.
|
66
|
+
ignored = [ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef]
|
67
|
+
return not any(map(lambda t: isinstance(node, t), ignored))
|
68
|
+
|
69
|
+
def generic_visit(self, node):
|
70
|
+
if not self.should_check(node):
|
71
|
+
super().generic_visit(node)
|
72
|
+
return
|
73
|
+
|
74
|
+
if not (self.top_level or self.current_scope.allows_more_stmt):
|
75
|
+
raise TaichiSyntaxError(f"No more statements allowed, at {self.get_error_location(node)}")
|
76
|
+
old_top_level = self.top_level
|
77
|
+
if old_top_level:
|
78
|
+
self._scope_guards.append(self.new_scope())
|
79
|
+
# Marking here before the visit has the effect of disallow for-loops in
|
80
|
+
# nested blocks. E.g. if |node| is a IfStmt, then the checker would disallow
|
81
|
+
# for-loops inside it.
|
82
|
+
self.current_scope.mark_no_more_for_loop()
|
83
|
+
super().generic_visit(node)
|
84
|
+
if old_top_level:
|
85
|
+
self._scope_guards.pop()
|
86
|
+
|
87
|
+
@staticmethod
|
88
|
+
def visit_for(node):
|
89
|
+
# TODO: since autodiff is enhanced, AST checker rules should be relaxed. This part should be updated.
|
90
|
+
# original code is #def visit_For(self, node) without #@staticmethod before fix pylint R0201
|
91
|
+
return
|
92
|
+
# is_static = (isinstance(node.iter, ast.Call)
|
93
|
+
# and isinstance(node.iter.func, ast.Attribute)
|
94
|
+
# and isinstance(node.iter.func.value, ast.Name)
|
95
|
+
# and node.iter.func.value.id == 'ti'
|
96
|
+
# and node.iter.func.attr == 'static')
|
97
|
+
# if not (self.top_level or self.current_scope.allows_for_loop
|
98
|
+
# or is_static):
|
99
|
+
# raise TaichiSyntaxError(
|
100
|
+
# f'No more for loops allowed, at {self.get_error_location(node)}'
|
101
|
+
# )
|
102
|
+
# with self.new_scope():
|
103
|
+
# super().generic_visit(node)
|
104
|
+
#
|
105
|
+
# if not (self.top_level or is_static):
|
106
|
+
# self.current_scope.mark_no_more_stmt()
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# type: ignore
|
2
|
+
|
3
|
+
"""Provides helpers to resolve AST nodes."""
|
4
|
+
|
5
|
+
import ast
|
6
|
+
|
7
|
+
|
8
|
+
class ASTResolver:
|
9
|
+
"""Provides helper methods to resolve AST nodes."""
|
10
|
+
|
11
|
+
@staticmethod
|
12
|
+
def resolve_to(node, wanted, scope):
|
13
|
+
"""Check if symbol ``node`` resolves to ``wanted`` object.
|
14
|
+
|
15
|
+
This is only intended to check if a given AST node resolves to a symbol
|
16
|
+
under some namespaces, e.g. the ``a.b.c.foo`` pattern, but not meant for
|
17
|
+
more complicated expressions like ``(a + b).foo``.
|
18
|
+
|
19
|
+
Args:
|
20
|
+
node (Union[ast.Attribute, ast.Name]): an AST node to be resolved.
|
21
|
+
wanted (Any): The expected python object.
|
22
|
+
scope (Dict[str, Any]): Maps from symbol names to objects, for
|
23
|
+
example, globals()
|
24
|
+
|
25
|
+
Returns:
|
26
|
+
bool: The checked result.
|
27
|
+
"""
|
28
|
+
if isinstance(node, ast.Name):
|
29
|
+
return scope.get(node.id) is wanted
|
30
|
+
|
31
|
+
if not isinstance(node, ast.Attribute):
|
32
|
+
return False
|
33
|
+
|
34
|
+
v = node.value
|
35
|
+
chain = [node.attr]
|
36
|
+
while isinstance(v, ast.Attribute):
|
37
|
+
chain.append(v.attr)
|
38
|
+
v = v.value
|
39
|
+
if not isinstance(v, ast.Name):
|
40
|
+
# Example cases that fall under this branch:
|
41
|
+
#
|
42
|
+
# x[i].attr: ast.Subscript
|
43
|
+
# (a + b).attr: ast.BinOp
|
44
|
+
# ...
|
45
|
+
return False
|
46
|
+
chain.append(v.id)
|
47
|
+
|
48
|
+
for attr in reversed(chain):
|
49
|
+
try:
|
50
|
+
if isinstance(scope, dict):
|
51
|
+
scope = scope[attr]
|
52
|
+
else:
|
53
|
+
scope = getattr(scope, attr)
|
54
|
+
except (KeyError, AttributeError):
|
55
|
+
return False
|
56
|
+
# The name ``scope`` here could be a bit confusing
|
57
|
+
return scope is wanted
|
@@ -0,0 +1,9 @@
|
|
1
|
+
# type: ignore
|
2
|
+
|
3
|
+
from taichi.lang.ast.ast_transformer import ASTTransformer
|
4
|
+
from taichi.lang.ast.ast_transformer_utils import ASTTransformerContext
|
5
|
+
|
6
|
+
|
7
|
+
def transform_tree(tree, ctx: ASTTransformerContext):
|
8
|
+
ASTTransformer()(ctx, tree)
|
9
|
+
return ctx.return_data
|