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.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -1
  3. data/README.md +18 -1
  4. data/lib/rlsl/base_translator/call_parser.rb +68 -0
  5. data/lib/rlsl/base_translator/code_rewriter.rb +107 -0
  6. data/lib/rlsl/base_translator/code_scanner.rb +102 -0
  7. data/lib/rlsl/base_translator.rb +159 -63
  8. data/lib/rlsl/code_generator/math_prelude.rb +79 -0
  9. data/lib/rlsl/code_generator/ruby_wrapper_generator.rb +97 -0
  10. data/lib/rlsl/code_generator/shader_function_generator.rb +19 -0
  11. data/lib/rlsl/code_generator/template_context.rb +41 -0
  12. data/lib/rlsl/code_generator/uniform_struct_generator.rb +29 -0
  13. data/lib/rlsl/code_generator.rb +26 -201
  14. data/lib/rlsl/compiled_shader.rb +4 -12
  15. data/lib/rlsl/function_context.rb +31 -14
  16. data/lib/rlsl/glsl/translator.rb +19 -38
  17. data/lib/rlsl/msl/shader.rb +8 -38
  18. data/lib/rlsl/msl/translator.rb +19 -36
  19. data/lib/rlsl/msl/uniform_buffer_packer.rb +68 -0
  20. data/lib/rlsl/prism/ast_visitor/control_flow_visiting.rb +96 -0
  21. data/lib/rlsl/prism/ast_visitor/definition_visiting.rb +79 -0
  22. data/lib/rlsl/prism/ast_visitor/expression_visiting.rb +168 -0
  23. data/lib/rlsl/prism/ast_visitor/scope_context.rb +44 -0
  24. data/lib/rlsl/prism/ast_visitor/visitor_registry.rb +21 -0
  25. data/lib/rlsl/prism/ast_visitor.rb +54 -298
  26. data/lib/rlsl/prism/builtins/function_registry.rb +114 -0
  27. data/lib/rlsl/prism/builtins/operator_rules.rb +99 -0
  28. data/lib/rlsl/prism/builtins/swizzle_rules.rb +38 -0
  29. data/lib/rlsl/prism/builtins.rb +31 -148
  30. data/lib/rlsl/prism/compilation_unit.rb +7 -0
  31. data/lib/rlsl/prism/emitters/base_emitter/control_flow_emission.rb +83 -0
  32. data/lib/rlsl/prism/emitters/base_emitter/definition_emission.rb +104 -0
  33. data/lib/rlsl/prism/emitters/base_emitter/expression_emission.rb +92 -0
  34. data/lib/rlsl/prism/emitters/base_emitter/statement_emission.rb +89 -0
  35. data/lib/rlsl/prism/emitters/base_emitter.rb +68 -423
  36. data/lib/rlsl/prism/emitters/c_emitter.rb +78 -121
  37. data/lib/rlsl/prism/emitters/glsl_emitter.rb +30 -65
  38. data/lib/rlsl/prism/emitters/msl_emitter.rb +35 -62
  39. data/lib/rlsl/prism/emitters/target_emitter.rb +77 -0
  40. data/lib/rlsl/prism/emitters/target_profile.rb +34 -0
  41. data/lib/rlsl/prism/emitters/wgsl_emitter.rb +65 -61
  42. data/lib/rlsl/prism/ir/control_flow.rb +83 -0
  43. data/lib/rlsl/prism/ir/definitions.rb +67 -0
  44. data/lib/rlsl/prism/ir/expressions.rb +197 -0
  45. data/lib/rlsl/prism/ir/node.rb +21 -0
  46. data/lib/rlsl/prism/ir/nodes.rb +4 -371
  47. data/lib/rlsl/prism/ir/traversal.rb +62 -0
  48. data/lib/rlsl/prism/source_extractor/block_locator.rb +52 -0
  49. data/lib/rlsl/prism/source_extractor.rb +14 -133
  50. data/lib/rlsl/prism/source_unit/parser.rb +78 -0
  51. data/lib/rlsl/prism/source_unit.rb +42 -0
  52. data/lib/rlsl/prism/target_capability_validator.rb +85 -0
  53. data/lib/rlsl/prism/transpiler.rb +63 -60
  54. data/lib/rlsl/prism/type_inference/call_type_resolver.rb +35 -0
  55. data/lib/rlsl/prism/type_inference/call_validator.rb +71 -0
  56. data/lib/rlsl/prism/type_inference/collection_type_resolver.rb +80 -0
  57. data/lib/rlsl/prism/type_inference/control_flow_inferer.rb +66 -0
  58. data/lib/rlsl/prism/type_inference/definition_inferer.rb +41 -0
  59. data/lib/rlsl/prism/type_inference/expression_inferer.rb +92 -0
  60. data/lib/rlsl/prism/type_inference/field_type_resolver.rb +17 -0
  61. data/lib/rlsl/prism/type_inference/inferer_registry.rb +38 -0
  62. data/lib/rlsl/prism/type_inference/scope_stack.rb +47 -0
  63. data/lib/rlsl/prism/type_inference/type_environment.rb +112 -0
  64. data/lib/rlsl/prism/type_inference/type_shapes.rb +33 -0
  65. data/lib/rlsl/prism/type_inference.rb +114 -248
  66. data/lib/rlsl/runtime_shader.rb +47 -0
  67. data/lib/rlsl/shader_builder/build_service.rb +77 -0
  68. data/lib/rlsl/shader_builder/native_extension_compiler.rb +71 -0
  69. data/lib/rlsl/shader_builder/shader_definition.rb +68 -0
  70. data/lib/rlsl/shader_builder/source_resolver.rb +91 -0
  71. data/lib/rlsl/shader_builder.rb +22 -113
  72. data/lib/rlsl/types/catalog.rb +47 -0
  73. data/lib/rlsl/types/target_resolver.rb +15 -0
  74. data/lib/rlsl/types/type_spec.rb +167 -0
  75. data/lib/rlsl/types/value_normalizer.rb +81 -0
  76. data/lib/rlsl/types.rb +11 -29
  77. data/lib/rlsl/uniform_context.rb +6 -12
  78. data/lib/rlsl/version.rb +1 -1
  79. data/lib/rlsl/wgsl/translator.rb +23 -39
  80. data/lib/rlsl.rb +14 -12
  81. metadata +55 -16
