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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -1
- data/README.md +2 -0
- data/lib/rlsl/base_translator/call_parser.rb +68 -0
- data/lib/rlsl/base_translator/code_rewriter.rb +107 -0
- data/lib/rlsl/base_translator/code_scanner.rb +102 -0
- data/lib/rlsl/base_translator.rb +159 -63
- data/lib/rlsl/code_generator/math_prelude.rb +79 -0
- data/lib/rlsl/code_generator/ruby_wrapper_generator.rb +97 -0
- data/lib/rlsl/code_generator/shader_function_generator.rb +19 -0
- data/lib/rlsl/code_generator/template_context.rb +41 -0
- data/lib/rlsl/code_generator/uniform_struct_generator.rb +29 -0
- data/lib/rlsl/code_generator.rb +26 -201
- data/lib/rlsl/compiled_shader.rb +4 -12
- data/lib/rlsl/function_context.rb +31 -14
- data/lib/rlsl/glsl/translator.rb +19 -38
- data/lib/rlsl/msl/shader.rb +8 -38
- data/lib/rlsl/msl/translator.rb +19 -36
- data/lib/rlsl/msl/uniform_buffer_packer.rb +68 -0
- data/lib/rlsl/prism/ast_visitor/control_flow_visiting.rb +96 -0
- data/lib/rlsl/prism/ast_visitor/definition_visiting.rb +79 -0
- data/lib/rlsl/prism/ast_visitor/expression_visiting.rb +168 -0
- data/lib/rlsl/prism/ast_visitor/scope_context.rb +44 -0
- data/lib/rlsl/prism/ast_visitor/visitor_registry.rb +21 -0
- data/lib/rlsl/prism/ast_visitor.rb +54 -298
- data/lib/rlsl/prism/builtins/function_registry.rb +114 -0
- data/lib/rlsl/prism/builtins/operator_rules.rb +99 -0
- data/lib/rlsl/prism/builtins/swizzle_rules.rb +38 -0
- data/lib/rlsl/prism/builtins.rb +31 -148
- data/lib/rlsl/prism/compilation_unit.rb +7 -0
- data/lib/rlsl/prism/emitters/base_emitter/control_flow_emission.rb +83 -0
- data/lib/rlsl/prism/emitters/base_emitter/definition_emission.rb +104 -0
- data/lib/rlsl/prism/emitters/base_emitter/expression_emission.rb +92 -0
- data/lib/rlsl/prism/emitters/base_emitter/statement_emission.rb +89 -0
- data/lib/rlsl/prism/emitters/base_emitter.rb +68 -423
- data/lib/rlsl/prism/emitters/c_emitter.rb +78 -121
- data/lib/rlsl/prism/emitters/glsl_emitter.rb +30 -65
- data/lib/rlsl/prism/emitters/msl_emitter.rb +35 -62
- data/lib/rlsl/prism/emitters/target_emitter.rb +77 -0
- data/lib/rlsl/prism/emitters/target_profile.rb +34 -0
- data/lib/rlsl/prism/emitters/wgsl_emitter.rb +65 -61
- data/lib/rlsl/prism/ir/control_flow.rb +83 -0
- data/lib/rlsl/prism/ir/definitions.rb +67 -0
- data/lib/rlsl/prism/ir/expressions.rb +197 -0
- data/lib/rlsl/prism/ir/node.rb +21 -0
- data/lib/rlsl/prism/ir/nodes.rb +4 -371
- data/lib/rlsl/prism/ir/traversal.rb +62 -0
- data/lib/rlsl/prism/source_extractor/block_locator.rb +52 -0
- data/lib/rlsl/prism/source_extractor.rb +14 -133
- data/lib/rlsl/prism/source_unit/parser.rb +78 -0
- data/lib/rlsl/prism/source_unit.rb +42 -0
- data/lib/rlsl/prism/target_capability_validator.rb +85 -0
- data/lib/rlsl/prism/transpiler.rb +63 -60
- data/lib/rlsl/prism/type_inference/call_type_resolver.rb +35 -0
- data/lib/rlsl/prism/type_inference/call_validator.rb +71 -0
- data/lib/rlsl/prism/type_inference/collection_type_resolver.rb +80 -0
- data/lib/rlsl/prism/type_inference/control_flow_inferer.rb +66 -0
- data/lib/rlsl/prism/type_inference/definition_inferer.rb +41 -0
- data/lib/rlsl/prism/type_inference/expression_inferer.rb +92 -0
- data/lib/rlsl/prism/type_inference/field_type_resolver.rb +17 -0
- data/lib/rlsl/prism/type_inference/inferer_registry.rb +38 -0
- data/lib/rlsl/prism/type_inference/scope_stack.rb +47 -0
- data/lib/rlsl/prism/type_inference/type_environment.rb +112 -0
- data/lib/rlsl/prism/type_inference/type_shapes.rb +33 -0
- data/lib/rlsl/prism/type_inference.rb +114 -248
- data/lib/rlsl/runtime_shader.rb +47 -0
- data/lib/rlsl/shader_builder/build_service.rb +77 -0
- data/lib/rlsl/shader_builder/native_extension_compiler.rb +71 -0
- data/lib/rlsl/shader_builder/shader_definition.rb +68 -0
- data/lib/rlsl/shader_builder/source_resolver.rb +91 -0
- data/lib/rlsl/shader_builder.rb +22 -113
- data/lib/rlsl/types/catalog.rb +47 -0
- data/lib/rlsl/types/target_resolver.rb +15 -0
- data/lib/rlsl/types/type_spec.rb +167 -0
- data/lib/rlsl/types/value_normalizer.rb +81 -0
- data/lib/rlsl/types.rb +11 -29
- data/lib/rlsl/uniform_context.rb +6 -12
- data/lib/rlsl/version.rb +1 -1
- data/lib/rlsl/wgsl/translator.rb +23 -39
- data/lib/rlsl.rb +14 -12
- metadata +55 -2
data/lib/rlsl/prism/builtins.rb
CHANGED
|
@@ -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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
19
|
+
FunctionRegistry.function?(name)
|
|
105
20
|
end
|
|
106
21
|
|
|
107
22
|
def function_signature(name)
|
|
108
|
-
|
|
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
|
-
|
|
35
|
+
OperatorRules.binary_operator?(op)
|
|
113
36
|
end
|
|
114
37
|
|
|
115
38
|
def unary_operator?(op)
|
|
116
|
-
|
|
39
|
+
OperatorRules.unary_operator?(op)
|
|
117
40
|
end
|
|
118
41
|
|
|
119
42
|
def single_component_field?(name)
|
|
120
|
-
|
|
43
|
+
SwizzleRules.single_component_field?(name)
|
|
121
44
|
end
|
|
122
45
|
|
|
123
46
|
def swizzle?(name)
|
|
124
|
-
|
|
47
|
+
SwizzleRules.swizzle?(name)
|
|
125
48
|
end
|
|
126
49
|
|
|
127
50
|
def swizzle_type(components)
|
|
128
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
63
|
+
OperatorRules.vector_type?(type)
|
|
177
64
|
end
|
|
178
65
|
|
|
179
66
|
def matrix_type?(type)
|
|
180
|
-
|
|
67
|
+
OperatorRules.matrix_type?(type)
|
|
181
68
|
end
|
|
182
69
|
|
|
183
70
|
def scalar_type?(type)
|
|
184
|
-
|
|
71
|
+
OperatorRules.scalar_type?(type)
|
|
185
72
|
end
|
|
186
73
|
|
|
187
74
|
def matrix_vector_result(matrix_type)
|
|
188
|
-
|
|
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,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
|