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
@@ -0,0 +1,96 @@
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
+ unless Builtins.valid_swizzle_for_type?(node.components, node.receiver.type)
69
+ raise SignatureError, "Invalid swizzle #{node.components.inspect} for #{node.receiver.type || :unknown}"
70
+ end
71
+
72
+ node.type = Builtins.swizzle_type(node.components)
73
+ node
74
+ end
75
+
76
+ def infer_parenthesized(node)
77
+ @infer.call(node.expression)
78
+ node.type = node.expression.type
79
+ node
80
+ end
81
+
82
+ def infer_array_literal(node)
83
+ node.elements.each { |element| @infer.call(element) }
84
+ node.type = @collection_type_resolver.resolve_array_literal(node)
85
+ node
86
+ end
87
+
88
+ def infer_array_index(node)
89
+ @infer.call(node.array)
90
+ @infer.call(node.index)
91
+ node.type = @collection_type_resolver.resolve_array_index(node)
92
+ node
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,38 @@
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
+ if node.receiver.type == :uniforms
12
+ type = @uniforms[node.field.to_sym]
13
+ return type if type
14
+
15
+ raise SignatureError, "Unknown uniform field #{node.field.inspect}"
16
+ end
17
+
18
+ if Builtins.single_component_field?(node.field)
19
+ unless Builtins.valid_swizzle_for_type?(node.field, node.receiver.type)
20
+ raise SignatureError, "Invalid component #{node.field.inspect} for #{node.receiver.type || :unknown}"
21
+ end
22
+
23
+ return :float
24
+ end
25
+
26
+ if Builtins.swizzle?(node.field)
27
+ unless Builtins.valid_swizzle_for_type?(node.field, node.receiver.type)
28
+ raise SignatureError, "Invalid swizzle #{node.field.inspect} for #{node.receiver.type || :unknown}"
29
+ end
30
+
31
+ return Builtins.swizzle_type(node.field)
32
+ end
33
+
34
+ raise SignatureError, "Unknown field #{node.field.inspect} for #{node.receiver.type || :unknown}"
35
+ end
36
+ end
37
+ end
38
+ 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 RLSL::InternalError, "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, :element_count) 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, length = nil)
19
+ ArrayType.new(element_type, length)
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