rlsl 0.1.1 → 1.0.1

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 (91) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -0
  3. data/CHANGELOG.md +13 -2
  4. data/README.md +101 -26
  5. data/Rakefile +7 -0
  6. data/lib/rlsl/base_translator/call_parser.rb +79 -0
  7. data/lib/rlsl/base_translator/code_rewriter.rb +107 -0
  8. data/lib/rlsl/base_translator/code_scanner.rb +140 -0
  9. data/lib/rlsl/base_translator.rb +182 -64
  10. data/lib/rlsl/code_generator/math_prelude.rb +172 -0
  11. data/lib/rlsl/code_generator/ruby_wrapper_generator.rb +137 -0
  12. data/lib/rlsl/code_generator/shader_function_generator.rb +19 -0
  13. data/lib/rlsl/code_generator/template_context.rb +44 -0
  14. data/lib/rlsl/code_generator/uniform_struct_generator.rb +29 -0
  15. data/lib/rlsl/code_generator.rb +30 -202
  16. data/lib/rlsl/compiled_shader.rb +5 -13
  17. data/lib/rlsl/errors.rb +29 -0
  18. data/lib/rlsl/function_context.rb +31 -14
  19. data/lib/rlsl/glsl/translator.rb +35 -41
  20. data/lib/rlsl/msl/shader.rb +34 -46
  21. data/lib/rlsl/msl/translator.rb +38 -34
  22. data/lib/rlsl/msl/uniform_buffer_packer.rb +72 -0
  23. data/lib/rlsl/prism/ast_visitor/control_flow_visiting.rb +137 -0
  24. data/lib/rlsl/prism/ast_visitor/definition_visiting.rb +92 -0
  25. data/lib/rlsl/prism/ast_visitor/expression_visiting.rb +172 -0
  26. data/lib/rlsl/prism/ast_visitor/scope_context.rb +48 -0
  27. data/lib/rlsl/prism/ast_visitor/visitor_registry.rb +21 -0
  28. data/lib/rlsl/prism/ast_visitor.rb +100 -286
  29. data/lib/rlsl/prism/builtins/function_registry.rb +131 -0
  30. data/lib/rlsl/prism/builtins/operator_rules.rb +123 -0
  31. data/lib/rlsl/prism/builtins/swizzle_rules.rb +47 -0
  32. data/lib/rlsl/prism/builtins.rb +39 -148
  33. data/lib/rlsl/prism/compilation_unit.rb +7 -0
  34. data/lib/rlsl/prism/emitters/base_emitter/control_flow_emission.rb +126 -0
  35. data/lib/rlsl/prism/emitters/base_emitter/definition_emission.rb +134 -0
  36. data/lib/rlsl/prism/emitters/base_emitter/expression_emission.rb +108 -0
  37. data/lib/rlsl/prism/emitters/base_emitter/statement_emission.rb +95 -0
  38. data/lib/rlsl/prism/emitters/base_emitter.rb +120 -414
  39. data/lib/rlsl/prism/emitters/c_emitter.rb +165 -112
  40. data/lib/rlsl/prism/emitters/glsl_emitter.rb +63 -50
  41. data/lib/rlsl/prism/emitters/msl_emitter.rb +67 -52
  42. data/lib/rlsl/prism/emitters/target_emitter.rb +124 -0
  43. data/lib/rlsl/prism/emitters/target_profile.rb +34 -0
  44. data/lib/rlsl/prism/emitters/wgsl_emitter.rb +217 -58
  45. data/lib/rlsl/prism/errors.rb +9 -0
  46. data/lib/rlsl/prism/ir/control_flow.rb +85 -0
  47. data/lib/rlsl/prism/ir/definitions.rb +82 -0
  48. data/lib/rlsl/prism/ir/expressions.rb +201 -0
  49. data/lib/rlsl/prism/ir/node.rb +21 -0
  50. data/lib/rlsl/prism/ir/nodes.rb +4 -371
  51. data/lib/rlsl/prism/ir/traversal.rb +66 -0
  52. data/lib/rlsl/prism/mutation_analyzer.rb +30 -0
  53. data/lib/rlsl/prism/node_traversal.rb +41 -0
  54. data/lib/rlsl/prism/parameter_list.rb +46 -0
  55. data/lib/rlsl/prism/return_flow_validator.rb +73 -0
  56. data/lib/rlsl/prism/source_extractor/block_locator.rb +50 -0
  57. data/lib/rlsl/prism/source_extractor.rb +19 -137
  58. data/lib/rlsl/prism/source_unit/parser.rb +88 -0
  59. data/lib/rlsl/prism/source_unit.rb +42 -0
  60. data/lib/rlsl/prism/target_capability_validator.rb +110 -0
  61. data/lib/rlsl/prism/transpiler.rb +99 -59
  62. data/lib/rlsl/prism/type_inference/call_type_resolver.rb +59 -0
  63. data/lib/rlsl/prism/type_inference/call_validator.rb +75 -0
  64. data/lib/rlsl/prism/type_inference/collection_type_resolver.rb +106 -0
  65. data/lib/rlsl/prism/type_inference/control_flow_inferer.rb +147 -0
  66. data/lib/rlsl/prism/type_inference/definition_inferer.rb +56 -0
  67. data/lib/rlsl/prism/type_inference/expression_inferer.rb +96 -0
  68. data/lib/rlsl/prism/type_inference/field_type_resolver.rb +38 -0
  69. data/lib/rlsl/prism/type_inference/inferer_registry.rb +38 -0
  70. data/lib/rlsl/prism/type_inference/scope_stack.rb +47 -0
  71. data/lib/rlsl/prism/type_inference/type_environment.rb +112 -0
  72. data/lib/rlsl/prism/type_inference/type_shapes.rb +33 -0
  73. data/lib/rlsl/prism/type_inference.rb +120 -249
  74. data/lib/rlsl/runtime_shader.rb +47 -0
  75. data/lib/rlsl/shader_builder/build_service.rb +104 -0
  76. data/lib/rlsl/shader_builder/native_extension_compiler.rb +97 -0
  77. data/lib/rlsl/shader_builder/shader_definition.rb +68 -0
  78. data/lib/rlsl/shader_builder/source_resolver.rb +109 -0
  79. data/lib/rlsl/shader_builder.rb +60 -111
  80. data/lib/rlsl/shader_name.rb +18 -0
  81. data/lib/rlsl/types/catalog.rb +47 -0
  82. data/lib/rlsl/types/target_resolver.rb +15 -0
  83. data/lib/rlsl/types/type_spec.rb +167 -0
  84. data/lib/rlsl/types/value_normalizer.rb +86 -0
  85. data/lib/rlsl/types.rb +9 -31
  86. data/lib/rlsl/uniform_context.rb +22 -11
  87. data/lib/rlsl/version.rb +1 -1
  88. data/lib/rlsl/wgsl/translator.rb +46 -39
  89. data/lib/rlsl/wgsl/uniform_layout.rb +25 -0
  90. data/lib/rlsl.rb +38 -15
  91. metadata +76 -11
