konpeito 0.1.0
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.
- checksums.yaml +7 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +75 -0
- data/CONTRIBUTING.md +123 -0
- data/LICENSE +21 -0
- data/README.md +257 -0
- data/Rakefile +11 -0
- data/bin/konpeito +6 -0
- data/konpeito.gemspec +43 -0
- data/lib/konpeito/ast/typed_ast.rb +620 -0
- data/lib/konpeito/ast/visitor.rb +78 -0
- data/lib/konpeito/cache/cache_manager.rb +230 -0
- data/lib/konpeito/cache/dependency_graph.rb +192 -0
- data/lib/konpeito/cache.rb +8 -0
- data/lib/konpeito/cli/base_command.rb +187 -0
- data/lib/konpeito/cli/build_command.rb +220 -0
- data/lib/konpeito/cli/check_command.rb +104 -0
- data/lib/konpeito/cli/config.rb +231 -0
- data/lib/konpeito/cli/deps_command.rb +128 -0
- data/lib/konpeito/cli/doctor_command.rb +340 -0
- data/lib/konpeito/cli/fmt_command.rb +199 -0
- data/lib/konpeito/cli/init_command.rb +312 -0
- data/lib/konpeito/cli/lsp_command.rb +40 -0
- data/lib/konpeito/cli/run_command.rb +150 -0
- data/lib/konpeito/cli/test_command.rb +248 -0
- data/lib/konpeito/cli/watch_command.rb +212 -0
- data/lib/konpeito/cli.rb +301 -0
- data/lib/konpeito/codegen/builtin_methods.rb +229 -0
- data/lib/konpeito/codegen/cruby_backend.rb +1090 -0
- data/lib/konpeito/codegen/debug_info.rb +352 -0
- data/lib/konpeito/codegen/inliner.rb +486 -0
- data/lib/konpeito/codegen/jvm_backend.rb +197 -0
- data/lib/konpeito/codegen/jvm_generator.rb +13412 -0
- data/lib/konpeito/codegen/llvm_generator.rb +13191 -0
- data/lib/konpeito/codegen/loop_optimizer.rb +363 -0
- data/lib/konpeito/codegen/monomorphizer.rb +359 -0
- data/lib/konpeito/codegen/profile_runtime.c +341 -0
- data/lib/konpeito/codegen/profiler.rb +99 -0
- data/lib/konpeito/compiler.rb +592 -0
- data/lib/konpeito/dependency_resolver.rb +296 -0
- data/lib/konpeito/diagnostics/collector.rb +127 -0
- data/lib/konpeito/diagnostics/diagnostic.rb +237 -0
- data/lib/konpeito/diagnostics/renderer.rb +144 -0
- data/lib/konpeito/formatter/formatter.rb +1214 -0
- data/lib/konpeito/hir/builder.rb +7167 -0
- data/lib/konpeito/hir/nodes.rb +2465 -0
- data/lib/konpeito/lsp/document_manager.rb +820 -0
- data/lib/konpeito/lsp/server.rb +183 -0
- data/lib/konpeito/lsp/transport.rb +38 -0
- data/lib/konpeito/parser/prism_adapter.rb +65 -0
- data/lib/konpeito/platform.rb +103 -0
- data/lib/konpeito/profile/report.rb +136 -0
- data/lib/konpeito/rbs_inline/preprocessor.rb +199 -0
- data/lib/konpeito/stdlib/compression/compression.rb +72 -0
- data/lib/konpeito/stdlib/compression/compression.rbs +60 -0
- data/lib/konpeito/stdlib/compression/compression_native.c +415 -0
- data/lib/konpeito/stdlib/compression/extconf.rb +19 -0
- data/lib/konpeito/stdlib/crypto/crypto.rb +85 -0
- data/lib/konpeito/stdlib/crypto/crypto.rbs +74 -0
- data/lib/konpeito/stdlib/crypto/crypto_native.c +312 -0
- data/lib/konpeito/stdlib/crypto/extconf.rb +40 -0
- data/lib/konpeito/stdlib/http/extconf.rb +19 -0
- data/lib/konpeito/stdlib/http/http.rb +125 -0
- data/lib/konpeito/stdlib/http/http.rbs +57 -0
- data/lib/konpeito/stdlib/http/http_native.c +440 -0
- data/lib/konpeito/stdlib/json/extconf.rb +17 -0
- data/lib/konpeito/stdlib/json/json.rb +44 -0
- data/lib/konpeito/stdlib/json/json.rbs +33 -0
- data/lib/konpeito/stdlib/json/json_native.c +286 -0
- data/lib/konpeito/stdlib/ui/extconf.rb +216 -0
- data/lib/konpeito/stdlib/ui/konpeito_ui_native.cpp +1625 -0
- data/lib/konpeito/stdlib/ui/konpeito_ui_native.h +162 -0
- data/lib/konpeito/stdlib/ui/ui.rb +318 -0
- data/lib/konpeito/stdlib/ui/ui.rbs +247 -0
- data/lib/konpeito/type_checker/annotation_parser.rb +67 -0
- data/lib/konpeito/type_checker/hm_inferrer.rb +2565 -0
- data/lib/konpeito/type_checker/inferrer.rb +565 -0
- data/lib/konpeito/type_checker/rbs_loader.rb +1621 -0
- data/lib/konpeito/type_checker/type_resolver.rb +276 -0
- data/lib/konpeito/type_checker/types.rb +1434 -0
- data/lib/konpeito/type_checker/unification.rb +323 -0
- data/lib/konpeito/ui/animation/animated_state.rb +80 -0
- data/lib/konpeito/ui/animation/easing.rb +59 -0
- data/lib/konpeito/ui/animation/value_tween.rb +66 -0
- data/lib/konpeito/ui/app.rb +379 -0
- data/lib/konpeito/ui/box.rb +38 -0
- data/lib/konpeito/ui/castella.rb +70 -0
- data/lib/konpeito/ui/castella_native.rb +76 -0
- data/lib/konpeito/ui/chart/area_chart.rb +305 -0
- data/lib/konpeito/ui/chart/bar_chart.rb +288 -0
- data/lib/konpeito/ui/chart/base_chart.rb +210 -0
- data/lib/konpeito/ui/chart/chart_helpers.rb +79 -0
- data/lib/konpeito/ui/chart/gauge_chart.rb +171 -0
- data/lib/konpeito/ui/chart/heatmap_chart.rb +222 -0
- data/lib/konpeito/ui/chart/line_chart.rb +289 -0
- data/lib/konpeito/ui/chart/pie_chart.rb +219 -0
- data/lib/konpeito/ui/chart/scales.rb +77 -0
- data/lib/konpeito/ui/chart/scatter_chart.rb +303 -0
- data/lib/konpeito/ui/chart/stacked_bar_chart.rb +276 -0
- data/lib/konpeito/ui/column.rb +271 -0
- data/lib/konpeito/ui/core.rb +2199 -0
- data/lib/konpeito/ui/dsl.rb +443 -0
- data/lib/konpeito/ui/frame.rb +171 -0
- data/lib/konpeito/ui/frame_native.rb +494 -0
- data/lib/konpeito/ui/markdown/ast.rb +124 -0
- data/lib/konpeito/ui/markdown/mermaid/layout.rb +387 -0
- data/lib/konpeito/ui/markdown/mermaid/models.rb +232 -0
- data/lib/konpeito/ui/markdown/mermaid/parser.rb +519 -0
- data/lib/konpeito/ui/markdown/mermaid/renderer.rb +336 -0
- data/lib/konpeito/ui/markdown/parser.rb +805 -0
- data/lib/konpeito/ui/markdown/renderer.rb +639 -0
- data/lib/konpeito/ui/markdown/theme.rb +165 -0
- data/lib/konpeito/ui/render_node.rb +260 -0
- data/lib/konpeito/ui/row.rb +207 -0
- data/lib/konpeito/ui/spacer.rb +18 -0
- data/lib/konpeito/ui/style.rb +799 -0
- data/lib/konpeito/ui/theme.rb +563 -0
- data/lib/konpeito/ui/themes/material.rb +35 -0
- data/lib/konpeito/ui/themes/tokyo_night.rb +6 -0
- data/lib/konpeito/ui/widgets/button.rb +103 -0
- data/lib/konpeito/ui/widgets/calendar.rb +1034 -0
- data/lib/konpeito/ui/widgets/checkbox.rb +119 -0
- data/lib/konpeito/ui/widgets/container.rb +91 -0
- data/lib/konpeito/ui/widgets/data_table.rb +667 -0
- data/lib/konpeito/ui/widgets/divider.rb +29 -0
- data/lib/konpeito/ui/widgets/image.rb +105 -0
- data/lib/konpeito/ui/widgets/input.rb +485 -0
- data/lib/konpeito/ui/widgets/markdown.rb +57 -0
- data/lib/konpeito/ui/widgets/modal.rb +163 -0
- data/lib/konpeito/ui/widgets/multiline_input.rb +968 -0
- data/lib/konpeito/ui/widgets/multiline_text.rb +180 -0
- data/lib/konpeito/ui/widgets/net_image.rb +100 -0
- data/lib/konpeito/ui/widgets/progress_bar.rb +70 -0
- data/lib/konpeito/ui/widgets/radio_buttons.rb +93 -0
- data/lib/konpeito/ui/widgets/slider.rb +133 -0
- data/lib/konpeito/ui/widgets/switch.rb +84 -0
- data/lib/konpeito/ui/widgets/tabs.rb +157 -0
- data/lib/konpeito/ui/widgets/text.rb +110 -0
- data/lib/konpeito/ui/widgets/tree.rb +426 -0
- data/lib/konpeito/version.rb +5 -0
- data/lib/konpeito.rb +109 -0
- data/test_native_array.rb +172 -0
- data/test_native_array_class.rb +197 -0
- data/test_native_class.rb +151 -0
- data/tools/konpeito-asm/build.sh +65 -0
- data/tools/konpeito-asm/lib/asm-9.7.1.jar +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KArray.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCompression.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KConditionVariable.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCrypto.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KFile.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHTTP.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHash.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON$Parser.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KMath.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactor.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactorPort.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KSizedQueue.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KThread.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KTime.class +0 -0
- data/tools/konpeito-asm/runtime-classes/konpeito/runtime/RubyDispatch.class +0 -0
- data/tools/konpeito-asm/src/ClassIntrospector.java +312 -0
- data/tools/konpeito-asm/src/KonpeitoAssembler.java +659 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KArray.java +390 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KCompression.java +168 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KConditionVariable.java +48 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KCrypto.java +151 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KFile.java +100 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KHTTP.java +113 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KHash.java +228 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KJSON.java +405 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KMath.java +54 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KRactor.java +244 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KRactorPort.java +53 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KSizedQueue.java +49 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KThread.java +49 -0
- data/tools/konpeito-asm/src/konpeito/runtime/KTime.java +53 -0
- data/tools/konpeito-asm/src/konpeito/runtime/RubyDispatch.java +416 -0
- metadata +267 -0
|
@@ -0,0 +1,620 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Konpeito
|
|
4
|
+
module AST
|
|
5
|
+
# Wrapper for Prism AST nodes with type information
|
|
6
|
+
class TypedNode
|
|
7
|
+
attr_reader :node, :type, :children
|
|
8
|
+
|
|
9
|
+
def initialize(node, type, children = [])
|
|
10
|
+
@node = node
|
|
11
|
+
@type = type
|
|
12
|
+
@children = children
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def location
|
|
16
|
+
node.location
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def node_type
|
|
20
|
+
node.class.name.split("::").last.sub(/Node$/, "").gsub(/([a-z])([A-Z])/, '\1_\2').downcase.to_sym
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def inspect
|
|
24
|
+
"#<TypedNode #{node_type} : #{type}>"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Builds a typed AST from Prism AST
|
|
29
|
+
class TypedASTBuilder < Visitor
|
|
30
|
+
attr_reader :inferrer, :rbs_loader, :use_hm
|
|
31
|
+
|
|
32
|
+
def initialize(rbs_loader, use_hm: true, file_path: nil, source: nil)
|
|
33
|
+
@rbs_loader = rbs_loader
|
|
34
|
+
@use_hm = use_hm
|
|
35
|
+
@file_path = file_path
|
|
36
|
+
@source = source
|
|
37
|
+
|
|
38
|
+
if use_hm
|
|
39
|
+
@hm_inferrer = TypeChecker::HMInferrer.new(rbs_loader, file_path: file_path, source: source)
|
|
40
|
+
@inferrer = nil # Will use HM inferrer
|
|
41
|
+
else
|
|
42
|
+
@hm_inferrer = nil
|
|
43
|
+
@inferrer = TypeChecker::Inferrer.new(rbs_loader)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Get diagnostics from the HM inferrer
|
|
48
|
+
def diagnostics
|
|
49
|
+
@hm_inferrer&.diagnostics || []
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def build(ast)
|
|
53
|
+
# If using HM inference, run whole-program analysis first
|
|
54
|
+
if @use_hm && @hm_inferrer
|
|
55
|
+
@hm_inferrer.analyze(ast)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
visit(ast)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Get type for a node (uses HM inferrer if available)
|
|
62
|
+
def infer_type(node)
|
|
63
|
+
if @use_hm && @hm_inferrer
|
|
64
|
+
@hm_inferrer.type_for(node)
|
|
65
|
+
else
|
|
66
|
+
@inferrer.infer(node)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
def visit(node)
|
|
73
|
+
return nil unless node
|
|
74
|
+
|
|
75
|
+
method_name = :"visit_#{node_type(node)}"
|
|
76
|
+
if respond_to?(method_name, true)
|
|
77
|
+
send(method_name, node)
|
|
78
|
+
else
|
|
79
|
+
visit_default(node)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def visit_default(node)
|
|
84
|
+
type = infer_type(node)
|
|
85
|
+
children = node.compact_child_nodes.map { |child| visit(child) }.compact
|
|
86
|
+
TypedNode.new(node, type, children)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def visit_program(node)
|
|
90
|
+
type = infer_type(node)
|
|
91
|
+
children = [visit(node.statements)].compact
|
|
92
|
+
TypedNode.new(node, type, children)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def visit_statements(node)
|
|
96
|
+
type = infer_type(node)
|
|
97
|
+
children = node.body.map { |stmt| visit(stmt) }.compact
|
|
98
|
+
TypedNode.new(node, type, children)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def visit_def(node)
|
|
102
|
+
# Create a new scope for method body
|
|
103
|
+
type = infer_type(node)
|
|
104
|
+
|
|
105
|
+
children = []
|
|
106
|
+
children << visit(node.parameters) if node.parameters
|
|
107
|
+
children << visit(node.body) if node.body
|
|
108
|
+
children.compact!
|
|
109
|
+
|
|
110
|
+
TypedNode.new(node, type, children)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def visit_class(node)
|
|
114
|
+
type = infer_type(node)
|
|
115
|
+
|
|
116
|
+
children = []
|
|
117
|
+
children << visit(node.constant_path) if node.constant_path
|
|
118
|
+
children << visit(node.superclass) if node.superclass
|
|
119
|
+
children << visit(node.body) if node.body
|
|
120
|
+
children.compact!
|
|
121
|
+
|
|
122
|
+
TypedNode.new(node, type, children)
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def visit_module(node)
|
|
126
|
+
type = infer_type(node)
|
|
127
|
+
|
|
128
|
+
children = []
|
|
129
|
+
children << visit(node.constant_path) if node.constant_path
|
|
130
|
+
children << visit(node.body) if node.body
|
|
131
|
+
children.compact!
|
|
132
|
+
|
|
133
|
+
TypedNode.new(node, type, children)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def visit_if(node)
|
|
137
|
+
type = infer_type(node)
|
|
138
|
+
|
|
139
|
+
children = []
|
|
140
|
+
children << visit(node.predicate)
|
|
141
|
+
children << visit(node.statements) if node.statements
|
|
142
|
+
children << visit(node.subsequent) if node.subsequent
|
|
143
|
+
children.compact!
|
|
144
|
+
|
|
145
|
+
TypedNode.new(node, type, children)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def visit_unless(node)
|
|
149
|
+
type = infer_type(node)
|
|
150
|
+
|
|
151
|
+
children = []
|
|
152
|
+
children << visit(node.predicate)
|
|
153
|
+
children << visit(node.statements) if node.statements
|
|
154
|
+
children << visit(node.else_clause) if node.else_clause
|
|
155
|
+
children.compact!
|
|
156
|
+
|
|
157
|
+
TypedNode.new(node, type, children)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def visit_and(node)
|
|
161
|
+
type = infer_type(node)
|
|
162
|
+
|
|
163
|
+
children = []
|
|
164
|
+
children << visit(node.left)
|
|
165
|
+
children << visit(node.right)
|
|
166
|
+
children.compact!
|
|
167
|
+
|
|
168
|
+
TypedNode.new(node, type, children)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def visit_or(node)
|
|
172
|
+
type = infer_type(node)
|
|
173
|
+
|
|
174
|
+
children = []
|
|
175
|
+
children << visit(node.left)
|
|
176
|
+
children << visit(node.right)
|
|
177
|
+
children.compact!
|
|
178
|
+
|
|
179
|
+
TypedNode.new(node, type, children)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# Compound assignment visitors
|
|
183
|
+
def visit_local_variable_operator_write(node)
|
|
184
|
+
type = infer_type(node)
|
|
185
|
+
children = [visit(node.value)].compact
|
|
186
|
+
TypedNode.new(node, type, children)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def visit_local_variable_or_write(node)
|
|
190
|
+
type = infer_type(node)
|
|
191
|
+
children = [visit(node.value)].compact
|
|
192
|
+
TypedNode.new(node, type, children)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def visit_local_variable_and_write(node)
|
|
196
|
+
type = infer_type(node)
|
|
197
|
+
children = [visit(node.value)].compact
|
|
198
|
+
TypedNode.new(node, type, children)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def visit_instance_variable_operator_write(node)
|
|
202
|
+
type = infer_type(node)
|
|
203
|
+
children = [visit(node.value)].compact
|
|
204
|
+
TypedNode.new(node, type, children)
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def visit_instance_variable_or_write(node)
|
|
208
|
+
type = infer_type(node)
|
|
209
|
+
children = [visit(node.value)].compact
|
|
210
|
+
TypedNode.new(node, type, children)
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def visit_instance_variable_and_write(node)
|
|
214
|
+
type = infer_type(node)
|
|
215
|
+
children = [visit(node.value)].compact
|
|
216
|
+
TypedNode.new(node, type, children)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def visit_class_variable_operator_write(node)
|
|
220
|
+
type = infer_type(node)
|
|
221
|
+
children = [visit(node.value)].compact
|
|
222
|
+
TypedNode.new(node, type, children)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def visit_class_variable_or_write(node)
|
|
226
|
+
type = infer_type(node)
|
|
227
|
+
children = [visit(node.value)].compact
|
|
228
|
+
TypedNode.new(node, type, children)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def visit_class_variable_and_write(node)
|
|
232
|
+
type = infer_type(node)
|
|
233
|
+
children = [visit(node.value)].compact
|
|
234
|
+
TypedNode.new(node, type, children)
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
def visit_while(node)
|
|
238
|
+
type = infer_type(node)
|
|
239
|
+
|
|
240
|
+
children = []
|
|
241
|
+
children << visit(node.predicate)
|
|
242
|
+
children << visit(node.statements) if node.statements
|
|
243
|
+
children.compact!
|
|
244
|
+
|
|
245
|
+
TypedNode.new(node, type, children)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def visit_until(node)
|
|
249
|
+
type = infer_type(node)
|
|
250
|
+
|
|
251
|
+
children = []
|
|
252
|
+
children << visit(node.predicate)
|
|
253
|
+
children << visit(node.statements) if node.statements
|
|
254
|
+
children.compact!
|
|
255
|
+
|
|
256
|
+
TypedNode.new(node, type, children)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def visit_break(node)
|
|
260
|
+
type = infer_type(node)
|
|
261
|
+
children = []
|
|
262
|
+
children << visit(node.arguments) if node.arguments
|
|
263
|
+
children.compact!
|
|
264
|
+
TypedNode.new(node, type, children)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def visit_next(node)
|
|
268
|
+
type = infer_type(node)
|
|
269
|
+
children = []
|
|
270
|
+
children << visit(node.arguments) if node.arguments
|
|
271
|
+
children.compact!
|
|
272
|
+
TypedNode.new(node, type, children)
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def visit_range(node)
|
|
276
|
+
type = infer_type(node)
|
|
277
|
+
children = []
|
|
278
|
+
children << visit(node.left) if node.left
|
|
279
|
+
children << visit(node.right) if node.right
|
|
280
|
+
children.compact!
|
|
281
|
+
TypedNode.new(node, type, children)
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def visit_global_variable_read(node)
|
|
285
|
+
type = infer_type(node)
|
|
286
|
+
TypedNode.new(node, type, [])
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def visit_global_variable_write(node)
|
|
290
|
+
type = infer_type(node)
|
|
291
|
+
children = [visit(node.value)].compact
|
|
292
|
+
TypedNode.new(node, type, children)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def visit_multi_write(node)
|
|
296
|
+
type = infer_type(node)
|
|
297
|
+
children = []
|
|
298
|
+
# Visit the value (RHS)
|
|
299
|
+
children << visit(node.value) if node.value
|
|
300
|
+
children.compact!
|
|
301
|
+
TypedNode.new(node, type, children)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def visit_super(node)
|
|
305
|
+
type = infer_type(node)
|
|
306
|
+
children = []
|
|
307
|
+
children << visit(node.arguments) if node.arguments
|
|
308
|
+
children.compact!
|
|
309
|
+
TypedNode.new(node, type, children)
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def visit_forwarding_super(node)
|
|
313
|
+
type = infer_type(node)
|
|
314
|
+
TypedNode.new(node, type, [])
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def visit_case(node)
|
|
318
|
+
type = infer_type(node)
|
|
319
|
+
|
|
320
|
+
children = []
|
|
321
|
+
children << visit(node.predicate) if node.predicate
|
|
322
|
+
node.conditions.each { |cond| children << visit(cond) }
|
|
323
|
+
children << visit(node.else_clause) if node.else_clause
|
|
324
|
+
children.compact!
|
|
325
|
+
|
|
326
|
+
TypedNode.new(node, type, children)
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def visit_when(node)
|
|
330
|
+
type = infer_type(node)
|
|
331
|
+
|
|
332
|
+
children = []
|
|
333
|
+
node.conditions.each { |cond| children << visit(cond) }
|
|
334
|
+
children << visit(node.statements) if node.statements
|
|
335
|
+
children.compact!
|
|
336
|
+
|
|
337
|
+
TypedNode.new(node, type, children)
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
# ========================================
|
|
341
|
+
# Pattern Matching visitors
|
|
342
|
+
# ========================================
|
|
343
|
+
|
|
344
|
+
# case/in statement
|
|
345
|
+
def visit_case_match(node)
|
|
346
|
+
type = infer_type(node)
|
|
347
|
+
|
|
348
|
+
children = []
|
|
349
|
+
children << visit(node.predicate) if node.predicate
|
|
350
|
+
node.conditions.each { |cond| children << visit(cond) }
|
|
351
|
+
children << visit(node.else_clause) if node.else_clause
|
|
352
|
+
children.compact!
|
|
353
|
+
|
|
354
|
+
TypedNode.new(node, type, children)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
# in clause
|
|
358
|
+
def visit_in(node)
|
|
359
|
+
type = infer_type(node)
|
|
360
|
+
|
|
361
|
+
children = []
|
|
362
|
+
children << visit(node.pattern) if node.pattern
|
|
363
|
+
children << visit(node.statements) if node.statements
|
|
364
|
+
children.compact!
|
|
365
|
+
|
|
366
|
+
TypedNode.new(node, type, children)
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
# expr in pattern (returns boolean)
|
|
370
|
+
def visit_match_predicate(node)
|
|
371
|
+
type = TypeChecker::Types::BOOL
|
|
372
|
+
|
|
373
|
+
children = []
|
|
374
|
+
children << visit(node.value)
|
|
375
|
+
children << visit(node.pattern)
|
|
376
|
+
children.compact!
|
|
377
|
+
|
|
378
|
+
TypedNode.new(node, type, children)
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
# expr => pattern (raises on failure)
|
|
382
|
+
def visit_match_required(node)
|
|
383
|
+
type = infer_type(node)
|
|
384
|
+
|
|
385
|
+
children = []
|
|
386
|
+
children << visit(node.value)
|
|
387
|
+
children << visit(node.pattern)
|
|
388
|
+
children.compact!
|
|
389
|
+
|
|
390
|
+
TypedNode.new(node, type, children)
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
# [a, b, *rest] pattern
|
|
394
|
+
def visit_array_pattern(node)
|
|
395
|
+
type = TypeChecker::Types::UNTYPED
|
|
396
|
+
|
|
397
|
+
children = []
|
|
398
|
+
children << visit(node.constant) if node.constant
|
|
399
|
+
node.requireds.each { |req| children << visit(req) }
|
|
400
|
+
children << visit(node.rest) if node.rest
|
|
401
|
+
node.posts.each { |post| children << visit(post) }
|
|
402
|
+
children.compact!
|
|
403
|
+
|
|
404
|
+
TypedNode.new(node, type, children)
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
# {x:, y: pattern} pattern
|
|
408
|
+
def visit_hash_pattern(node)
|
|
409
|
+
type = TypeChecker::Types::UNTYPED
|
|
410
|
+
|
|
411
|
+
children = []
|
|
412
|
+
children << visit(node.constant) if node.constant
|
|
413
|
+
node.elements.each { |elem| children << visit(elem) }
|
|
414
|
+
children << visit(node.rest) if node.rest
|
|
415
|
+
children.compact!
|
|
416
|
+
|
|
417
|
+
TypedNode.new(node, type, children)
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
# a | b pattern
|
|
421
|
+
def visit_alternation_pattern(node)
|
|
422
|
+
type = TypeChecker::Types::UNTYPED
|
|
423
|
+
|
|
424
|
+
children = []
|
|
425
|
+
children << visit(node.left)
|
|
426
|
+
children << visit(node.right)
|
|
427
|
+
children.compact!
|
|
428
|
+
|
|
429
|
+
TypedNode.new(node, type, children)
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
# pattern => var capture
|
|
433
|
+
def visit_capture_pattern(node)
|
|
434
|
+
type = TypeChecker::Types::UNTYPED
|
|
435
|
+
|
|
436
|
+
children = []
|
|
437
|
+
children << visit(node.value)
|
|
438
|
+
children << visit(node.target)
|
|
439
|
+
children.compact!
|
|
440
|
+
|
|
441
|
+
TypedNode.new(node, type, children)
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
# ^var pinned pattern
|
|
445
|
+
def visit_pinned_variable(node)
|
|
446
|
+
type = TypeChecker::Types::UNTYPED
|
|
447
|
+
|
|
448
|
+
children = []
|
|
449
|
+
children << visit(node.variable)
|
|
450
|
+
children.compact!
|
|
451
|
+
|
|
452
|
+
TypedNode.new(node, type, children)
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
# ^(expr) pinned expression
|
|
456
|
+
def visit_pinned_expression(node)
|
|
457
|
+
type = TypeChecker::Types::UNTYPED
|
|
458
|
+
|
|
459
|
+
children = []
|
|
460
|
+
children << visit(node.expression)
|
|
461
|
+
children.compact!
|
|
462
|
+
|
|
463
|
+
TypedNode.new(node, type, children)
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
# [*a, pattern, *b] find pattern
|
|
467
|
+
def visit_find_pattern(node)
|
|
468
|
+
type = TypeChecker::Types::UNTYPED
|
|
469
|
+
|
|
470
|
+
children = []
|
|
471
|
+
children << visit(node.left) if node.left
|
|
472
|
+
node.requireds.each { |req| children << visit(req) }
|
|
473
|
+
children << visit(node.right) if node.right
|
|
474
|
+
children.compact!
|
|
475
|
+
|
|
476
|
+
TypedNode.new(node, type, children)
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
# *rest splat
|
|
480
|
+
def visit_splat(node)
|
|
481
|
+
type = TypeChecker::Types::UNTYPED
|
|
482
|
+
children = []
|
|
483
|
+
children << visit(node.expression) if node.expression
|
|
484
|
+
children.compact!
|
|
485
|
+
TypedNode.new(node, type, children)
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
# **rest keyword splat (in pattern context)
|
|
489
|
+
def visit_assoc_splat(node)
|
|
490
|
+
type = TypeChecker::Types::UNTYPED
|
|
491
|
+
children = []
|
|
492
|
+
children << visit(node.value) if node.value
|
|
493
|
+
children.compact!
|
|
494
|
+
TypedNode.new(node, type, children)
|
|
495
|
+
end
|
|
496
|
+
|
|
497
|
+
# x: in hash pattern (shorthand)
|
|
498
|
+
def visit_no_keywords(node)
|
|
499
|
+
type = TypeChecker::Types::UNTYPED
|
|
500
|
+
TypedNode.new(node, type, [])
|
|
501
|
+
end
|
|
502
|
+
|
|
503
|
+
def visit_call(node)
|
|
504
|
+
type = infer_type(node)
|
|
505
|
+
|
|
506
|
+
children = []
|
|
507
|
+
children << visit(node.receiver) if node.receiver
|
|
508
|
+
children << visit(node.arguments) if node.arguments
|
|
509
|
+
children << visit(node.block) if node.block
|
|
510
|
+
children.compact!
|
|
511
|
+
|
|
512
|
+
TypedNode.new(node, type, children)
|
|
513
|
+
end
|
|
514
|
+
|
|
515
|
+
def visit_arguments(node)
|
|
516
|
+
type = TypeChecker::Types::UNTYPED
|
|
517
|
+
children = node.arguments.map { |arg| visit(arg) }.compact
|
|
518
|
+
TypedNode.new(node, type, children)
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def visit_block(node)
|
|
522
|
+
type = infer_type(node)
|
|
523
|
+
|
|
524
|
+
children = []
|
|
525
|
+
children << visit(node.parameters) if node.parameters
|
|
526
|
+
children << visit(node.body) if node.body
|
|
527
|
+
children.compact!
|
|
528
|
+
|
|
529
|
+
TypedNode.new(node, type, children)
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
def visit_array(node)
|
|
533
|
+
type = infer_type(node)
|
|
534
|
+
children = node.elements.map { |elem| visit(elem) }.compact
|
|
535
|
+
TypedNode.new(node, type, children)
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
def visit_hash(node)
|
|
539
|
+
type = infer_type(node)
|
|
540
|
+
children = node.elements.map { |elem| visit(elem) }.compact
|
|
541
|
+
TypedNode.new(node, type, children)
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
def visit_assoc(node)
|
|
545
|
+
type = TypeChecker::Types::UNTYPED
|
|
546
|
+
children = [visit(node.key), visit(node.value)].compact
|
|
547
|
+
TypedNode.new(node, type, children)
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
def visit_begin(node)
|
|
551
|
+
type = infer_type(node)
|
|
552
|
+
|
|
553
|
+
children = []
|
|
554
|
+
children << visit(node.statements) if node.statements
|
|
555
|
+
children << visit(node.rescue_clause) if node.rescue_clause
|
|
556
|
+
children << visit(node.else_clause) if node.else_clause
|
|
557
|
+
children << visit(node.ensure_clause) if node.ensure_clause
|
|
558
|
+
children.compact!
|
|
559
|
+
|
|
560
|
+
TypedNode.new(node, type, children)
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
def visit_rescue(node)
|
|
564
|
+
type = infer_type(node)
|
|
565
|
+
|
|
566
|
+
children = []
|
|
567
|
+
node.exceptions&.each { |ex| children << visit(ex) }
|
|
568
|
+
children << visit(node.statements) if node.statements
|
|
569
|
+
children << visit(node.subsequent) if node.subsequent
|
|
570
|
+
children.compact!
|
|
571
|
+
|
|
572
|
+
TypedNode.new(node, type, children)
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
# Terminal nodes (no children)
|
|
576
|
+
%i[
|
|
577
|
+
integer float string symbol true false nil
|
|
578
|
+
local_variable_read instance_variable_read class_variable_read
|
|
579
|
+
constant_read self source_file source_line
|
|
580
|
+
].each do |name|
|
|
581
|
+
define_method(:"visit_#{name}") do |node|
|
|
582
|
+
type = infer_type(node)
|
|
583
|
+
TypedNode.new(node, type, [])
|
|
584
|
+
end
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
# Assignment nodes
|
|
588
|
+
def visit_local_variable_write(node)
|
|
589
|
+
type = infer_type(node)
|
|
590
|
+
children = [visit(node.value)].compact
|
|
591
|
+
TypedNode.new(node, type, children)
|
|
592
|
+
end
|
|
593
|
+
|
|
594
|
+
def visit_instance_variable_write(node)
|
|
595
|
+
type = infer_type(node)
|
|
596
|
+
children = [visit(node.value)].compact
|
|
597
|
+
TypedNode.new(node, type, children)
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
def visit_class_variable_write(node)
|
|
601
|
+
type = infer_type(node)
|
|
602
|
+
children = [visit(node.value)].compact
|
|
603
|
+
TypedNode.new(node, type, children)
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
def visit_constant_write(node)
|
|
607
|
+
type = infer_type(node)
|
|
608
|
+
children = [visit(node.value)].compact
|
|
609
|
+
TypedNode.new(node, type, children)
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
def visit_return(node)
|
|
613
|
+
type = infer_type(node)
|
|
614
|
+
children = node.arguments ? [visit(node.arguments)] : []
|
|
615
|
+
children.compact!
|
|
616
|
+
TypedNode.new(node, type, children)
|
|
617
|
+
end
|
|
618
|
+
end
|
|
619
|
+
end
|
|
620
|
+
end
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Konpeito
|
|
4
|
+
module AST
|
|
5
|
+
# Base visitor class for traversing Prism AST nodes
|
|
6
|
+
# Subclass and override visit_* methods to handle specific node types
|
|
7
|
+
class Visitor
|
|
8
|
+
def visit(node)
|
|
9
|
+
return unless node
|
|
10
|
+
|
|
11
|
+
method_name = :"visit_#{node_type(node)}"
|
|
12
|
+
if respond_to?(method_name, true)
|
|
13
|
+
send(method_name, node)
|
|
14
|
+
else
|
|
15
|
+
visit_default(node)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def visit_all(nodes)
|
|
20
|
+
nodes.each { |node| visit(node) }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def visit_default(node)
|
|
26
|
+
visit_children(node)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def visit_children(node)
|
|
30
|
+
node.compact_child_nodes.each { |child| visit(child) }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def node_type(node)
|
|
34
|
+
# Convert Prism::FooNode to :foo
|
|
35
|
+
node.class.name.split("::").last.sub(/Node$/, "").gsub(/([a-z])([A-Z])/, '\1_\2').downcase
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Override these methods in subclasses to handle specific node types
|
|
39
|
+
# Example method signatures:
|
|
40
|
+
|
|
41
|
+
# def visit_program(node); end
|
|
42
|
+
# def visit_statements(node); end
|
|
43
|
+
# def visit_def(node); end
|
|
44
|
+
# def visit_class(node); end
|
|
45
|
+
# def visit_module(node); end
|
|
46
|
+
# def visit_if(node); end
|
|
47
|
+
# def visit_unless(node); end
|
|
48
|
+
# def visit_while(node); end
|
|
49
|
+
# def visit_until(node); end
|
|
50
|
+
# def visit_for(node); end
|
|
51
|
+
# def visit_case(node); end
|
|
52
|
+
# def visit_call(node); end
|
|
53
|
+
# def visit_local_variable_read(node); end
|
|
54
|
+
# def visit_local_variable_write(node); end
|
|
55
|
+
# def visit_instance_variable_read(node); end
|
|
56
|
+
# def visit_instance_variable_write(node); end
|
|
57
|
+
# def visit_class_variable_read(node); end
|
|
58
|
+
# def visit_class_variable_write(node); end
|
|
59
|
+
# def visit_constant_read(node); end
|
|
60
|
+
# def visit_constant_write(node); end
|
|
61
|
+
# def visit_integer(node); end
|
|
62
|
+
# def visit_float(node); end
|
|
63
|
+
# def visit_string(node); end
|
|
64
|
+
# def visit_symbol(node); end
|
|
65
|
+
# def visit_array(node); end
|
|
66
|
+
# def visit_hash(node); end
|
|
67
|
+
# def visit_block(node); end
|
|
68
|
+
# def visit_lambda(node); end
|
|
69
|
+
# def visit_begin(node); end
|
|
70
|
+
# def visit_rescue(node); end
|
|
71
|
+
# def visit_ensure(node); end
|
|
72
|
+
# def visit_return(node); end
|
|
73
|
+
# def visit_break(node); end
|
|
74
|
+
# def visit_next(node); end
|
|
75
|
+
# def visit_yield(node); end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|