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.
Files changed (180) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-version +1 -0
  3. data/CHANGELOG.md +75 -0
  4. data/CONTRIBUTING.md +123 -0
  5. data/LICENSE +21 -0
  6. data/README.md +257 -0
  7. data/Rakefile +11 -0
  8. data/bin/konpeito +6 -0
  9. data/konpeito.gemspec +43 -0
  10. data/lib/konpeito/ast/typed_ast.rb +620 -0
  11. data/lib/konpeito/ast/visitor.rb +78 -0
  12. data/lib/konpeito/cache/cache_manager.rb +230 -0
  13. data/lib/konpeito/cache/dependency_graph.rb +192 -0
  14. data/lib/konpeito/cache.rb +8 -0
  15. data/lib/konpeito/cli/base_command.rb +187 -0
  16. data/lib/konpeito/cli/build_command.rb +220 -0
  17. data/lib/konpeito/cli/check_command.rb +104 -0
  18. data/lib/konpeito/cli/config.rb +231 -0
  19. data/lib/konpeito/cli/deps_command.rb +128 -0
  20. data/lib/konpeito/cli/doctor_command.rb +340 -0
  21. data/lib/konpeito/cli/fmt_command.rb +199 -0
  22. data/lib/konpeito/cli/init_command.rb +312 -0
  23. data/lib/konpeito/cli/lsp_command.rb +40 -0
  24. data/lib/konpeito/cli/run_command.rb +150 -0
  25. data/lib/konpeito/cli/test_command.rb +248 -0
  26. data/lib/konpeito/cli/watch_command.rb +212 -0
  27. data/lib/konpeito/cli.rb +301 -0
  28. data/lib/konpeito/codegen/builtin_methods.rb +229 -0
  29. data/lib/konpeito/codegen/cruby_backend.rb +1090 -0
  30. data/lib/konpeito/codegen/debug_info.rb +352 -0
  31. data/lib/konpeito/codegen/inliner.rb +486 -0
  32. data/lib/konpeito/codegen/jvm_backend.rb +197 -0
  33. data/lib/konpeito/codegen/jvm_generator.rb +13412 -0
  34. data/lib/konpeito/codegen/llvm_generator.rb +13191 -0
  35. data/lib/konpeito/codegen/loop_optimizer.rb +363 -0
  36. data/lib/konpeito/codegen/monomorphizer.rb +359 -0
  37. data/lib/konpeito/codegen/profile_runtime.c +341 -0
  38. data/lib/konpeito/codegen/profiler.rb +99 -0
  39. data/lib/konpeito/compiler.rb +592 -0
  40. data/lib/konpeito/dependency_resolver.rb +296 -0
  41. data/lib/konpeito/diagnostics/collector.rb +127 -0
  42. data/lib/konpeito/diagnostics/diagnostic.rb +237 -0
  43. data/lib/konpeito/diagnostics/renderer.rb +144 -0
  44. data/lib/konpeito/formatter/formatter.rb +1214 -0
  45. data/lib/konpeito/hir/builder.rb +7167 -0
  46. data/lib/konpeito/hir/nodes.rb +2465 -0
  47. data/lib/konpeito/lsp/document_manager.rb +820 -0
  48. data/lib/konpeito/lsp/server.rb +183 -0
  49. data/lib/konpeito/lsp/transport.rb +38 -0
  50. data/lib/konpeito/parser/prism_adapter.rb +65 -0
  51. data/lib/konpeito/platform.rb +103 -0
  52. data/lib/konpeito/profile/report.rb +136 -0
  53. data/lib/konpeito/rbs_inline/preprocessor.rb +199 -0
  54. data/lib/konpeito/stdlib/compression/compression.rb +72 -0
  55. data/lib/konpeito/stdlib/compression/compression.rbs +60 -0
  56. data/lib/konpeito/stdlib/compression/compression_native.c +415 -0
  57. data/lib/konpeito/stdlib/compression/extconf.rb +19 -0
  58. data/lib/konpeito/stdlib/crypto/crypto.rb +85 -0
  59. data/lib/konpeito/stdlib/crypto/crypto.rbs +74 -0
  60. data/lib/konpeito/stdlib/crypto/crypto_native.c +312 -0
  61. data/lib/konpeito/stdlib/crypto/extconf.rb +40 -0
  62. data/lib/konpeito/stdlib/http/extconf.rb +19 -0
  63. data/lib/konpeito/stdlib/http/http.rb +125 -0
  64. data/lib/konpeito/stdlib/http/http.rbs +57 -0
  65. data/lib/konpeito/stdlib/http/http_native.c +440 -0
  66. data/lib/konpeito/stdlib/json/extconf.rb +17 -0
  67. data/lib/konpeito/stdlib/json/json.rb +44 -0
  68. data/lib/konpeito/stdlib/json/json.rbs +33 -0
  69. data/lib/konpeito/stdlib/json/json_native.c +286 -0
  70. data/lib/konpeito/stdlib/ui/extconf.rb +216 -0
  71. data/lib/konpeito/stdlib/ui/konpeito_ui_native.cpp +1625 -0
  72. data/lib/konpeito/stdlib/ui/konpeito_ui_native.h +162 -0
  73. data/lib/konpeito/stdlib/ui/ui.rb +318 -0
  74. data/lib/konpeito/stdlib/ui/ui.rbs +247 -0
  75. data/lib/konpeito/type_checker/annotation_parser.rb +67 -0
  76. data/lib/konpeito/type_checker/hm_inferrer.rb +2565 -0
  77. data/lib/konpeito/type_checker/inferrer.rb +565 -0
  78. data/lib/konpeito/type_checker/rbs_loader.rb +1621 -0
  79. data/lib/konpeito/type_checker/type_resolver.rb +276 -0
  80. data/lib/konpeito/type_checker/types.rb +1434 -0
  81. data/lib/konpeito/type_checker/unification.rb +323 -0
  82. data/lib/konpeito/ui/animation/animated_state.rb +80 -0
  83. data/lib/konpeito/ui/animation/easing.rb +59 -0
  84. data/lib/konpeito/ui/animation/value_tween.rb +66 -0
  85. data/lib/konpeito/ui/app.rb +379 -0
  86. data/lib/konpeito/ui/box.rb +38 -0
  87. data/lib/konpeito/ui/castella.rb +70 -0
  88. data/lib/konpeito/ui/castella_native.rb +76 -0
  89. data/lib/konpeito/ui/chart/area_chart.rb +305 -0
  90. data/lib/konpeito/ui/chart/bar_chart.rb +288 -0
  91. data/lib/konpeito/ui/chart/base_chart.rb +210 -0
  92. data/lib/konpeito/ui/chart/chart_helpers.rb +79 -0
  93. data/lib/konpeito/ui/chart/gauge_chart.rb +171 -0
  94. data/lib/konpeito/ui/chart/heatmap_chart.rb +222 -0
  95. data/lib/konpeito/ui/chart/line_chart.rb +289 -0
  96. data/lib/konpeito/ui/chart/pie_chart.rb +219 -0
  97. data/lib/konpeito/ui/chart/scales.rb +77 -0
  98. data/lib/konpeito/ui/chart/scatter_chart.rb +303 -0
  99. data/lib/konpeito/ui/chart/stacked_bar_chart.rb +276 -0
  100. data/lib/konpeito/ui/column.rb +271 -0
  101. data/lib/konpeito/ui/core.rb +2199 -0
  102. data/lib/konpeito/ui/dsl.rb +443 -0
  103. data/lib/konpeito/ui/frame.rb +171 -0
  104. data/lib/konpeito/ui/frame_native.rb +494 -0
  105. data/lib/konpeito/ui/markdown/ast.rb +124 -0
  106. data/lib/konpeito/ui/markdown/mermaid/layout.rb +387 -0
  107. data/lib/konpeito/ui/markdown/mermaid/models.rb +232 -0
  108. data/lib/konpeito/ui/markdown/mermaid/parser.rb +519 -0
  109. data/lib/konpeito/ui/markdown/mermaid/renderer.rb +336 -0
  110. data/lib/konpeito/ui/markdown/parser.rb +805 -0
  111. data/lib/konpeito/ui/markdown/renderer.rb +639 -0
  112. data/lib/konpeito/ui/markdown/theme.rb +165 -0
  113. data/lib/konpeito/ui/render_node.rb +260 -0
  114. data/lib/konpeito/ui/row.rb +207 -0
  115. data/lib/konpeito/ui/spacer.rb +18 -0
  116. data/lib/konpeito/ui/style.rb +799 -0
  117. data/lib/konpeito/ui/theme.rb +563 -0
  118. data/lib/konpeito/ui/themes/material.rb +35 -0
  119. data/lib/konpeito/ui/themes/tokyo_night.rb +6 -0
  120. data/lib/konpeito/ui/widgets/button.rb +103 -0
  121. data/lib/konpeito/ui/widgets/calendar.rb +1034 -0
  122. data/lib/konpeito/ui/widgets/checkbox.rb +119 -0
  123. data/lib/konpeito/ui/widgets/container.rb +91 -0
  124. data/lib/konpeito/ui/widgets/data_table.rb +667 -0
  125. data/lib/konpeito/ui/widgets/divider.rb +29 -0
  126. data/lib/konpeito/ui/widgets/image.rb +105 -0
  127. data/lib/konpeito/ui/widgets/input.rb +485 -0
  128. data/lib/konpeito/ui/widgets/markdown.rb +57 -0
  129. data/lib/konpeito/ui/widgets/modal.rb +163 -0
  130. data/lib/konpeito/ui/widgets/multiline_input.rb +968 -0
  131. data/lib/konpeito/ui/widgets/multiline_text.rb +180 -0
  132. data/lib/konpeito/ui/widgets/net_image.rb +100 -0
  133. data/lib/konpeito/ui/widgets/progress_bar.rb +70 -0
  134. data/lib/konpeito/ui/widgets/radio_buttons.rb +93 -0
  135. data/lib/konpeito/ui/widgets/slider.rb +133 -0
  136. data/lib/konpeito/ui/widgets/switch.rb +84 -0
  137. data/lib/konpeito/ui/widgets/tabs.rb +157 -0
  138. data/lib/konpeito/ui/widgets/text.rb +110 -0
  139. data/lib/konpeito/ui/widgets/tree.rb +426 -0
  140. data/lib/konpeito/version.rb +5 -0
  141. data/lib/konpeito.rb +109 -0
  142. data/test_native_array.rb +172 -0
  143. data/test_native_array_class.rb +197 -0
  144. data/test_native_class.rb +151 -0
  145. data/tools/konpeito-asm/build.sh +65 -0
  146. data/tools/konpeito-asm/lib/asm-9.7.1.jar +0 -0
  147. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KArray.class +0 -0
  148. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCompression.class +0 -0
  149. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KConditionVariable.class +0 -0
  150. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KCrypto.class +0 -0
  151. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KFile.class +0 -0
  152. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHTTP.class +0 -0
  153. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KHash.class +0 -0
  154. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON$Parser.class +0 -0
  155. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KJSON.class +0 -0
  156. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KMath.class +0 -0
  157. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactor.class +0 -0
  158. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KRactorPort.class +0 -0
  159. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KSizedQueue.class +0 -0
  160. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KThread.class +0 -0
  161. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/KTime.class +0 -0
  162. data/tools/konpeito-asm/runtime-classes/konpeito/runtime/RubyDispatch.class +0 -0
  163. data/tools/konpeito-asm/src/ClassIntrospector.java +312 -0
  164. data/tools/konpeito-asm/src/KonpeitoAssembler.java +659 -0
  165. data/tools/konpeito-asm/src/konpeito/runtime/KArray.java +390 -0
  166. data/tools/konpeito-asm/src/konpeito/runtime/KCompression.java +168 -0
  167. data/tools/konpeito-asm/src/konpeito/runtime/KConditionVariable.java +48 -0
  168. data/tools/konpeito-asm/src/konpeito/runtime/KCrypto.java +151 -0
  169. data/tools/konpeito-asm/src/konpeito/runtime/KFile.java +100 -0
  170. data/tools/konpeito-asm/src/konpeito/runtime/KHTTP.java +113 -0
  171. data/tools/konpeito-asm/src/konpeito/runtime/KHash.java +228 -0
  172. data/tools/konpeito-asm/src/konpeito/runtime/KJSON.java +405 -0
  173. data/tools/konpeito-asm/src/konpeito/runtime/KMath.java +54 -0
  174. data/tools/konpeito-asm/src/konpeito/runtime/KRactor.java +244 -0
  175. data/tools/konpeito-asm/src/konpeito/runtime/KRactorPort.java +53 -0
  176. data/tools/konpeito-asm/src/konpeito/runtime/KSizedQueue.java +49 -0
  177. data/tools/konpeito-asm/src/konpeito/runtime/KThread.java +49 -0
  178. data/tools/konpeito-asm/src/konpeito/runtime/KTime.java +53 -0
  179. data/tools/konpeito-asm/src/konpeito/runtime/RubyDispatch.java +416 -0
  180. metadata +267 -0