@@ -1,9 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "set"
4
+
5
+ require_relative "../ir/traversal"
6
+ require_relative "base_emitter/control_flow_emission"
7
+ require_relative "base_emitter/expression_emission"
8
+ require_relative "base_emitter/definition_emission"
9
+ require_relative "base_emitter/statement_emission"
10
+
3
11
  module RLSL
4
12
  module Prism
5
13
  module Emitters
6
14
  class BaseEmitter
15
+ include ControlFlowEmission
16
+ include ExpressionEmission
17
+ include DefinitionEmission
18
+ include StatementEmission
19
+
7
20
  PRECEDENCE = {
8
21
  "||" => 1,
9
22
  "&&" => 2,
@@ -13,63 +26,69 @@ module RLSL
13
26
  "*" => 6, "/" => 6, "%" => 6
14
27
  }.freeze
15
28
 
29
+ MULTILINE_NODES = [
30
+ IR::IfStatement,
31
+ IR::ForLoop,
32
+ IR::WhileLoop,
33
+ IR::FunctionDefinition
34
+ ].freeze
35
+
36
+ {
37
+ block: :emit_block,
38
+ var_decl: :emit_var_decl,
39
+ var_ref: :emit_var_ref,
40
+ literal: :emit_literal,
41
+ bool_literal: :emit_bool_literal,
42
+ binary_op: :emit_binary_op,
43
+ unary_op: :emit_unary_op,
44
+ func_call: :emit_func_call,
45
+ field_access: :emit_field_access,
46
+ swizzle: :emit_swizzle,
47
+ if_statement: :emit_if_statement,
48
+ ternary: :emit_ternary,
49
+ return: :emit_return,
50
+ assignment: :emit_assignment,
51
+ for_loop: :emit_for_loop,
52
+ while_loop: :emit_while_loop,
53
+ break: :emit_break,
54
+ constant: :emit_constant,
55
+ parenthesized: :emit_parenthesized,
56
+ function_definition: :emit_function_definition,
57
+ array_literal: :emit_array_literal,
58
+ array_index: :emit_array_index,
59
+ global_decl: :emit_global_decl,
60
+ multiple_assignment: :emit_multiple_assignment
61
+ }.each do |visit_name, emitter_name|
62
+ define_method(:"visit_#{visit_name}") do |node|
63
+ send(emitter_name, node)
64
+ end
65
+ end
66
+
16
67
  attr_reader :indent_level
