rlsl 0.1.1 → 1.0.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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -1
  3. data/README.md +2 -0
  4. data/lib/rlsl/base_translator/call_parser.rb +68 -0
  5. data/lib/rlsl/base_translator/code_rewriter.rb +107 -0
  6. data/lib/rlsl/base_translator/code_scanner.rb +102 -0
  7. data/lib/rlsl/base_translator.rb +159 -63
  8. data/lib/rlsl/code_generator/math_prelude.rb +79 -0
  9. data/lib/rlsl/code_generator/ruby_wrapper_generator.rb +97 -0
  10. data/lib/rlsl/code_generator/shader_function_generator.rb +19 -0
  11. data/lib/rlsl/code_generator/template_context.rb +41 -0
  12. data/lib/rlsl/code_generator/uniform_struct_generator.rb +29 -0
  13. data/lib/rlsl/code_generator.rb +26 -201
  14. data/lib/rlsl/compiled_shader.rb +4 -12
  15. data/lib/rlsl/function_context.rb +31 -14
  16. data/lib/rlsl/glsl/translator.rb +19 -38
  17. data/lib/rlsl/msl/shader.rb +8 -38
  18. data/lib/rlsl/msl/translator.rb +19 -36
  19. data/lib/rlsl/msl/uniform_buffer_packer.rb +68 -0
  20. data/lib/rlsl/prism/ast_visitor/control_flow_visiting.rb +96 -0
  21. data/lib/rlsl/prism/ast_visitor/definition_visiting.rb +79 -0
  22. data/lib/rlsl/prism/ast_visitor/expression_visiting.rb +168 -0
  23. data/lib/rlsl/prism/ast_visitor/scope_context.rb +44 -0
  24. data/lib/rlsl/prism/ast_visitor/visitor_registry.rb +21 -0
  25. data/lib/rlsl/prism/ast_visitor.rb +54 -298
  26. data/lib/rlsl/prism/builtins/function_registry.rb +114 -0
  27. data/lib/rlsl/prism/builtins/operator_rules.rb +99 -0
  28. data/lib/rlsl/prism/builtins/swizzle_rules.rb +38 -0
  29. data/lib/rlsl/prism/builtins.rb +31 -148
  30. data/lib/rlsl/prism/compilation_unit.rb +7 -0
  31. data/lib/rlsl/prism/emitters/base_emitter/control_flow_emission.rb +83 -0
  32. data/lib/rlsl/prism/emitters/base_emitter/definition_emission.rb +104 -0
  33. data/lib/rlsl/prism/emitters/base_emitter/expression_emission.rb +92 -0
  34. data/lib/rlsl/prism/emitters/base_emitter/statement_emission.rb +89 -0
  35. data/lib/rlsl/prism/emitters/base_emitter.rb +68 -423
  36. data/lib/rlsl/prism/emitters/c_emitter.rb +78 -121
  37. data/lib/rlsl/prism/emitters/glsl_emitter.rb +30 -65
  38. data/lib/rlsl/prism/emitters/msl_emitter.rb +35 -62
  39. data/lib/rlsl/prism/emitters/target_emitter.rb +77 -0
  40. data/lib/rlsl/prism/emitters/target_profile.rb +34 -0
  41. data/lib/rlsl/prism/emitters/wgsl_emitter.rb +65 -61
  42. data/lib/rlsl/prism/ir/control_flow.rb +83 -0
  43. data/lib/rlsl/prism/ir/definitions.rb +67 -0
  44. data/lib/rlsl/prism/ir/expressions.rb +197 -0
  45. data/lib/rlsl/prism/ir/node.rb +21 -0
  46. data/lib/rlsl/prism/ir/nodes.rb +4 -371
  47. data/lib/rlsl/prism/ir/traversal.rb +62 -0
  48. data/lib/rlsl/prism/source_extractor/block_locator.rb +52 -0
  49. data/lib/rlsl/prism/source_extractor.rb +14 -133
  50. data/lib/rlsl/prism/source_unit/parser.rb +78 -0
  51. data/lib/rlsl/prism/source_unit.rb +42 -0
  52. data/lib/rlsl/prism/target_capability_validator.rb +85 -0
  53. data/lib/rlsl/prism/transpiler.rb +63 -60
  54. data/lib/rlsl/prism/type_inference/call_type_resolver.rb +35 -0
  55. data/lib/rlsl/prism/type_inference/call_validator.rb +71 -0
  56. data/lib/rlsl/prism/type_inference/collection_type_resolver.rb +80 -0
  57. data/lib/rlsl/prism/type_inference/control_flow_inferer.rb +66 -0
  58. data/lib/rlsl/prism/type_inference/definition_inferer.rb +41 -0
  59. data/lib/rlsl/prism/type_inference/expression_inferer.rb +92 -0
  60. data/lib/rlsl/prism/type_inference/field_type_resolver.rb +17 -0
  61. data/lib/rlsl/prism/type_inference/inferer_registry.rb +38 -0
  62. data/lib/rlsl/prism/type_inference/scope_stack.rb +47 -0
  63. data/lib/rlsl/prism/type_inference/type_environment.rb +112 -0
  64. data/lib/rlsl/prism/type_inference/type_shapes.rb +33 -0
  65. data/lib/rlsl/prism/type_inference.rb +114 -248
  66. data/lib/rlsl/runtime_shader.rb +47 -0
  67. data/lib/rlsl/shader_builder/build_service.rb +77 -0
  68. data/lib/rlsl/shader_builder/native_extension_compiler.rb +71 -0
  69. data/lib/rlsl/shader_builder/shader_definition.rb +68 -0
  70. data/lib/rlsl/shader_builder/source_resolver.rb +91 -0
  71. data/lib/rlsl/shader_builder.rb +22 -113
  72. data/lib/rlsl/types/catalog.rb +47 -0
  73. data/lib/rlsl/types/target_resolver.rb +15 -0
  74. data/lib/rlsl/types/type_spec.rb +167 -0
  75. data/lib/rlsl/types/value_normalizer.rb +81 -0
  76. data/lib/rlsl/types.rb +11 -29
  77. data/lib/rlsl/uniform_context.rb +6 -12
  78. data/lib/rlsl/version.rb +1 -1
  79. data/lib/rlsl/wgsl/translator.rb +23 -39
  80. data/lib/rlsl.rb +14 -12
  81. metadata +55 -2
