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,108 @@
|
|
|
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
|
+
return "#{type} #{node.name}" unless node.initializer
|
|
11
|
+
|
|
12
|
+
if node.initializer.is_a?(IR::ArrayLiteral)
|
|
13
|
+
value = emit(node.initializer)
|
|
14
|
+
element_type = type_name(TypeShapes.element_type(node.type) || :float)
|
|
15
|
+
return "#{element_type} #{node.name}[#{node.initializer.elements.length}] = #{value}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
value = emit(node.initializer)
|
|
19
|
+
"#{type} #{node.name} = #{value}"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def emit_var_ref(node)
|
|
23
|
+
node.name.to_s
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def emit_literal(node)
|
|
27
|
+
format_number(node.value, type: node.type)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def emit_bool_literal(node)
|
|
31
|
+
node.value.to_s
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def emit_binary_op(node)
|
|
35
|
+
left = emit_with_precedence(node.left, node.operator, side: :left)
|
|
36
|
+
right = emit_with_precedence(node.right, node.operator, side: :right)
|
|
37
|
+
"#{left} #{node.operator} #{right}"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def emit_unary_op(node)
|
|
41
|
+
operand = emit(node.operand)
|
|
42
|
+
operand = "(#{operand})" if node.operand.is_a?(IR::BinaryOp) ||
|
|
43
|
+
node.operand.is_a?(IR::Ternary) ||
|
|
44
|
+
node.operand.is_a?(IR::UnaryOp)
|
|
45
|
+
"#{node.operator}#{operand}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def emit_func_call(node)
|
|
49
|
+
func_name = function_name(node.name)
|
|
50
|
+
args = node.args.map { |arg| emit(arg) }.join(", ")
|
|
51
|
+
|
|
52
|
+
if node.receiver
|
|
53
|
+
receiver = emit(node.receiver)
|
|
54
|
+
"#{func_name}(#{receiver}, #{args})"
|
|
55
|
+
else
|
|
56
|
+
"#{func_name}(#{args})"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def emit_field_access(node)
|
|
61
|
+
"#{emit(node.receiver)}.#{node.field}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def emit_swizzle(node)
|
|
65
|
+
"#{emit(node.receiver)}.#{node.components}"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def emit_ternary(node)
|
|
69
|
+
"(#{emit(node.condition)} ? #{emit(node.then_expr)} : #{emit(node.else_expr)})"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def emit_assignment(node)
|
|
73
|
+
"#{emit(node.target)} = #{emit(node.value)}"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def emit_constant(node)
|
|
77
|
+
case node.name
|
|
78
|
+
when :PI
|
|
79
|
+
"3.14159265358979323846"
|
|
80
|
+
when :TAU
|
|
81
|
+
"6.28318530717958647692"
|
|
82
|
+
else
|
|
83
|
+
node.name.to_s
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def emit_parenthesized(node)
|
|
88
|
+
"(#{emit(node.expression)})"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def emit_array_index(node)
|
|
92
|
+
array = emit(node.array)
|
|
93
|
+
index = if node.index.is_a?(IR::Literal) && node.index.value.to_i == node.index.value
|
|
94
|
+
node.index.value.to_i.to_s
|
|
95
|
+
else
|
|
96
|
+
emit(node.index)
|
|
97
|
+
end
|
|
98
|
+
"#{array}[#{index}]"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def emit_typed_argument(node, _expected_type)
|
|
102
|
+
emit(node)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -0,0 +1,95 @@
|
|
|
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
|
+
if node.is_a?(IR::VarDecl)
|
|
31
|
+
return "#{emit_statement(node)}#{indent}return #{node.name};\n"
|
|
32
|
+
end
|
|
33
|
+
if node.is_a?(IR::Assignment)
|
|
34
|
+
return "#{emit_statement(node)}#{indent}return #{emit(node.target)};\n"
|
|
35
|
+
end
|
|
36
|
+
return emit_statement(node) if terminal_passthrough_node?(node)
|
|
37
|
+
return emit_tuple_return(node) if node.is_a?(IR::ArrayLiteral)
|
|
38
|
+
|
|
39
|
+
"#{indent}return #{emit_return_expression(node)};\n"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def emit_branch(node, needs_return:)
|
|
43
|
+
with_indent do
|
|
44
|
+
if node.is_a?(IR::Block)
|
|
45
|
+
emit(node, needs_return: needs_return)
|
|
46
|
+
else
|
|
47
|
+
emit_statement(node, needs_return: needs_return)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def emit_indented_block(node, needs_return: false)
|
|
53
|
+
with_indent do
|
|
54
|
+
if node.is_a?(IR::Block)
|
|
55
|
+
emit(node, needs_return: needs_return)
|
|
56
|
+
else
|
|
57
|
+
emit_statement(node, needs_return: needs_return)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def statement_terminator(node)
|
|
65
|
+
multiline_node?(node) ? "\n" : ";\n"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def multiline_node?(node)
|
|
69
|
+
MULTILINE_NODES.any? { |klass| node.is_a?(klass) }
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def terminal_passthrough_node?(node)
|
|
73
|
+
[
|
|
74
|
+
IR::Return,
|
|
75
|
+
IR::VarDecl,
|
|
76
|
+
IR::Assignment,
|
|
77
|
+
IR::ForLoop,
|
|
78
|
+
IR::WhileLoop,
|
|
79
|
+
IR::FunctionDefinition,
|
|
80
|
+
IR::GlobalDecl,
|
|
81
|
+
IR::MultipleAssignment
|
|
82
|
+
].any? { |klass| node.is_a?(klass) }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def with_indent
|
|
86
|
+
@indent_level += 1
|
|
87
|
+
yield
|
|
88
|
+
ensure
|
|
89
|
+
@indent_level -= 1
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|