17
68
 
18
69
  def initialize
19
70
  @indent_level = 0
71
+ @return_context_stack = [false]
72
+ @return_struct_name_stack = []
73
+ @return_type_stack = []
74
+ @temporary_index = 0
75
+ @emit_depth = 0
76
+ @occupied_names = Set.new
20
77
  end
21
78
 
22
79
  def emit(node, needs_return: false)
23
- case node
24
- when IR::Block
25
- emit_block(node, needs_return: needs_return)
26
- when IR::VarDecl
27
- emit_var_decl(node)
28
- when IR::VarRef
29
- emit_var_ref(node)
30
- when IR::Literal
31
- emit_literal(node)
32
- when IR::BoolLiteral
33
- emit_bool_literal(node)
34
- when IR::BinaryOp
35
- emit_binary_op(node)
36
- when IR::UnaryOp
37
- emit_unary_op(node)
38
- when IR::FuncCall
39
- emit_func_call(node)
40
- when IR::FieldAccess
41
- emit_field_access(node)
42
- when IR::Swizzle
43
- emit_swizzle(node)
44
- when IR::IfStatement
45
- emit_if_statement(node)
46
- when IR::Return
47
- emit_return(node)
48
- when IR::Assignment
49
- emit_assignment(node)
50
- when IR::ForLoop
51
- emit_for_loop(node)
52
- when IR::WhileLoop
53
- emit_while_loop(node)
54
- when IR::Break
55
- emit_break(node)
56
- when IR::Constant
57
- emit_constant(node)
58
- when IR::Parenthesized
59
- emit_parenthesized(node)
60
- when IR::FunctionDefinition
61
- emit_function_definition(node)
62
- when IR::ArrayLiteral
63
- emit_array_literal(node)
64
- when IR::ArrayIndex
65
- emit_array_index(node)
66
- when IR::GlobalDecl
67
- emit_global_decl(node)
68
- when IR::MultipleAssignment
69
- emit_multiple_assignment(node)
70
- else
71
- raise "Unknown IR node: #{node.class}"
80
+ @occupied_names = source_names(node) if @emit_depth.zero?
81
+ @emit_depth += 1
82
+ with_return_context(needs_return) do
83
+ return node.accept(self) if node.respond_to?(:accept)
84
+
85
+ raise RLSL::InternalError, "Unknown IR node: #{node.class}"
72
86
  end
87
+ rescue RLSL::Error => error
88
+ error.with_source_location(node.location) if node.respond_to?(:location)
89
+ raise
90
+ ensure
91
+ @emit_depth -= 1
73
92
  end
74
93
 
75
94
  protected
@@ -78,401 +97,88 @@ module RLSL
78
97
  type.to_s
79
98
  end
80
99
 