@@ -1,195 +1,78 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "builtins/function_registry"
4
+ require_relative "builtins/operator_rules"
5
+ require_relative "builtins/swizzle_rules"
6
+
3
7
  module RLSL
4
8
  module Prism
5
9
  module Builtins
6
- FUNCTIONS = {
7
- vec2: { args: %i[any any], returns: :vec2, variadic: true, min_args: 1 },
8
- vec3: { args: %i[any any any], returns: :vec3, variadic: true, min_args: 1 },
9
- vec4: { args: %i[any any any any], returns: :vec4, variadic: true, min_args: 1 },
10
-
11
- mat2: { args: %i[any any any any], returns: :mat2, variadic: true, min_args: 1 },
12
- mat3: { args: %i[any any any any any any any any any], returns: :mat3, variadic: true, min_args: 1 },
13
- mat4: { args: %i[any any any any any any any any any any any any any any any any], returns: :mat4, variadic: true, min_args: 1 },
14
-
15
- sin: { args: [:float], returns: :float },
16
- cos: { args: [:float], returns: :float },
17
- tan: { args: [:float], returns: :float },
18
- asin: { args: [:float], returns: :float },
19
- acos: { args: [:float], returns: :float },
20
- atan: { args: %i[float float], returns: :float, variadic: true, min_args: 1 },
21
- atan2: { args: %i[float float], returns: :float },
22
-
23
- pow: { args: %i[float float], returns: :float },
24
- exp: { args: [:float], returns: :float },
25
- log: { args: [:float], returns: :float },
26
- sqrt: { args: [:any], returns: :same },
27
-
28
- abs: { args: [:any], returns: :same },
29
- sign: { args: [:any], returns: :same },
30
- floor: { args: [:any], returns: :same },
31
- ceil: { args: [:any], returns: :same },
32
- fract: { args: [:any], returns: :same },
33
- mod: { args: %i[any float], returns: :first },
34
- min: { args: %i[any any], returns: :first },
35
- max: { args: %i[any any], returns: :first },
36
- clamp: { args: %i[any any any], returns: :first },
37
- mix: { args: %i[any any float], returns: :first },
38
- step: { args: %i[float any], returns: :second },
39
- smoothstep: { args: %i[float float any], returns: :third },
40
-
41
- length: { args: [:any], returns: :float },
42
- distance: { args: %i[any any], returns: :float },
43
- dot: { args: %i[any any], returns: :float },
44
- cross: { args: %i[vec3 vec3], returns: :vec3 },
45
- normalize: { args: [:any], returns: :same },
46
- reflect: { args: %i[any any], returns: :first },
47
- refract: { args: %i[any any float], returns: :first },
48
-
49
- hash21: { args: [:vec2], returns: :float },
50
- hash22: { args: [:vec2], returns: :vec2 },
51
-
52
- lessThan: { args: %i[any any], returns: :bool },
53
- lessThanEqual: { args: %i[any any], returns: :bool },
54
- greaterThan: { args: %i[any any], returns: :bool },
55
- greaterThanEqual: { args: %i[any any], returns: :bool },
56
- equal: { args: %i[any any], returns: :bool },
57
- notEqual: { args: %i[any any], returns: :bool },
58
-
59
- inverse: { args: [:any], returns: :same },
60
- transpose: { args: [:any], returns: :same },
61
- determinant: { args: [:any], returns: :float },
62
-
63
- texture2D: { args: %i[sampler2D vec2], returns: :vec4 },
64
- texture: { args: %i[sampler2D vec2], returns: :vec4 },
65
- textureLod: { args: %i[sampler2D vec2 float], returns: :vec4 }
66
- }.freeze
67
-
68
- BINARY_OPERATORS = {
69
- "+" => :arithmetic,
70
- "-" => :arithmetic,
71
- "*" => :arithmetic,
72
- "/" => :arithmetic,
73
- "%" => :arithmetic,
74
-
75
- "==" => :comparison,
76
- "!=" => :comparison,
77
- "<" => :comparison,
78
- ">" => :comparison,
79
- "<=" => :comparison,
80
- ">=" => :comparison,
81
-
82
- "&&" => :logical,
83
- "||" => :logical
84
- }.freeze
85
-
86
- UNARY_OPERATORS = {
87
- "-" => :negate,
88
- "!" => :not
89
- }.freeze
90
-
91
- SWIZZLE_COMPONENTS = {
92
- "x" => 0, "r" => 0, "s" => 0,
93
- "y" => 1, "g" => 1, "t" => 1,
94
- "z" => 2, "b" => 2, "p" => 2,
95
- "w" => 3, "a" => 3, "q" => 3
96
- }.freeze
97
-
98
- SINGLE_COMPONENT_FIELDS = %w[x y z w r g b a s t p q].freeze
99
-
100
- SWIZZLE_PATTERNS = /\A[xyzwrgba]{2,4}\z/
10
+ FUNCTIONS = FunctionRegistry::FUNCTIONS
11
+ BINARY_OPERATORS = OperatorRules::BINARY_OPERATORS
12
+ UNARY_OPERATORS = OperatorRules::UNARY_OPERATORS
13
+ SWIZZLE_COMPONENTS = SwizzleRules::SWIZZLE_COMPONENTS
14
+ SINGLE_COMPONENT_FIELDS = SwizzleRules::SINGLE_COMPONENT_FIELDS
15
+ SWIZZLE_PATTERNS = SwizzleRules::SWIZZLE_PATTERNS
101
16
 
