alex-rkelly 1.0.5

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 (201) hide show
  1. data/.gemtest +0 -0
  2. data/CHANGELOG.rdoc +21 -0
  3. data/Manifest.txt +199 -0
  4. data/README.rdoc +58 -0
  5. data/Rakefile +38 -0
  6. data/lib/parser.y +871 -0
  7. data/lib/rkelly/constants.rb +3 -0
  8. data/lib/rkelly/generated_parser.rb +3274 -0
  9. data/lib/rkelly/js/array.rb +15 -0
  10. data/lib/rkelly/js/base.rb +91 -0
  11. data/lib/rkelly/js/boolean.rb +21 -0
  12. data/lib/rkelly/js/function.rb +39 -0
  13. data/lib/rkelly/js/function_prototype.rb +15 -0
  14. data/lib/rkelly/js/global_object.rb +52 -0
  15. data/lib/rkelly/js/math.rb +10 -0
  16. data/lib/rkelly/js/nan.rb +18 -0
  17. data/lib/rkelly/js/number.rb +22 -0
  18. data/lib/rkelly/js/object.rb +30 -0
  19. data/lib/rkelly/js/object_prototype.rb +14 -0
  20. data/lib/rkelly/js/property.rb +20 -0
  21. data/lib/rkelly/js/scope.rb +6 -0
  22. data/lib/rkelly/js/string.rb +21 -0
  23. data/lib/rkelly/js.rb +14 -0
  24. data/lib/rkelly/lexeme.rb +18 -0
  25. data/lib/rkelly/nodes/binary_node.rb +18 -0
  26. data/lib/rkelly/nodes/bracket_accessor_node.rb +11 -0
  27. data/lib/rkelly/nodes/case_clause_node.rb +11 -0
  28. data/lib/rkelly/nodes/comma_node.rb +11 -0
  29. data/lib/rkelly/nodes/conditional_node.rb +11 -0
  30. data/lib/rkelly/nodes/dot_accessor_node.rb +11 -0
  31. data/lib/rkelly/nodes/for_in_node.rb +12 -0
  32. data/lib/rkelly/nodes/for_node.rb +13 -0
  33. data/lib/rkelly/nodes/function_call_node.rb +16 -0
  34. data/lib/rkelly/nodes/function_decl_node.rb +6 -0
  35. data/lib/rkelly/nodes/function_expr_node.rb +12 -0
  36. data/lib/rkelly/nodes/if_node.rb +12 -0
  37. data/lib/rkelly/nodes/label_node.rb +11 -0
  38. data/lib/rkelly/nodes/new_expr_node.rb +11 -0
  39. data/lib/rkelly/nodes/node.rb +88 -0
  40. data/lib/rkelly/nodes/not_strict_equal_node.rb +6 -0
  41. data/lib/rkelly/nodes/op_equal_node.rb +16 -0
  42. data/lib/rkelly/nodes/postfix_node.rb +11 -0
  43. data/lib/rkelly/nodes/prefix_node.rb +6 -0
  44. data/lib/rkelly/nodes/property_node.rb +13 -0
  45. data/lib/rkelly/nodes/resolve_node.rb +19 -0
  46. data/lib/rkelly/nodes/strict_equal_node.rb +6 -0
  47. data/lib/rkelly/nodes/try_node.rb +13 -0
  48. data/lib/rkelly/nodes/var_decl_node.rb +15 -0
  49. data/lib/rkelly/nodes.rb +25 -0
  50. data/lib/rkelly/parser.rb +104 -0
  51. data/lib/rkelly/runtime/ruby_function.rb +13 -0
  52. data/lib/rkelly/runtime/scope_chain.rb +57 -0
  53. data/lib/rkelly/runtime.rb +36 -0
  54. data/lib/rkelly/syntax_error.rb +4 -0
  55. data/lib/rkelly/token.rb +15 -0
  56. data/lib/rkelly/tokenizer.rb +152 -0
  57. data/lib/rkelly/visitable.rb +16 -0
  58. data/lib/rkelly/visitors/dot_visitor.rb +228 -0
  59. data/lib/rkelly/visitors/ecma_visitor.rb +322 -0
  60. data/lib/rkelly/visitors/enumerable_visitor.rb +18 -0
  61. data/lib/rkelly/visitors/evaluation_visitor.rb +419 -0
  62. data/lib/rkelly/visitors/function_visitor.rb +46 -0
  63. data/lib/rkelly/visitors/pointcut_visitor.rb +31 -0
  64. data/lib/rkelly/visitors/real_sexp_visitor.rb +16 -0
  65. data/lib/rkelly/visitors/sexp_visitor.rb +373 -0
  66. data/lib/rkelly/visitors/visitor.rb +136 -0
  67. data/lib/rkelly/visitors.rb +4 -0
  68. data/lib/rkelly.rb +14 -0
  69. data/test/ecma_script_test_case.rb +21 -0
  70. data/test/execute_test_case.rb +16 -0
  71. data/test/execution_contexts/test_10_1_3-1.rb +32 -0
  72. data/test/expressions/test_11_3_1.rb +64 -0
  73. data/test/expressions/test_11_3_2.rb +64 -0
  74. data/test/expressions/test_11_4_2.rb +13 -0
  75. data/test/expressions/test_11_4_3.rb +52 -0
  76. data/test/expressions/test_11_4_4.rb +68 -0
  77. data/test/expressions/test_11_4_5.rb +69 -0
  78. data/test/expressions/test_11_4_6.rb +88 -0
  79. data/test/expressions/test_11_4_8.rb +28 -0
  80. data/test/expressions/test_11_4_9.rb +103 -0
  81. data/test/expressions/test_11_5_1.rb +51 -0
  82. data/test/expressions/test_11_5_2.rb +80 -0
  83. data/test/expressions/test_11_5_3.rb +88 -0
  84. data/test/expressions/test_11_6_1-1.rb +19 -0
  85. data/test/expressions/test_11_9_1.rb +19 -0
  86. data/test/function/test_15_3_1_1-1.rb +34 -0
  87. data/test/global_object/test_15_1_1_1.rb +29 -0
  88. data/test/global_object/test_15_1_1_2.rb +17 -0
  89. data/test/global_object/test_15_1_1_3.rb +9 -0
  90. data/test/helper.rb +5 -0
  91. data/test/node_test_case.rb +11 -0
  92. data/test/object/test_15_2_1_1.rb +257 -0
  93. data/test/object/test_15_2_1_2.rb +21 -0
  94. data/test/object/test_15_2_2_1.rb +52 -0
  95. data/test/statements/test_12_5-1.rb +27 -0
  96. data/test/test_add_node.rb +8 -0
  97. data/test/test_arguments_node.rb +8 -0
  98. data/test/test_array_node.rb +9 -0
  99. data/test/test_assign_expr_node.rb +8 -0
  100. data/test/test_automatic_semicolon_insertion.rb +137 -0
  101. data/test/test_bit_and_node.rb +8 -0
  102. data/test/test_bit_or_node.rb +8 -0
  103. data/test/test_bit_x_or_node.rb +8 -0
  104. data/test/test_bitwise_not_node.rb +8 -0
  105. data/test/test_block_node.rb +14 -0
  106. data/test/test_bracket_accessor_node.rb +16 -0
  107. data/test/test_break_node.rb +11 -0
  108. data/test/test_case_block_node.rb +11 -0
  109. data/test/test_case_clause_node.rb +15 -0
  110. data/test/test_comma_node.rb +13 -0
  111. data/test/test_comments.rb +44 -0
  112. data/test/test_conditional_node.rb +17 -0
  113. data/test/test_const_statement_node.rb +14 -0
  114. data/test/test_continue_node.rb +11 -0
  115. data/test/test_delete_node.rb +8 -0
  116. data/test/test_divide_node.rb +8 -0
  117. data/test/test_do_while_node.rb +13 -0
  118. data/test/test_dot_accessor_node.rb +9 -0
  119. data/test/test_ecma_visitor.rb +210 -0
  120. data/test/test_element_node.rb +8 -0
  121. data/test/test_empty_statement_node.rb +8 -0
  122. data/test/test_equal_node.rb +8 -0
  123. data/test/test_evaluation_visitor.rb +66 -0
  124. data/test/test_expression_statement_node.rb +10 -0
  125. data/test/test_false_node.rb +8 -0
  126. data/test/test_for_in_node.rb +17 -0
  127. data/test/test_for_node.rb +24 -0
  128. data/test/test_function_body_node.rb +8 -0
  129. data/test/test_function_call_node.rb +10 -0
  130. data/test/test_function_decl_node.rb +16 -0
  131. data/test/test_function_expr_node.rb +16 -0
  132. data/test/test_function_visitor.rb +26 -0
  133. data/test/test_getter_property_node.rb +10 -0
  134. data/test/test_global_object.rb +49 -0
  135. data/test/test_greater_node.rb +8 -0
  136. data/test/test_greater_or_equal_node.rb +8 -0
  137. data/test/test_if_node.rb +17 -0
  138. data/test/test_in_node.rb +8 -0
  139. data/test/test_instance_of_node.rb +8 -0
  140. data/test/test_label_node.rb +13 -0
  141. data/test/test_left_shift_node.rb +8 -0
  142. data/test/test_less_node.rb +8 -0
  143. data/test/test_less_or_equal_node.rb +8 -0
  144. data/test/test_line_number.rb +23 -0
  145. data/test/test_logical_and_node.rb +8 -0
  146. data/test/test_logical_not_node.rb +8 -0
  147. data/test/test_logical_or_node.rb +8 -0
  148. data/test/test_modulus_node.rb +8 -0
  149. data/test/test_multiply_node.rb +8 -0
  150. data/test/test_new_expr_node.rb +9 -0
  151. data/test/test_not_equal_node.rb +8 -0
  152. data/test/test_not_strict_equal_node.rb +8 -0
  153. data/test/test_null_node.rb +8 -0
  154. data/test/test_number_node.rb +8 -0
  155. data/test/test_object_literal_node.rb +9 -0
  156. data/test/test_op_and_equal_node.rb +10 -0
  157. data/test/test_op_divide_equal_node.rb +10 -0
  158. data/test/test_op_equal_node.rb +10 -0
  159. data/test/test_op_l_shift_equal_node.rb +10 -0
  160. data/test/test_op_minus_equal_node.rb +10 -0
  161. data/test/test_op_mod_equal_node.rb +10 -0
  162. data/test/test_op_multiply_equal_node.rb +10 -0
  163. data/test/test_op_or_equal_node.rb +10 -0
  164. data/test/test_op_plus_equal_node.rb +10 -0
  165. data/test/test_op_r_shift_equal_node.rb +10 -0
  166. data/test/test_op_u_r_shift_equal_node.rb +10 -0
  167. data/test/test_op_x_or_equal_node.rb +10 -0
  168. data/test/test_parameter_node.rb +8 -0
  169. data/test/test_parser.rb +1361 -0
  170. data/test/test_pointcut_visitor.rb +34 -0
  171. data/test/test_postfix_node.rb +8 -0
  172. data/test/test_prefix_node.rb +8 -0
  173. data/test/test_property_node.rb +8 -0
  174. data/test/test_regexp_node.rb +8 -0
  175. data/test/test_resolve_node.rb +22 -0
  176. data/test/test_return_node.rb +11 -0
  177. data/test/test_right_shift_node.rb +8 -0
  178. data/test/test_rkelly.rb +19 -0
  179. data/test/test_runtime.rb +12 -0
  180. data/test/test_scope_chain.rb +50 -0
  181. data/test/test_setter_property_node.rb +10 -0
  182. data/test/test_source_elements.rb +9 -0
  183. data/test/test_strict_equal_node.rb +8 -0
  184. data/test/test_string_node.rb +8 -0
  185. data/test/test_subtract_node.rb +8 -0
  186. data/test/test_switch_node.rb +12 -0
  187. data/test/test_this_node.rb +8 -0
  188. data/test/test_throw_node.rb +7 -0
  189. data/test/test_tokenizer.rb +191 -0
  190. data/test/test_true_node.rb +8 -0
  191. data/test/test_try_node.rb +59 -0
  192. data/test/test_type_of_node.rb +8 -0
  193. data/test/test_unary_minus_node.rb +8 -0
  194. data/test/test_unary_plus_node.rb +8 -0
  195. data/test/test_unsigned_right_shift_node.rb +8 -0
  196. data/test/test_var_decl_node.rb +21 -0
  197. data/test/test_var_statement_node.rb +14 -0
  198. data/test/test_void_node.rb +8 -0
  199. data/test/test_while_node.rb +15 -0
  200. data/test/test_with_node.rb +8 -0
  201. metadata +410 -0