81
- def emit_block(node, needs_return: false)
82
- statements = node.statements
83
- return "" if statements.empty?
84
-
85
- if needs_return && statements.any?
86
- result = statements[0...-1].map { |stmt| emit_statement(stmt) }.join
87
- result + emit_with_return(statements.last)
88
- else
89
- statements.map { |stmt| emit_statement(stmt) }.join
90
- end
91
- end
92
-
93
- def emit_with_return(node)
94
- if node.is_a?(IR::IfStatement)
95
- emit_if_with_return(node)
96
- elsif node.is_a?(IR::Return)
97
- emit_statement(node)
98
- elsif node.is_a?(IR::FunctionDefinition) || node.is_a?(IR::GlobalDecl) ||
99
- node.is_a?(IR::MultipleAssignment)
100
- emit_statement(node)
101
- elsif node.is_a?(IR::ArrayLiteral)
102
- emit_tuple_return(node)
103
- else
104
- "#{indent}return #{emit(node)};\n"
105
- end
106
- end
107
-
108
- def emit_tuple_return(node)
109
- elements = node.elements.map { |elem| emit(elem) }.join(", ")
110
- "#{indent}return (#{current_return_struct_name}){#{elements}};\n"
111
- end
112
-
113
- def emit_if_with_return(node)
114
- condition = emit(node.condition)
115
- then_code = emit_branch_with_return(node.then_branch)
100
+ def format_number(value, type: nil)
101
+ return value.to_i.to_s if type == :int || value.is_a?(Integer)
116
102
 
117
- if node.else_branch
118
- if elsif_node?(node.else_branch)
119
- elsif_code = emit_elsif_with_return(node.else_branch)
120
- "#{indent}if (#{condition}) {\n#{then_code}#{indent}} #{elsif_code}\n"
121
- else
122
- else_code = emit_branch_with_return(node.else_branch)
123
- "#{indent}if (#{condition}) {\n#{then_code}#{indent}} else {\n#{else_code}#{indent}}\n"
124
- end
125
- else
126
- "#{indent}if (#{condition}) {\n#{then_code}#{indent}}\n"
127
- end
128
- end
129
-
130
- def emit_elsif_with_return(node)
131
- if_node = node.is_a?(IR::Block) ? node.statements.first : node
132
- condition = emit(if_node.condition)
133
- then_code = emit_branch_with_return(if_node.then_branch)
134
-
135
- if if_node.else_branch
136
- if elsif_node?(if_node.else_branch)
137
- elsif_code = emit_elsif_with_return(if_node.else_branch)
138
- "else if (#{condition}) {\n#{then_code}#{indent}} #{elsif_code}"
139
- else
140
- else_code = emit_branch_with_return(if_node.else_branch)
141
- "else if (#{condition}) {\n#{then_code}#{indent}} else {\n#{else_code}#{indent}}"
142
- end
103
+ if value.is_a?(Float)
104
+ formatted = value.to_s
105
+ formatted += ".0" unless formatted.include?(".")
106
+ formatted
143
107
  else
144
- "else if (#{condition}) {\n#{then_code}#{indent}}"
108
+ value.to_s
145
109
  end
146
110
  end
147
111
 
148
- def emit_branch_with_return(node)
149
- @indent_level += 1
150
- result = if node.is_a?(IR::Block)
151
- emit_block(node, needs_return: true)
152
- else
153
- emit_with_return(node)
154
- end
155
- @indent_level -= 1
156
- result
112
+ def indent
113
+ " " * @indent_level
157
114
  end
158
115
 
159
- def emit_statement(node, needs_return: false)
160
- if needs_return && !node.is_a?(IR::Return) && !node.is_a?(IR::IfStatement) &&
161
- !node.is_a?(IR::ForLoop) && !node.is_a?(IR::WhileLoop) && !node.is_a?(IR::VarDecl) &&
162
- !node.is_a?(IR::Assignment) && !node.is_a?(IR::FunctionDefinition) &&
163
- !node.is_a?(IR::GlobalDecl) && !node.is_a?(IR::MultipleAssignment)
164
- return "#{indent}return #{emit(node)};\n"
165
- end
166
-
116
+ def emit_with_precedence(node, parent_op, side: :left)
167
117
  code = emit(node)