102
17
  class << self
103
18
  def function?(name)
104
- FUNCTIONS.key?(name.to_sym)
19
+ FunctionRegistry.function?(name)
105
20
  end
106
21
 
107
22
  def function_signature(name)
108
- FUNCTIONS[name.to_sym]
23
+ FunctionRegistry.function_signature(name)
24
+ end
25
+
26
+ def supported_on_target?(name, target)
27
+ FunctionRegistry.supported_on_target?(name, target)
28
+ end
29
+
30
+ def explicit_types(name)
31
+ FunctionRegistry.explicit_types(name)
109
32
  end
110
33
 
111
34
  def binary_operator?(op)
112
- BINARY_OPERATORS.key?(op.to_s)
35
+ OperatorRules.binary_operator?(op)
113
36
  end
114
37
 
115
38
  def unary_operator?(op)
116
- UNARY_OPERATORS.key?(op.to_s)
39
+ OperatorRules.unary_operator?(op)
117
40
  end
118
41
 
119
42
  def single_component_field?(name)
120
- SINGLE_COMPONENT_FIELDS.include?(name.to_s)
43
+ SwizzleRules.single_component_field?(name)
121
44
  end
122
45
 
123
46
  def swizzle?(name)
124
- name.to_s.match?(SWIZZLE_PATTERNS)
47
+ SwizzleRules.swizzle?(name)
125
48
  end
