rlsl 0.1.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.
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RLSL
4
+ module Prism
5
+ module Emitters
6
+ class CEmitter < BaseEmitter
7
+ TYPE_MAP = {
8
+ float: "float",
9
+ int: "int",
10
+ bool: "int",
11
+ vec2: "vec2",
12
+ vec3: "vec3",
13
+ vec4: "vec4",
14
+ mat2: "mat2",
15
+ mat3: "mat3",
16
+ mat4: "mat4",
17
+ sampler2D: "sampler2D"
18
+ }.freeze
19
+
20
+ VECTOR_CONSTRUCTORS = {
21
+ vec2: "vec2_new",
22
+ vec3: "vec3_new",
23
+ vec4: "vec4_new"
24
+ }.freeze
25
+
26
+ MATRIX_CONSTRUCTORS = {
27
+ mat2: "mat2_new",
28
+ mat3: "mat3_new",
29
+ mat4: "mat4_new"
30
+ }.freeze
31
+
32
+ TEXTURE_FUNCTIONS = {
33
+ texture2D: "texture_sample",
34
+ texture: "texture_sample",
35
+ textureLod: "texture_sample_lod"
36
+ }.freeze
37
+
38
+ VECTOR_OPS = {
39
+ "+" => "add",
40
+ "-" => "sub",
41
+ "*" => "mul",
42
+ "/" => "div"
43
+ }.freeze
44
+
45
+ MATH_FUNCTIONS = {
46
+ sin: "sinf",
47
+ cos: "cosf",
48
+ tan: "tanf",
49
+ asin: "asinf",
50
+ acos: "acosf",
51
+ atan: "atanf",
52
+ atan2: "atan2f",
53
+ sqrt: "sqrtf",
54
+ pow: "powf",
55
+ exp: "expf",
56
+ log: "logf",
57
+ abs: "fabsf",
58
+ floor: "floorf",
59
+ ceil: "ceilf",
60
+ min: "fminf",
61
+ max: "fmaxf",
62
+ fract: "fract",
63
+ mod: "fmodf",
64
+ clamp: "clamp_f",
65
+ mix: "mix_f",
66
+ smoothstep: "smoothstep",
67
+ length: "vec_length",
68
+ normalize: "vec_normalize",
69
+ dot: "vec_dot"
70
+ }.freeze
71
+
72
+ protected
73
+
74
+ def type_name(type)
75
+ TYPE_MAP[type&.to_sym] || "float"
76
+ end
77
+
78
+ def format_number(value)
79
+ formatted = super(value)
80
+ "#{formatted}f"
81
+ end
82
+
83
+ def emit_func_call(node)
84
+ name = node.name.to_sym
85
+
86
+ if VECTOR_CONSTRUCTORS.key?(name)
87
+ args = node.args.map { |arg| emit(arg) }.join(", ")
88
+ return "#{VECTOR_CONSTRUCTORS[name]}(#{args})"
89
+ end
90
+
91
+ if MATRIX_CONSTRUCTORS.key?(name)
92
+ args = node.args.map { |arg| emit(arg) }.join(", ")
93
+ return "#{MATRIX_CONSTRUCTORS[name]}(#{args})"
94
+ end
95
+
96
+ if TEXTURE_FUNCTIONS.key?(name)
97
+ args = node.args.map { |arg| emit(arg) }.join(", ")
98
+ return "#{TEXTURE_FUNCTIONS[name]}(#{args})"
99
+ end
100
+
101
+ if %i[length normalize dot].include?(name) && node.args.first&.type
102
+ vec_type = node.args.first.type
103
+ if %i[vec2 vec3 vec4].include?(vec_type)
104
+ func_name = "#{vec_type}_#{name}"
105
+ args = node.args.map { |arg| emit(arg) }.join(", ")
106
+ return "#{func_name}(#{args})"
107
+ end
108
+ end
109
+
110
+ if MATH_FUNCTIONS.key?(name)
111
+ func_name = MATH_FUNCTIONS[name]
112
+
113
+ if name == :mix && node.args.first&.type
114
+ first_type = node.args.first.type
115
+ if %i[vec2 vec3 vec4].include?(first_type)
116
+ func_name = "mix_v3"
117
+ end
118
+ end
119
+
120
+ args = node.args.map { |arg| emit(arg) }.join(", ")
121
+ return "#{func_name}(#{args})"
122
+ end
123
+
124
+ super
125
+ end
126
+
127
+ def emit_binary_op(node)
128
+ left_type = node.left.type
129
+ op = node.operator
130
+
131
+ if vector_type?(left_type) && VECTOR_OPS.key?(op)
132
+ vec_func = "#{left_type}_#{VECTOR_OPS[op]}"
133
+ left = emit(node.left)
134
+ right = emit(node.right)
135
+ return "#{vec_func}(#{left}, #{right})"
136
+ end
137
+
138
+ super
139
+ end
140
+
141
+ def emit_bool_literal(node)
142
+ node.value ? "1" : "0"
143
+ end
144
+
145
+ private
146
+
147
+ def vector_type?(type)
148
+ %i[vec2 vec3 vec4].include?(type)
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RLSL
4
+ module Prism
5
+ module Emitters
6
+ class GLSLEmitter < BaseEmitter
7
+ TYPE_MAP = {
8
+ float: "float",
9
+ int: "int",
10
+ bool: "bool",
11
+ vec2: "vec2",
12
+ vec3: "vec3",
13
+ vec4: "vec4",
14
+ mat2: "mat2",
15
+ mat3: "mat3",
16
+ mat4: "mat4",
17
+ sampler2D: "sampler2D"
18
+ }.freeze
19
+
20
+ VECTOR_CONSTRUCTORS = {
21
+ vec2: "vec2",
22
+ vec3: "vec3",
23
+ vec4: "vec4"
24
+ }.freeze
25
+
26
+ MATRIX_CONSTRUCTORS = {
27
+ mat2: "mat2",
28
+ mat3: "mat3",
29
+ mat4: "mat4"
30
+ }.freeze
31
+
32
+ TEXTURE_FUNCTIONS = {
33
+ texture2D: "texture2D",
34
+ texture: "texture",
35
+ textureLod: "textureLod"
36
+ }.freeze
37
+
38
+ protected
39
+
40
+ def type_name(type)
41
+ TYPE_MAP[type&.to_sym] || "float"
42
+ end
43
+
44
+ def emit_func_call(node)
45
+ name = node.name.to_sym
46
+
47
+ if VECTOR_CONSTRUCTORS.key?(name)
48
+ args = node.args.map { |arg| emit(arg) }.join(", ")
49
+ return "#{VECTOR_CONSTRUCTORS[name]}(#{args})"
50
+ end
51
+
52
+ if MATRIX_CONSTRUCTORS.key?(name)
53
+ args = node.args.map { |arg| emit(arg) }.join(", ")
54
+ return "#{MATRIX_CONSTRUCTORS[name]}(#{args})"
55
+ end
56
+
57
+ if TEXTURE_FUNCTIONS.key?(name)
58
+ args = node.args.map { |arg| emit(arg) }.join(", ")
59
+ return "#{TEXTURE_FUNCTIONS[name]}(#{args})"
60
+ end
61
+
62
+ args = node.args.map { |arg| emit(arg) }.join(", ")
63
+ "#{name}(#{args})"
64
+ end
65
+
66
+ def emit_binary_op(node)
67
+ left = emit_with_precedence(node.left, node.operator)
68
+ right = emit_with_precedence(node.right, node.operator)
69
+ "#{left} #{node.operator} #{right}"
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RLSL
4
+ module Prism
5
+ module Emitters
6
+ class MSLEmitter < BaseEmitter
7
+ TYPE_MAP = {
8
+ float: "float",
9
+ int: "int",
10
+ bool: "bool",
11
+ vec2: "float2",
12
+ vec3: "float3",
13
+ vec4: "float4",
14
+ mat2: "float2x2",
15
+ mat3: "float3x3",
16
+ mat4: "float4x4",
17
+ sampler2D: "texture2d<float>"
18
+ }.freeze
19
+
20
+ VECTOR_CONSTRUCTORS = {
21
+ vec2: "float2",
22
+ vec3: "float3",
23
+ vec4: "float4"
24
+ }.freeze
25
+
26
+ MATRIX_CONSTRUCTORS = {
27
+ mat2: "float2x2",
28
+ mat3: "float3x3",
29
+ mat4: "float4x4"
30
+ }.freeze
31
+
32
+ TEXTURE_FUNCTIONS = {
33
+ texture2D: "sample",
34
+ texture: "sample",
35
+ textureLod: "sample"
36
+ }.freeze
37
+
38
+ protected
39
+
40
+ def type_name(type)
41
+ TYPE_MAP[type&.to_sym] || "float"
42
+ end
43
+
44
+ def emit_func_call(node)
45
+ name = node.name.to_sym
46
+
47
+ if VECTOR_CONSTRUCTORS.key?(name)
48
+ args = node.args.map { |arg| emit(arg) }.join(", ")
49
+ return "#{VECTOR_CONSTRUCTORS[name]}(#{args})"
50
+ end
51
+
52
+ if MATRIX_CONSTRUCTORS.key?(name)
53
+ args = node.args.map { |arg| emit(arg) }.join(", ")
54
+ return "#{MATRIX_CONSTRUCTORS[name]}(#{args})"
55
+ end
56
+
57
+ # MSL texture sampling: texture.sample(sampler, uv)
58
+ if TEXTURE_FUNCTIONS.key?(name) && node.args.length >= 2
59
+ texture = emit(node.args[0])
60
+ uv = emit(node.args[1])
61
+ return "#{texture}.sample(textureSampler, #{uv})"
62
+ end
63
+
64
+ args = node.args.map { |arg| emit(arg) }.join(", ")
65
+ "#{name}(#{args})"
66
+ end
67
+
68
+ def emit_binary_op(node)
69
+ left = emit_with_precedence(node.left, node.operator)
70
+ right = emit_with_precedence(node.right, node.operator)
71
+ "#{left} #{node.operator} #{right}"
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RLSL
4
+ module Prism
5
+ module Emitters
6
+ class WGSLEmitter < BaseEmitter
7
+ TYPE_MAP = {
8
+ float: "f32",
9
+ int: "i32",
10
+ bool: "bool",
11
+ vec2: "vec2<f32>",
12
+ vec3: "vec3<f32>",
13
+ vec4: "vec4<f32>",
14
+ mat2: "mat2x2<f32>",
15
+ mat3: "mat3x3<f32>",
16
+ mat4: "mat4x4<f32>",
17
+ sampler2D: "texture_2d<f32>"
18
+ }.freeze
19
+
20
+ VECTOR_CONSTRUCTORS = {
21
+ vec2: "vec2<f32>",
22
+ vec3: "vec3<f32>",
23
+ vec4: "vec4<f32>"
24
+ }.freeze
25
+
26
+ MATRIX_CONSTRUCTORS = {
27
+ mat2: "mat2x2<f32>",
28
+ mat3: "mat3x3<f32>",
29
+ mat4: "mat4x4<f32>"
30
+ }.freeze
31
+
32
+ TEXTURE_FUNCTIONS = {
33
+ texture2D: "textureSample",
34
+ texture: "textureSample",
35
+ textureLod: "textureSampleLevel"
36
+ }.freeze
37
+
38
+ protected
39
+
40
+ def type_name(type)
41
+ TYPE_MAP[type&.to_sym] || "f32"
42
+ end
43
+
44
+ def emit_var_decl(node)
45
+ type = type_name(node.type || :float)
46
+ value = emit(node.initializer)
47
+ "let #{node.name}: #{type} = #{value}"
48
+ end
49
+
50
+ def emit_func_call(node)
51
+ name = node.name.to_sym
52
+
53
+ if VECTOR_CONSTRUCTORS.key?(name)
54
+ args = node.args.map { |arg| emit(arg) }.join(", ")
55
+ return "#{VECTOR_CONSTRUCTORS[name]}(#{args})"
56
+ end
57
+
58
+ if MATRIX_CONSTRUCTORS.key?(name)
59
+ args = node.args.map { |arg| emit(arg) }.join(", ")
60
+ return "#{MATRIX_CONSTRUCTORS[name]}(#{args})"
61
+ end
62
+
63
+ if TEXTURE_FUNCTIONS.key?(name)
64
+ args = node.args.map { |arg| emit(arg) }.join(", ")
65
+ return "#{TEXTURE_FUNCTIONS[name]}(#{args})"
66
+ end
67
+
68
+ args = node.args.map { |arg| emit(arg) }.join(", ")
69
+ "#{name}(#{args})"
70
+ end
71
+
72
+ def emit_for_loop(node)
73
+ var = node.variable
74
+ start_val = emit(node.range_start)
75
+ end_val = emit(node.range_end)
76
+ body = emit_indented_block(node.body)
77
+
78
+ "for (var #{var}: i32 = #{start_val}; #{var} < #{end_val}; #{var}++) {\n#{body}#{indent}}"
79
+ end
80
+
81
+ def emit_binary_op(node)
82
+ left = emit_with_precedence(node.left, node.operator)
83
+ right = emit_with_precedence(node.right, node.operator)
84
+ "#{left} #{node.operator} #{right}"
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end