168
- if node.is_a?(IR::IfStatement) || node.is_a?(IR::ForLoop) ||
169
- node.is_a?(IR::WhileLoop) || node.is_a?(IR::FunctionDefinition)
170
- "#{indent}#{code}\n"
171
- else
172
- "#{indent}#{code};\n"
173
- end
174
- end
175
-
176
- def emit_var_decl(node)
177
- type = type_name(node.type || :float)
178
- value = emit(node.initializer)
179
- "#{type} #{node.name} = #{value}"
180
- end
181
-
182
- def emit_var_ref(node)
183
- node.name.to_s
184
- end
185
-
186
- def emit_literal(node)
187
- format_number(node.value)
188
- end
189
-
190
- def emit_bool_literal(node)
191
- node.value.to_s
192
- end
193
-
194
- def emit_binary_op(node)
195
- left = emit_with_precedence(node.left, node.operator)
196
- right = emit_with_precedence(node.right, node.operator)
197
- "#{left} #{node.operator} #{right}"
198
- end
199
-
200
- def emit_unary_op(node)
201
- operand = emit(node.operand)
202
- "#{node.operator}#{operand}"
203
- end
204
-
205
- def emit_func_call(node)
206
- func_name = function_name(node.name)
207
- args = node.args.map { |arg| emit(arg) }.join(", ")
208
-
209
- if node.receiver
210
- receiver = emit(node.receiver)
211
- "#{func_name}(#{receiver}, #{args})"
212
- else
213
- "#{func_name}(#{args})"
214
- end
215
- end
216
-
217
- def emit_field_access(node)
218
- receiver = emit(node.receiver)
219
- "#{receiver}.#{node.field}"
220
- end
221
-
222
- def emit_swizzle(node)
223
- receiver = emit(node.receiver)
224
- "#{receiver}.#{node.components}"
225
- end
226
-
227
- def emit_if_statement(node)
228
- condition = emit(node.condition)
229
- then_code = emit_indented_block(node.then_branch)
230
-
231
- if node.else_branch
232
- if elsif_node?(node.else_branch)
233
- elsif_code = emit_elsif(node.else_branch)
234
- "if (#{condition}) {\n#{then_code}#{indent}} #{elsif_code}"
235
- else
236
- else_code = emit_indented_block(node.else_branch)
237
- "if (#{condition}) {\n#{then_code}#{indent}} else {\n#{else_code}#{indent}}"
238
- end
239
- else
240
- "if (#{condition}) {\n#{then_code}#{indent}}"
241
- end
242
- end
243
-
244
- def elsif_node?(node)
245
- return true if node.is_a?(IR::IfStatement)
246
- return false unless node.is_a?(IR::Block)
247
-
248
- node.statements.length == 1 && node.statements.first.is_a?(IR::IfStatement)
249
- end
118
+ return code unless node.is_a?(IR::BinaryOp)
250
119
 
251
- def emit_elsif(node)
252
- if_node = node.is_a?(IR::Block) ? node.statements.first : node
253
- condition = emit(if_node.condition)
254
- then_code = emit_indented_block(if_node.then_branch)
255
-
256
- if if_node.else_branch
257
- if elsif_node?(if_node.else_branch)
258
- elsif_code = emit_elsif(if_node.else_branch)
259
- "else if (#{condition}) {\n#{then_code}#{indent}} #{elsif_code}"
260
- else
261
- else_code = emit_indented_block(if_node.else_branch)
262
- "else if (#{condition}) {\n#{then_code}#{indent}} else {\n#{else_code}#{indent}}"
263
- end
264
- else
265
- "else if (#{condition}) {\n#{then_code}#{indent}}"
266
- end
120
+ node_prec = PRECEDENCE[node.operator] || 10
121
+ parent_prec = PRECEDENCE[parent_op] || 10
122
+ needs_parentheses = node_prec < parent_prec || (side == :right && node_prec == parent_prec)
123
+ needs_parentheses ? "(#{code})" : code
267
124
  end