126
49
 
127
50
  def swizzle_type(components)
128
- case components.length
129
- when 2 then :vec2
130
- when 3 then :vec3
131
- when 4 then :vec4
132
- else :float
133
- end
51
+ SwizzleRules.swizzle_type(components)
134
52
  end
135
53
 
136
54
  def resolve_return_type(rule, arg_types)
137
- case rule
138
- when :same then arg_types.first
139
- when :first then arg_types.first
140
- when :second then arg_types[1]
141
- when :third then arg_types[2]
142
- when Symbol then rule
143
- end
55
+ FunctionRegistry.resolve_return_type(rule, arg_types)
144
56
  end
145
57
 
146
58
  def binary_op_result_type(op, left_type, right_type)
147
- op_kind = BINARY_OPERATORS[op.to_s]
148
-
149
- case op_kind
150
- when :comparison, :logical
151
- :bool
152
- when :arithmetic
153
- if matrix_type?(left_type) && vector_type?(right_type)
154
- matrix_vector_result(left_type)
155
- elsif vector_type?(left_type) && matrix_type?(right_type)
156
- matrix_vector_result(right_type)
157
- elsif matrix_type?(left_type) && matrix_type?(right_type)
158
- left_type
159
- elsif matrix_type?(left_type) && scalar_type?(right_type)
160
- left_type
161
- elsif scalar_type?(left_type) && matrix_type?(right_type)
162
- right_type
163
- elsif vector_type?(left_type) && vector_type?(right_type)
164
- left_type
165
- elsif vector_type?(left_type) && scalar_type?(right_type)
166
- left_type
167
- elsif scalar_type?(left_type) && vector_type?(right_type)
168
- right_type
169
- else
170
- :float
171
- end
172
- end
59
+ OperatorRules.binary_op_result_type(op, left_type, right_type)
173
60
  end
174
61
 
175
62
  def vector_type?(type)
176
- %i[vec2 vec3 vec4].include?(type)
63
+ OperatorRules.vector_type?(type)
177
64
  end
178
65
 
179
66
  def matrix_type?(type)
180
- %i[mat2 mat3 mat4].include?(type)
67
+ OperatorRules.matrix_type?(type)
181
68
  end
182
69
 
183
70
  def scalar_type?(type)
184
- %i[float int].include?(type)
71
+ OperatorRules.scalar_type?(type)
185
72
  end
186
73
 
187
74
  def matrix_vector_result(matrix_type)
188
- case matrix_type
189
- when :mat2 then :vec2
190
- when :mat3 then :vec3
191
- when :mat4 then :vec4
192
- end
75
+ OperatorRules.matrix_vector_result(matrix_type)
193
76
  end
194
77
  end