@@ -0,0 +1,2465 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Konpeito
4
+ module HIR
5
+ # Source location information for debug info
6
+ class SourceLocation
7
+ attr_reader :line, :column, :file
8
+
9
+ def initialize(line: nil, column: nil, file: nil)
10
+ @line = line
11
+ @column = column
12
+ @file = file
13
+ end
14
+
15
+ def self.from_prism(prism_location, file: nil)
16
+ return nil unless prism_location
17
+
18
+ new(
19
+ line: prism_location.start_line,
20
+ column: prism_location.start_column,
21
+ file: file
22
+ )
23
+ end
24
+ end
25
+
26
+ # Base class for all HIR nodes
27
+ class Node
28
+ attr_reader :type # TypeChecker::Types::Type
29
+ attr_accessor :location # SourceLocation for debug info
30
+
31
+ def initialize(type: TypeChecker::Types::UNTYPED, location: nil)
32
+ @type = type
33
+ @location = location
34
+ end
35
+ end
36
+
37
+ # Program is the top-level container
38
+ class Program < Node
39
+ attr_reader :functions, :classes, :modules
40
+
41
+ def initialize(functions: [], classes: [], modules: [])
42
+ super(type: TypeChecker::Types::NIL)
43
+ @functions = functions
44
+ @classes = classes
45
+ @modules = modules
46
+ end
47
+ end
48
+
49
+ # Class definition
50
+ class ClassDef < Node
51
+ attr_reader :name, :superclass, :instance_vars
52
+ attr_accessor :method_names # Names of methods defined in this class
53
+ attr_accessor :included_modules # Module names included by this class
54
+ attr_accessor :extended_modules # Module names extended by this class
55
+ attr_accessor :prepended_modules # Module names prepended by this class
56
+ attr_accessor :private_methods # Set of private method names
57
+ attr_accessor :protected_methods # Set of protected method names
58
+ attr_accessor :aliases # Array of [new_name, old_name] pairs
59
+ attr_accessor :reopened # true if this is reopening an existing class
60
+ attr_accessor :singleton_methods # Names of class-level methods (def self.xxx or class << self)
61
+ attr_accessor :instance_var_types # HM-inferred ivar types: { "name" => :Integer, "age" => :String, ... }
62
+
63
+ def initialize(name:, superclass: nil, method_names: [], instance_vars: [], included_modules: [], extended_modules: [], prepended_modules: [])
64
+ super(type: TypeChecker::Types::NIL)
65
+ @name = name
66
+ @superclass = superclass
67
+ @method_names = method_names
68
+ @instance_vars = instance_vars
69
+ @included_modules = included_modules
70
+ @extended_modules = extended_modules
71
+ @prepended_modules = prepended_modules
72
+ @private_methods = Set.new
73
+ @protected_methods = Set.new
74
+ @aliases = []
75
+ @reopened = false
76
+ @singleton_methods = []
77
+ @instance_var_types = {}
78
+ end
79
+ end
80
+
81
+ # Module definition
82
+ class ModuleDef < Node
83
+ attr_reader :name, :methods, :singleton_methods, :constants
84
+
85
+ def initialize(name:, methods: [], singleton_methods: [], constants: {})
86
+ super(type: TypeChecker::Types::NIL)
87
+ @name = name
88
+ @methods = methods
89
+ @singleton_methods = singleton_methods
90
+ @constants = constants # Hash of name -> value
91
+ end
92
+ end
93
+
94
+ # Function/method definition
95
+ class Function < Node
96
+ attr_reader :name, :params, :body, :return_type
97
+ attr_accessor :is_instance_method
98
+ attr_accessor :owner_class # Class name this method belongs to (nil for top-level)
99
+ attr_accessor :owner_module # Module name this method belongs to (nil for top-level or class methods)
100
+
101
+ def initialize(name:, params: [], body: [], return_type: TypeChecker::Types::UNTYPED, is_instance_method: true, owner_class: nil, owner_module: nil, location: nil)
102
+ super(type: TypeChecker::Types::SYMBOL, location: location)
103
+ @name = name
104
+ @params = params
105
+ @body = body # Array of BasicBlock
106
+ @return_type = return_type
107
+ @is_instance_method = is_instance_method
108
+ @owner_class = owner_class
109
+ @owner_module = owner_module
110
+ end
111
+
112
+ def entry_block
113
+ body.first
114
+ end
115
+
116
+ def class_method?
117
+ !is_instance_method && owner_class
118
+ end
119
+ end
120
+
121
+ # Function parameter
122
+ class Param < Node
123
+ attr_reader :name, :default_value, :rest, :keyword, :keyword_rest, :block
124
+
125
+ def initialize(name:, type: TypeChecker::Types::UNTYPED, default_value: nil, rest: false, keyword: false, keyword_rest: false, block: false)
126
+ super(type: type)
127
+ @name = name
128
+ @default_value = default_value
129
+ @rest = rest
130
+ @keyword = keyword
131
+ @keyword_rest = keyword_rest # **kwargs
132
+ @block = block
133
+ end
134
+ end
135
+
136
+ # Basic block (sequence of instructions ending in a terminator)
137
+ class BasicBlock
138
+ attr_reader :label, :instructions, :terminator
139
+
140
+ def initialize(label:)
141
+ @label = label
142
+ @instructions = []
143
+ @terminator = nil
144
+ end
145
+
146
+ def add_instruction(inst)
147
+ @instructions << inst
148
+ end
149
+
150
+ def set_terminator(term)
151
+ @terminator = term
152
+ end
153
+ end
154
+
155
+ # Base class for instructions
156
+ class Instruction < Node
157
+ attr_reader :result_var # Variable to store result (nil if void)
158
+
159
+ def initialize(type: TypeChecker::Types::UNTYPED, result_var: nil)
160
+ super(type: type)
161
+ @result_var = result_var
162
+ end
163
+ end
164
+
165
+ # Terminators (end a basic block)
166
+ class Terminator < Node; end
167
+
168
+ class Return < Terminator
169
+ attr_reader :value
170
+
171
+ def initialize(value: nil)
172
+ super(type: TypeChecker::Types::BOTTOM)
173
+ @value = value
174
+ end
175
+ end
176
+
177
+ class Branch < Terminator
178
+ attr_reader :condition, :then_block, :else_block
179
+
180
+ def initialize(condition:, then_block:, else_block:)
181
+ super(type: TypeChecker::Types::BOTTOM)
182
+ @condition = condition
183
+ @then_block = then_block
184
+ @else_block = else_block
185
+ end
186
+ end
187
+
188
+ class Jump < Terminator
189
+ attr_reader :target
190
+
191
+ def initialize(target:)
192
+ super(type: TypeChecker::Types::BOTTOM)
193
+ @target = target
194
+ end
195
+ end
196
+
197
+ # Include statement for including modules into classes
198
+ class IncludeStatement < Instruction
199
+ attr_reader :module_name
200
+
201
+ def initialize(module_name:)
202
+ super(type: TypeChecker::Types::NIL)
203
+ @module_name = module_name
204
+ end
205
+ end
206
+
207
+ # Variable operations
208
+ class LocalVar < Node
209
+ attr_reader :name
210
+
211
+ def initialize(name:, type: TypeChecker::Types::UNTYPED)
212
+ super(type: type)
213
+ @name = name
214
+ end
215
+ end
216
+
217
+ class LoadLocal < Instruction
218
+ attr_reader :var
219
+
220
+ def initialize(var:, type: TypeChecker::Types::UNTYPED, result_var: nil)
221
+ super(type: type, result_var: result_var)
222
+ @var = var
223
+ end
224
+ end
225
+
226
+ class StoreLocal < Instruction
227
+ attr_reader :var, :value
228
+
229
+ def initialize(var:, value:, type: TypeChecker::Types::UNTYPED)
230
+ super(type: type)
231
+ @var = var
232
+ @value = value
233
+ end
234
+ end
235
+
236
+ class LoadInstanceVar < Instruction
237
+ attr_reader :name
238
+
239
+ def initialize(name:, type: TypeChecker::Types::UNTYPED, result_var: nil)
240
+ super(type: type, result_var: result_var)
241
+ @name = name
242
+ end
243
+ end
244
+
245
+ class StoreInstanceVar < Instruction
246
+ attr_reader :name, :value
247
+
248
+ def initialize(name:, value:, type: TypeChecker::Types::UNTYPED)
249
+ super(type: type)
250
+ @name = name
251
+ @value = value
252
+ end
253
+ end
254
+
255
+ # Class variable operations (@@var)
256
+ class LoadClassVar < Instruction
257
+ attr_reader :name
258
+
259
+ def initialize(name:, type: TypeChecker::Types::UNTYPED, result_var: nil)
260
+ super(type: type, result_var: result_var)
261
+ @name = name # e.g., "@@counter"
262
+ end
263
+ end
264
+
265
+ class StoreClassVar < Instruction
266
+ attr_reader :name, :value
267
+
268
+ def initialize(name:, value:, type: TypeChecker::Types::UNTYPED)
269
+ super(type: type)
270
+ @name = name # e.g., "@@counter"
271
+ @value = value
272
+ end
273
+ end
274
+
275
+ # Constant assignment: CONSTANT = value
276
+ class StoreConstant < Instruction
277
+ attr_reader :name, :value, :scope
278
+
279
+ def initialize(name:, value:, scope: nil, type: TypeChecker::Types::UNTYPED)
280
+ super(type: type)
281
+ @name = name # e.g., "VERSION"
282
+ @value = value # The value HIR node
283
+ @scope = scope # nil for top-level, module/class name otherwise
284
+ end
285
+ end
286
+
287
+ # Literals
288
+ class Literal < Instruction
289
+ attr_reader :value
290
+
291
+ def initialize(value:, type:, result_var: nil)
292
+ super(type: type, result_var: result_var)
293
+ @value = value
294
+ end
295
+ end
296
+
297
+ class IntegerLit < Literal
298
+ def initialize(value:, result_var: nil)
299
+ super(value: value, type: TypeChecker::Types::INTEGER, result_var: result_var)
300
+ end
301
+ end
302
+
303
+ class FloatLit < Literal
304
+ def initialize(value:, result_var: nil)
305
+ super(value: value, type: TypeChecker::Types::FLOAT, result_var: result_var)
306
+ end
307
+ end
308
+
309
+ class StringLit < Literal
310
+ def initialize(value:, result_var: nil)
311
+ super(value: value, type: TypeChecker::Types::STRING, result_var: result_var)
312
+ end
313
+ end
314
+
315
+ # String concatenation chain optimization: a + b + c + d
316
+ # Instead of creating intermediate strings with rb_str_plus,
317
+ # we use rb_str_dup + rb_str_concat for efficiency
318
+ class StringConcat < Instruction
319
+ attr_reader :parts, :result_var
320
+
321
+ def initialize(parts:, result_var: nil)
322
+ @parts = parts # Array of HIR instructions representing string parts
323
+ @result_var = result_var
324
+ end
325
+
326
+ def type
327
+ TypeChecker::Types::STRING
328
+ end
329
+ end
330
+
331
+ class SymbolLit < Literal
332
+ def initialize(value:, result_var: nil)
333
+ super(value: value, type: TypeChecker::Types::SYMBOL, result_var: result_var)
334
+ end
335
+ end
336
+
337
+ class RegexpLit < Instruction
338
+ attr_reader :pattern, :options, :result_var
339
+
340
+ def initialize(pattern:, options: 0, result_var: nil)
341
+ @pattern = pattern
342
+ @options = options # Integer: Regexp::IGNORECASE | Regexp::EXTENDED | Regexp::MULTILINE
343
+ @result_var = result_var
344
+ end
345
+
346
+ def type
347
+ TypeChecker::Types::REGEXP
348
+ end
349
+ end
350
+
351
+ class NilLit < Literal
352
+ def initialize(result_var: nil)
353
+ super(value: nil, type: TypeChecker::Types::NIL, result_var: result_var)
354
+ end
355
+ end
356
+
357
+ class BoolLit < Literal
358
+ def initialize(value:, result_var: nil)
359
+ type = value ? TypeChecker::Types::TRUE_CLASS : TypeChecker::Types::FALSE_CLASS
360
+ super(value: value, type: type, result_var: result_var)
361
+ end
362
+ end
363
+
364
+ # Array literal
365
+ class ArrayLit < Instruction
366
+ attr_reader :elements
367
+
368
+ def initialize(elements:, element_type: TypeChecker::Types::UNTYPED, result_var: nil)
369
+ super(type: TypeChecker::Types.array(element_type), result_var: result_var)
370
+ @elements = elements
371
+ end
372
+ end
373
+
374
+ # Hash literal
375
+ class HashLit < Instruction
376
+ attr_reader :pairs # Array of [key, value] pairs
377
+
378
+ def initialize(pairs:, key_type: TypeChecker::Types::UNTYPED, value_type: TypeChecker::Types::UNTYPED, result_var: nil)
379
+ super(type: TypeChecker::Types.hash_type(key_type, value_type), result_var: result_var)
380
+ @pairs = pairs
381
+ end
382
+ end
383
+
384
+ # Method call
385
+ class Call < Instruction
386
+ attr_reader :receiver, :method_name, :args, :block, :keyword_args, :safe_navigation
387
+
388
+ def initialize(receiver:, method_name:, args: [], block: nil, keyword_args: {}, type: TypeChecker::Types::UNTYPED, result_var: nil, safe_navigation: false)
389
+ super(type: type, result_var: result_var)
390
+ @receiver = receiver
391
+ @method_name = method_name
392
+ @args = args
393
+ @block = block
394
+ @keyword_args = keyword_args # Hash of { keyword_name => HIR instruction }
395
+ @safe_navigation = safe_navigation
396
+ end
397
+
398
+ def has_keyword_args?
399
+ !@keyword_args.empty?
400
+ end
401
+ end
402
+
403
+ # Self reference
404
+ class SelfRef < Instruction
405
+ def initialize(type: TypeChecker::Types::UNTYPED, result_var: nil)
406
+ super(type: type, result_var: result_var)
407
+ end
408
+ end
409
+
410
+ # Range literal
411
+ class RangeLit < Instruction
412
+ attr_reader :left, :right, :exclusive
413
+
414
+ def initialize(left:, right:, exclusive:, type: TypeChecker::Types::UNTYPED, result_var: nil)
415
+ super(type: type, result_var: result_var)
416
+ @left = left
417
+ @right = right
418
+ @exclusive = exclusive
419
+ end
420
+ end
421
+
422
+ # Global variable read
423
+ class LoadGlobalVar < Instruction
424
+ attr_reader :name
425
+
426
+ def initialize(name:, type: TypeChecker::Types::UNTYPED, result_var: nil)
427
+ super(type: type, result_var: result_var)
428
+ @name = name
429
+ end
430
+ end
431
+
432
+ # Global variable write
433
+ class StoreGlobalVar < Instruction
434
+ attr_reader :name, :value
435
+
436
+ def initialize(name:, value:, type: TypeChecker::Types::UNTYPED)
437
+ super(type: type)
438
+ @name = name
439
+ @value = value
440
+ end
441
+ end
442
+
443
+ # Splat argument at call site
444
+ class SplatArg < Instruction
445
+ attr_reader :expression
446
+
447
+ def initialize(expression:, type: TypeChecker::Types::UNTYPED, result_var: nil)
448
+ super(type: type, result_var: result_var)
449
+ @expression = expression
450
+ end
451
+ end
452
+
453
+ # defined? operator
454
+ class DefinedCheck < Instruction
455
+ attr_reader :check_type, :name
456
+
457
+ def initialize(check_type:, name:, type: TypeChecker::Types::UNTYPED, result_var: nil)
458
+ super(type: type, result_var: result_var)
459
+ @check_type = check_type # :local_variable, :constant, :method, :expression
460
+ @name = name
461
+ end
462
+ end
463
+
464
+ # Super method call
465
+ class SuperCall < Instruction
466
+ attr_reader :args, :forward_args
467
+
468
+ def initialize(args: [], forward_args: false, type: TypeChecker::Types::UNTYPED, result_var: nil)
469
+ super(type: type, result_var: result_var)
470
+ @args = args
471
+ @forward_args = forward_args
472
+ end
473
+ end
474
+
475
+ # Multi-write array element extraction
476
+ class MultiWriteExtract < Instruction
477
+ attr_reader :array, :index
478
+
479
+ def initialize(array:, index:, type: TypeChecker::Types::UNTYPED, result_var: nil)
480
+ super(type: type, result_var: result_var)
481
+ @array = array
482
+ @index = index
483
+ end
484
+ end
485
+
486
+ # Constant lookup
487
+ class ConstantLookup < Instruction
488
+ attr_reader :name, :scope
489
+
490
+ def initialize(name:, scope: nil, type: TypeChecker::Types::UNTYPED, result_var: nil)
491
+ super(type: type, result_var: result_var)
492
+ @name = name
493
+ @scope = scope
494
+ end
495
+ end
496
+
497
+ # Captured variable from outer scope (for closures)
498
+ class Capture
499
+ attr_reader :name, :type
500
+
501
+ def initialize(name:, type:)
502
+ @name = name
503
+ @type = type
504
+ end
505
+ end
506
+
507
+ # Block/Lambda definition
508
+ class BlockDef < Node
509
+ attr_reader :params, :body, :captures, :is_lambda
510
+
511
+ def initialize(params: [], body: [], captures: [], is_lambda: false)
512
+ super(type: TypeChecker::Types::ClassInstance.new(:Proc))
513
+ @params = params
514
+ @body = body # Array of BasicBlock
515
+ @captures = captures # Array of Capture objects
516
+ @is_lambda = is_lambda
517
+ end
518
+ end
519
+
520
+ # Create a Proc/Lambda object from a block definition
521
+ class ProcNew < Instruction
522
+ attr_reader :block_def
523
+
524
+ def initialize(block_def:, result_var: nil)
525
+ super(type: TypeChecker::Types::ClassInstance.new(:Proc), result_var: result_var)
526
+ @block_def = block_def
527
+ end
528
+ end
529
+
530
+ # Call a Proc/Lambda object
531
+ class ProcCall < Instruction
532
+ attr_reader :proc_value, :args
533
+
534
+ def initialize(proc_value:, args: [], type: TypeChecker::Types::UNTYPED, result_var: nil)
535
+ super(type: type, result_var: result_var)
536
+ @proc_value = proc_value # HIR instruction that evaluates to the Proc
537
+ @args = args # Array of HIR instructions for arguments
538
+ end
539
+ end
540
+
541
+ # ========================================
542
+ # Fiber operations
543
+ # Cooperative concurrency primitives
544
+ # ========================================
545
+
546
+ # Create a new Fiber from a block definition
547
+ # Fiber.new { |arg| ... }
548
+ class FiberNew < Instruction
549
+ attr_reader :block_def
550
+
551
+ def initialize(block_def:, result_var: nil)
552
+ super(type: TypeChecker::Types::FIBER, result_var: result_var)
553
+ @block_def = block_def # BlockDef with fiber body
554
+ end
555
+ end
556
+
557
+ # Resume a fiber with optional arguments
558
+ # fiber.resume(arg1, arg2)
559
+ class FiberResume < Instruction
560
+ attr_reader :fiber, :args
561
+
562
+ def initialize(fiber:, args: [], type: TypeChecker::Types::UNTYPED, result_var: nil)
563
+ super(type: type, result_var: result_var)
564
+ @fiber = fiber # HIR instruction evaluating to Fiber
565
+ @args = args # Array of HIR instructions for arguments
566
+ end
567
+ end
568
+
569
+ # Yield from within a fiber
570
+ # Fiber.yield(value)
571
+ class FiberYield < Instruction
572
+ attr_reader :args
573
+
574
+ def initialize(args: [], type: TypeChecker::Types::UNTYPED, result_var: nil)
575
+ super(type: type, result_var: result_var)
576
+ @args = args # Array of HIR instructions for yield values
577
+ end
578
+ end
579
+
580
+ # Check if fiber is alive
581
+ # fiber.alive?
582
+ class FiberAlive < Instruction
583
+ attr_reader :fiber
584
+
585
+ def initialize(fiber:, result_var: nil)
586
+ super(type: TypeChecker::Types::BOOL, result_var: result_var)
587
+ @fiber = fiber # HIR instruction evaluating to Fiber
588
+ end
589
+ end
590
+
591
+ # Get current fiber
592
+ # Fiber.current
593
+ class FiberCurrent < Instruction
594
+ def initialize(result_var: nil)
595
+ super(type: TypeChecker::Types::FIBER, result_var: result_var)
596
+ end
597
+ end
598
+
599
+ # ========================================
600
+ # Thread operations
601
+ # OS-level threading with GVL
602
+ # ========================================
603
+
604
+ # Create a new Thread from a block definition
605
+ # Thread.new { ... }
606
+ class ThreadNew < Instruction
607
+ attr_reader :block_def
608
+
609
+ def initialize(block_def:, result_var: nil)
610
+ super(type: TypeChecker::Types::THREAD, result_var: result_var)
611
+ @block_def = block_def # BlockDef with thread body
612
+ end
613
+ end
614
+
615
+ # Wait for thread completion
616
+ # thread.join or thread.join(timeout)
617
+ class ThreadJoin < Instruction
618
+ attr_reader :thread, :timeout
619
+
620
+ def initialize(thread:, timeout: nil, type: TypeChecker::Types::THREAD, result_var: nil)
621
+ super(type: type, result_var: result_var)
622
+ @thread = thread # HIR instruction evaluating to Thread
623
+ @timeout = timeout # Optional timeout value
624
+ end
625
+ end
626
+
627
+ # Get thread return value
628
+ # thread.value
629
+ class ThreadValue < Instruction
630
+ attr_reader :thread
631
+
632
+ def initialize(thread:, type: TypeChecker::Types::UNTYPED, result_var: nil)
633
+ super(type: type, result_var: result_var)
634
+ @thread = thread # HIR instruction evaluating to Thread
635
+ end
636
+ end
637
+
638
+ # Get current thread
639
+ # Thread.current
640
+ class ThreadCurrent < Instruction
641
+ def initialize(result_var: nil)
642
+ super(type: TypeChecker::Types::THREAD, result_var: result_var)
643
+ end
644
+ end
645
+
646
+ # ========================================
647
+ # Mutex operations
648
+ # Thread synchronization primitives
649
+ # ========================================
650
+
651
+ # Create a new Mutex
652
+ # Mutex.new
653
+ class MutexNew < Instruction
654
+ def initialize(result_var: nil)
655
+ super(type: TypeChecker::Types::MUTEX, result_var: result_var)
656
+ end
657
+ end
658
+
659
+ # Lock a mutex
660
+ # mutex.lock
661
+ class MutexLock < Instruction
662
+ attr_reader :mutex
663
+
664
+ def initialize(mutex:, result_var: nil)
665
+ super(type: TypeChecker::Types::MUTEX, result_var: result_var)
666
+ @mutex = mutex # HIR instruction evaluating to Mutex
667
+ end
668
+ end
669
+
670
+ # Unlock a mutex
671
+ # mutex.unlock
672
+ class MutexUnlock < Instruction
673
+ attr_reader :mutex
674
+
675
+ def initialize(mutex:, result_var: nil)
676
+ super(type: TypeChecker::Types::MUTEX, result_var: result_var)
677
+ @mutex = mutex # HIR instruction evaluating to Mutex
678
+ end
679
+ end
680
+
681
+ # Execute block with mutex locked
682
+ # mutex.synchronize { ... }
683
+ class MutexSynchronize < Instruction
684
+ attr_reader :mutex, :block_def
685
+
686
+ def initialize(mutex:, block_def:, type: TypeChecker::Types::UNTYPED, result_var: nil)
687
+ super(type: type, result_var: result_var)
688
+ @mutex = mutex # HIR instruction evaluating to Mutex
689
+ @block_def = block_def # BlockDef with synchronized body
690
+ end
691
+ end
692
+
693
+ # ========================================
694
+ # Queue operations
695
+ # Thread-safe queue for producer/consumer
696
+ # ========================================
697
+
698
+ # Create a new Queue
699
+ # Queue.new
700
+ class QueueNew < Instruction
701
+ def initialize(result_var: nil)
702
+ super(type: TypeChecker::Types::QUEUE, result_var: result_var)
703
+ end
704
+ end
705
+
706
+ # Push value to queue
707
+ # queue.push(value) or queue << value
708
+ class QueuePush < Instruction
709
+ attr_reader :queue, :value
710
+
711
+ def initialize(queue:, value:, result_var: nil)
712
+ super(type: TypeChecker::Types::QUEUE, result_var: result_var)
713
+ @queue = queue # HIR instruction evaluating to Queue
714
+ @value = value # Value to push
715
+ end
716
+ end
717
+
718
+ # Pop value from queue (blocking)
719
+ # queue.pop or queue.pop(non_block)
720
+ class QueuePop < Instruction
721
+ attr_reader :queue, :non_block
722
+
723
+ def initialize(queue:, non_block: nil, type: TypeChecker::Types::UNTYPED, result_var: nil)
724
+ super(type: type, result_var: result_var)
725
+ @queue = queue # HIR instruction evaluating to Queue
726
+ @non_block = non_block # Optional non-blocking flag
727
+ end
728
+ end
729
+
730
+ # ========================================
731
+ # ConditionVariable operations
732
+ # ========================================
733
+
734
+ # Create a new ConditionVariable
735
+ # ConditionVariable.new
736
+ class ConditionVariableNew < Instruction
737
+ def initialize(result_var: nil)
738
+ super(type: TypeChecker::Types::CONDITION_VARIABLE, result_var: result_var)
739
+ end
740
+ end
741
+
742
+ # Wait on condition variable (releases mutex, waits, reacquires)
743
+ # cv.wait(mutex) or cv.wait(mutex, timeout)
744
+ class ConditionVariableWait < Instruction
745
+ attr_reader :cv, :mutex, :timeout
746
+
747
+ def initialize(cv:, mutex:, timeout: nil, result_var: nil)
748
+ super(type: TypeChecker::Types::CONDITION_VARIABLE, result_var: result_var)
749
+ @cv = cv # HIR instruction evaluating to ConditionVariable
750
+ @mutex = mutex # HIR instruction evaluating to Mutex
751
+ @timeout = timeout # Optional timeout value
752
+ end
753
+ end
754
+
755
+ # Signal one waiting thread
756
+ # cv.signal
757
+ class ConditionVariableSignal < Instruction
758
+ attr_reader :cv
759
+
760
+ def initialize(cv:, result_var: nil)
761
+ super(type: TypeChecker::Types::CONDITION_VARIABLE, result_var: result_var)
762
+ @cv = cv # HIR instruction evaluating to ConditionVariable
763
+ end
764
+ end
765
+
766
+ # Broadcast to all waiting threads
767
+ # cv.broadcast
768
+ class ConditionVariableBroadcast < Instruction
769
+ attr_reader :cv
770
+
771
+ def initialize(cv:, result_var: nil)
772
+ super(type: TypeChecker::Types::CONDITION_VARIABLE, result_var: result_var)
773
+ @cv = cv # HIR instruction evaluating to ConditionVariable
774
+ end
775
+ end
776
+
777
+ # ========================================
778
+ # SizedQueue operations
779
+ # ========================================
780
+
781
+ # Create a new SizedQueue with max size
782
+ # SizedQueue.new(max)
783
+ class SizedQueueNew < Instruction
784
+ attr_reader :max_size
785
+
786
+ def initialize(max_size:, result_var: nil)
787
+ super(type: TypeChecker::Types::SIZED_QUEUE, result_var: result_var)
788
+ @max_size = max_size # HIR instruction evaluating to max size
789
+ end
790
+ end
791
+
792
+ # Push to sized queue (blocks if full)
793
+ # sq.push(value) or sq << value
794
+ class SizedQueuePush < Instruction
795
+ attr_reader :queue, :value
796
+
797
+ def initialize(queue:, value:, result_var: nil)
798
+ super(type: TypeChecker::Types::SIZED_QUEUE, result_var: result_var)
799
+ @queue = queue # HIR instruction evaluating to SizedQueue
800
+ @value = value # Value to push
801
+ end
802
+ end
803
+
804
+ # Pop from sized queue (blocks if empty)
805
+ # sq.pop or sq.pop(non_block)
806
+ class SizedQueuePop < Instruction
807
+ attr_reader :queue, :non_block
808
+
809
+ def initialize(queue:, non_block: nil, type: TypeChecker::Types::UNTYPED, result_var: nil)
810
+ super(type: type, result_var: result_var)
811
+ @queue = queue # HIR instruction evaluating to SizedQueue
812
+ @non_block = non_block # Optional non-blocking flag
813
+ end
814
+ end
815
+
816
+ # ========================================
817
+ # Ractor operations
818
+ # Ruby 4.0 Ractor with Port-based communication
819
+ # ========================================
820
+
821
+ # Create a new Ractor
822
+ # Ractor.new { block } or Ractor.new(name: "worker") { block }
823
+ class RactorNew < Instruction
824
+ attr_reader :block_def, :args, :name
825
+
826
+ def initialize(block_def:, args: [], name: nil, result_var: nil)
827
+ super(type: TypeChecker::Types::RACTOR, result_var: result_var)
828
+ @block_def = block_def
829
+ @args = args
830
+ @name = name # Optional name string (HIR instruction or nil)
831
+ end
832
+ end
833
+
834
+ # Send message to Ractor
835
+ # ractor.send(msg) or ractor << msg
836
+ class RactorSend < Instruction
837
+ attr_reader :ractor, :value
838
+
839
+ def initialize(ractor:, value:, result_var: nil)
840
+ super(type: TypeChecker::Types::RACTOR, result_var: result_var)
841
+ @ractor = ractor
842
+ @value = value
843
+ end
844
+ end
845
+
846
+ # Receive message on current Ractor
847
+ # Ractor.receive
848
+ class RactorReceive < Instruction
849
+ def initialize(type: TypeChecker::Types::UNTYPED, result_var: nil)
850
+ super(type: type, result_var: result_var)
851
+ end
852
+ end
853
+
854
+ # Wait for Ractor completion
855
+ # ractor.join
856
+ class RactorJoin < Instruction
857
+ attr_reader :ractor
858
+
859
+ def initialize(ractor:, result_var: nil)
860
+ super(type: TypeChecker::Types::RACTOR, result_var: result_var)
861
+ @ractor = ractor
862
+ end
863
+ end
864
+
865
+ # Get Ractor return value
866
+ # ractor.value
867
+ class RactorValue < Instruction
868
+ attr_reader :ractor
869
+
870
+ def initialize(ractor:, type: TypeChecker::Types::UNTYPED, result_var: nil)
871
+ super(type: type, result_var: result_var)
872
+ @ractor = ractor
873
+ end
874
+ end
875
+
876
+ # Close Ractor
877
+ # ractor.close
878
+ class RactorClose < Instruction
879
+ attr_reader :ractor
880
+
881
+ def initialize(ractor:, result_var: nil)
882
+ super(type: TypeChecker::Types::NIL, result_var: result_var)
883
+ @ractor = ractor
884
+ end
885
+ end
886
+
887
+ # Get current Ractor
888
+ # Ractor.current
889
+ class RactorCurrent < Instruction
890
+ def initialize(result_var: nil)
891
+ super(type: TypeChecker::Types::RACTOR, result_var: result_var)
892
+ end
893
+ end
894
+
895
+ # Get main Ractor
896
+ # Ractor.main
897
+ class RactorMain < Instruction
898
+ def initialize(result_var: nil)
899
+ super(type: TypeChecker::Types::RACTOR, result_var: result_var)
900
+ end
901
+ end
902
+
903
+ # Get Ractor name
904
+ # ractor.name
905
+ class RactorName < Instruction
906
+ attr_reader :ractor
907
+
908
+ def initialize(ractor:, result_var: nil)
909
+ super(type: TypeChecker::Types::STRING, result_var: result_var)
910
+ @ractor = ractor
911
+ end
912
+ end
913
+
914
+ # Ractor-local storage get
915
+ # Ractor[:key]
916
+ class RactorLocalGet < Instruction
917
+ attr_reader :key
918
+
919
+ def initialize(key:, result_var: nil)
920
+ super(type: TypeChecker::Types::UNTYPED, result_var: result_var)
921
+ @key = key # HIR instruction for key (SymbolLit or StringLit)
922
+ end
923
+ end
924
+
925
+ # Ractor-local storage set
926
+ # Ractor[:key] = value
927
+ class RactorLocalSet < Instruction
928
+ attr_reader :key, :value
929
+
930
+ def initialize(key:, value:, result_var: nil)
931
+ super(type: TypeChecker::Types::UNTYPED, result_var: result_var)
932
+ @key = key # HIR instruction for key
933
+ @value = value # HIR instruction for value
934
+ end
935
+ end
936
+
937
+ # Ractor.make_shareable(obj)
938
+ class RactorMakeSharable < Instruction
939
+ attr_reader :value
940
+
941
+ def initialize(value:, result_var: nil)
942
+ super(type: TypeChecker::Types::UNTYPED, result_var: result_var)
943
+ @value = value
944
+ end
945
+ end
946
+
947
+ # Ractor.shareable?(obj)
948
+ class RactorSharable < Instruction
949
+ attr_reader :value
950
+
951
+ def initialize(value:, result_var: nil)
952
+ super(type: TypeChecker::Types::BOOL, result_var: result_var)
953
+ @value = value
954
+ end
955
+ end
956
+
957
+ # ractor.monitor(port)
958
+ class RactorMonitor < Instruction
959
+ attr_reader :ractor, :port
960
+
961
+ def initialize(ractor:, port:, result_var: nil)
962
+ super(type: TypeChecker::Types::NIL, result_var: result_var)
963
+ @ractor = ractor
964
+ @port = port
965
+ end
966
+ end
967
+
968
+ # ractor.unmonitor(port)
969
+ class RactorUnmonitor < Instruction
970
+ attr_reader :ractor, :port
971
+
972
+ def initialize(ractor:, port:, result_var: nil)
973
+ super(type: TypeChecker::Types::NIL, result_var: result_var)
974
+ @ractor = ractor
975
+ @port = port
976
+ end
977
+ end
978
+
979
+ # ========================================
980
+ # Ractor::Port operations
981
+ # ========================================
982
+
983
+ # Create a new Ractor::Port
984
+ # Ractor::Port.new
985
+ class RactorPortNew < Instruction
986
+ def initialize(result_var: nil)
987
+ super(type: TypeChecker::Types::RACTOR_PORT, result_var: result_var)
988
+ end
989
+ end
990
+
991
+ # Send message to port
992
+ # port.send(msg) or port << msg
993
+ class RactorPortSend < Instruction
994
+ attr_reader :port, :value
995
+
996
+ def initialize(port:, value:, result_var: nil)
997
+ super(type: TypeChecker::Types::RACTOR_PORT, result_var: result_var)
998
+ @port = port
999
+ @value = value
1000
+ end
1001
+ end
1002
+
1003
+ # Receive message from port
1004
+ # port.receive
1005
+ class RactorPortReceive < Instruction
1006
+ attr_reader :port
1007
+
1008
+ def initialize(port:, type: TypeChecker::Types::UNTYPED, result_var: nil)
1009
+ super(type: type, result_var: result_var)
1010
+ @port = port
1011
+ end
1012
+ end
1013
+
1014
+ # Close port
1015
+ # port.close
1016
+ class RactorPortClose < Instruction
1017
+ attr_reader :port
1018
+
1019
+ def initialize(port:, result_var: nil)
1020
+ super(type: TypeChecker::Types::NIL, result_var: result_var)
1021
+ @port = port
1022
+ end
1023
+ end
1024
+
1025
+ # ========================================
1026
+ # Ractor.select
1027
+ # ========================================
1028
+
1029
+ # Select from multiple ports/ractors
1030
+ # Ractor.select(*ports_or_ractors)
1031
+ class RactorSelect < Instruction
1032
+ attr_reader :sources
1033
+
1034
+ def initialize(sources:, result_var: nil)
1035
+ super(type: TypeChecker::Types::UNTYPED, result_var: result_var)
1036
+ @sources = sources
1037
+ end
1038
+ end
1039
+
1040
+ # Yield to block
1041
+ class Yield < Instruction
1042
+ attr_reader :args
1043
+
1044
+ def initialize(args: [], type: TypeChecker::Types::UNTYPED, result_var: nil)
1045
+ super(type: type, result_var: result_var)
1046
+ @args = args
1047
+ end
1048
+ end
1049
+
1050
+ # Exception handling
1051
+ class RaiseException < Terminator
1052
+ attr_reader :exception
1053
+
1054
+ def initialize(exception:)
1055
+ super(type: TypeChecker::Types::BOTTOM)
1056
+ @exception = exception
1057
+ end
1058
+ end
1059
+
1060
+ # Rescue clause: represents a single rescue handler
1061
+ # rescue TypeError, ArgumentError => e
1062
+ # handle_error
1063
+ # end
1064
+ class RescueClause < Node
1065
+ attr_reader :exception_classes # Array of exception class names (e.g., ["TypeError", "ArgumentError"])
1066
+ attr_reader :exception_var # Local variable name for caught exception (e.g., "e"), nil if not specified
1067
+ attr_reader :body_blocks # Array of BasicBlock for handler body
1068
+
1069
+ def initialize(exception_classes: [], exception_var: nil, body_blocks: [])
1070
+ super(type: TypeChecker::Types::UNTYPED)
1071
+ @exception_classes = exception_classes.empty? ? ["StandardError"] : exception_classes
1072
+ @exception_var = exception_var
1073
+ @body_blocks = body_blocks
1074
+ end
1075
+ end
1076
+
1077
+ class BeginRescue < Instruction
1078
+ attr_reader :try_blocks, :rescue_clauses, :else_blocks, :ensure_blocks
1079
+ attr_accessor :non_try_instruction_ids
1080
+
1081
+ def initialize(try_blocks:, rescue_clauses: [], else_blocks: [], ensure_blocks: [], type: TypeChecker::Types::UNTYPED, result_var: nil)
1082
+ super(type: type, result_var: result_var)
1083
+ @try_blocks = try_blocks
1084
+ @rescue_clauses = rescue_clauses # Array of RescueClause
1085
+ @else_blocks = else_blocks # Array of BasicBlock (runs if no exception)
1086
+ @ensure_blocks = ensure_blocks # Array of BasicBlock (always runs)
1087
+ @non_try_instruction_ids = nil # Set of object_ids for all rescue/else/ensure instructions
1088
+ end
1089
+ end
1090
+
1091
+ # Case/when statement
1092
+ # case x
1093
+ # when 1 then "one"
1094
+ # when 2, 3 then "small"
1095
+ # else "other"
1096
+ # end
1097
+ class CaseStatement < Instruction
1098
+ attr_reader :predicate # HIR instruction for the value being matched (nil for case without predicate)
1099
+ attr_reader :when_clauses # Array of WhenClause
1100
+ attr_reader :else_body # Array of HIR instructions for else branch (nil if no else)
1101
+ attr_accessor :sub_instruction_ids # Set of object_ids for when/else instructions (including sub-exprs)
1102
+
1103
+ def initialize(predicate:, when_clauses: [], else_body: nil, type: TypeChecker::Types::UNTYPED, result_var: nil)
1104
+ super(type: type, result_var: result_var)
1105
+ @predicate = predicate
1106
+ @when_clauses = when_clauses
1107
+ @else_body = else_body
1108
+ @sub_instruction_ids = nil
1109
+ end
1110
+ end
1111
+
1112
+ # Single when clause in a case statement
1113
+ # when 1, 2, 3 then body
1114
+ class WhenClause < Node
1115
+ attr_reader :conditions # Array of HIR instructions (match values/ranges/classes)
1116
+ attr_reader :body # Array of HIR instructions for the clause body
1117
+
1118
+ def initialize(conditions: [], body: [])
1119
+ super(type: TypeChecker::Types::UNTYPED)
1120
+ @conditions = conditions
1121
+ @body = body
1122
+ end
1123
+ end
1124
+
1125
+ # ========================================
1126
+ # Pattern Matching (case/in)
1127
+ # Ruby 3.0+ pattern matching support
1128
+ # ========================================
1129
+
1130
+ # Case/in pattern matching statement
1131
+ # case x
1132
+ # in 1 then "one"
1133
+ # in Integer => n then n.to_s
1134
+ # in [a, b] then a + b
1135
+ # else "other"
1136
+ # end
1137
+ class CaseMatchStatement < Instruction
1138
+ attr_reader :predicate # HIR instruction for the value being matched
1139
+ attr_reader :in_clauses # Array of InClause
1140
+ attr_reader :else_body # Array of HIR instructions for else branch (nil raises NoMatchingPatternError)
1141
+
1142
+ def initialize(predicate:, in_clauses: [], else_body: nil, type: TypeChecker::Types::UNTYPED, result_var: nil)
1143
+ super(type: type, result_var: result_var)
1144
+ @predicate = predicate
1145
+ @in_clauses = in_clauses
1146
+ @else_body = else_body
1147
+ end
1148
+ end
1149
+
1150
+ # Single in clause in a case/in statement
1151
+ # in Pattern [if guard] then body
1152
+ class InClause < Node
1153
+ attr_reader :pattern # Pattern node
1154
+ attr_reader :guard # Optional guard expression (HIR instruction)
1155
+ attr_reader :body # Array of HIR instructions for the clause body
1156
+ attr_reader :bindings # Hash of { variable_name => type } for pattern variables
1157
+
1158
+ def initialize(pattern:, guard: nil, body: [], bindings: {})
1159
+ super(type: TypeChecker::Types::UNTYPED)
1160
+ @pattern = pattern
1161
+ @guard = guard
1162
+ @body = body
1163
+ @bindings = bindings
1164
+ end
1165
+ end
1166
+
1167
+ # Base class for pattern nodes
1168
+ class Pattern < Node
1169
+ attr_reader :bindings # Hash of { variable_name => type } - variables bound by this pattern
1170
+
1171
+ def initialize(bindings: {})
1172
+ super(type: TypeChecker::Types::UNTYPED)
1173
+ @bindings = bindings
1174
+ end
1175
+ end
1176
+
1177
+ # Literal pattern: matches a specific value using ===
1178
+ # in 42 / in "hello" / in :symbol / in nil / in true / in false
1179
+ class LiteralPattern < Pattern
1180
+ attr_reader :value # HIR Literal node (IntegerLit, StringLit, etc.)
1181
+
1182
+ def initialize(value:, bindings: {})
1183
+ super(bindings: bindings)
1184
+ @value = value
1185
+ end
1186
+ end
1187
+
1188
+ # Variable pattern: binds matched value to a variable
1189
+ # in x
1190
+ class VariablePattern < Pattern
1191
+ attr_reader :name # Variable name (String)
1192
+ attr_reader :var_type # Inferred type for the variable
1193
+
1194
+ def initialize(name:, var_type: TypeChecker::Types::UNTYPED, bindings: nil)
1195
+ bindings ||= { name => var_type }
1196
+ super(bindings: bindings)
1197
+ @name = name
1198
+ @var_type = var_type
1199
+ end
1200
+ end
1201
+
1202
+ # Constant/Type pattern: matches class or constant using ===
1203
+ # in Integer / in String / in MyClass
1204
+ class ConstantPattern < Pattern
1205
+ attr_reader :constant_name # Constant name (String)
1206
+ attr_accessor :narrowed_type # Type to narrow to in the matched branch
1207
+
1208
+ def initialize(constant_name:, narrowed_type: nil, bindings: {})
1209
+ super(bindings: bindings)
1210
+ @constant_name = constant_name
1211
+ @narrowed_type = narrowed_type
1212
+ end
1213
+ end
1214
+
1215
+ # Alternation pattern: matches any of several patterns
1216
+ # in 1 | 2 | 3 / in Integer | String
1217
+ class AlternationPattern < Pattern
1218
+ attr_reader :alternatives # Array of Pattern nodes
1219
+
1220
+ def initialize(alternatives:, bindings: {})
1221
+ super(bindings: bindings)
1222
+ @alternatives = alternatives
1223
+ end
1224
+ end
1225
+
1226
+ # Array pattern: matches Array-like objects via deconstruct
1227
+ # in [a, b] / in [a, *rest] / in [*pre, x, *post]
1228
+ # in Point[x, y]
1229
+ class ArrayPattern < Pattern
1230
+ attr_reader :constant # Optional constant for type check (String, e.g., "Point")
1231
+ attr_reader :requireds # Required element patterns before rest (Array of Pattern)
1232
+ attr_reader :rest # Rest pattern (*args), RestPattern or nil
1233
+ attr_reader :posts # Post-rest required patterns (Array of Pattern)
1234
+
1235
+ def initialize(constant: nil, requireds: [], rest: nil, posts: [], bindings: {})
1236
+ super(bindings: bindings)
1237
+ @constant = constant
1238
+ @requireds = requireds
1239
+ @rest = rest
1240
+ @posts = posts
1241
+ end
1242
+ end
1243
+
1244
+ # Hash pattern: matches Hash-like objects via deconstruct_keys
1245
+ # in {x:, y:} / in {name: String => n}
1246
+ class HashPattern < Pattern
1247
+ attr_reader :constant # Optional constant for type check (String)
1248
+ attr_reader :elements # Array of HashPatternElement
1249
+ attr_reader :rest # Rest pattern (**rest), RestPattern or nil
1250
+
1251
+ def initialize(constant: nil, elements: [], rest: nil, bindings: {})
1252
+ super(bindings: bindings)
1253
+ @constant = constant
1254
+ @elements = elements
1255
+ @rest = rest
1256
+ end
1257
+ end
1258
+
1259
+ # Single element in a hash pattern
1260
+ # x: or x: Pattern
1261
+ class HashPatternElement < Node
1262
+ attr_reader :key # Symbol key (String)
1263
+ attr_reader :value_pattern # Pattern for value (nil for shorthand `x:`)
1264
+
1265
+ def initialize(key:, value_pattern: nil)
1266
+ super(type: TypeChecker::Types::UNTYPED)
1267
+ @key = key
1268
+ @value_pattern = value_pattern
1269
+ end
1270
+ end
1271
+
1272
+ # Rest pattern: captures remaining elements
1273
+ # *rest or **rest or * or **
1274
+ class RestPattern < Pattern
1275
+ attr_reader :name # Variable name (String), nil for anonymous * or **
1276
+
1277
+ def initialize(name: nil, bindings: nil)
1278
+ bindings ||= name ? { name => TypeChecker::Types::ClassInstance.new(:Array) } : {}
1279
+ super(bindings: bindings)
1280
+ @name = name
1281
+ end
1282
+ end
1283
+
1284
+ # Capture pattern: matches a pattern and binds to variable
1285
+ # in Integer => n / in [a, b] => arr
1286
+ class CapturePattern < Pattern
1287
+ attr_reader :value_pattern # Pattern to match
1288
+ attr_reader :target # Variable name to bind (String)
1289
+
1290
+ def initialize(value_pattern:, target:, bindings: nil)
1291
+ # Merge bindings from value_pattern with the capture target
1292
+ pattern_bindings = value_pattern.bindings.dup
1293
+ pattern_bindings[target] = TypeChecker::Types::UNTYPED
1294
+ bindings ||= pattern_bindings
1295
+ super(bindings: bindings)
1296
+ @value_pattern = value_pattern
1297
+ @target = target
1298
+ end
1299
+ end
1300
+
1301
+ # Pinned variable pattern: matches against existing variable value
1302
+ # in ^x
1303
+ class PinnedPattern < Pattern
1304
+ attr_reader :variable_name # Variable name to match against (String)
1305
+ attr_reader :variable # HIR LoadLocal instruction (populated during codegen)
1306
+
1307
+ def initialize(variable_name:, variable: nil)
1308
+ super(bindings: {})
1309
+ @variable_name = variable_name
1310
+ @variable = variable
1311
+ end
1312
+ end
1313
+
1314
+ # Match predicate expression: expr in pattern (returns true/false)
1315
+ # value in [a, b]
1316
+ class MatchPredicate < Instruction
1317
+ attr_reader :value # Expression to match (HIR instruction)
1318
+ attr_reader :pattern # Pattern to match against
1319
+
1320
+ def initialize(value:, pattern:, result_var: nil)
1321
+ super(type: TypeChecker::Types::BOOL, result_var: result_var)
1322
+ @value = value
1323
+ @pattern = pattern
1324
+ end
1325
+ end
1326
+
1327
+ # Match required expression: expr => pattern (raises NoMatchingPatternError on failure)
1328
+ # value => [a, b]
1329
+ class MatchRequired < Instruction
1330
+ attr_reader :value # Expression to match (HIR instruction)
1331
+ attr_reader :pattern # Pattern to match against
1332
+
1333
+ def initialize(value:, pattern:, type: TypeChecker::Types::UNTYPED, result_var: nil)
1334
+ super(type: type, result_var: result_var)
1335
+ @value = value
1336
+ @pattern = pattern
1337
+ end
1338
+ end
1339
+
1340
+ # Phi node (for SSA form)
1341
+ class Phi < Instruction
1342
+ attr_reader :incoming # Hash of { block_label => value }
1343
+
1344
+ def initialize(incoming:, type: TypeChecker::Types::UNTYPED, result_var: nil)
1345
+ super(type: type, result_var: result_var)
1346
+ @incoming = incoming
1347
+ end
1348
+ end
1349
+
1350
+ # ========================================
1351
+ # NativeArray operations
1352
+ # Contiguous memory arrays with unboxed numeric elements
1353
+ # ========================================
1354
+
1355
+ # Allocate a NativeArray
1356
+ # NativeArray[Float64] → double* with capacity
1357
+ class NativeArrayAlloc < Instruction
1358
+ attr_reader :size, :element_type
1359
+
1360
+ def initialize(size:, element_type:, result_var: nil)
1361
+ array_type = TypeChecker::Types::NativeArrayType.new(element_type)
1362
+ super(type: array_type, result_var: result_var)
1363
+ @size = size # HIR value (IntegerLit or LoadLocal)
1364
+ @element_type = element_type # :Int64 or :Float64
1365
+ end
1366
+ end
1367
+
1368
+ # Get element from NativeArray (unboxed)
1369
+ # arr[i] → double or i64
1370
+ class NativeArrayGet < Instruction
1371
+ attr_reader :array, :index, :element_type
1372
+
1373
+ def initialize(array:, index:, element_type:, result_var: nil)
1374
+ elem_internal_type = case element_type
1375
+ when :Int64 then TypeChecker::Types::INTEGER
1376
+ when :Float64 then TypeChecker::Types::FLOAT
1377
+ else TypeChecker::Types::UNTYPED
1378
+ end
1379
+ super(type: elem_internal_type, result_var: result_var)
1380
+ @array = array # HIR value (the NativeArray)
1381
+ @index = index # HIR value (index)
1382
+ @element_type = element_type # :Int64 or :Float64
1383
+ end
1384
+ end
1385
+
1386
+ # Set element in NativeArray
1387
+ # arr[i] = value
1388
+ class NativeArraySet < Instruction
1389
+ attr_reader :array, :index, :value, :element_type
1390
+
1391
+ def initialize(array:, index:, value:, element_type:)
1392
+ super(type: TypeChecker::Types::NIL)
1393
+ @array = array
1394
+ @index = index
1395
+ @value = value
1396
+ @element_type = element_type
1397
+ end
1398
+ end
1399
+
1400
+ # Get length of NativeArray (stored with array metadata)
1401
+ class NativeArrayLength < Instruction
1402
+ attr_reader :array
1403
+
1404
+ def initialize(array:, result_var: nil)
1405
+ super(type: TypeChecker::Types::INTEGER, result_var: result_var)
1406
+ @array = array
1407
+ end
1408
+ end
1409
+
1410
+ # ========================================
1411
+ # StaticArray operations
1412
+ # Fixed-size stack-allocated array with compile-time known size
1413
+ # ========================================
1414
+
1415
+ # Allocate a StaticArray on stack
1416
+ # StaticArray[Float, 4].new() → stack-allocated [4 x double]
1417
+ class StaticArrayAlloc < Instruction
1418
+ attr_reader :element_type, :size, :initial_value
1419
+
1420
+ def initialize(element_type:, size:, initial_value: nil, result_var: nil)
1421
+ array_type = TypeChecker::Types::StaticArrayType.new(element_type, size)
1422
+ super(type: array_type, result_var: result_var)
1423
+ @element_type = element_type # :Int64 or :Float64
1424
+ @size = size # Compile-time constant integer
1425
+ @initial_value = initial_value # Optional fill value (HIR value)
1426
+ end
1427
+ end
1428
+
1429
+ # Get element from StaticArray (unboxed)
1430
+ # arr[i] → double or i64
1431
+ class StaticArrayGet < Instruction
1432
+ attr_reader :array, :index, :element_type, :size
1433
+
1434
+ def initialize(array:, index:, element_type:, size:, result_var: nil)
1435
+ elem_internal_type = case element_type
1436
+ when :Int64 then TypeChecker::Types::INTEGER
1437
+ when :Float64 then TypeChecker::Types::FLOAT
1438
+ else TypeChecker::Types::UNTYPED
1439
+ end
1440
+ super(type: elem_internal_type, result_var: result_var)
1441
+ @array = array # HIR value (the StaticArray pointer)
1442
+ @index = index # HIR value (index)
1443
+ @element_type = element_type # :Int64 or :Float64
1444
+ @size = size # Compile-time size for bounds check optimization
1445
+ end
1446
+ end
1447
+
1448
+ # Set element in StaticArray
1449
+ # arr[i] = value
1450
+ class StaticArraySet < Instruction
1451
+ attr_reader :array, :index, :value, :element_type, :size
1452
+
1453
+ def initialize(array:, index:, value:, element_type:, size:)
1454
+ super(type: TypeChecker::Types::NIL)
1455
+ @array = array
1456
+ @index = index
1457
+ @value = value
1458
+ @element_type = element_type
1459
+ @size = size
1460
+ end
1461
+ end
1462
+
1463
+ # Get size of StaticArray (compile-time constant)
1464
+ # arr.size → Integer (known at compile time)
1465
+ class StaticArraySize < Instruction
1466
+ attr_reader :array, :size
1467
+
1468
+ def initialize(array:, size:, result_var: nil)
1469
+ super(type: TypeChecker::Types::INTEGER, result_var: result_var)
1470
+ @array = array
1471
+ @size = size # Compile-time known size
1472
+ end
1473
+ end
1474
+
1475
+ # ========================================
1476
+ # ByteBuffer operations
1477
+ # Growable byte array for efficient I/O
1478
+ # ========================================
1479
+
1480
+ # Allocate a new ByteBuffer
1481
+ # ByteBuffer.new(1024) → ptr to buffer struct
1482
+ class ByteBufferAlloc < Instruction
1483
+ attr_reader :capacity
1484
+
1485
+ def initialize(capacity:, result_var: nil)
1486
+ super(type: TypeChecker::Types::BYTEBUFFER, result_var: result_var)
1487
+ @capacity = capacity # HIR value for initial capacity
1488
+ end
1489
+ end
1490
+
1491
+ # Get byte from ByteBuffer
1492
+ # buf[i] → Integer (0-255)
1493
+ class ByteBufferGet < Instruction
1494
+ attr_reader :buffer, :index
1495
+
1496
+ def initialize(buffer:, index:, result_var: nil)
1497
+ super(type: TypeChecker::Types::INTEGER, result_var: result_var)
1498
+ @buffer = buffer # HIR value (the ByteBuffer)
1499
+ @index = index # HIR value (index)
1500
+ end
1501
+ end
1502
+
1503
+ # Set byte in ByteBuffer
1504
+ # buf[i] = byte
1505
+ class ByteBufferSet < Instruction
1506
+ attr_reader :buffer, :index, :byte
1507
+
1508
+ def initialize(buffer:, index:, byte:)
1509
+ super(type: TypeChecker::Types::INTEGER)
1510
+ @buffer = buffer
1511
+ @index = index
1512
+ @byte = byte # HIR value (0-255)
1513
+ end
1514
+ end
1515
+
1516
+ # Get length of ByteBuffer
1517
+ class ByteBufferLength < Instruction
1518
+ attr_reader :buffer
1519
+
1520
+ def initialize(buffer:, result_var: nil)
1521
+ super(type: TypeChecker::Types::INTEGER, result_var: result_var)
1522
+ @buffer = buffer
1523
+ end
1524
+ end
1525
+
1526
+ # Append to ByteBuffer
1527
+ # buf << byte, buf.write(string), buf.write_bytes(other_buf)
1528
+ class ByteBufferAppend < Instruction
1529
+ attr_reader :buffer, :value, :append_type
1530
+
1531
+ # @param append_type [:byte, :string, :buffer]
1532
+ def initialize(buffer:, value:, append_type:, result_var: nil)
1533
+ super(type: TypeChecker::Types::BYTEBUFFER, result_var: result_var)
1534
+ @buffer = buffer
1535
+ @value = value
1536
+ @append_type = append_type
1537
+ end
1538
+ end
1539
+
1540
+ # Search for byte or sequence in ByteBuffer
1541
+ # buf.index_of(32) → Integer? (finds ASCII space)
1542
+ # buf.index_of_seq("\r\n") → Integer?
1543
+ class ByteBufferIndexOf < Instruction
1544
+ attr_reader :buffer, :pattern, :search_type, :start_offset
1545
+
1546
+ # @param search_type [:byte, :sequence]
1547
+ def initialize(buffer:, pattern:, search_type:, start_offset: nil, result_var: nil)
1548
+ super(type: TypeChecker::Types.optional(TypeChecker::Types::INTEGER), result_var: result_var)
1549
+ @buffer = buffer
1550
+ @pattern = pattern # HIR value (byte integer or string)
1551
+ @search_type = search_type
1552
+ @start_offset = start_offset # Optional start offset for search
1553
+ end
1554
+ end
1555
+
1556
+ # Convert ByteBuffer to String
1557
+ # buf.to_s → String
1558
+ class ByteBufferToString < Instruction
1559
+ attr_reader :buffer, :ascii_only
1560
+
1561
+ def initialize(buffer:, ascii_only: false, result_var: nil)
1562
+ super(type: TypeChecker::Types::STRING, result_var: result_var)
1563
+ @buffer = buffer
1564
+ @ascii_only = ascii_only # Use faster ASCII conversion if true
1565
+ end
1566
+ end
1567
+
1568
+ # Create ByteSlice from ByteBuffer
1569
+ # buf.slice(start, length) → ByteSlice
1570
+ class ByteBufferSlice < Instruction
1571
+ attr_reader :buffer, :start, :length
1572
+
1573
+ def initialize(buffer:, start:, length:, result_var: nil)
1574
+ super(type: TypeChecker::Types::BYTESLICE, result_var: result_var)
1575
+ @buffer = buffer
1576
+ @start = start # HIR value
1577
+ @length = length # HIR value
1578
+ end
1579
+ end
1580
+
1581
+ # ========================================
1582
+ # ByteSlice operations
1583
+ # Zero-copy view into ByteBuffer
1584
+ # ========================================
1585
+
1586
+ # Get byte from ByteSlice
1587
+ class ByteSliceGet < Instruction
1588
+ attr_reader :slice, :index
1589
+
1590
+ def initialize(slice:, index:, result_var: nil)
1591
+ super(type: TypeChecker::Types::INTEGER, result_var: result_var)
1592
+ @slice = slice
1593
+ @index = index
1594
+ end
1595
+ end
1596
+
1597
+ # Get length of ByteSlice
1598
+ class ByteSliceLength < Instruction
1599
+ attr_reader :slice
1600
+
1601
+ def initialize(slice:, result_var: nil)
1602
+ super(type: TypeChecker::Types::INTEGER, result_var: result_var)
1603
+ @slice = slice
1604
+ end
1605
+ end
1606
+
1607
+ # Convert ByteSlice to String
1608
+ class ByteSliceToString < Instruction
1609
+ attr_reader :slice
1610
+
1611
+ def initialize(slice:, result_var: nil)
1612
+ super(type: TypeChecker::Types::STRING, result_var: result_var)
1613
+ @slice = slice
1614
+ end
1615
+ end
1616
+
1617
+ # ========================================
1618
+ # Slice[T] operations
1619
+ # Generic bounds-checked pointer view
1620
+ # ========================================
1621
+
1622
+ # Allocate a new Slice with given size
1623
+ # Slice.new(10) → { ptr, size }
1624
+ class SliceAlloc < Instruction
1625
+ attr_reader :size, :element_type
1626
+
1627
+ def initialize(size:, element_type:, result_var: nil)
1628
+ slice_type = TypeChecker::Types::SliceType.new(element_type)
1629
+ super(type: slice_type, result_var: result_var)
1630
+ @size = size # HIR value
1631
+ @element_type = element_type # :Int64 or :Float64
1632
+ end
1633
+ end
1634
+
1635
+ # Get empty Slice singleton
1636
+ # Slice.empty → { null, 0 }
1637
+ class SliceEmpty < Instruction
1638
+ attr_reader :element_type
1639
+
1640
+ def initialize(element_type:, result_var: nil)
1641
+ slice_type = TypeChecker::Types::SliceType.new(element_type)
1642
+ super(type: slice_type, result_var: result_var)
1643
+ @element_type = element_type
1644
+ end
1645
+ end
1646
+
1647
+ # Get element from Slice (bounds-checked)
1648
+ # slice[i] → T
1649
+ class SliceGet < Instruction
1650
+ attr_reader :slice, :index, :element_type
1651
+
1652
+ def initialize(slice:, index:, element_type:, result_var: nil)
1653
+ result_type = element_type == :Int64 ? TypeChecker::Types::INTEGER : TypeChecker::Types::FLOAT
1654
+ super(type: result_type, result_var: result_var)
1655
+ @slice = slice # HIR value
1656
+ @index = index # HIR value
1657
+ @element_type = element_type
1658
+ end
1659
+ end
1660
+
1661
+ # Set element in Slice (bounds-checked)
1662
+ # slice[i] = value → value
1663
+ class SliceSet < Instruction
1664
+ attr_reader :slice, :index, :value, :element_type
1665
+
1666
+ def initialize(slice:, index:, value:, element_type:, result_var: nil)
1667
+ result_type = element_type == :Int64 ? TypeChecker::Types::INTEGER : TypeChecker::Types::FLOAT
1668
+ super(type: result_type, result_var: result_var)
1669
+ @slice = slice
1670
+ @index = index
1671
+ @value = value
1672
+ @element_type = element_type
1673
+ end
1674
+ end
1675
+
1676
+ # Get size of Slice
1677
+ # slice.size → Integer
1678
+ class SliceSize < Instruction
1679
+ attr_reader :slice
1680
+
1681
+ def initialize(slice:, result_var: nil)
1682
+ super(type: TypeChecker::Types::INTEGER, result_var: result_var)
1683
+ @slice = slice
1684
+ end
1685
+ end
1686
+
1687
+ # Create subslice (view, no copy)
1688
+ # slice[start, count] → Slice[T]
1689
+ class SliceSubslice < Instruction
1690
+ attr_reader :slice, :start, :count, :element_type
1691
+
1692
+ def initialize(slice:, start:, count:, element_type:, result_var: nil)
1693
+ slice_type = TypeChecker::Types::SliceType.new(element_type)
1694
+ super(type: slice_type, result_var: result_var)
1695
+ @slice = slice
1696
+ @start = start # HIR value
1697
+ @count = count # HIR value
1698
+ @element_type = element_type
1699
+ end
1700
+ end
1701
+
1702
+ # Copy elements from another Slice
1703
+ # slice.copy_from(source) → self
1704
+ class SliceCopyFrom < Instruction
1705
+ attr_reader :dest, :source, :element_type
1706
+
1707
+ def initialize(dest:, source:, element_type:, result_var: nil)
1708
+ slice_type = TypeChecker::Types::SliceType.new(element_type)
1709
+ super(type: slice_type, result_var: result_var)
1710
+ @dest = dest
1711
+ @source = source
1712
+ @element_type = element_type
1713
+ end
1714
+ end
1715
+
1716
+ # Fill Slice with a value
1717
+ # slice.fill(value) → self
1718
+ class SliceFill < Instruction
1719
+ attr_reader :slice, :value, :element_type
1720
+
1721
+ def initialize(slice:, value:, element_type:, result_var: nil)
1722
+ slice_type = TypeChecker::Types::SliceType.new(element_type)
1723
+ super(type: slice_type, result_var: result_var)
1724
+ @slice = slice
1725
+ @value = value # HIR value
1726
+ @element_type = element_type
1727
+ end
1728
+ end
1729
+
1730
+ # Convert NativeArray or StaticArray to Slice (zero-copy view)
1731
+ # array.to_slice → Slice[T]
1732
+ class ToSlice < Instruction
1733
+ attr_reader :source, :element_type, :source_kind
1734
+
1735
+ # @param source [HIR value] NativeArray or StaticArray
1736
+ # @param element_type [Symbol] :Int64 or :Float64
1737
+ # @param source_kind [Symbol] :native_array or :static_array
1738
+ def initialize(source:, element_type:, source_kind:, result_var: nil)
1739
+ slice_type = TypeChecker::Types::SliceType.new(element_type)
1740
+ super(type: slice_type, result_var: result_var)
1741
+ @source = source
1742
+ @element_type = element_type
1743
+ @source_kind = source_kind
1744
+ end
1745
+ end
1746
+
1747
+ # ========================================
1748
+ # StringBuffer operations
1749
+ # Efficient string building
1750
+ # ========================================
1751
+
1752
+ # Allocate a new StringBuffer
1753
+ # StringBuffer.new(256) → VALUE (rb_str_buf_new result)
1754
+ class StringBufferAlloc < Instruction
1755
+ attr_reader :capacity
1756
+
1757
+ def initialize(capacity:, result_var: nil)
1758
+ super(type: TypeChecker::Types::STRINGBUFFER, result_var: result_var)
1759
+ @capacity = capacity # HIR value (nil for default)
1760
+ end
1761
+ end
1762
+
1763
+ # Append to StringBuffer
1764
+ # buf << string
1765
+ class StringBufferAppend < Instruction
1766
+ attr_reader :buffer, :value
1767
+
1768
+ def initialize(buffer:, value:, result_var: nil)
1769
+ super(type: TypeChecker::Types::STRINGBUFFER, result_var: result_var)
1770
+ @buffer = buffer
1771
+ @value = value # HIR value (string to append)
1772
+ end
1773
+ end
1774
+
1775
+ # Get current length of StringBuffer
1776
+ class StringBufferLength < Instruction
1777
+ attr_reader :buffer
1778
+
1779
+ def initialize(buffer:, result_var: nil)
1780
+ super(type: TypeChecker::Types::INTEGER, result_var: result_var)
1781
+ @buffer = buffer
1782
+ end
1783
+ end
1784
+
1785
+ # Convert StringBuffer to String (returns the internal string)
1786
+ class StringBufferToString < Instruction
1787
+ attr_reader :buffer
1788
+
1789
+ def initialize(buffer:, result_var: nil)
1790
+ super(type: TypeChecker::Types::STRING, result_var: result_var)
1791
+ @buffer = buffer
1792
+ end
1793
+ end
1794
+
1795
+ # ========================================
1796
+ # NativeString operations
1797
+ # UTF-8 native string with byte and character level operations
1798
+ # Memory layout: { ptr (i8*), byte_len (i64), char_len (i64), flags (i64) }
1799
+ # ========================================
1800
+
1801
+ # Create NativeString from Ruby String
1802
+ # NativeString.from(str) → NativeString
1803
+ class NativeStringFromRuby < Instruction
1804
+ attr_reader :string
1805
+
1806
+ def initialize(string:, result_var: nil)
1807
+ super(type: TypeChecker::Types::NATIVESTRING, result_var: result_var)
1808
+ @string = string # HIR value (Ruby String VALUE)
1809
+ end
1810
+ end
1811
+
1812
+ # Get byte at index (O(1))
1813
+ # ns.byte_at(i) → Integer (0-255)
1814
+ class NativeStringByteAt < Instruction
1815
+ attr_reader :native_string, :index
1816
+
1817
+ def initialize(native_string:, index:, result_var: nil)
1818
+ super(type: TypeChecker::Types::INTEGER, result_var: result_var)
1819
+ @native_string = native_string
1820
+ @index = index
1821
+ end
1822
+ end
1823
+
1824
+ # Get byte length (O(1))
1825
+ # ns.byte_length → Integer
1826
+ class NativeStringByteLength < Instruction
1827
+ attr_reader :native_string
1828
+
1829
+ def initialize(native_string:, result_var: nil)
1830
+ super(type: TypeChecker::Types::INTEGER, result_var: result_var)
1831
+ @native_string = native_string
1832
+ end
1833
+ end
1834
+
1835
+ # Search for byte in NativeString
1836
+ # ns.byte_index_of(byte) → Integer?
1837
+ # ns.byte_index_of(byte, start_offset) → Integer?
1838
+ class NativeStringByteIndexOf < Instruction
1839
+ attr_reader :native_string, :byte, :start_offset
1840
+
1841
+ def initialize(native_string:, byte:, start_offset: nil, result_var: nil)
1842
+ super(type: TypeChecker::Types.optional(TypeChecker::Types::INTEGER), result_var: result_var)
1843
+ @native_string = native_string
1844
+ @byte = byte # HIR value (0-255)
1845
+ @start_offset = start_offset # Optional HIR value
1846
+ end
1847
+ end
1848
+
1849
+ # Create byte-level slice of NativeString
1850
+ # ns.byte_slice(start, length) → NativeString
1851
+ class NativeStringByteSlice < Instruction
1852
+ attr_reader :native_string, :start, :length
1853
+
1854
+ def initialize(native_string:, start:, length:, result_var: nil)
1855
+ super(type: TypeChecker::Types::NATIVESTRING, result_var: result_var)
1856
+ @native_string = native_string
1857
+ @start = start # HIR value (byte offset)
1858
+ @length = length # HIR value (byte count)
1859
+ end
1860
+ end
1861
+
1862
+ # Get character at index (UTF-8 aware, O(n) worst case)
1863
+ # ns.char_at(i) → String (single character)
1864
+ class NativeStringCharAt < Instruction
1865
+ attr_reader :native_string, :index
1866
+
1867
+ def initialize(native_string:, index:, result_var: nil)
1868
+ super(type: TypeChecker::Types::STRING, result_var: result_var)
1869
+ @native_string = native_string
1870
+ @index = index # Character index (not byte index)
1871
+ end
1872
+ end
1873
+
1874
+ # Get character length (UTF-8 aware, cached after first call)
1875
+ # ns.char_length → Integer
1876
+ class NativeStringCharLength < Instruction
1877
+ attr_reader :native_string
1878
+
1879
+ def initialize(native_string:, result_var: nil)
1880
+ super(type: TypeChecker::Types::INTEGER, result_var: result_var)
1881
+ @native_string = native_string
1882
+ end
1883
+ end
1884
+
1885
+ # Search for substring in NativeString
1886
+ # ns.char_index_of(needle) → Integer? (character index)
1887
+ class NativeStringCharIndexOf < Instruction
1888
+ attr_reader :native_string, :needle
1889
+
1890
+ def initialize(native_string:, needle:, result_var: nil)
1891
+ super(type: TypeChecker::Types.optional(TypeChecker::Types::INTEGER), result_var: result_var)
1892
+ @native_string = native_string
1893
+ @needle = needle # HIR value (String to find)
1894
+ end
1895
+ end
1896
+
1897
+ # Create character-level slice of NativeString (UTF-8 aware)
1898
+ # ns.char_slice(start, length) → NativeString
1899
+ class NativeStringCharSlice < Instruction
1900
+ attr_reader :native_string, :start, :length
1901
+
1902
+ def initialize(native_string:, start:, length:, result_var: nil)
1903
+ super(type: TypeChecker::Types::NATIVESTRING, result_var: result_var)
1904
+ @native_string = native_string
1905
+ @start = start # HIR value (character offset)
1906
+ @length = length # HIR value (character count)
1907
+ end
1908
+ end
1909
+
1910
+ # Check if NativeString is ASCII-only (O(1) after creation)
1911
+ # ns.ascii_only? → bool
1912
+ class NativeStringAsciiOnly < Instruction
1913
+ attr_reader :native_string
1914
+
1915
+ def initialize(native_string:, result_var: nil)
1916
+ super(type: TypeChecker::Types::BOOL, result_var: result_var)
1917
+ @native_string = native_string
1918
+ end
1919
+ end
1920
+
1921
+ # Check if NativeString starts with prefix
1922
+ # ns.starts_with?(prefix) → bool
1923
+ class NativeStringStartsWith < Instruction
1924
+ attr_reader :native_string, :prefix
1925
+
1926
+ def initialize(native_string:, prefix:, result_var: nil)
1927
+ super(type: TypeChecker::Types::BOOL, result_var: result_var)
1928
+ @native_string = native_string
1929
+ @prefix = prefix # HIR value (String)
1930
+ end
1931
+ end
1932
+
1933
+ # Check if NativeString ends with suffix
1934
+ # ns.ends_with?(suffix) → bool
1935
+ class NativeStringEndsWith < Instruction
1936
+ attr_reader :native_string, :suffix
1937
+
1938
+ def initialize(native_string:, suffix:, result_var: nil)
1939
+ super(type: TypeChecker::Types::BOOL, result_var: result_var)
1940
+ @native_string = native_string
1941
+ @suffix = suffix # HIR value (String)
1942
+ end
1943
+ end
1944
+
1945
+ # Check if NativeString has valid UTF-8 encoding
1946
+ # ns.valid_encoding? → bool
1947
+ class NativeStringValidEncoding < Instruction
1948
+ attr_reader :native_string
1949
+
1950
+ def initialize(native_string:, result_var: nil)
1951
+ super(type: TypeChecker::Types::BOOL, result_var: result_var)
1952
+ @native_string = native_string
1953
+ end
1954
+ end
1955
+
1956
+ # Convert NativeString to Ruby String
1957
+ # ns.to_s → String
1958
+ class NativeStringToRuby < Instruction
1959
+ attr_reader :native_string
1960
+
1961
+ def initialize(native_string:, result_var: nil)
1962
+ super(type: TypeChecker::Types::STRING, result_var: result_var)
1963
+ @native_string = native_string
1964
+ end
1965
+ end
1966
+
1967
+ # Compare two NativeStrings
1968
+ # ns == other → bool
1969
+ class NativeStringCompare < Instruction
1970
+ attr_reader :native_string, :other
1971
+
1972
+ def initialize(native_string:, other:, result_var: nil)
1973
+ super(type: TypeChecker::Types::BOOL, result_var: result_var)
1974
+ @native_string = native_string
1975
+ @other = other # HIR value (NativeString)
1976
+ end
1977
+ end
1978
+
1979
+ # ========================================
1980
+ # NativeClass operations
1981
+ # Fixed-layout structs with unboxed numeric fields
1982
+ # ========================================
1983
+
1984
+ # Allocate a new NativeClass instance
1985
+ # Point.new → struct { double x; double y; }
1986
+ class NativeNew < Instruction
1987
+ attr_reader :class_type, :args
1988
+
1989
+ def initialize(class_type:, result_var: nil, args: [])
1990
+ super(type: class_type, result_var: result_var)
1991
+ @class_type = class_type # NativeClassType
1992
+ @args = args # Constructor arguments (for JVM <init>)
1993
+ end
1994
+ end
1995
+
1996
+ # Get field from NativeClass (unboxed)
1997
+ # point.x → double or i64
1998
+ class NativeFieldGet < Instruction
1999
+ attr_reader :object, :field_name, :class_type
2000
+
2001
+ def initialize(object:, field_name:, class_type:, result_var: nil)
2002
+ field_type_tag = class_type.llvm_field_type_tag(field_name)
2003
+ internal_type = case field_type_tag
2004
+ when :i64 then TypeChecker::Types::INTEGER
2005
+ when :double then TypeChecker::Types::FLOAT
2006
+ else TypeChecker::Types::UNTYPED
2007
+ end
2008
+ super(type: internal_type, result_var: result_var)
2009
+ @object = object # HIR value (the NativeClass instance)
2010
+ @field_name = field_name.to_sym
2011
+ @class_type = class_type # NativeClassType
2012
+ end
2013
+ end
2014
+
2015
+ # Set field in NativeClass
2016
+ # point.x = value
2017
+ class NativeFieldSet < Instruction
2018
+ attr_reader :object, :field_name, :value, :class_type
2019
+
2020
+ def initialize(object:, field_name:, value:, class_type:)
2021
+ field_type_tag = class_type.llvm_field_type_tag(field_name)
2022
+ internal_type = case field_type_tag
2023
+ when :i64 then TypeChecker::Types::INTEGER
2024
+ when :double then TypeChecker::Types::FLOAT
2025
+ else TypeChecker::Types::UNTYPED
2026
+ end
2027
+ super(type: internal_type)
2028
+ @object = object
2029
+ @field_name = field_name.to_sym
2030
+ @value = value
2031
+ @class_type = class_type
2032
+ end
2033
+ end
2034
+
2035
+ # Call a method on a NativeClass instance
2036
+ # Uses static dispatch (direct function call) instead of rb_funcallv
2037
+ # point.length_squared or point.add(other)
2038
+ class NativeMethodCall < Instruction
2039
+ attr_reader :receiver, :method_name, :args, :class_type, :method_sig, :owner_class
2040
+
2041
+ # @param receiver [Instruction] The NativeClass instance
2042
+ # @param method_name [Symbol] Method name
2043
+ # @param args [Array<Instruction>] Arguments (excluding self)
2044
+ # @param class_type [NativeClassType] Type of receiver
2045
+ # @param method_sig [NativeMethodType] Method signature
2046
+ # @param owner_class [NativeClassType] Class that implements the method (may be superclass)
2047
+ # @param result_var [String, nil] Result variable name
2048
+ def initialize(receiver:, method_name:, args:, class_type:,
2049
+ method_sig:, owner_class:, result_var: nil)
2050
+ # Determine return type from method signature
2051
+ return_type = if method_sig
2052
+ method_sig.return_type_as_internal
2053
+ else
2054
+ TypeChecker::Types::UNTYPED
2055
+ end
2056
+ super(type: return_type, result_var: result_var)
2057
+ @receiver = receiver
2058
+ @method_name = method_name.to_sym
2059
+ @args = args
2060
+ @class_type = class_type
2061
+ @method_sig = method_sig
2062
+ @owner_class = owner_class
2063
+ end
2064
+ end
2065
+
2066
+ # Direct call to an external C function
2067
+ # Bypasses Ruby method dispatch entirely
2068
+ # Used for @cfunc annotated methods
2069
+ #
2070
+ # Example:
2071
+ # # @cfunc "fast_sin" : (Float) -> Float
2072
+ # def self.sin: (Float) -> Float
2073
+ #
2074
+ # Generates direct C function call without rb_funcallv
2075
+ class CFuncCall < Instruction
2076
+ attr_reader :c_func_name, :args, :cfunc_type
2077
+
2078
+ # @param c_func_name [String] The C function name
2079
+ # @param args [Array<Instruction>] Arguments as HIR instructions
2080
+ # @param cfunc_type [CFuncType] The function type signature
2081
+ # @param result_var [String, nil] Result variable name
2082
+ def initialize(c_func_name:, args:, cfunc_type:, result_var: nil)
2083
+ return_type = cfunc_to_internal_type(cfunc_type.return_type)
2084
+ super(type: return_type, result_var: result_var)
2085
+ @c_func_name = c_func_name
2086
+ @args = args
2087
+ @cfunc_type = cfunc_type
2088
+ end
2089
+
2090
+ private
2091
+
2092
+ def cfunc_to_internal_type(type_sym)
2093
+ case type_sym
2094
+ when :Float then TypeChecker::Types::FLOAT
2095
+ when :Integer then TypeChecker::Types::INTEGER
2096
+ when :String then TypeChecker::Types::STRING
2097
+ when :Bool then TypeChecker::Types::BOOL
2098
+ when :void then TypeChecker::Types::NIL
2099
+ else TypeChecker::Types::UNTYPED
2100
+ end
2101
+ end
2102
+ end
2103
+
2104
+ # ========================================
2105
+ # Extern class operations
2106
+ # External C struct wrapper operations
2107
+ # ========================================
2108
+
2109
+ # Allocate an extern class wrapper (holds void* pointer)
2110
+ class ExternNew < Instruction
2111
+ attr_reader :extern_type
2112
+
2113
+ # @param extern_type [ExternClassType] The extern class type
2114
+ # @param result_var [String, nil] Result variable name
2115
+ def initialize(extern_type:, result_var: nil)
2116
+ super(type: extern_type, result_var: result_var)
2117
+ @extern_type = extern_type
2118
+ end
2119
+ end
2120
+
2121
+ # Call extern class constructor (singleton method returning opaque pointer)
2122
+ # Example: db = SQLiteDB.open("test.db")
2123
+ class ExternConstructorCall < Instruction
2124
+ attr_reader :extern_type, :c_func_name, :args, :method_sig
2125
+
2126
+ # @param extern_type [ExternClassType] The extern class type
2127
+ # @param c_func_name [String] C function name to call
2128
+ # @param args [Array<Instruction>] Arguments as HIR instructions
2129
+ # @param method_sig [ExternMethodType] Method signature
2130
+ # @param result_var [String, nil] Result variable name
2131
+ def initialize(extern_type:, c_func_name:, args:, method_sig:, result_var: nil)
2132
+ super(type: extern_type, result_var: result_var)
2133
+ @extern_type = extern_type
2134
+ @c_func_name = c_func_name
2135
+ @args = args
2136
+ @method_sig = method_sig
2137
+ end
2138
+ end
2139
+
2140
+ # Call extern class instance method (passes opaque pointer as first arg)
2141
+ # Example: results = db.execute("SELECT * FROM users")
2142
+ class ExternMethodCall < Instruction
2143
+ attr_reader :receiver, :c_func_name, :args, :extern_type, :method_sig
2144
+
2145
+ # @param receiver [Instruction, String] Receiver (extern class instance)
2146
+ # @param c_func_name [String] C function name to call
2147
+ # @param args [Array<Instruction>] Arguments (excluding opaque pointer)
2148
+ # @param extern_type [ExternClassType] The extern class type
2149
+ # @param method_sig [ExternMethodType] Method signature
2150
+ # @param result_var [String, nil] Result variable name
2151
+ def initialize(receiver:, c_func_name:, args:, extern_type:, method_sig:, result_var: nil)
2152
+ return_type = extern_to_internal_type(method_sig.return_type)
2153
+ super(type: return_type, result_var: result_var)
2154
+ @receiver = receiver
2155
+ @c_func_name = c_func_name
2156
+ @args = args
2157
+ @extern_type = extern_type
2158
+ @method_sig = method_sig
2159
+ end
2160
+
2161
+ private
2162
+
2163
+ def extern_to_internal_type(type_sym)
2164
+ case type_sym
2165
+ when :Float then TypeChecker::Types::FLOAT
2166
+ when :Integer then TypeChecker::Types::INTEGER
2167
+ when :String then TypeChecker::Types::STRING
2168
+ when :Bool then TypeChecker::Types::BOOL
2169
+ when :Array then TypeChecker::Types::ClassInstance.new(:Array)
2170
+ when :Hash then TypeChecker::Types::ClassInstance.new(:Hash)
2171
+ when :void then TypeChecker::Types::NIL
2172
+ when :ptr then TypeChecker::Types::UNTYPED
2173
+ else TypeChecker::Types::UNTYPED
2174
+ end
2175
+ end
2176
+ end
2177
+
2178
+ # ========================================
2179
+ # SIMD class operations
2180
+ # Fixed-size vector operations for @simd classes
2181
+ # ========================================
2182
+
2183
+ # Allocate a new SIMD class instance (zero-initialized vector)
2184
+ class SIMDNew < Instruction
2185
+ attr_reader :simd_type
2186
+
2187
+ # @param simd_type [SIMDClassType] The SIMD class type
2188
+ # @param result_var [String, nil] Result variable name
2189
+ def initialize(simd_type:, result_var: nil)
2190
+ super(type: simd_type, result_var: result_var)
2191
+ @simd_type = simd_type
2192
+ end
2193
+ end
2194
+
2195
+ # Get field from SIMD class (extract element from vector)
2196
+ class SIMDFieldGet < Instruction
2197
+ attr_reader :object, :field_name, :simd_type
2198
+
2199
+ # @param object [Instruction, String] SIMD class instance
2200
+ # @param field_name [Symbol] Field name (e.g., :x, :y, :z, :w)
2201
+ # @param simd_type [SIMDClassType] The SIMD class type
2202
+ # @param result_var [String, nil] Result variable name
2203
+ def initialize(object:, field_name:, simd_type:, result_var: nil)
2204
+ super(type: TypeChecker::Types::FLOAT, result_var: result_var)
2205
+ @object = object
2206
+ @field_name = field_name.to_sym
2207
+ @simd_type = simd_type
2208
+ end
2209
+ end
2210
+
2211
+ # Set field in SIMD class (insert element into vector)
2212
+ class SIMDFieldSet < Instruction
2213
+ attr_reader :object, :field_name, :value, :simd_type
2214
+
2215
+ # @param object [Instruction, String] SIMD class instance
2216
+ # @param field_name [Symbol] Field name (e.g., :x, :y, :z, :w)
2217
+ # @param value [Instruction, String] Value to set
2218
+ # @param simd_type [SIMDClassType] The SIMD class type
2219
+ def initialize(object:, field_name:, value:, simd_type:)
2220
+ super(type: TypeChecker::Types::FLOAT)
2221
+ @object = object
2222
+ @field_name = field_name.to_sym
2223
+ @value = value
2224
+ @simd_type = simd_type
2225
+ end
2226
+ end
2227
+
2228
+ # Call a method on SIMD class (vector arithmetic operation)
2229
+ class SIMDMethodCall < Instruction
2230
+ attr_reader :receiver, :method_name, :args, :simd_type, :method_sig
2231
+
2232
+ # @param receiver [Instruction, String] SIMD class instance
2233
+ # @param method_name [Symbol] Method name (e.g., :add, :dot, :scale)
2234
+ # @param args [Array<Instruction>] Arguments
2235
+ # @param simd_type [SIMDClassType] The SIMD class type
2236
+ # @param method_sig [NativeMethodType, nil] Method signature
2237
+ # @param result_var [String, nil] Result variable name
2238
+ def initialize(receiver:, method_name:, args:, simd_type:, method_sig: nil, result_var: nil)
2239
+ # Determine return type: scalar (Float64) or vector (Self)
2240
+ return_type = if method_sig&.return_type == :Float64
2241
+ TypeChecker::Types::FLOAT
2242
+ else
2243
+ simd_type
2244
+ end
2245
+ super(type: return_type, result_var: result_var)
2246
+ @receiver = receiver
2247
+ @method_name = method_name.to_sym
2248
+ @args = args
2249
+ @simd_type = simd_type
2250
+ @method_sig = method_sig
2251
+ end
2252
+ end
2253
+
2254
+ # ========================================
2255
+ # JSON operations (yyjson-based)
2256
+ # Direct JSON parsing to NativeClass without VALUE conversion overhead
2257
+ # ========================================
2258
+
2259
+ # Parse JSON string directly into a NativeClass
2260
+ # KonpeitoJSON.parse_as(json_string, User) → User (NativeClass)
2261
+ # Avoids VALUE conversion for unboxed fields (Integer, Float, Bool)
2262
+ class JSONParseAs < Instruction
2263
+ attr_reader :json_expr, :target_class
2264
+
2265
+ # @param json_expr [Instruction] HIR expression for JSON string
2266
+ # @param target_class [NativeClassType] Target NativeClass type
2267
+ # @param result_var [String, nil] Result variable name
2268
+ def initialize(json_expr:, target_class:, result_var: nil)
2269
+ super(type: target_class, result_var: result_var)
2270
+ @json_expr = json_expr
2271
+ @target_class = target_class
2272
+ end
2273
+ end
2274
+
2275
+ # Parse JSON array directly into a NativeArray
2276
+ # KonpeitoJSON.parse_array_as(json_string, User) → NativeArray[User]
2277
+ class JSONParseArrayAs < Instruction
2278
+ attr_reader :json_expr, :element_class
2279
+
2280
+ # @param json_expr [Instruction] HIR expression for JSON string
2281
+ # @param element_class [NativeClassType] Element NativeClass type
2282
+ # @param result_var [String, nil] Result variable name
2283
+ def initialize(json_expr:, element_class:, result_var: nil)
2284
+ array_type = TypeChecker::Types::NativeArrayType.new(element_class)
2285
+ super(type: array_type, result_var: result_var)
2286
+ @json_expr = json_expr
2287
+ @element_class = element_class
2288
+ end
2289
+ end
2290
+
2291
+ # ========================================
2292
+ # NativeHash operations
2293
+ # Generic hash with Robin Hood hashing
2294
+ # Memory layout: { buckets (ptr), size (i64), capacity (i64) }
2295
+ # Each bucket: { hash (i64), key (K), value (V), state (i8) }
2296
+ # ========================================
2297
+
2298
+ # Allocate a new NativeHash
2299
+ # NativeHashStringInteger.new(capacity) → NativeHash[String, Integer]
2300
+ class NativeHashAlloc < Instruction
2301
+ attr_reader :key_type, :value_type, :capacity
2302
+
2303
+ # @param key_type [Symbol] :String, :Symbol, or :Integer
2304
+ # @param value_type [Symbol, NativeClassType] Value type
2305
+ # @param capacity [Instruction, nil] Optional initial capacity
2306
+ def initialize(key_type:, value_type:, capacity: nil, result_var: nil)
2307
+ hash_type = TypeChecker::Types::NativeHashType.new(key_type, value_type)
2308
+ super(type: hash_type, result_var: result_var)
2309
+ @key_type = key_type
2310
+ @value_type = value_type
2311
+ @capacity = capacity # HIR value (nil for default 16)
2312
+ end
2313
+ end
2314
+
2315
+ # Get value from NativeHash
2316
+ # hash[key] → V | nil
2317
+ class NativeHashGet < Instruction
2318
+ attr_reader :hash_var, :key, :key_type, :value_type
2319
+
2320
+ def initialize(hash_var:, key:, key_type:, value_type:, result_var: nil)
2321
+ # Result is the value type (nullable)
2322
+ result_type = case value_type
2323
+ when :Integer then TypeChecker::Types::INTEGER
2324
+ when :Float then TypeChecker::Types::FLOAT
2325
+ when :Bool then TypeChecker::Types::BOOL
2326
+ when :String, :Object, :Array, :Hash then TypeChecker::Types::ClassInstance.new(value_type)
2327
+ else
2328
+ # NativeClass
2329
+ value_type
2330
+ end
2331
+ super(type: result_type, result_var: result_var)
2332
+ @hash_var = hash_var # HIR value
2333
+ @key = key # HIR value
2334
+ @key_type = key_type
2335
+ @value_type = value_type
2336
+ end
2337
+ end
2338
+
2339
+ # Set value in NativeHash
2340
+ # hash[key] = value → value
2341
+ class NativeHashSet < Instruction
2342
+ attr_reader :hash_var, :key, :value, :key_type, :value_type
2343
+
2344
+ def initialize(hash_var:, key:, value:, key_type:, value_type:, result_var: nil)
2345
+ result_type = case value_type
2346
+ when :Integer then TypeChecker::Types::INTEGER
2347
+ when :Float then TypeChecker::Types::FLOAT
2348
+ when :Bool then TypeChecker::Types::BOOL
2349
+ when :String, :Object, :Array, :Hash then TypeChecker::Types::ClassInstance.new(value_type)
2350
+ else
2351
+ value_type
2352
+ end
2353
+ super(type: result_type, result_var: result_var)
2354
+ @hash_var = hash_var
2355
+ @key = key
2356
+ @value = value
2357
+ @key_type = key_type
2358
+ @value_type = value_type
2359
+ end
2360
+ end
2361
+
2362
+ # Get size of NativeHash
2363
+ # hash.size → Integer
2364
+ class NativeHashSize < Instruction
2365
+ attr_reader :hash_var
2366
+
2367
+ def initialize(hash_var:, result_var: nil)
2368
+ super(type: TypeChecker::Types::INTEGER, result_var: result_var)
2369
+ @hash_var = hash_var
2370
+ end
2371
+ end
2372
+
2373
+ # Check if key exists in NativeHash
2374
+ # hash.has_key?(key) → bool
2375
+ class NativeHashHasKey < Instruction
2376
+ attr_reader :hash_var, :key, :key_type
2377
+
2378
+ def initialize(hash_var:, key:, key_type:, result_var: nil)
2379
+ super(type: TypeChecker::Types::BOOL, result_var: result_var)
2380
+ @hash_var = hash_var
2381
+ @key = key
2382
+ @key_type = key_type
2383
+ end
2384
+ end
2385
+
2386
+ # Delete key from NativeHash
2387
+ # hash.delete(key) → V | nil
2388
+ class NativeHashDelete < Instruction
2389
+ attr_reader :hash_var, :key, :key_type, :value_type
2390
+
2391
+ def initialize(hash_var:, key:, key_type:, value_type:, result_var: nil)
2392
+ result_type = case value_type
2393
+ when :Integer then TypeChecker::Types::INTEGER
2394
+ when :Float then TypeChecker::Types::FLOAT
2395
+ when :Bool then TypeChecker::Types::BOOL
2396
+ when :String, :Object, :Array, :Hash then TypeChecker::Types::ClassInstance.new(value_type)
2397
+ else
2398
+ value_type
2399
+ end
2400
+ super(type: result_type, result_var: result_var)
2401
+ @hash_var = hash_var
2402
+ @key = key
2403
+ @key_type = key_type
2404
+ @value_type = value_type
2405
+ end
2406
+ end
2407
+
2408
+ # Clear all entries from NativeHash
2409
+ # hash.clear → self
2410
+ class NativeHashClear < Instruction
2411
+ attr_reader :hash_var, :key_type, :value_type
2412
+
2413
+ def initialize(hash_var:, key_type:, value_type:, result_var: nil)
2414
+ hash_type = TypeChecker::Types::NativeHashType.new(key_type, value_type)
2415
+ super(type: hash_type, result_var: result_var)
2416
+ @hash_var = hash_var
2417
+ @key_type = key_type
2418
+ @value_type = value_type
2419
+ end
2420
+ end
2421
+
2422
+ # Get all keys from NativeHash
2423
+ # hash.keys → Array[K]
2424
+ class NativeHashKeys < Instruction
2425
+ attr_reader :hash_var, :key_type
2426
+
2427
+ def initialize(hash_var:, key_type:, result_var: nil)
2428
+ # Returns Array of keys (Ruby Array, not NativeArray)
2429
+ super(type: TypeChecker::Types::ClassInstance.new(:Array), result_var: result_var)
2430
+ @hash_var = hash_var
2431
+ @key_type = key_type
2432
+ end
2433
+ end
2434
+
2435
+ # Get all values from NativeHash
2436
+ # hash.values → Array[V]
2437
+ class NativeHashValues < Instruction
2438
+ attr_reader :hash_var, :key_type, :value_type
2439
+
2440
+ def initialize(hash_var:, key_type:, value_type:, result_var: nil)
2441
+ # Returns Array of values (Ruby Array)
2442
+ super(type: TypeChecker::Types::ClassInstance.new(:Array), result_var: result_var)
2443
+ @hash_var = hash_var
2444
+ @key_type = key_type
2445
+ @value_type = value_type
2446
+ end
2447
+ end
2448
+
2449
+ # Iterate over NativeHash entries
2450
+ # hash.each { |k, v| ... }
2451
+ class NativeHashEach < Instruction
2452
+ attr_reader :hash_var, :key_type, :value_type, :block_params, :block_body
2453
+
2454
+ def initialize(hash_var:, key_type:, value_type:, block_params:, block_body:, result_var: nil)
2455
+ hash_type = TypeChecker::Types::NativeHashType.new(key_type, value_type)
2456
+ super(type: hash_type, result_var: result_var)
2457
+ @hash_var = hash_var
2458
+ @key_type = key_type
2459
+ @value_type = value_type
2460
+ @block_params = block_params # Array of param names [key_var, value_var]
2461
+ @block_body = block_body # Array of BasicBlocks
2462
+ end
2463
+ end
2464
+ end
2465
+ end