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.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -0
- data/CHANGELOG.md +13 -2
- data/README.md +101 -26
- data/Rakefile +7 -0
- data/lib/rlsl/base_translator/call_parser.rb +79 -0
- data/lib/rlsl/base_translator/code_rewriter.rb +107 -0
- data/lib/rlsl/base_translator/code_scanner.rb +140 -0
- data/lib/rlsl/base_translator.rb +182 -64
- data/lib/rlsl/code_generator/math_prelude.rb +172 -0
- data/lib/rlsl/code_generator/ruby_wrapper_generator.rb +137 -0
- data/lib/rlsl/code_generator/shader_function_generator.rb +19 -0
- data/lib/rlsl/code_generator/template_context.rb +44 -0
- data/lib/rlsl/code_generator/uniform_struct_generator.rb +29 -0
- data/lib/rlsl/code_generator.rb +30 -202
- data/lib/rlsl/compiled_shader.rb +5 -13
- data/lib/rlsl/errors.rb +29 -0
- data/lib/rlsl/function_context.rb +31 -14
- data/lib/rlsl/glsl/translator.rb +35 -41
- data/lib/rlsl/msl/shader.rb +34 -46
- data/lib/rlsl/msl/translator.rb +38 -34
- data/lib/rlsl/msl/uniform_buffer_packer.rb +72 -0
- data/lib/rlsl/prism/ast_visitor/control_flow_visiting.rb +137 -0
- data/lib/rlsl/prism/ast_visitor/definition_visiting.rb +92 -0
- data/lib/rlsl/prism/ast_visitor/expression_visiting.rb +172 -0
- data/lib/rlsl/prism/ast_visitor/scope_context.rb +48 -0
- data/lib/rlsl/prism/ast_visitor/visitor_registry.rb +21 -0
- data/lib/rlsl/prism/ast_visitor.rb +100 -286
- data/lib/rlsl/prism/builtins/function_registry.rb +131 -0
- data/lib/rlsl/prism/builtins/operator_rules.rb +123 -0
- data/lib/rlsl/prism/builtins/swizzle_rules.rb +47 -0
- data/lib/rlsl/prism/builtins.rb +39 -148
- data/lib/rlsl/prism/compilation_unit.rb +7 -0
- data/lib/rlsl/prism/emitters/base_emitter/control_flow_emission.rb +126 -0
- data/lib/rlsl/prism/emitters/base_emitter/definition_emission.rb +134 -0
- data/lib/rlsl/prism/emitters/base_emitter/expression_emission.rb +108 -0
- data/lib/rlsl/prism/emitters/base_emitter/statement_emission.rb +95 -0
- data/lib/rlsl/prism/emitters/base_emitter.rb +120 -414
- data/lib/rlsl/prism/emitters/c_emitter.rb +165 -112
- data/lib/rlsl/prism/emitters/glsl_emitter.rb +63 -50
- data/lib/rlsl/prism/emitters/msl_emitter.rb +67 -52
- data/lib/rlsl/prism/emitters/target_emitter.rb +124 -0
- data/lib/rlsl/prism/emitters/target_profile.rb +34 -0
- data/lib/rlsl/prism/emitters/wgsl_emitter.rb +217 -58
- data/lib/rlsl/prism/errors.rb +9 -0
- data/lib/rlsl/prism/ir/control_flow.rb +85 -0
- data/lib/rlsl/prism/ir/definitions.rb +82 -0
- data/lib/rlsl/prism/ir/expressions.rb +201 -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 +66 -0
- data/lib/rlsl/prism/mutation_analyzer.rb +30 -0
- data/lib/rlsl/prism/node_traversal.rb +41 -0
- data/lib/rlsl/prism/parameter_list.rb +46 -0
- data/lib/rlsl/prism/return_flow_validator.rb +73 -0
- data/lib/rlsl/prism/source_extractor/block_locator.rb +50 -0
- data/lib/rlsl/prism/source_extractor.rb +19 -137
- data/lib/rlsl/prism/source_unit/parser.rb +88 -0
- data/lib/rlsl/prism/source_unit.rb +42 -0
- data/lib/rlsl/prism/target_capability_validator.rb +110 -0
- data/lib/rlsl/prism/transpiler.rb +99 -59
- data/lib/rlsl/prism/type_inference/call_type_resolver.rb +59 -0
- data/lib/rlsl/prism/type_inference/call_validator.rb +75 -0
- data/lib/rlsl/prism/type_inference/collection_type_resolver.rb +106 -0
- data/lib/rlsl/prism/type_inference/control_flow_inferer.rb +147 -0
- data/lib/rlsl/prism/type_inference/definition_inferer.rb +56 -0
- data/lib/rlsl/prism/type_inference/expression_inferer.rb +96 -0
- data/lib/rlsl/prism/type_inference/field_type_resolver.rb +38 -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 +120 -249
- data/lib/rlsl/runtime_shader.rb +47 -0
- data/lib/rlsl/shader_builder/build_service.rb +104 -0
- data/lib/rlsl/shader_builder/native_extension_compiler.rb +97 -0
- data/lib/rlsl/shader_builder/shader_definition.rb +68 -0
- data/lib/rlsl/shader_builder/source_resolver.rb +109 -0
- data/lib/rlsl/shader_builder.rb +60 -111
- data/lib/rlsl/shader_name.rb +18 -0
- 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 +86 -0
- data/lib/rlsl/types.rb +9 -31
- data/lib/rlsl/uniform_context.rb +22 -11
- data/lib/rlsl/version.rb +1 -1
- data/lib/rlsl/wgsl/translator.rb +46 -39
- data/lib/rlsl/wgsl/uniform_layout.rb +25 -0
- data/lib/rlsl.rb +38 -15
- metadata +76 -11
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RLSL
|
|
4
|
+
module Prism
|
|
5
|
+
module IR
|
|
6
|
+
class Block < Node
|
|
7
|
+
attr_reader :statements
|
|
8
|
+
|
|
9
|
+
visits :visit_block
|
|
10
|
+
|
|
11
|
+
def initialize(statements = [])
|
|
12
|
+
super()
|
|
13
|
+
@statements = statements
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class VarDecl < Node
|
|
18
|
+
attr_reader :name, :initializer
|
|
19
|
+
attr_accessor :mutable
|
|
20
|
+
|
|
21
|
+
visits :visit_var_decl
|
|
22
|
+
|
|
23
|
+
def initialize(name, initializer, type = nil, mutable: false)
|
|
24
|
+
super()
|
|
25
|
+
@name = name
|
|
26
|
+
@initializer = initializer
|
|
27
|
+
@type = type
|
|
28
|
+
@mutable = mutable
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class VarRef < Node
|
|
33
|
+
attr_reader :name
|
|
34
|
+
|
|
35
|
+
visits :visit_var_ref
|
|
36
|
+
|
|
37
|
+
def initialize(name, type = nil)
|
|
38
|
+
super()
|
|
39
|
+
@name = name
|
|
40
|
+
@type = type
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class Literal < Node
|
|
45
|
+
attr_reader :value
|
|
46
|
+
|
|
47
|
+
visits :visit_literal
|
|
48
|
+
|
|
49
|
+
def initialize(value, type = nil)
|
|
50
|
+
super()
|
|
51
|
+
@value = value
|
|
52
|
+
@type = type || (value.is_a?(Float) ? :float : :int)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
class BoolLiteral < Node
|
|
57
|
+
attr_reader :value
|
|
58
|
+
|
|
59
|
+
visits :visit_bool_literal
|
|
60
|
+
|
|
61
|
+
def initialize(value)
|
|
62
|
+
super()
|
|
63
|
+
@value = value
|
|
64
|
+
@type = :bool
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
class BinaryOp < Node
|
|
69
|
+
attr_reader :operator, :left, :right
|
|
70
|
+
|
|
71
|
+
visits :visit_binary_op
|
|
72
|
+
|
|
73
|
+
def initialize(operator, left, right, type = nil)
|
|
74
|
+
super()
|
|
75
|
+
@operator = operator
|
|
76
|
+
@left = left
|
|
77
|
+
@right = right
|
|
78
|
+
@type = type
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
class UnaryOp < Node
|
|
83
|
+
attr_reader :operator, :operand
|
|
84
|
+
|
|
85
|
+
visits :visit_unary_op
|
|
86
|
+
|
|
87
|
+
def initialize(operator, operand, type = nil)
|
|
88
|
+
super()
|
|
89
|
+
@operator = operator
|
|
90
|
+
@operand = operand
|
|
91
|
+
@type = type
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
class FuncCall < Node
|
|
96
|
+
attr_reader :name, :args, :receiver
|
|
97
|
+
attr_accessor :expected_arg_types
|
|
98
|
+
|
|
99
|
+
visits :visit_func_call
|
|
100
|
+
|
|
101
|
+
def initialize(name, args = [], receiver = nil, type = nil)
|
|
102
|
+
super()
|
|
103
|
+
@name = name
|
|
104
|
+
@args = args
|
|
105
|
+
@receiver = receiver
|
|
106
|
+
@expected_arg_types = []
|
|
107
|
+
@type = type
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
class FieldAccess < Node
|
|
112
|
+
attr_reader :receiver, :field
|
|
113
|
+
|
|
114
|
+
visits :visit_field_access
|
|
115
|
+
|
|
116
|
+
def initialize(receiver, field, type = nil)
|
|
117
|
+
super()
|
|
118
|
+
@receiver = receiver
|
|
119
|
+
@field = field
|
|
120
|
+
@type = type
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
class Swizzle < Node
|
|
125
|
+
attr_reader :receiver, :components
|
|
126
|
+
|
|
127
|
+
visits :visit_swizzle
|
|
128
|
+
|
|
129
|
+
def initialize(receiver, components, type = nil)
|
|
130
|
+
super()
|
|
131
|
+
@receiver = receiver
|
|
132
|
+
@components = components
|
|
133
|
+
@type = type
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
class Ternary < Node
|
|
138
|
+
attr_reader :condition, :then_expr, :else_expr
|
|
139
|
+
|
|
140
|
+
visits :visit_ternary
|
|
141
|
+
|
|
142
|
+
def initialize(condition, then_expr, else_expr, type = nil)
|
|
143
|
+
super()
|
|
144
|
+
@condition = condition
|
|
145
|
+
@then_expr = then_expr
|
|
146
|
+
@else_expr = else_expr
|
|
147
|
+
@type = type
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
class Constant < Node
|
|
152
|
+
attr_reader :name
|
|
153
|
+
|
|
154
|
+
visits :visit_constant
|
|
155
|
+
|
|
156
|
+
def initialize(name, type = :float)
|
|
157
|
+
super()
|
|
158
|
+
@name = name
|
|
159
|
+
@type = type
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
class Parenthesized < Node
|
|
164
|
+
attr_reader :expression
|
|
165
|
+
|
|
166
|
+
visits :visit_parenthesized
|
|
167
|
+
|
|
168
|
+
def initialize(expression)
|
|
169
|
+
super()
|
|
170
|
+
@expression = expression
|
|
171
|
+
@type = expression&.type
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
class ArrayLiteral < Node
|
|
176
|
+
attr_reader :elements
|
|
177
|
+
|
|
178
|
+
visits :visit_array_literal
|
|
179
|
+
|
|
180
|
+
def initialize(elements, type = nil)
|
|
181
|
+
super()
|
|
182
|
+
@elements = elements
|
|
183
|
+
@type = type
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
class ArrayIndex < Node
|
|
188
|
+
attr_reader :array, :index
|
|
189
|
+
|
|
190
|
+
visits :visit_array_index
|
|
191
|
+
|
|
192
|
+
def initialize(array, index, type = nil)
|
|
193
|
+
super()
|
|
194
|
+
@array = array
|
|
195
|
+
@index = index
|
|
196
|
+
@type = type
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RLSL
|
|
4
|
+
module Prism
|
|
5
|
+
module IR
|
|
6
|
+
class Node
|
|
7
|
+
attr_accessor :type, :location
|
|
8
|
+
|
|
9
|
+
def self.visits(method_name)
|
|
10
|
+
define_method(:accept) do |visitor|
|
|
11
|
+
visitor.public_send(method_name, self)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def accept(_visitor)
|
|
16
|
+
raise NotImplementedError
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
data/lib/rlsl/prism/ir/nodes.rb
CHANGED
|
@@ -1,373 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
attr_accessor :type
|
|
8
|
-
|
|
9
|
-
def accept(visitor)
|
|
10
|
-
raise NotImplementedError
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
class Block < Node
|
|
15
|
-
attr_reader :statements
|
|
16
|
-
|
|
17
|
-
def initialize(statements = [])
|
|
18
|
-
super()
|
|
19
|
-
@statements = statements
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def accept(visitor)
|
|
23
|
-
visitor.visit_block(self)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
class VarDecl < Node
|
|
28
|
-
attr_reader :name, :initializer
|
|
29
|
-
|
|
30
|
-
def initialize(name, initializer, type = nil)
|
|
31
|
-
super()
|
|
32
|
-
@name = name
|
|
33
|
-
@initializer = initializer
|
|
34
|
-
@type = type
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def accept(visitor)
|
|
38
|
-
visitor.visit_var_decl(self)
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
class VarRef < Node
|
|
43
|
-
attr_reader :name
|
|
44
|
-
|
|
45
|
-
def initialize(name, type = nil)
|
|
46
|
-
super()
|
|
47
|
-
@name = name
|
|
48
|
-
@type = type
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def accept(visitor)
|
|
52
|
-
visitor.visit_var_ref(self)
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
class Literal < Node
|
|
57
|
-
attr_reader :value
|
|
58
|
-
|
|
59
|
-
def initialize(value, type = nil)
|
|
60
|
-
super()
|
|
61
|
-
@value = value
|
|
62
|
-
@type = type || (value.is_a?(Float) ? :float : :int)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def accept(visitor)
|
|
66
|
-
visitor.visit_literal(self)
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
class BoolLiteral < Node
|
|
71
|
-
attr_reader :value
|
|
72
|
-
|
|
73
|
-
def initialize(value)
|
|
74
|
-
super()
|
|
75
|
-
@value = value
|
|
76
|
-
@type = :bool
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def accept(visitor)
|
|
80
|
-
visitor.visit_bool_literal(self)
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
class BinaryOp < Node
|
|
85
|
-
attr_reader :operator, :left, :right
|
|
86
|
-
|
|
87
|
-
def initialize(operator, left, right, type = nil)
|
|
88
|
-
super()
|
|
89
|
-
@operator = operator
|
|
90
|
-
@left = left
|
|
91
|
-
@right = right
|
|
92
|
-
@type = type
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def accept(visitor)
|
|
96
|
-
visitor.visit_binary_op(self)
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
class UnaryOp < Node
|
|
101
|
-
attr_reader :operator, :operand
|
|
102
|
-
|
|
103
|
-
def initialize(operator, operand, type = nil)
|
|
104
|
-
super()
|
|
105
|
-
@operator = operator
|
|
106
|
-
@operand = operand
|
|
107
|
-
@type = type
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def accept(visitor)
|
|
111
|
-
visitor.visit_unary_op(self)
|
|
112
|
-
end
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
class FuncCall < Node
|
|
116
|
-
attr_reader :name, :args, :receiver
|
|
117
|
-
|
|
118
|
-
def initialize(name, args = [], receiver = nil, type = nil)
|
|
119
|
-
super()
|
|
120
|
-
@name = name
|
|
121
|
-
@args = args
|
|
122
|
-
@receiver = receiver
|
|
123
|
-
@type = type
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def accept(visitor)
|
|
127
|
-
visitor.visit_func_call(self)
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
class FieldAccess < Node
|
|
132
|
-
attr_reader :receiver, :field
|
|
133
|
-
|
|
134
|
-
def initialize(receiver, field, type = nil)
|
|
135
|
-
super()
|
|
136
|
-
@receiver = receiver
|
|
137
|
-
@field = field
|
|
138
|
-
@type = type
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
def accept(visitor)
|
|
142
|
-
visitor.visit_field_access(self)
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
class Swizzle < Node
|
|
147
|
-
attr_reader :receiver, :components
|
|
148
|
-
|
|
149
|
-
def initialize(receiver, components, type = nil)
|
|
150
|
-
super()
|
|
151
|
-
@receiver = receiver
|
|
152
|
-
@components = components
|
|
153
|
-
@type = type
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def accept(visitor)
|
|
157
|
-
visitor.visit_swizzle(self)
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
class IfStatement < Node
|
|
162
|
-
attr_reader :condition, :then_branch, :else_branch
|
|
163
|
-
|
|
164
|
-
def initialize(condition, then_branch, else_branch = nil, type = nil)
|
|
165
|
-
super()
|
|
166
|
-
@condition = condition
|
|
167
|
-
@then_branch = then_branch
|
|
168
|
-
@else_branch = else_branch
|
|
169
|
-
@type = type
|
|
170
|
-
end
|
|
171
|
-
|
|
172
|
-
def accept(visitor)
|
|
173
|
-
visitor.visit_if_statement(self)
|
|
174
|
-
end
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
class Return < Node
|
|
178
|
-
attr_reader :expression
|
|
179
|
-
|
|
180
|
-
def initialize(expression)
|
|
181
|
-
super()
|
|
182
|
-
@expression = expression
|
|
183
|
-
@type = expression&.type
|
|
184
|
-
end
|
|
185
|
-
|
|
186
|
-
def accept(visitor)
|
|
187
|
-
visitor.visit_return(self)
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
|
|
191
|
-
class Assignment < Node
|
|
192
|
-
attr_reader :target, :value
|
|
193
|
-
|
|
194
|
-
def initialize(target, value)
|
|
195
|
-
super()
|
|
196
|
-
@target = target
|
|
197
|
-
@value = value
|
|
198
|
-
@type = value&.type
|
|
199
|
-
end
|
|
200
|
-
|
|
201
|
-
def accept(visitor)
|
|
202
|
-
visitor.visit_assignment(self)
|
|
203
|
-
end
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
class ForLoop < Node
|
|
207
|
-
attr_reader :variable, :range_start, :range_end, :body
|
|
208
|
-
|
|
209
|
-
def initialize(variable, range_start, range_end, body)
|
|
210
|
-
super()
|
|
211
|
-
@variable = variable
|
|
212
|
-
@range_start = range_start
|
|
213
|
-
@range_end = range_end
|
|
214
|
-
@body = body
|
|
215
|
-
@type = nil
|
|
216
|
-
end
|
|
217
|
-
|
|
218
|
-
def accept(visitor)
|
|
219
|
-
visitor.visit_for_loop(self)
|
|
220
|
-
end
|
|
221
|
-
end
|
|
222
|
-
|
|
223
|
-
class WhileLoop < Node
|
|
224
|
-
attr_reader :condition, :body
|
|
225
|
-
|
|
226
|
-
def initialize(condition, body)
|
|
227
|
-
super()
|
|
228
|
-
@condition = condition
|
|
229
|
-
@body = body
|
|
230
|
-
@type = nil
|
|
231
|
-
end
|
|
232
|
-
|
|
233
|
-
def accept(visitor)
|
|
234
|
-
visitor.visit_while_loop(self)
|
|
235
|
-
end
|
|
236
|
-
end
|
|
237
|
-
|
|
238
|
-
class Break < Node
|
|
239
|
-
def initialize
|
|
240
|
-
super()
|
|
241
|
-
@type = nil
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
def accept(visitor)
|
|
245
|
-
visitor.visit_break(self)
|
|
246
|
-
end
|
|
247
|
-
end
|
|
248
|
-
|
|
249
|
-
class Constant < Node
|
|
250
|
-
attr_reader :name
|
|
251
|
-
|
|
252
|
-
def initialize(name, type = :float)
|
|
253
|
-
super()
|
|
254
|
-
@name = name
|
|
255
|
-
@type = type
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
def accept(visitor)
|
|
259
|
-
visitor.visit_constant(self)
|
|
260
|
-
end
|
|
261
|
-
end
|
|
262
|
-
|
|
263
|
-
class Parenthesized < Node
|
|
264
|
-
attr_reader :expression
|
|
265
|
-
|
|
266
|
-
def initialize(expression)
|
|
267
|
-
super()
|
|
268
|
-
@expression = expression
|
|
269
|
-
@type = expression&.type
|
|
270
|
-
end
|
|
271
|
-
|
|
272
|
-
def accept(visitor)
|
|
273
|
-
visitor.visit_parenthesized(self)
|
|
274
|
-
end
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
class ArrayLiteral < Node
|
|
278
|
-
attr_reader :elements
|
|
279
|
-
|
|
280
|
-
def initialize(elements, type = nil)
|
|
281
|
-
super()
|
|
282
|
-
@elements = elements
|
|
283
|
-
@type = type
|
|
284
|
-
end
|
|
285
|
-
|
|
286
|
-
def accept(visitor)
|
|
287
|
-
visitor.visit_array_literal(self)
|
|
288
|
-
end
|
|
289
|
-
end
|
|
290
|
-
|
|
291
|
-
class ArrayIndex < Node
|
|
292
|
-
attr_reader :array, :index
|
|
293
|
-
|
|
294
|
-
def initialize(array, index, type = nil)
|
|
295
|
-
super()
|
|
296
|
-
@array = array
|
|
297
|
-
@index = index
|
|
298
|
-
@type = type
|
|
299
|
-
end
|
|
300
|
-
|
|
301
|
-
def accept(visitor)
|
|
302
|
-
visitor.visit_array_index(self)
|
|
303
|
-
end
|
|
304
|
-
end
|
|
305
|
-
|
|
306
|
-
class GlobalDecl < Node
|
|
307
|
-
attr_reader :name, :initializer
|
|
308
|
-
attr_accessor :is_const, :is_static, :array_size, :element_type
|
|
309
|
-
|
|
310
|
-
def initialize(name, initializer, type: nil, is_const: false, is_static: true, array_size: nil, element_type: nil)
|
|
311
|
-
super()
|
|
312
|
-
@name = name
|
|
313
|
-
@initializer = initializer
|
|
314
|
-
@type = type
|
|
315
|
-
@is_const = is_const
|
|
316
|
-
@is_static = is_static
|
|
317
|
-
@array_size = array_size
|
|
318
|
-
@element_type = element_type
|
|
319
|
-
end
|
|
320
|
-
|
|
321
|
-
def accept(visitor)
|
|
322
|
-
visitor.visit_global_decl(self)
|
|
323
|
-
end
|
|
324
|
-
end
|
|
325
|
-
|
|
326
|
-
class FunctionDefinition < Node
|
|
327
|
-
attr_reader :name, :params, :body
|
|
328
|
-
attr_accessor :return_type, :param_types
|
|
329
|
-
|
|
330
|
-
def initialize(name, params, body, return_type: nil, param_types: {})
|
|
331
|
-
super()
|
|
332
|
-
@name = name
|
|
333
|
-
@params = params
|
|
334
|
-
@body = body
|
|
335
|
-
@return_type = return_type
|
|
336
|
-
@param_types = param_types
|
|
337
|
-
@type = return_type
|
|
338
|
-
end
|
|
339
|
-
|
|
340
|
-
def accept(visitor)
|
|
341
|
-
visitor.visit_function_definition(self)
|
|
342
|
-
end
|
|
343
|
-
end
|
|
344
|
-
|
|
345
|
-
class MultipleAssignment < Node
|
|
346
|
-
attr_reader :targets, :value
|
|
347
|
-
|
|
348
|
-
def initialize(targets, value)
|
|
349
|
-
super()
|
|
350
|
-
@targets = targets
|
|
351
|
-
@value = value
|
|
352
|
-
@type = nil
|
|
353
|
-
end
|
|
354
|
-
|
|
355
|
-
def accept(visitor)
|
|
356
|
-
visitor.visit_multiple_assignment(self)
|
|
357
|
-
end
|
|
358
|
-
end
|
|
359
|
-
|
|
360
|
-
class TupleType
|
|
361
|
-
attr_reader :types
|
|
362
|
-
|
|
363
|
-
def initialize(*types)
|
|
364
|
-
@types = types
|
|
365
|
-
end
|
|
366
|
-
|
|
367
|
-
def to_sym
|
|
368
|
-
:"tuple_#{types.map(&:to_s).join('_')}"
|
|
369
|
-
end
|
|
370
|
-
end
|
|
371
|
-
end
|
|
372
|
-
end
|
|
373
|
-
end
|
|
3
|
+
require_relative "node"
|
|
4
|
+
require_relative "expressions"
|
|
5
|
+
require_relative "control_flow"
|
|
6
|
+
require_relative "definitions"
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RLSL
|
|
4
|
+
module Prism
|
|
5
|
+
module IR
|
|
6
|
+
module Traversal
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def each(node, &block)
|
|
10
|
+
return enum_for(:each, node) unless block_given?
|
|
11
|
+
return if node.nil?
|
|
12
|
+
|
|
13
|
+
stack = [node]
|
|
14
|
+
until stack.empty?
|
|
15
|
+
current = stack.pop
|
|
16
|
+
yield current
|
|
17
|
+
stack.concat(child_nodes(current).reverse)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def child_nodes(node)
|
|
22
|
+
case node
|
|
23
|
+
when Block
|
|
24
|
+
node.statements
|
|
25
|
+
when VarDecl
|
|
26
|
+
[node.initializer]
|
|
27
|
+
when BinaryOp
|
|
28
|
+
[node.left, node.right]
|
|
29
|
+
when UnaryOp
|
|
30
|
+
[node.operand]
|
|
31
|
+
when FuncCall
|
|
32
|
+
[node.receiver, *node.args]
|
|
33
|
+
when FieldAccess, Swizzle
|
|
34
|
+
[node.receiver]
|
|
35
|
+
when IfStatement
|
|
36
|
+
[node.condition, node.then_branch, node.else_branch]
|
|
37
|
+
when Ternary
|
|
38
|
+
[node.condition, node.then_expr, node.else_expr]
|
|
39
|
+
when Return
|
|
40
|
+
[node.expression]
|
|
41
|
+
when Assignment
|
|
42
|
+
[node.target, node.value]
|
|
43
|
+
when ForLoop
|
|
44
|
+
[node.range_start, node.range_end, node.body]
|
|
45
|
+
when WhileLoop
|
|
46
|
+
[node.condition, node.body]
|
|
47
|
+
when Parenthesized
|
|
48
|
+
[node.expression]
|
|
49
|
+
when ArrayLiteral
|
|
50
|
+
node.elements
|
|
51
|
+
when ArrayIndex
|
|
52
|
+
[node.array, node.index]
|
|
53
|
+
when GlobalDecl
|
|
54
|
+
[node.initializer]
|
|
55
|
+
when FunctionDefinition
|
|
56
|
+
[node.body]
|
|
57
|
+
when MultipleAssignment
|
|
58
|
+
[*node.targets, node.value]
|
|
59
|
+
else
|
|
60
|
+
[]
|
|
61
|
+
end.compact
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "set"
|
|
4
|
+
|
|
5
|
+
require_relative "ir/traversal"
|
|
6
|
+
|
|
7
|
+
module RLSL
|
|
8
|
+
module Prism
|
|
9
|
+
class MutationAnalyzer
|
|
10
|
+
def analyze(node)
|
|
11
|
+
assigned_names = IR::Traversal.each(node).filter_map do |current|
|
|
12
|
+
case current
|
|
13
|
+
when IR::Assignment
|
|
14
|
+
current.target.name if current.target.is_a?(IR::VarRef)
|
|
15
|
+
when IR::MultipleAssignment
|
|
16
|
+
current.targets.select { |target| target.is_a?(IR::VarRef) }.map(&:name)
|
|
17
|
+
end
|
|
18
|
+
end.flatten.to_set
|
|
19
|
+
|
|
20
|
+
IR::Traversal.each(node) do |current|
|
|
21
|
+
next unless current.is_a?(IR::VarDecl)
|
|
22
|
+
|
|
23
|
+
current.mutable = assigned_names.include?(current.name)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
node
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|