195
78
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RLSL
4
+ module Prism
5
+ CompilationUnit = Struct.new(:source_unit, :ir, keyword_init: true)
6
+ end
7
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RLSL
4
+ module Prism
5
+ module Emitters
6
+ class BaseEmitter
7
+ module ControlFlowEmission
8
+ def emit_tuple_return(node)
9
+ elements = node.elements.map { |elem| emit(elem) }.join(", ")
10
+ "#{indent}return (#{current_return_struct_name}){#{elements}};\n"
11
+ end
12
+
13
+ def emit_if_statement(node)
14
+ emit_conditional(node, needs_return: return_context?)
15
+ end
16
+
17
+ def emit_conditional(node, needs_return:)
18
+ condition = emit(node.condition)
19
+ then_code = emit_branch(node.then_branch, needs_return: needs_return)
20
+
21
+ return "#{indent}if (#{condition}) {\n#{then_code}#{indent}}#{needs_return ? "\n" : ""}" unless node.else_branch
22
+
23
+ if elsif_node?(node.else_branch)
24
+ elsif_code = emit_elsif(node.else_branch, needs_return: needs_return)
25
+ "#{indent}if (#{condition}) {\n#{then_code}#{indent}} #{elsif_code}#{needs_return ? "\n" : ""}"
26
+ else
27
+ else_code = emit_branch(node.else_branch, needs_return: needs_return)
28
+ "#{indent}if (#{condition}) {\n#{then_code}#{indent}} else {\n#{else_code}#{indent}}#{needs_return ? "\n" : ""}"
29
+ end
30
+ end
31
+
32
+ def emit_elsif(node, needs_return: false)
33
+ if_node = node.is_a?(IR::Block) ? node.statements.first : node
34
+ condition = emit(if_node.condition)
35
+ then_code = emit_branch(if_node.then_branch, needs_return: needs_return)
36
+
37
+ return "else if (#{condition}) {\n#{then_code}#{indent}}" unless if_node.else_branch
38
+
39
+ if elsif_node?(if_node.else_branch)
40
+ elsif_code = emit_elsif(if_node.else_branch, needs_return: needs_return)
41
+ "else if (#{condition}) {\n#{then_code}#{indent}} #{elsif_code}"
42
+ else
43
+ else_code = emit_branch(if_node.else_branch, needs_return: needs_return)
44
+ "else if (#{condition}) {\n#{then_code}#{indent}} else {\n#{else_code}#{indent}}"
45
+ end
46
+ end
47
+
48
+ def elsif_node?(node)
49
+ return true if node.is_a?(IR::IfStatement)
50
+ return false unless node.is_a?(IR::Block)
51
+
52
+ node.statements.length == 1 && node.statements.first.is_a?(IR::IfStatement)
53
+ end
54
+
55
+ def emit_return(node)
56
+ node.expression ? "return #{emit(node.expression)}" : "return"
57
+ end
58
+
59
+ def emit_for_loop(node)
60
+ var = node.variable
61
+ start_val = emit(node.range_start)
62
+ end_val = emit(node.range_end)
63
+ body = emit_indented_block(node.body)
64
+
65
+ "for (int #{var} = #{start_val}; #{var} < #{end_val}; #{var}++) {\n#{body}#{indent}}"
66
+ end
67
+
68
+ def emit_while_loop(node)
69
+ condition = emit(node.condition)
70
+ body = emit_indented_block(node.body)
71
+
72
+ "while (#{condition}) {\n#{body}#{indent}}"
73
+ end
74
+
75
+ def emit_break(_node)
76
+ "break"
77
+ end
78
+
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RLSL
4
+ module Prism
5
+ module Emitters
6
+ class BaseEmitter
7
+ module DefinitionEmission
8
+ def emit_function_definition(node)
9
+ name = node.name
10
+ params = node.params.map do |param|
11
+ "#{type_name(node.param_types[param] || :float)} #{param}"
12
+ end.join(", ")
13
+
14
+ if node.return_type.is_a?(Array)
15
+ @current_return_struct_name = "#{name}_result"
16
+ struct_def = emit_result_struct(name, node.return_type)
17
+ body = emit_indented_block(node.body, needs_return: true)
18
+ @current_return_struct_name = nil
19
+ "#{struct_def}static inline #{name}_result #{name}(#{params}) {\n#{body}\n#{indent}}\n"
20
+ else
21
+ body = emit_indented_block(node.body, needs_return: true)
22
+ "static inline #{type_name(node.return_type || :float)} #{name}(#{params}) {\n#{body}\n#{indent}}\n"
23
+ end
24
+ end
25
+
26
+ def emit_result_struct(func_name, types)
27
+ fields = types.each_with_index.map { |type, index| "#{type_name(type)} v#{index};" }.join(" ")
28
+ "typedef struct { #{fields} } #{func_name}_result;\n"
29
+ end
30
+
31
+ def current_return_struct_name
32
+ @current_return_struct_name || "result"
33
+ end
34
+
35
+ def emit_array_literal(node, for_static_init: false)
36
+ elements = node.elements.map { |elem| emit_for_static_init(elem, for_static_init) }.join(", ")
37
+ "{#{elements}}"
38
+ end
39
+
40
+ def emit_for_static_init(node, for_static_init)
41
+ return emit(node) unless for_static_init
42
+
43
+ case node
44
+ when IR::FuncCall
45
+ if %i[vec2 vec3 vec4].include?(node.name)
46
+ args = node.args.map { |arg| emit_for_static_init(arg, true) }.join(", ")
47
+ "{#{args}}"
48
+ else
49
+ emit(node)
50
+ end
51
+ when IR::ArrayLiteral
52
+ emit_array_literal(node, for_static_init: true)
53
+ else
54
+ emit(node)
55
+ end
56
+ end
57
+
58
+ def emit_global_decl(node)
59
+ prefix = ""
60
+ prefix += "static " if node.is_static
61
+ prefix += "const " if node.is_const
62
+
63
+ if node.initializer.is_a?(IR::ArrayLiteral)
64
+ elem_type = type_name(node.element_type || :float)
65
+ size = node.array_size || node.initializer.elements.length
66
+ elements = emit_array_literal(node.initializer, for_static_init: true)
67
+ "#{prefix}#{elem_type} #{node.name}[#{size}] = #{elements}"
68
+ else
69
+ value = node.is_const ? emit_for_static_init(node.initializer, true) : emit(node.initializer)
70
+ "#{prefix}#{type_name(node.type || :float)} #{node.name} = #{value}"
71
+ end
72
+ end
73
+
74
+ def emit_multiple_assignment(node)
75
+ value_code = emit(node.value)
76
+
77
+ if node.value.is_a?(IR::FuncCall)
78
+ emit_multi_return_assignment(node, value_code)
79
+ else
80
+ emit_indexed_assignment(node, value_code)
81
+ end
82
+ end
83
+
84
+ private
85
+
86
+ def emit_multi_return_assignment(node, value_code)
87
+ func_name = node.value.name
88
+ lines = ["#{func_name}_result _tmp_#{func_name} = #{value_code}"]
89
+ node.targets.each_with_index do |target, index|
90
+ lines << "#{type_name(target.type || :float)} #{target.name} = _tmp_#{func_name}.v#{index}"
91
+ end
92
+ lines.join(";\n#{indent}")
93
+ end
94
+
95
+ def emit_indexed_assignment(node, value_code)
96
+ node.targets.each_with_index.map do |target, index|
97
+ "#{type_name(target.type || :float)} #{target.name} = #{value_code}[#{index}]"
98
+ end.join(";\n#{indent}")
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RLSL
4
+ module Prism
5
+ module Emitters
6
+ class BaseEmitter
7
+ module ExpressionEmission
8
+ def emit_var_decl(node)
9
+ type = type_name(node.type || :float)
10
+ value = emit(node.initializer)
11
+ "#{type} #{node.name} = #{value}"
12
+ end
13
+
14
+ def emit_var_ref(node)
15
+ node.name.to_s
16
+ end
17
+
18
+ def emit_literal(node)
19
+ format_number(node.value)
20
+ end
21
+
22
+ def emit_bool_literal(node)
23
+ node.value.to_s
24
+ end
25
+
26
+ def emit_binary_op(node)
27
+ left = emit_with_precedence(node.left, node.operator)
28
+ right = emit_with_precedence(node.right, node.operator)
29
+ "#{left} #{node.operator} #{right}"
30
+ end
31
+
32
+ def emit_unary_op(node)
33
+ "#{node.operator}#{emit(node.operand)}"
34
+ end
35
+
36
+ def emit_func_call(node)
37
+ func_name = function_name(node.name)
38
+ args = node.args.map { |arg| emit(arg) }.join(", ")
39
+
40
+ if node.receiver
41
+ receiver = emit(node.receiver)
42
+ "#{func_name}(#{receiver}, #{args})"
43
+ else
44
+ "#{func_name}(#{args})"
45
+ end
46
+ end
47
+
48
+ def emit_field_access(node)
49
+ "#{emit(node.receiver)}.#{node.field}"
50
+ end
51
+
52
+ def emit_swizzle(node)
53
+ "#{emit(node.receiver)}.#{node.components}"
54
+ end
55
+
56
+ def emit_ternary(node)
57
+ "(#{emit(node.condition)} ? #{emit(node.then_expr)} : #{emit(node.else_expr)})"
58
+ end
59
+
60
+ def emit_assignment(node)
61
+ "#{emit(node.target)} = #{emit(node.value)}"
62
+ end
63
+
64
+ def emit_constant(node)
65
+ case node.name
66
+ when :PI
67
+ "3.14159265358979323846"
68
+ when :TAU
69
+ "6.28318530717958647692"
70
+ else
71
+ node.name.to_s
72
+ end
73
+ end
74
+
75
+ def emit_parenthesized(node)
76
+ "(#{emit(node.expression)})"
77
+ end
78
+
79
+ def emit_array_index(node)
80
+ array = emit(node.array)
81
+ index = if node.index.is_a?(IR::Literal) && node.index.value.to_i == node.index.value
82
+ node.index.value.to_i.to_s
83
+ else
84
+ emit(node.index)
85
+ end
86
+ "#{array}[#{index}]"
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RLSL
4
+ module Prism
5
+ module Emitters
6
+ class BaseEmitter
7
+ module StatementEmission
8
+ def emit_block(node, needs_return = nil)
9
+ statements = node.statements
10
+ return "" if statements.empty?
11
+
12
+ emit_statements(statements, returning: needs_return.nil? ? return_context? : needs_return)
13
+ end
14
+
15
+ def emit_statements(statements, returning:)
16
+ return statements.map { |statement| emit_statement(statement) }.join unless returning
17
+
18
+ leading = statements[0...-1].map { |statement| emit_statement(statement) }.join
19
+ leading + emit_terminal_statement(statements.last)
20
+ end
21
+
22
+ def emit_statement(node, needs_return: false)
23
+ return emit_terminal_statement(node) if needs_return
24
+
25
+ "#{indent}#{emit(node)}#{statement_terminator(node)}"
26
+ end
27
+
28
+ def emit_terminal_statement(node)
29
+ return emit(node, needs_return: true) if node.is_a?(IR::IfStatement)
30
+ return emit_statement(node) if terminal_passthrough_node?(node)
31
+ return emit_tuple_return(node) if node.is_a?(IR::ArrayLiteral)
32
+
33
+ "#{indent}return #{emit(node)};\n"
34
+ end
35
+
36
+ def emit_branch(node, needs_return:)
37
+ with_indent do
38
+ if node.is_a?(IR::Block)
39
+ emit(node, needs_return: needs_return)
40
+ else
41
+ emit_statement(node, needs_return: needs_return)
42
+ end
43
+ end
44
+ end
45
+
46
+ def emit_indented_block(node, needs_return: false)
47
+ with_indent do
48
+ if node.is_a?(IR::Block)
49
+ emit(node, needs_return: needs_return)
50
+ else
51
+ emit_statement(node, needs_return: needs_return)
52
+ end
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def statement_terminator(node)
59
+ multiline_node?(node) ? "\n" : ";\n"
60
+ end
61
+
62
+ def multiline_node?(node)
63
+ MULTILINE_NODES.any? { |klass| node.is_a?(klass) }
64
+ end
65
+
66
+ def terminal_passthrough_node?(node)
67
+ [
68
+ IR::Return,
69
+ IR::VarDecl,
70
+ IR::Assignment,
71
+ IR::ForLoop,
72
+ IR::WhileLoop,
73
+ IR::FunctionDefinition,
74
+ IR::GlobalDecl,
75
+ IR::MultipleAssignment
76
+ ].any? { |klass| node.is_a?(klass) }
77
+ end
78
+
79
+ def with_indent
80
+ @indent_level += 1
81
+ yield
82
+ ensure
83
+ @indent_level -= 1
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end