rlsl 0.1.0 → 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 +14 -1
- data/README.md +18 -1
- 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 -16
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RLSL
|
|
4
|
+
module Prism
|
|
5
|
+
class ExpressionInferer
|
|
6
|
+
def initialize(infer:, lookup:, call_type_resolver:, field_type_resolver:, collection_type_resolver:)
|
|
7
|
+
@infer = infer
|
|
8
|
+
@lookup = lookup
|
|
9
|
+
@call_type_resolver = call_type_resolver
|
|
10
|
+
@field_type_resolver = field_type_resolver
|
|
11
|
+
@collection_type_resolver = collection_type_resolver
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def infer_var_ref(node)
|
|
15
|
+
node.type ||= @lookup.call(node.name)
|
|
16
|
+
node
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def infer_literal(node)
|
|
20
|
+
node
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def infer_bool_literal(node)
|
|
24
|
+
node.type = :bool
|
|
25
|
+
node
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def infer_binary_op(node)
|
|
29
|
+
@infer.call(node.left)
|
|
30
|
+
@infer.call(node.right)
|
|
31
|
+
|
|
32
|
+
node.type = Builtins.binary_op_result_type(
|
|
33
|
+
node.operator,
|
|
34
|
+
node.left.type,
|
|
35
|
+
node.right.type
|
|
36
|
+
)
|
|
37
|
+
node
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def infer_unary_op(node)
|
|
41
|
+
@infer.call(node.operand)
|
|
42
|
+
|
|
43
|
+
case node.operator.to_s
|
|
44
|
+
when "-"
|
|
45
|
+
node.type = node.operand.type
|
|
46
|
+
when "!"
|
|
47
|
+
node.type = :bool
|
|
48
|
+
end
|
|
49
|
+
node
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def infer_func_call(node)
|
|
53
|
+
node.args.each { |arg| @infer.call(arg) }
|
|
54
|
+
@infer.call(node.receiver) if node.receiver
|
|
55
|
+
|
|
56
|
+
node.type = @call_type_resolver.resolve(node)
|
|
57
|
+
node
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def infer_field_access(node)
|
|
61
|
+
@infer.call(node.receiver)
|
|
62
|
+
node.type = @field_type_resolver.resolve(node)
|
|
63
|
+
node
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def infer_swizzle(node)
|
|
67
|
+
@infer.call(node.receiver)
|
|
68
|
+
node.type = Builtins.swizzle_type(node.components)
|
|
69
|
+
node
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def infer_parenthesized(node)
|
|
73
|
+
@infer.call(node.expression)
|
|
74
|
+
node.type = node.expression.type
|
|
75
|
+
node
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def infer_array_literal(node)
|
|
79
|
+
node.elements.each { |element| @infer.call(element) }
|
|
80
|
+
node.type = @collection_type_resolver.resolve_array_literal(node)
|
|
81
|
+
node
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def infer_array_index(node)
|
|
85
|
+
@infer.call(node.array)
|
|
86
|
+
@infer.call(node.index)
|
|
87
|
+
node.type = @collection_type_resolver.resolve_array_index(node)
|
|
88
|
+
node
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RLSL
|
|
4
|
+
module Prism
|
|
5
|
+
class FieldTypeResolver
|
|
6
|
+
def initialize(uniforms:)
|
|
7
|
+
@uniforms = uniforms
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def resolve(node)
|
|
11
|
+
return :float if Builtins.single_component_field?(node.field)
|
|
12
|
+
|
|
13
|
+
@uniforms[node.field.to_sym] || :float
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RLSL
|
|
4
|
+
module Prism
|
|
5
|
+
class InfererRegistry
|
|
6
|
+
def initialize
|
|
7
|
+
@handlers = {}
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def register(node_class, target = nil, method_name = nil, &block)
|
|
11
|
+
@handlers[node_class] = block || build_handler(target, method_name)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def register_methods(target, mapping)
|
|
15
|
+
mapping.each do |node_class, method_name|
|
|
16
|
+
register(node_class, target, method_name)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def infer(node, **options)
|
|
21
|
+
handler = @handlers[node.class]
|
|
22
|
+
return unless handler
|
|
23
|
+
|
|
24
|
+
handler.call(node, **options)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def build_handler(target, method_name)
|
|
30
|
+
lambda do |node, **options|
|
|
31
|
+
return target.send(method_name, node) if options.empty?
|
|
32
|
+
|
|
33
|
+
target.send(method_name, node, **options)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RLSL
|
|
4
|
+
module Prism
|
|
5
|
+
class ScopeStack
|
|
6
|
+
def initialize
|
|
7
|
+
@scopes = [{}]
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def push(initial_scope = {})
|
|
11
|
+
@scopes << normalize(initial_scope)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def pop
|
|
15
|
+
raise "Cannot pop the global scope" if @scopes.length == 1
|
|
16
|
+
|
|
17
|
+
@scopes.pop
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def register(name, type)
|
|
21
|
+
@scopes.last[name.to_sym] = type
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def lookup(name)
|
|
25
|
+
@scopes.reverse_each do |scope|
|
|
26
|
+
return scope[name.to_sym] if scope.key?(name.to_sym)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
nil
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def to_h
|
|
33
|
+
@scopes.each_with_object({}) do |scope, merged|
|
|
34
|
+
merged.merge!(scope)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def normalize(scope)
|
|
41
|
+
scope.each_with_object({}) do |(name, type), normalized|
|
|
42
|
+
normalized[name.to_sym] = type
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RLSL
|
|
4
|
+
module Prism
|
|
5
|
+
class TypeEnvironment
|
|
6
|
+
include TypeShapes
|
|
7
|
+
|
|
8
|
+
ARRAY_ELEMENT_SUFFIX = "_element_type"
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@value_scopes = ScopeStack.new
|
|
12
|
+
@array_element_scopes = ScopeStack.new
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def push(initial_scope = {})
|
|
16
|
+
value_scope = {}
|
|
17
|
+
array_scope = {}
|
|
18
|
+
|
|
19
|
+
normalize(initial_scope).each do |name, type|
|
|
20
|
+
register_in_scopes(value_scope, array_scope, name, type)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
@value_scopes.push(value_scope)
|
|
24
|
+
@array_element_scopes.push(array_scope)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def pop
|
|
28
|
+
@value_scopes.pop
|
|
29
|
+
@array_element_scopes.pop
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def register(name, type)
|
|
33
|
+
register_in_scopes(@value_scopes, @array_element_scopes, name, type)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def lookup(name)
|
|
37
|
+
normalized_name = name.to_sym
|
|
38
|
+
return array_element_type(metadata_base_name(normalized_name)) if metadata_name?(normalized_name)
|
|
39
|
+
|
|
40
|
+
@value_scopes.lookup(normalized_name)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def array_element_type(name)
|
|
44
|
+
normalized_name = name.to_sym
|
|
45
|
+
explicit_type = @array_element_scopes.lookup(normalized_name)
|
|
46
|
+
return explicit_type if explicit_type
|
|
47
|
+
|
|
48
|
+
value_type = @value_scopes.lookup(normalized_name)
|
|
49
|
+
return TypeShapes.element_type(value_type) if TypeShapes.array?(value_type)
|
|
50
|
+
|
|
51
|
+
nil
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def to_h
|
|
55
|
+
values = @value_scopes.to_h
|
|
56
|
+
elements = @array_element_scopes.to_h.each_with_object({}) do |(name, type), memo|
|
|
57
|
+
memo[metadata_name(name)] = type
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
values.each do |name, type|
|
|
61
|
+
next unless TypeShapes.array?(type)
|
|
62
|
+
|
|
63
|
+
elements[metadata_name(name)] ||= TypeShapes.element_type(type)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
values.merge(elements)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def register_in_scopes(value_scope, array_scope, name, type)
|
|
72
|
+
normalized_name = name.to_sym
|
|
73
|
+
|
|
74
|
+
if metadata_name?(normalized_name)
|
|
75
|
+
write_scope(array_scope, metadata_base_name(normalized_name), type)
|
|
76
|
+
return
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
write_scope(value_scope, normalized_name, type)
|
|
80
|
+
return unless TypeShapes.array?(type)
|
|
81
|
+
|
|
82
|
+
write_scope(array_scope, normalized_name, TypeShapes.element_type(type))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def normalize(scope)
|
|
86
|
+
scope.each_with_object({}) do |(name, type), normalized|
|
|
87
|
+
normalized[name.to_sym] = type
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def metadata_name?(name)
|
|
92
|
+
name.to_s.end_with?(ARRAY_ELEMENT_SUFFIX)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def metadata_name(name)
|
|
96
|
+
:"#{name}#{ARRAY_ELEMENT_SUFFIX}"
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def metadata_base_name(name)
|
|
100
|
+
name.to_s.delete_suffix(ARRAY_ELEMENT_SUFFIX).to_sym
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def write_scope(scope, name, type)
|
|
104
|
+
if scope.respond_to?(:register)
|
|
105
|
+
scope.register(name, type)
|
|
106
|
+
else
|
|
107
|
+
scope[name.to_sym] = type
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RLSL
|
|
4
|
+
module Prism
|
|
5
|
+
module TypeShapes
|
|
6
|
+
ArrayType = Struct.new(:element_type) do
|
|
7
|
+
def to_sym
|
|
8
|
+
:"array_#{element_type}"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def to_s
|
|
12
|
+
to_sym.to_s
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
module_function
|
|
17
|
+
|
|
18
|
+
def array(element_type)
|
|
19
|
+
ArrayType.new(element_type)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def array?(type)
|
|
23
|
+
type.is_a?(ArrayType)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def element_type(type)
|
|
27
|
+
return type.element_type if array?(type)
|
|
28
|
+
|
|
29
|
+
nil
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|