@@ -1,9 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "base_emitter/control_flow_emission"
4
+ require_relative "base_emitter/expression_emission"
5
+ require_relative "base_emitter/definition_emission"
6
+ require_relative "base_emitter/statement_emission"
7
+
3
8
  module RLSL
4
9
  module Prism
5
10
  module Emitters
6
11
  class BaseEmitter
12
+ include ControlFlowEmission
13
+ include ExpressionEmission
14
+ include DefinitionEmission
15
+ include StatementEmission
16
+
7
17
  PRECEDENCE = {
8
18
  "||" => 1,
9
19
  "&&" => 2,
@@ -13,61 +23,55 @@ module RLSL
13
23
  "*" => 6, "/" => 6, "%" => 6
14
24
  }.freeze
15
25
 
26
+ MULTILINE_NODES = [
27
+ IR::IfStatement,
28
+ IR::ForLoop,
29
+ IR::WhileLoop,
30
+ IR::FunctionDefinition
31
+ ].freeze
32
+
33
+ {
34
+ block: :emit_block,
35
+ var_decl: :emit_var_decl,
36
+ var_ref: :emit_var_ref,
37
+ literal: :emit_literal,
38
+ bool_literal: :emit_bool_literal,
39
+ binary_op: :emit_binary_op,
40
+ unary_op: :emit_unary_op,
41
+ func_call: :emit_func_call,
42
+ field_access: :emit_field_access,
43
+ swizzle: :emit_swizzle,
44
+ if_statement: :emit_if_statement,
45
+ ternary: :emit_ternary,
46
+ return: :emit_return,
47
+ assignment: :emit_assignment,
48
+ for_loop: :emit_for_loop,
49
+ while_loop: :emit_while_loop,
50
+ break: :emit_break,
51
+ constant: :emit_constant,
52
+ parenthesized: :emit_parenthesized,
53
+ function_definition: :emit_function_definition,
54
+ array_literal: :emit_array_literal,
55
+ array_index: :emit_array_index,
56
+ global_decl: :emit_global_decl,
57
+ multiple_assignment: :emit_multiple_assignment
58
+ }.each do |visit_name, emitter_name|
59
+ define_method(:"visit_#{visit_name}") do |node|
60
+ send(emitter_name, node)
61
+ end
62
+ end
63
+
16
64
  attr_reader :indent_level
17
65
 
18
66
  def initialize
19
67
  @indent_level = 0
68
+ @return_context_stack = [false]
20
69
  end
21
70
 
22
71
  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
72
+ with_return_context(needs_return) do
73
+ return node.accept(self) if node.respond_to?(:accept)
74
+
71
75
  raise "Unknown IR node: #{node.class}"
72
76
  end
73
77
  end
@@ -78,364 +82,6 @@ module RLSL
78
82
  type.to_s
79
83
  end
80
84
 
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
85
  def format_number(value)
440
86
  if value.is_a?(Float)
441
87
  formatted = value.to_s
@@ -450,30 +96,29 @@ module RLSL
450
96
  " " * @indent_level
451
97
  end
452
98
 
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
99
  def emit_with_precedence(node, parent_op)
465
100
  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
101
+ return code unless node.is_a?(IR::BinaryOp)
102
+
103
+ node_prec = PRECEDENCE[node.operator] || 10
104
+ parent_prec = PRECEDENCE[parent_op] || 10
105
+ node_prec < parent_prec ? "(#{code})" : code
472
106
  end
473
107
 
474
108
  def function_name(name)
475
109
  name.to_s
476
110
  end
111
+
112
+ def with_return_context(enabled)
113
+ @return_context_stack << enabled
114
+ yield
115
+ ensure
116
+ @return_context_stack.pop
117
+ end
118
+
119
+ def return_context?
120
+ @return_context_stack.last
121
+ end
477
122
  end
478
123
  end
479
124
  end