@@ -0,0 +1,228 @@
1
+ module RKelly
2
+ module Visitors
3
+ class DotVisitor < Visitor
4
+ class Node < Struct.new(:node_id, :fields)
5
+ ESCAPE = /([<>"\\])/
6
+ def to_s
7
+ counter = 0
8
+ label = fields.map { |f|
9
+ s = "<f#{counter}> #{f.to_s.gsub(ESCAPE, '\\\\\1').gsub(/[\r\n]/,' ')}"
10
+ counter += 1
11
+ s
12
+ }.join('|')
13
+ "\"#{node_id}\" [\nlabel = \"#{label}\"\nshape = \"record\"\n];"
14
+ end
15
+ end
16
+
17
+ class Arrow < Struct.new(:from, :to, :label)
18
+ def to_s
19
+ "\"#{from.node_id}\":f0 -> \"#{to.node_id}\":f0"
20
+ end
21
+ end
22
+
23
+ attr_reader :nodes, :arrows
24
+ def initialize
25
+ @stack = []
26
+ @node_index = 0
27
+ @nodes = []
28
+ @arrows = []
29
+ end
30
+
31
+ ## Terminal nodes
32
+ %w{
33
+ BreakNode ContinueNode EmptyStatementNode FalseNode
34
+ NullNode NumberNode ParameterNode RegexpNode ResolveNode StringNode
35
+ ThisNode TrueNode
36
+ }.each do |type|
37
+ define_method(:"visit_#{type}") do |o|
38
+ node = Node.new(@node_index += 1, [type, o.value].compact)
39
+ add_arrow_for(node)
40
+ @nodes << node
41
+ end
42
+ end
43
+ ## End Terminal nodes
44
+
45
+ # Single value nodes
46
+ %w{
47
+ AssignExprNode BitwiseNotNode BlockNode DeleteNode ElementNode
48
+ ExpressionStatementNode FunctionBodyNode LogicalNotNode ReturnNode
49
+ ThrowNode TypeOfNode UnaryMinusNode UnaryPlusNode VoidNode
50
+ }.each do |type|
51
+ define_method(:"visit_#{type}") do |o|
52
+ node = Node.new(@node_index += 1, [type])
53
+ add_arrow_for(node)
54
+ @nodes << node
55
+ @stack.push(node)
56
+ o.value && o.value.accept(self)
57
+ @stack.pop
58
+ end
59
+ end
60
+ # End Single value nodes
61
+
62
+ # Binary nodes
63
+ %w{
64
+ AddNode BitAndNode BitOrNode BitXOrNode CaseClauseNode CommaNode
65
+ DivideNode DoWhileNode EqualNode GreaterNode GreaterOrEqualNode InNode
66
+ InstanceOfNode LeftShiftNode LessNode LessOrEqualNode LogicalAndNode
67
+ LogicalOrNode ModulusNode MultiplyNode NotEqualNode NotStrictEqualNode
68
+ OpAndEqualNode OpDivideEqualNode OpEqualNode OpLShiftEqualNode
69
+ OpMinusEqualNode OpModEqualNode OpMultiplyEqualNode OpOrEqualNode
70
+ OpPlusEqualNode OpRShiftEqualNode OpURShiftEqualNode OpXOrEqualNode
71
+ RightShiftNode StrictEqualNode SubtractNode SwitchNode
72
+ UnsignedRightShiftNode WhileNode WithNode
73
+ }.each do |type|
74
+ define_method(:"visit_#{type}") do |o|
75
+ node = Node.new(@node_index += 1, [type])
76
+ add_arrow_for(node)
77
+ @nodes << node
78
+ @stack.push(node)
79
+ o.left && o.left.accept(self)
80
+ o.value && o.value.accept(self)
81
+ @stack.pop
82
+ end
83
+ end
84
+ # End Binary nodes
85
+
86
+ # Array Value Nodes
87
+ %w{
88
+ ArgumentsNode ArrayNode CaseBlockNode ConstStatementNode
89
+ ObjectLiteralNode SourceElementsNode VarStatementNode
90
+ }.each do |type|
91
+ define_method(:"visit_#{type}") do |o|
92
+ node = Node.new(@node_index += 1, [type])
93
+ add_arrow_for(node)
94
+ @nodes << node
95
+ @stack.push(node)
96
+ o.value && o.value.each { |v| v && v.accept(self) }
97
+ @stack.pop
98
+ end
99
+ end
100
+ # END Array Value Nodes
101
+
102
+ # Name and Value Nodes
103
+ %w{
104
+ LabelNode PropertyNode GetterPropertyNode SetterPropertyNode VarDeclNode
105
+ }.each do |type|
106
+ define_method(:"visit_#{type}") do |o|
107
+ node = Node.new(@node_index += 1, [type, o.name || 'NULL'])
108
+ add_arrow_for(node)
109
+ @nodes << node
110
+ @stack.push(node)
111
+ o.value && o.value.accept(self)
112
+ @stack.pop
113
+ end
114
+ end
115
+ # END Name and Value Nodes
116
+
117
+ %w{ PostfixNode PrefixNode }.each do |type|
118
+ define_method(:"visit_#{type}") do |o|
119
+ node = Node.new(@node_index += 1, [type, o.value])
120
+ add_arrow_for(node)
121
+ @nodes << node
122
+ @stack.push(node)
123
+ o.operand && o.operand.accept(self)
124
+ @stack.pop
125
+ end
126
+ end
127
+
128
+ def visit_ForNode(o)
129
+ node = Node.new(@node_index += 1, ['ForNode'])
130
+ add_arrow_for(node)
131
+ @nodes << node
132
+ @stack.push(node)
133
+ [:init, :test, :counter, :value].each do |method|
134
+ o.send(method) && o.send(method).accept(self)
135
+ end
136
+ @stack.pop
137
+ end
138
+
139
+ %w{ IfNode ConditionalNode }.each do |type|
140
+ define_method(:"visit_#{type}") do |o|
141
+ node = Node.new(@node_index += 1, [type])
142
+ add_arrow_for(node)
143
+ @nodes << node
144
+ @stack.push(node)
145
+ [:conditions, :value, :else].each do |method|
146
+ o.send(method) && o.send(method).accept(self)
147
+ end
148
+ @stack.pop
149
+ end
150
+ end
151
+
152
+ def visit_ForInNode(o)
153
+ node = Node.new(@node_index += 1, ['ForInNode'])
154
+ add_arrow_for(node)
155
+ @nodes << node
156
+ @stack.push(node)
157
+ [:left, :right, :value].each do |method|
158
+ o.send(method) && o.send(method).accept(self)
159
+ end
160
+ @stack.pop
161
+ end
162
+
163
+ def visit_TryNode(o)
164
+ node = Node.new(@node_index += 1, ['TryNode', o.catch_var || 'NULL'])
165
+ add_arrow_for(node)
166
+ @nodes << node
167
+ @stack.push(node)
168
+ [:value, :catch_block, :finally_block].each do |method|
169
+ o.send(method) && o.send(method).accept(self)
170
+ end
171
+ @stack.pop
172
+ end
173
+
174
+ def visit_BracketAccessorNode(o)
175
+ node = Node.new(@node_index += 1, ['BracketAccessorNode'])
176
+ add_arrow_for(node)
177
+ @nodes << node
178
+ @stack.push(node)
179
+ [:value, :accessor].each do |method|
180
+ o.send(method) && o.send(method).accept(self)
181
+ end
182
+ @stack.pop
183
+ end
184
+
185
+ %w{ NewExprNode FunctionCallNode }.each do |type|
186
+ define_method(:"visit_#{type}") do |o|
187
+ node = Node.new(@node_index += 1, [type])
188
+ add_arrow_for(node)
189
+ @nodes << node
190
+ @stack.push(node)
191
+ [:value, :arguments].each do |method|
192
+ o.send(method) && o.send(method).accept(self)
193
+ end
194
+ @stack.pop
195
+ end
196
+ end
197
+
198
+ %w{ FunctionExprNode FunctionDeclNode }.each do |type|
199
+ define_method(:"visit_#{type}") do |o|
200
+ node = Node.new(@node_index += 1, [type, o.value || 'NULL'])
201
+ add_arrow_for(node)
202
+ @nodes << node
203
+ @stack.push(node)
204
+ o.arguments.each { |a| a && a.accept(self) }
205
+ o.function_body && o.function_body.accept(self)
206
+ @stack.pop
207
+ end
208
+ end
209
+
210
+ def visit_DotAccessorNode(o)
211
+ node = Node.new(@node_index += 1, ['DotAccessorNode', o.accessor])
212
+ add_arrow_for(node)
213
+ @nodes << node
214
+ @stack.push(node)
215
+ [:value].each do |method|
216
+ o.send(method) && o.send(method).accept(self)
217
+ end
218
+ @stack.pop
219
+ end
220
+
221
+ private
222
+ def add_arrow_for(node, label = nil)
223
+ @arrows << Arrow.new(@stack.last, node, label) if @stack.length > 0
224
+ end
225
+
226
+ end
227
+ end
228
+ end
@@ -0,0 +1,322 @@
1
+ module RKelly
2
+ module Visitors
3
+ class ECMAVisitor < Visitor
4
+ def initialize
5
+ @indent = 0
6
+ end
7
+
8
+ def visit_ParentheticalNode(o)
9
+ "(#{o.value.accept(self)})"
10
+ end
11
+
12
+ def visit_SourceElementsNode(o)
13
+ o.value.map { |x| "#{indent}#{x.accept(self)}" }.join("\n")
14
+ end
15
+
16
+ def visit_VarStatementNode(o)
17
+ "var #{o.value.map { |x| x.accept(self) }.join(', ')};"
18
+ end
19
+
20
+ def visit_ConstStatementNode(o)
21
+ "const #{o.value.map { |x| x.accept(self) }.join(', ')};"
22
+ end
23
+
24
+ def visit_VarDeclNode(o)
25
+ "#{o.name}#{o.value ? o.value.accept(self) : nil}"
26
+ end
27
+
28
+ def visit_AssignExprNode(o)
29
+ " = #{o.value.accept(self)}"
30
+ end
31
+
32
+ def visit_NumberNode(o)
33
+ o.value.to_s
34
+ end
35
+
36
+ def visit_ForNode(o)
37
+ init = o.init ? o.init.accept(self) : ';'
38
+ init << ';' unless init.end_with? ';' # make sure it has a ;
39
+ test = o.test ? o.test.accept(self) : ''
40
+ counter = o.counter ? o.counter.accept(self) : ''
41
+ "for(#{init} #{test}; #{counter}) #{o.value.accept(self)}"
42
+ end
43
+
44
+ def visit_LessNode(o)
45
+ "#{o.left.accept(self)} < #{o.value.accept(self)}"
46
+ end
47
+
48
+ def visit_ResolveNode(o)
49
+ o.value
50
+ end
51
+
52
+ def visit_PostfixNode(o)
53
+ "#{o.operand.accept(self)}#{o.value}"
54
+ end
55
+
56
+ def visit_PrefixNode(o)
57
+ "#{o.value}#{o.operand.accept(self)}"
58
+ end
59
+
60
+ def visit_BlockNode(o)
61
+ @indent += 1
62
+ "{\n#{o.value.accept(self)}\n#{@indent -=1; indent}}"
63
+ end
64
+
65
+ def visit_ExpressionStatementNode(o)
66
+ "#{o.value.accept(self)};"
67
+ end
68
+
69
+ def visit_OpEqualNode(o)
70
+ "#{o.left.accept(self)} = #{o.value.accept(self)}"
71
+ end
72
+
73
+ def visit_FunctionCallNode(o)
74
+ "#{o.value.accept(self)}(#{o.arguments.accept(self)})"
75
+ end
76
+
77
+ def visit_ArgumentsNode(o)
78
+ o.value.map { |x| x.accept(self) }.join(', ')
79
+ end
80
+
81
+ def visit_StringNode(o)
82
+ o.value
83
+ end
84
+
85
+ def visit_NullNode(o)
86
+ "null"
87
+ end
88
+
89
+ def visit_FunctionDeclNode(o)
90
+ "#{indent}function #{o.value}(" +
91
+ "#{o.arguments.map { |x| x.accept(self) }.join(', ')})" +
92
+ "#{o.function_body.accept(self)}"
93
+ end
94
+
95
+ def visit_ParameterNode(o)
96
+ o.value
97
+ end
98
+
99
+ def visit_FunctionBodyNode(o)
100
+ @indent += 1
101
+ "{\n#{o.value.accept(self)}\n#{@indent -=1; indent}}"
102
+ end
103
+
104
+ def visit_BreakNode(o)
105
+ "break" + (o.value ? " #{o.value}" : '') + ';'
106
+ end
107
+
108
+ def visit_ContinueNode(o)
109
+ "continue" + (o.value ? " #{o.value}" : '') + ';'
110
+ end
111
+
112
+ def visit_TrueNode(o)
113
+ "true"
114
+ end
115
+
116
+ def visit_FalseNode(o)
117
+ "false"
118
+ end
119
+
120
+ def visit_EmptyStatementNode(o)
121
+ ';'
122
+ end
123
+
124
+ def visit_RegexpNode(o)
125
+ o.value
126
+ end
127
+
128
+ def visit_DotAccessorNode(o)
129
+ "#{o.value.accept(self)}.#{o.accessor}"
130
+ end
131
+
132
+ def visit_ThisNode(o)
133
+ "this"
134
+ end
135
+
136
+ def visit_BitwiseNotNode(o)
137
+ "~#{o.value.accept(self)}"
138
+ end
139
+
140
+ def visit_DeleteNode(o)
141
+ "delete #{o.value.accept(self)}"
142
+ end
143
+
144
+ def visit_ArrayNode(o)
145
+ "[#{o.value.map { |x| x ? x.accept(self) : '' }.join(', ')}]"
146
+ end
147
+
148
+ def visit_ElementNode(o)
149
+ o.value.accept(self)
150
+ end
151
+
152
+ def visit_LogicalNotNode(o)
153
+ "!#{o.value.accept(self)}"
154
+ end
155
+
156
+ def visit_UnaryMinusNode(o)
157
+ "-#{o.value.accept(self)}"
158
+ end
159
+
160
+ def visit_UnaryPlusNode(o)
161
+ "+#{o.value.accept(self)}"
162
+ end
163
+
164
+ def visit_ReturnNode(o)
165
+ "return" + (o.value ? " #{o.value.accept(self)}" : '') + ';'
166
+ end
167
+
168
+ def visit_ThrowNode(o)
169
+ "throw #{o.value.accept(self)};"
170
+ end
171
+
172
+ def visit_TypeOfNode(o)
173
+ "typeof #{o.value.accept(self)}"
174
+ end
175
+
176
+ def visit_VoidNode(o)
177
+ "void(#{o.value.accept(self)})"
178
+ end
179
+
180
+ [
181
+ [:Add, '+'],
182
+ [:BitAnd, '&'],
183
+ [:BitOr, '|'],
184
+ [:BitXOr, '^'],
185
+ [:Divide, '/'],
186
+ [:Equal, '=='],
187
+ [:Greater, '>'],
188
+ [:GreaterOrEqual, '>='],
189
+ [:In, 'in'],
190
+ [:InstanceOf, 'instanceof'],
191
+ [:LeftShift, '<<'],
192
+ [:LessOrEqual, '<='],
193
+ [:LogicalAnd, '&&'],
194
+ [:LogicalOr, '||'],
195
+ [:Modulus, '%'],
196
+ [:Multiply, '*'],
197
+ [:NotEqual, '!='],
198
+ [:NotStrictEqual, '!=='],
199
+ [:OpAndEqual, '&='],
200
+ [:OpDivideEqual, '/='],
201
+ [:OpLShiftEqual, '<<='],
202
+ [:OpMinusEqual, '-='],
203
+ [:OpModEqual, '%='],
204
+ [:OpMultiplyEqual, '*='],
205
+ [:OpOrEqual, '|='],
206
+ [:OpPlusEqual, '+='],
207
+ [:OpRShiftEqual, '>>='],
208
+ [:OpURShiftEqual, '>>>='],
209
+ [:OpXOrEqual, '^='],
210
+ [:RightShift, '>>'],
211
+ [:StrictEqual, '==='],
212
+ [:Subtract, '-'],
213
+ [:UnsignedRightShift, '>>>'],
214
+ ].each do |name,op|
215
+ define_method(:"visit_#{name}Node") do |o|
216
+ "#{o.left.accept(self)} #{op} #{o.value.accept(self)}"
217
+ end
218
+ end
219
+
220
+ def visit_WhileNode(o)
221
+ "while(#{o.left.accept(self)}) #{o.value.accept(self)}"
222
+ end
223
+
224
+ def visit_SwitchNode(o)
225
+ "switch(#{o.left.accept(self)}) #{o.value.accept(self)}"
226
+ end
227
+
228
+ def visit_CaseBlockNode(o)
229
+ @indent += 1
230
+ "{\n" + (o.value ? o.value.map { |x| x.accept(self) }.join('') : '') +
231
+ "#{@indent -=1; indent}}"
232
+ end
233
+
234
+ def visit_CaseClauseNode(o)
235
+ if o.left
236
+ case_code = "#{indent}case #{o.left.accept(self)}:\n"
237
+ else
238
+ case_code = "#{indent}default:\n"
239
+ end
240
+ @indent += 1
241
+ case_code += "#{o.value.accept(self)}\n"
242
+ @indent -= 1
243
+ case_code
244
+ end
245
+
246
+ def visit_DoWhileNode(o)
247
+ "do #{o.left.accept(self)} while(#{o.value.accept(self)});"
248
+ end
249
+
250
+ def visit_WithNode(o)
251
+ "with(#{o.left.accept(self)}) #{o.value.accept(self)}"
252
+ end
253
+
254
+ def visit_LabelNode(o)
255
+ "#{o.name}: #{o.value.accept(self)}"
256
+ end
257
+
258
+ def visit_ObjectLiteralNode(o)
259
+ @indent += 1
260
+ lit = "{" + (o.value.length > 0 ? "\n" : ' ') +
261
+ o.value.map { |x| "#{indent}#{x.accept(self)}" }.join(",\n") +
262
+ (o.value.length > 0 ? "\n" : '') + '}'
263
+ @indent -= 1
264
+ lit
265
+ end
266
+
267
+ def visit_PropertyNode(o)
268
+ "#{o.name}: #{o.value.accept(self)}"
269
+ end
270
+
271
+ def visit_GetterPropertyNode(o)
272
+ "get #{o.name}#{o.value.accept(self)}"
273
+ end
274
+
275
+ def visit_SetterPropertyNode(o)
276
+ "set #{o.name}#{o.value.accept(self)}"
277
+ end
278
+
279
+ def visit_FunctionExprNode(o)
280
+ "#{o.value}(#{o.arguments.map { |x| x.accept(self) }.join(', ')}) " +
281
+ "#{o.function_body.accept(self)}"
282
+ end
283
+
284
+ def visit_CommaNode(o)
285
+ "#{o.left.accept(self)}, #{o.value.accept(self)}"
286
+ end
287
+
288
+ def visit_IfNode(o)
289
+ "if(#{o.conditions.accept(self)}) #{o.value.accept(self)}" +
290
+ (o.else ? " else #{o.else.accept(self)}" : '')
291
+ end
292
+
293
+ def visit_ConditionalNode(o)
294
+ "#{o.conditions.accept(self)} ? #{o.value.accept(self)} : " +
295
+ "#{o.else.accept(self)}"
296
+ end
297
+
298
+ def visit_ForInNode(o)
299
+ var = o.left.is_a?(RKelly::Nodes::VarDeclNode) ? 'var ' : ''
300
+ "for(#{var}#{o.left.accept(self)} in #{o.right.accept(self)}) " +
301
+ "#{o.value.accept(self)}"
302
+ end
303
+
304
+ def visit_TryNode(o)
305
+ "try #{o.value.accept(self)}" +
306
+ (o.catch_block ? " catch(#{o.catch_var}) #{o.catch_block.accept(self)}" : '') +
307
+ (o.finally_block ? " finally #{o.finally_block.accept(self)}" : '')
308
+ end
309
+
310
+ def visit_BracketAccessorNode(o)
311
+ "#{o.value.accept(self)}[#{o.accessor.accept(self)}]"
312
+ end
313
+
314
+ def visit_NewExprNode(o)
315
+ "new #{o.value.accept(self)}(#{o.arguments.accept(self)})"
316
+ end
317
+
318
+ private
319
+ def indent; ' ' * @indent * 2; end
320
+ end
321
+ end
322
+ end
@@ -0,0 +1,18 @@
1
+ module RKelly
2
+ module Visitors
3
+ class EnumerableVisitor < Visitor
4
+ def initialize(block)
5
+ @block = block
6
+ end
7
+
8
+ ALL_NODES.each do |type|
9
+ eval <<-RUBY
10
+ def visit_#{type}Node(o)
11
+ @block[o]
12
+ super
13
+ end
14
+ RUBY
15
+ end
16
+ end
17
+ end
18
+ end