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,197 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RLSL
4
+ module Prism
5
+ module Builtins
6
+ FUNCTIONS = {
7
+ vec2: { args: %i[any any], returns: :vec2, variadic: true, min_args: 1 },
8
+ vec3: { args: %i[any any any], returns: :vec3, variadic: true, min_args: 1 },
9
+ vec4: { args: %i[any any any any], returns: :vec4, variadic: true, min_args: 1 },
10
+
11
+ mat2: { args: %i[any any any any], returns: :mat2, variadic: true, min_args: 1 },
12
+ mat3: { args: %i[any any any any any any any any any], returns: :mat3, variadic: true, min_args: 1 },
13
+ mat4: { args: %i[any any any any any any any any any any any any any any any any], returns: :mat4, variadic: true, min_args: 1 },
14
+
15
+ sin: { args: [:float], returns: :float },
16
+ cos: { args: [:float], returns: :float },
17
+ tan: { args: [:float], returns: :float },
18
+ asin: { args: [:float], returns: :float },
19
+ acos: { args: [:float], returns: :float },
20
+ atan: { args: %i[float float], returns: :float, variadic: true, min_args: 1 },
21
+ atan2: { args: %i[float float], returns: :float },
22
+
23
+ pow: { args: %i[float float], returns: :float },
24
+ exp: { args: [:float], returns: :float },
25
+ log: { args: [:float], returns: :float },
26
+ sqrt: { args: [:any], returns: :same },
27
+
28
+ abs: { args: [:any], returns: :same },
29
+ sign: { args: [:any], returns: :same },
30
+ floor: { args: [:any], returns: :same },
31
+ ceil: { args: [:any], returns: :same },
32
+ fract: { args: [:any], returns: :same },
33
+ mod: { args: %i[any float], returns: :first },
34
+ min: { args: %i[any any], returns: :first },
35
+ max: { args: %i[any any], returns: :first },
36
+ clamp: { args: %i[any any any], returns: :first },
37
+ mix: { args: %i[any any float], returns: :first },
38
+ step: { args: %i[float any], returns: :second },
39
+ smoothstep: { args: %i[float float any], returns: :third },
40
+
41
+ length: { args: [:any], returns: :float },
42
+ distance: { args: %i[any any], returns: :float },
43
+ dot: { args: %i[any any], returns: :float },
44
+ cross: { args: %i[vec3 vec3], returns: :vec3 },
45
+ normalize: { args: [:any], returns: :same },
46
+ reflect: { args: %i[any any], returns: :first },
47
+ refract: { args: %i[any any float], returns: :first },
48
+
49
+ hash21: { args: [:vec2], returns: :float },
50
+ hash22: { args: [:vec2], returns: :vec2 },
51
+
52
+ lessThan: { args: %i[any any], returns: :bool },
53
+ lessThanEqual: { args: %i[any any], returns: :bool },
54
+ greaterThan: { args: %i[any any], returns: :bool },
55
+ greaterThanEqual: { args: %i[any any], returns: :bool },
56
+ equal: { args: %i[any any], returns: :bool },
57
+ notEqual: { args: %i[any any], returns: :bool },
58
+
59
+ inverse: { args: [:any], returns: :same },
60
+ transpose: { args: [:any], returns: :same },
61
+ determinant: { args: [:any], returns: :float },
62
+
63
+ texture2D: { args: %i[sampler2D vec2], returns: :vec4 },
64
+ texture: { args: %i[sampler2D vec2], returns: :vec4 },
65
+ textureLod: { args: %i[sampler2D vec2 float], returns: :vec4 }
66
+ }.freeze
67
+
68
+ BINARY_OPERATORS = {
69
+ "+" => :arithmetic,
70
+ "-" => :arithmetic,
71
+ "*" => :arithmetic,
72
+ "/" => :arithmetic,
73
+ "%" => :arithmetic,
74
+
75
+ "==" => :comparison,
76
+ "!=" => :comparison,
77
+ "<" => :comparison,
78
+ ">" => :comparison,
79
+ "<=" => :comparison,
80
+ ">=" => :comparison,
81
+
82
+ "&&" => :logical,
83
+ "||" => :logical
84
+ }.freeze
85
+
86
+ UNARY_OPERATORS = {
87
+ "-" => :negate,
88
+ "!" => :not
89
+ }.freeze
90
+
91
+ SWIZZLE_COMPONENTS = {
92
+ "x" => 0, "r" => 0, "s" => 0,
93
+ "y" => 1, "g" => 1, "t" => 1,
94
+ "z" => 2, "b" => 2, "p" => 2,
95
+ "w" => 3, "a" => 3, "q" => 3
96
+ }.freeze
97
+
98
+ SINGLE_COMPONENT_FIELDS = %w[x y z w r g b a s t p q].freeze
99
+
100
+ SWIZZLE_PATTERNS = /\A[xyzwrgba]{2,4}\z/
101
+
102
+ class << self
103
+ def function?(name)
104
+ FUNCTIONS.key?(name.to_sym)
105
+ end
106
+
107
+ def function_signature(name)
108
+ FUNCTIONS[name.to_sym]
109
+ end
110
+
111
+ def binary_operator?(op)
112
+ BINARY_OPERATORS.key?(op.to_s)
113
+ end
114
+
115
+ def unary_operator?(op)
116
+ UNARY_OPERATORS.key?(op.to_s)
117
+ end
118
+
119
+ def single_component_field?(name)
120
+ SINGLE_COMPONENT_FIELDS.include?(name.to_s)
121
+ end
122
+
123
+ def swizzle?(name)
124
+ name.to_s.match?(SWIZZLE_PATTERNS)
125
+ end
126
+
127
+ def swizzle_type(components)
128
+ case components.length
129
+ when 2 then :vec2
130
+ when 3 then :vec3
131
+ when 4 then :vec4
132
+ else :float
133
+ end
134
+ end
135
+
136
+ def resolve_return_type(rule, arg_types)
137
+ case rule
138
+ when :same then arg_types.first
139
+ when :first then arg_types.first
140
+ when :second then arg_types[1]
141
+ when :third then arg_types[2]
142
+ when Symbol then rule
143
+ end
144
+ end
145
+
146
+ def binary_op_result_type(op, left_type, right_type)
147
+ op_kind = BINARY_OPERATORS[op.to_s]
148
+
149
+ case op_kind
150
+ when :comparison, :logical
151
+ :bool
152
+ when :arithmetic
153
+ if matrix_type?(left_type) && vector_type?(right_type)
154
+ matrix_vector_result(left_type)
155
+ elsif vector_type?(left_type) && matrix_type?(right_type)
156
+ matrix_vector_result(right_type)
157
+ elsif matrix_type?(left_type) && matrix_type?(right_type)
158
+ left_type
159
+ elsif matrix_type?(left_type) && scalar_type?(right_type)
160
+ left_type
161
+ elsif scalar_type?(left_type) && matrix_type?(right_type)
162
+ right_type
163
+ elsif vector_type?(left_type) && vector_type?(right_type)
164
+ left_type
165
+ elsif vector_type?(left_type) && scalar_type?(right_type)
166
+ left_type
167
+ elsif scalar_type?(left_type) && vector_type?(right_type)
168
+ right_type
169
+ else
170
+ :float
171
+ end
172
+ end
173
+ end
174
+
175
+ def vector_type?(type)
176
+ %i[vec2 vec3 vec4].include?(type)
177
+ end
178
+
179
+ def matrix_type?(type)
180
+ %i[mat2 mat3 mat4].include?(type)
181
+ end
182
+
183
+ def scalar_type?(type)
184
+ %i[float int].include?(type)
185
+ end
186
+
187
+ def matrix_vector_result(matrix_type)
188
+ case matrix_type
189
+ when :mat2 then :vec2
190
+ when :mat3 then :vec3
191
+ when :mat4 then :vec4
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
@@ -0,0 +1,480 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RLSL
4
+ module Prism
5
+ module Emitters
6
+ class BaseEmitter
7
+ PRECEDENCE = {
8
+ "||" => 1,
9
+ "&&" => 2,
10
+ "==" => 3, "!=" => 3,
11
+ "<" => 4, ">" => 4, "<=" => 4, ">=" => 4,
12
+ "+" => 5, "-" => 5,
13
+ "*" => 6, "/" => 6, "%" => 6
14
+ }.freeze
15
+
16
+ attr_reader :indent_level
17
+
18
+ def initialize
19
+ @indent_level = 0
20
+ end
21
+
22
+ def emit(node, needs_return: false)
23
+ case node
24
+ when IR::Block
25
+ emit_block(node, needs_return: needs_return)
26
+ when IR::VarDecl
27
+ emit_var_decl(node)
28
+ when IR::VarRef
29
+ emit_var_ref(node)
30
+ when IR::Literal
31
+ emit_literal(node)
32
+ when IR::BoolLiteral
33
+ emit_bool_literal(node)
34
+ when IR::BinaryOp
35
+ emit_binary_op(node)
36
+ when IR::UnaryOp
37
+ emit_unary_op(node)
38
+ when IR::FuncCall
39
+ emit_func_call(node)
40
+ when IR::FieldAccess
41
+ emit_field_access(node)
42
+ when IR::Swizzle
43
+ emit_swizzle(node)
44
+ when IR::IfStatement
45
+ emit_if_statement(node)
46
+ when IR::Return
47
+ emit_return(node)
48
+ when IR::Assignment
49
+ emit_assignment(node)
50
+ when IR::ForLoop
51
+ emit_for_loop(node)
52
+ when IR::WhileLoop
53
+ emit_while_loop(node)
54
+ when IR::Break
55
+ emit_break(node)
56
+ when IR::Constant
57
+ emit_constant(node)
58
+ when IR::Parenthesized
59
+ emit_parenthesized(node)
60
+ when IR::FunctionDefinition
61
+ emit_function_definition(node)
62
+ when IR::ArrayLiteral
63
+ emit_array_literal(node)
64
+ when IR::ArrayIndex
65
+ emit_array_index(node)
66
+ when IR::GlobalDecl
67
+ emit_global_decl(node)
68
+ when IR::MultipleAssignment
69
+ emit_multiple_assignment(node)
70
+ else
71
+ raise "Unknown IR node: #{node.class}"
72
+ end
73
+ end
74
+
75
+ protected
76
+
77
+ def type_name(type)
78
+ type.to_s
79
+ end
80
+
81
+ def emit_block(node, needs_return: false)
82
+ statements = node.statements
83
+ return "" if statements.empty?
84
+
85
+ if needs_return && statements.any?
86
+ result = statements[0...-1].map { |stmt| emit_statement(stmt) }.join
87
+ result + emit_with_return(statements.last)
88
+ else
89
+ statements.map { |stmt| emit_statement(stmt) }.join
90
+ end
91
+ end
92
+
93
+ def emit_with_return(node)
94
+ if node.is_a?(IR::IfStatement)
95
+ emit_if_with_return(node)
96
+ elsif node.is_a?(IR::Return)
97
+ emit_statement(node)
98
+ elsif node.is_a?(IR::FunctionDefinition) || node.is_a?(IR::GlobalDecl) ||
99
+ node.is_a?(IR::MultipleAssignment)
100
+ emit_statement(node)
101
+ elsif node.is_a?(IR::ArrayLiteral)
102
+ emit_tuple_return(node)
103
+ else
104
+ "#{indent}return #{emit(node)};\n"
105
+ end
106
+ end
107
+
108
+ def emit_tuple_return(node)
109
+ elements = node.elements.map { |elem| emit(elem) }.join(", ")
110
+ "#{indent}return (#{current_return_struct_name}){#{elements}};\n"
111
+ end
112
+
113
+ def emit_if_with_return(node)
114
+ condition = emit(node.condition)
115
+ then_code = emit_branch_with_return(node.then_branch)
116
+
117
+ if node.else_branch
118
+ if elsif_node?(node.else_branch)
119
+ elsif_code = emit_elsif_with_return(node.else_branch)
120
+ "#{indent}if (#{condition}) {\n#{then_code}#{indent}} #{elsif_code}\n"
121
+ else
122
+ else_code = emit_branch_with_return(node.else_branch)
123
+ "#{indent}if (#{condition}) {\n#{then_code}#{indent}} else {\n#{else_code}#{indent}}\n"
124
+ end
125
+ else
126
+ "#{indent}if (#{condition}) {\n#{then_code}#{indent}}\n"
127
+ end
128
+ end
129
+
130
+ def emit_elsif_with_return(node)
131
+ if_node = node.is_a?(IR::Block) ? node.statements.first : node
132
+ condition = emit(if_node.condition)
133
+ then_code = emit_branch_with_return(if_node.then_branch)
134
+
135
+ if if_node.else_branch
136
+ if elsif_node?(if_node.else_branch)
137
+ elsif_code = emit_elsif_with_return(if_node.else_branch)
138
+ "else if (#{condition}) {\n#{then_code}#{indent}} #{elsif_code}"
139
+ else
140
+ else_code = emit_branch_with_return(if_node.else_branch)
141
+ "else if (#{condition}) {\n#{then_code}#{indent}} else {\n#{else_code}#{indent}}"
142
+ end
143
+ else
144
+ "else if (#{condition}) {\n#{then_code}#{indent}}"
145
+ end
146
+ end
147
+
148
+ def emit_branch_with_return(node)
149
+ @indent_level += 1
150
+ result = if node.is_a?(IR::Block)
151
+ emit_block(node, needs_return: true)
152
+ else
153
+ emit_with_return(node)
154
+ end
155
+ @indent_level -= 1
156
+ result
157
+ end
158
+
159
+ def emit_statement(node, needs_return: false)
160
+ if needs_return && !node.is_a?(IR::Return) && !node.is_a?(IR::IfStatement) &&
161
+ !node.is_a?(IR::ForLoop) && !node.is_a?(IR::WhileLoop) && !node.is_a?(IR::VarDecl) &&
162
+ !node.is_a?(IR::Assignment) && !node.is_a?(IR::FunctionDefinition) &&
163
+ !node.is_a?(IR::GlobalDecl) && !node.is_a?(IR::MultipleAssignment)
164
+ return "#{indent}return #{emit(node)};\n"
165
+ end
166
+
167
+ code = emit(node)
168
+ if node.is_a?(IR::IfStatement) || node.is_a?(IR::ForLoop) ||
169
+ node.is_a?(IR::WhileLoop) || node.is_a?(IR::FunctionDefinition)
170
+ "#{indent}#{code}\n"
171
+ else
172
+ "#{indent}#{code};\n"
173
+ end
174
+ end
175
+
176
+ def emit_var_decl(node)
177
+ type = type_name(node.type || :float)
178
+ value = emit(node.initializer)
179
+ "#{type} #{node.name} = #{value}"
180
+ end
181
+
182
+ def emit_var_ref(node)
183
+ node.name.to_s
184
+ end
185
+
186
+ def emit_literal(node)
187
+ format_number(node.value)
188
+ end
189
+
190
+ def emit_bool_literal(node)
191
+ node.value.to_s
192
+ end
193
+
194
+ def emit_binary_op(node)
195
+ left = emit_with_precedence(node.left, node.operator)
196
+ right = emit_with_precedence(node.right, node.operator)
197
+ "#{left} #{node.operator} #{right}"
198
+ end
199
+
200
+ def emit_unary_op(node)
201
+ operand = emit(node.operand)
202
+ "#{node.operator}#{operand}"
203
+ end
204
+
205
+ def emit_func_call(node)
206
+ func_name = function_name(node.name)
207
+ args = node.args.map { |arg| emit(arg) }.join(", ")
208
+
209
+ if node.receiver
210
+ receiver = emit(node.receiver)
211
+ "#{func_name}(#{receiver}, #{args})"
212
+ else
213
+ "#{func_name}(#{args})"
214
+ end
215
+ end
216
+
217
+ def emit_field_access(node)
218
+ receiver = emit(node.receiver)
219
+ "#{receiver}.#{node.field}"
220
+ end
221
+
222
+ def emit_swizzle(node)
223
+ receiver = emit(node.receiver)
224
+ "#{receiver}.#{node.components}"
225
+ end
226
+
227
+ def emit_if_statement(node)
228
+ condition = emit(node.condition)
229
+ then_code = emit_indented_block(node.then_branch)
230
+
231
+ if node.else_branch
232
+ if elsif_node?(node.else_branch)
233
+ elsif_code = emit_elsif(node.else_branch)
234
+ "if (#{condition}) {\n#{then_code}#{indent}} #{elsif_code}"
235
+ else
236
+ else_code = emit_indented_block(node.else_branch)
237
+ "if (#{condition}) {\n#{then_code}#{indent}} else {\n#{else_code}#{indent}}"
238
+ end
239
+ else
240
+ "if (#{condition}) {\n#{then_code}#{indent}}"
241
+ end
242
+ end
243
+
244
+ def elsif_node?(node)
245
+ return true if node.is_a?(IR::IfStatement)
246
+ return false unless node.is_a?(IR::Block)
247
+
248
+ node.statements.length == 1 && node.statements.first.is_a?(IR::IfStatement)
249
+ end
250
+
251
+ def emit_elsif(node)
252
+ if_node = node.is_a?(IR::Block) ? node.statements.first : node
253
+ condition = emit(if_node.condition)
254
+ then_code = emit_indented_block(if_node.then_branch)
255
+
256
+ if if_node.else_branch
257
+ if elsif_node?(if_node.else_branch)
258
+ elsif_code = emit_elsif(if_node.else_branch)
259
+ "else if (#{condition}) {\n#{then_code}#{indent}} #{elsif_code}"
260
+ else
261
+ else_code = emit_indented_block(if_node.else_branch)
262
+ "else if (#{condition}) {\n#{then_code}#{indent}} else {\n#{else_code}#{indent}}"
263
+ end
264
+ else
265
+ "else if (#{condition}) {\n#{then_code}#{indent}}"
266
+ end
267
+ end
268
+
269
+ def emit_return(node)
270
+ if node.expression
271
+ "return #{emit(node.expression)}"
272
+ else
273
+ "return"
274
+ end
275
+ end
276
+
277
+ def emit_assignment(node)
278
+ target = emit(node.target)
279
+ value = emit(node.value)
280
+ "#{target} = #{value}"
281
+ end
282
+
283
+ def emit_for_loop(node)
284
+ var = node.variable
285
+ start_val = emit(node.range_start)
286
+ end_val = emit(node.range_end)
287
+ body = emit_indented_block(node.body)
288
+
289
+ "for (int #{var} = #{start_val}; #{var} < #{end_val}; #{var}++) {\n#{body}#{indent}}"
290
+ end
291
+
292
+ def emit_while_loop(node)
293
+ condition = emit(node.condition)
294
+ body = emit_indented_block(node.body)
295
+
296
+ "while (#{condition}) {\n#{body}#{indent}}"
297
+ end
298
+
299
+ def emit_break(_node)
300
+ "break"
301
+ end
302
+
303
+ def emit_constant(node)
304
+ case node.name
305
+ when :PI
306
+ "3.14159265358979323846"
307
+ when :TAU
308
+ "6.28318530717958647692"
309
+ else
310
+ node.name.to_s
311
+ end
312
+ end
313
+
314
+ def emit_parenthesized(node)
315
+ "(#{emit(node.expression)})"
316
+ end
317
+
318
+ def emit_function_definition(node)
319
+ name = node.name
320
+ params = node.params.map do |param|
321
+ param_type = type_name(node.param_types[param] || :float)
322
+ "#{param_type} #{param}"
323
+ end.join(", ")
324
+
325
+ if node.return_type.is_a?(Array)
326
+ @current_return_struct_name = "#{name}_result"
327
+ struct_def = emit_result_struct(name, node.return_type)
328
+
329
+ body = emit_indented_block(node.body, needs_return: true)
330
+
331
+ @current_return_struct_name = nil
332
+ "#{struct_def}static inline #{name}_result #{name}(#{params}) {\n#{body}\n#{indent}}\n"
333
+ else
334
+ return_type = type_name(node.return_type || :float)
335
+
336
+ body = emit_indented_block(node.body, needs_return: true)
337
+
338
+ "static inline #{return_type} #{name}(#{params}) {\n#{body}\n#{indent}}\n"
339
+ end
340
+ end
341
+
342
+ def emit_result_struct(func_name, types)
343
+ fields = types.each_with_index.map do |t, i|
344
+ "#{type_name(t)} v#{i};"
345
+ end.join(" ")
346
+ "typedef struct { #{fields} } #{func_name}_result;\n"
347
+ end
348
+
349
+ def current_return_struct_name
350
+ @current_return_struct_name || "result"
351
+ end
352
+
353
+ def emit_array_literal(node, for_static_init: false)
354
+ elements = node.elements.map { |elem| emit_for_static_init(elem, for_static_init) }.join(", ")
355
+ "{#{elements}}"
356
+ end
357
+
358
+ def emit_for_static_init(node, for_static_init)
359
+ return emit(node) unless for_static_init
360
+
361
+ case node
362
+ when IR::FuncCall
363
+ if %i[vec2 vec3 vec4].include?(node.name)
364
+ args = node.args.map { |arg| emit_for_static_init(arg, true) }.join(", ")
365
+ "{#{args}}"
366
+ else
367
+ emit(node)
368
+ end
369
+ when IR::ArrayLiteral
370
+ emit_array_literal(node, for_static_init: true)
371
+ else
372
+ emit(node)
373
+ end
374
+ end
375
+
376
+ def emit_array_index(node)
377
+ array = emit(node.array)
378
+ index = if node.index.is_a?(IR::Literal) && node.index.value.to_i == node.index.value
379
+ node.index.value.to_i.to_s
380
+ else
381
+ emit(node.index)
382
+ end
383
+ "#{array}[#{index}]"
384
+ end
385
+
386
+ def emit_global_decl(node)
387
+ name = node.name
388
+
389
+ if node.initializer.is_a?(IR::ArrayLiteral)
390
+ elem_type = type_name(node.element_type || :float)
391
+ size = node.array_size || node.initializer.elements.length
392
+ elements = emit_array_literal(node.initializer, for_static_init: true)
393
+
394
+ prefix = ""
395
+ prefix += "static " if node.is_static
396
+ prefix += "const " if node.is_const
397
+
398
+ "#{prefix}#{elem_type} #{name}[#{size}] = #{elements}"
399
+ else
400
+ var_type = type_name(node.type || :float)
401
+ value = if node.is_const
402
+ emit_for_static_init(node.initializer, true)
403
+ else
404
+ emit(node.initializer)
405
+ end
406
+
407
+ prefix = ""
408
+ prefix += "static " if node.is_static
409
+ prefix += "const " if node.is_const
410
+
411
+ "#{prefix}#{var_type} #{name} = #{value}"
412
+ end
413
+ end
414
+
415
+ def emit_multiple_assignment(node)
416
+ value_code = emit(node.value)
417
+
418
+ if node.value.is_a?(IR::FuncCall)
419
+ func_name = node.value.name
420
+ struct_name = "#{func_name}_result"
421
+
422
+ lines = []
423
+ lines << "#{struct_name} _tmp_#{func_name} = #{value_code}"
424
+ node.targets.each_with_index do |target, i|
425
+ target_type = type_name(target.type || :float)
426
+ lines << "#{target_type} #{target.name} = _tmp_#{func_name}.v#{i}"
427
+ end
428
+ lines.join(";\n#{indent}")
429
+ else
430
+ lines = []
431
+ node.targets.each_with_index do |target, i|
432
+ target_type = type_name(target.type || :float)
433
+ lines << "#{target_type} #{target.name} = #{value_code}[#{i}]"
434
+ end
435
+ lines.join(";\n#{indent}")
436
+ end
437
+ end
438
+
439
+ def format_number(value)
440
+ if value.is_a?(Float)
441
+ formatted = value.to_s
442
+ formatted += ".0" unless formatted.include?(".")
443
+ formatted
444
+ else
445
+ "#{value}.0"
446
+ end
447
+ end
448
+
449
+ def indent
450
+ " " * @indent_level
451
+ end
452
+
453
+ def emit_indented_block(node, needs_return: false)
454
+ @indent_level += 1
455
+ result = if node.is_a?(IR::Block)
456
+ emit_block(node, needs_return: needs_return)
457
+ else
458
+ emit_statement(node, needs_return: needs_return)
459
+ end
460
+ @indent_level -= 1
461
+ result
462
+ end
463
+
464
+ def emit_with_precedence(node, parent_op)
465
+ code = emit(node)
466
+ if node.is_a?(IR::BinaryOp)
467
+ node_prec = PRECEDENCE[node.operator] || 10
468
+ parent_prec = PRECEDENCE[parent_op] || 10
469
+ return "(#{code})" if node_prec < parent_prec
470
+ end
471
+ code
472
+ end
473
+
474
+ def function_name(name)
475
+ name.to_s
476
+ end
477
+ end
478
+ end
479
+ end
480
+ end