268
125
 
269
- def emit_return(node)
270
- if node.expression
271
- "return #{emit(node.expression)}"
272
- else
273
- "return"
274
- end
126
+ def function_name(name)
127
+ name.to_s
275
128
  end
276
129
 
277
- def emit_assignment(node)
278
- target = emit(node.target)
279
- value = emit(node.value)
280
- "#{target} = #{value}"
130
+ def function_qualifier
131
+ "static inline "
281
132
  end
282
133
 
283
- def emit_for_loop(node)
284
- var = node.variable
285
- start_val = emit(node.range_start)
286
- end_val = emit(node.range_end)
287
- body = emit_indented_block(node.body)
288
-
289
- "for (int #{var} = #{start_val}; #{var} < #{end_val}; #{var}++) {\n#{body}#{indent}}"
134
+ def with_return_struct_name(name)
135
+ @return_struct_name_stack << name
136
+ yield
137
+ ensure
138
+ @return_struct_name_stack.pop
290
139
  end
291
140
 
292
- def emit_while_loop(node)
293
- condition = emit(node.condition)
294
- body = emit_indented_block(node.body)
295
-
296
- "while (#{condition}) {\n#{body}#{indent}}"
141
+ def with_return_type(type)
142
+ @return_type_stack << type
143
+ yield
144
+ ensure
145
+ @return_type_stack.pop
297
146
  end
298
147
 
299
- def emit_break(_node)
300
- "break"
148
+ def current_return_type
149
+ @return_type_stack.last
301
150
  end
302
151
 
303
- def emit_constant(node)
304
- case node.name
305
- when :PI
306
- "3.14159265358979323846"
307
- when :TAU
308
- "6.28318530717958647692"
309
- else
310
- node.name.to_s
311
- end
152
+ def with_return_context(enabled)
153
+ @return_context_stack << enabled
154
+ yield
155
+ ensure
156
+ @return_context_stack.pop
312
157
  end
313
158
 
314
- def emit_parenthesized(node)
315
- "(#{emit(node.expression)})"
159
+ def return_context?
160
+ @return_context_stack.last
316
161
  end
317
162
 
318
- def emit_function_definition(node)
319
- name = node.name
320
- params = node.params.map do |param|
321
- param_type = type_name(node.param_types[param] || :float)
322
- "#{param_type} #{param}"
323
- end.join(", ")
324
-
325
- if node.return_type.is_a?(Array)
326
- @current_return_struct_name = "#{name}_result"
327
- struct_def = emit_result_struct(name, node.return_type)
328
-
329
- body = emit_indented_block(node.body, needs_return: true)
330
-
331
- @current_return_struct_name = nil
332
- "#{struct_def}static inline #{name}_result #{name}(#{params}) {\n#{body}\n#{indent}}\n"
333
- else
334
- return_type = type_name(node.return_type || :float)
335
-
336
- body = emit_indented_block(node.body, needs_return: true)
163
+ def next_temporary_name(prefix)
164
+ loop do
165
+ name = :"_rlsl_#{prefix}#{@temporary_index}"
166
+ @temporary_index += 1
167
+ next if @occupied_names.include?(name)
337
168
 
338
- "static inline #{return_type} #{name}(#{params}) {\n#{body}\n#{indent}}\n"
169
+ @occupied_names.add(name)
170
+ return name
339
171
  end
340
172
  end
341
173
 
342
- def emit_result_struct(func_name, types)
343
- fields = types.each_with_index.map do |t, i|
344
- "#{type_name(t)} v#{i};"
345
- end.join(" ")
346
- "typedef struct { #{fields} } #{func_name}_result;\n"
347
- end
348
-
349
- def current_return_struct_name
350
- @current_return_struct_name || "result"
351
- end
352
-
353
- def emit_array_literal(node, for_static_init: false)
354
- elements = node.elements.map { |elem| emit_for_static_init(elem, for_static_init) }.join(", ")
355
- "{#{elements}}"
356
- end
357
-
358
- def emit_for_static_init(node, for_static_init)
359
- return emit(node) unless for_static_init
360
-
361
- case node
362
- when IR::FuncCall
363
- if %i[vec2 vec3 vec4].include?(node.name)
364
- args = node.args.map { |arg| emit_for_static_init(arg, true) }.join(", ")
365
- "{#{args}}"
366
- else
367
- emit(node)
174
+ def source_names(node)
175
+ IR::Traversal.each(node).filter_map do |current|
176
+ if current.respond_to?(:name)
177
+ current.name.to_sym
178
+ elsif current.is_a?(IR::ForLoop)
179
+ current.variable.to_sym
368
180
  end
369
- when IR::ArrayLiteral
370
- emit_array_literal(node, for_static_init: true)
371
- else
372
- emit(node)
373
- end
374
- end
375
-
376
- def emit_array_index(node)
377
- array = emit(node.array)
378
- index = if node.index.is_a?(IR::Literal) && node.index.value.to_i == node.index.value
379
- node.index.value.to_i.to_s
380
- else
381
- emit(node.index)
382
- end
383
- "#{array}[#{index}]"
384
- end
385
-
386
- def emit_global_decl(node)
387
- name = node.name
388
-
389
- if node.initializer.is_a?(IR::ArrayLiteral)
390
- elem_type = type_name(node.element_type || :float)
391
- size = node.array_size || node.initializer.elements.length
392
- elements = emit_array_literal(node.initializer, for_static_init: true)
393
-
394
- prefix = ""
395
- prefix += "static " if node.is_static
396
- prefix += "const " if node.is_const
397
-
398
- "#{prefix}#{elem_type} #{name}[#{size}] = #{elements}"
399
- else
400
- var_type = type_name(node.type || :float)
401
- value = if node.is_const
402
- emit_for_static_init(node.initializer, true)
403
- else
404
- emit(node.initializer)
405
- end
406
-
407
- prefix = ""
408
- prefix += "static " if node.is_static
409
- prefix += "const " if node.is_const
410
-
411
- "#{prefix}#{var_type} #{name} = #{value}"
412
- end
413
- end
414
-
415
- def emit_multiple_assignment(node)
416
- value_code = emit(node.value)
417
-
418
- if node.value.is_a?(IR::FuncCall)
419
- func_name = node.value.name
420
- struct_name = "#{func_name}_result"
421
-
422
- lines = []
423
- lines << "#{struct_name} _tmp_#{func_name} = #{value_code}"
424
- node.targets.each_with_index do |target, i|
425
- target_type = type_name(target.type || :float)
426
- lines << "#{target_type} #{target.name} = _tmp_#{func_name}.v#{i}"
427
- end
428
- lines.join(";\n#{indent}")
429
- else
430
- lines = []
431
- node.targets.each_with_index do |target, i|
432
- target_type = type_name(target.type || :float)
433
- lines << "#{target_type} #{target.name} = #{value_code}[#{i}]"
434
- end
435
- lines.join(";\n#{indent}")
436
- end
437
- end
438
-
439
- def format_number(value)
440
- if value.is_a?(Float)
441
- formatted = value.to_s
442
- formatted += ".0" unless formatted.include?(".")
443
- formatted
444
- else
445
- "#{value}.0"
446
- end
447
- end
448
-
449
- def indent
450
- " " * @indent_level
451
- end
452
-
453
- def emit_indented_block(node, needs_return: false)
454
- @indent_level += 1
455
- result = if node.is_a?(IR::Block)
456
- emit_block(node, needs_return: needs_return)
457
- else
458
- emit_statement(node, needs_return: needs_return)
459
- end
460
- @indent_level -= 1
461
- result
462
- end
463
-
464
- def emit_with_precedence(node, parent_op)
465
- code = emit(node)
466
- if node.is_a?(IR::BinaryOp)
467
- node_prec = PRECEDENCE[node.operator] || 10
468
- parent_prec = PRECEDENCE[parent_op] || 10
469
- return "(#{code})" if node_prec < parent_prec
470
- end
471
- code
472
- end
473
-
474
- def function_name(name)
475
- name.to_s
181
+ end.to_set
476
182
  end
477
183
  end
478
184
  end