modulr 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.
Files changed (217) hide show
  1. data/LICENSE +22 -0
  2. data/README.markdown +62 -0
  3. data/Rakefile +55 -0
  4. data/VERSION +1 -0
  5. data/assets/modulr.js +58 -0
  6. data/bin/modulrize +39 -0
  7. data/example/foo/bar.js +1 -0
  8. data/example/foo/foo.js +3 -0
  9. data/example/increment.js +6 -0
  10. data/example/inspect.js +3 -0
  11. data/example/math.js +7 -0
  12. data/example/program.js +9 -0
  13. data/lib/modulr/collector.rb +60 -0
  14. data/lib/modulr/js_module.rb +88 -0
  15. data/lib/modulr/version.rb +6 -0
  16. data/lib/modulr.rb +21 -0
  17. data/vendor/rkelly/CHANGELOG.rdoc +13 -0
  18. data/vendor/rkelly/Manifest.txt +198 -0
  19. data/vendor/rkelly/README.rdoc +58 -0
  20. data/vendor/rkelly/Rakefile +39 -0
  21. data/vendor/rkelly/lib/parser.y +870 -0
  22. data/vendor/rkelly/lib/rkelly/constants.rb +3 -0
  23. data/vendor/rkelly/lib/rkelly/generated_parser.rb +3237 -0
  24. data/vendor/rkelly/lib/rkelly/js/array.rb +15 -0
  25. data/vendor/rkelly/lib/rkelly/js/base.rb +91 -0
  26. data/vendor/rkelly/lib/rkelly/js/boolean.rb +21 -0
  27. data/vendor/rkelly/lib/rkelly/js/function.rb +39 -0
  28. data/vendor/rkelly/lib/rkelly/js/function_prototype.rb +15 -0
  29. data/vendor/rkelly/lib/rkelly/js/global_object.rb +52 -0
  30. data/vendor/rkelly/lib/rkelly/js/math.rb +10 -0
  31. data/vendor/rkelly/lib/rkelly/js/nan.rb +18 -0
  32. data/vendor/rkelly/lib/rkelly/js/number.rb +22 -0
  33. data/vendor/rkelly/lib/rkelly/js/object.rb +30 -0
  34. data/vendor/rkelly/lib/rkelly/js/object_prototype.rb +14 -0
  35. data/vendor/rkelly/lib/rkelly/js/property.rb +20 -0
  36. data/vendor/rkelly/lib/rkelly/js/scope.rb +6 -0
  37. data/vendor/rkelly/lib/rkelly/js/string.rb +21 -0
  38. data/vendor/rkelly/lib/rkelly/js.rb +14 -0
  39. data/vendor/rkelly/lib/rkelly/lexeme.rb +18 -0
  40. data/vendor/rkelly/lib/rkelly/nodes/binary_node.rb +18 -0
  41. data/vendor/rkelly/lib/rkelly/nodes/bracket_accessor_node.rb +11 -0
  42. data/vendor/rkelly/lib/rkelly/nodes/case_clause_node.rb +11 -0
  43. data/vendor/rkelly/lib/rkelly/nodes/comma_node.rb +11 -0
  44. data/vendor/rkelly/lib/rkelly/nodes/conditional_node.rb +11 -0
  45. data/vendor/rkelly/lib/rkelly/nodes/dot_accessor_node.rb +11 -0
  46. data/vendor/rkelly/lib/rkelly/nodes/for_in_node.rb +12 -0
  47. data/vendor/rkelly/lib/rkelly/nodes/for_node.rb +13 -0
  48. data/vendor/rkelly/lib/rkelly/nodes/function_call_node.rb +16 -0
  49. data/vendor/rkelly/lib/rkelly/nodes/function_decl_node.rb +6 -0
  50. data/vendor/rkelly/lib/rkelly/nodes/function_expr_node.rb +12 -0
  51. data/vendor/rkelly/lib/rkelly/nodes/if_node.rb +12 -0
  52. data/vendor/rkelly/lib/rkelly/nodes/label_node.rb +11 -0
  53. data/vendor/rkelly/lib/rkelly/nodes/new_expr_node.rb +11 -0
  54. data/vendor/rkelly/lib/rkelly/nodes/node.rb +88 -0
  55. data/vendor/rkelly/lib/rkelly/nodes/not_strict_equal_node.rb +6 -0
  56. data/vendor/rkelly/lib/rkelly/nodes/op_equal_node.rb +16 -0
  57. data/vendor/rkelly/lib/rkelly/nodes/postfix_node.rb +11 -0
  58. data/vendor/rkelly/lib/rkelly/nodes/prefix_node.rb +6 -0
  59. data/vendor/rkelly/lib/rkelly/nodes/property_node.rb +13 -0
  60. data/vendor/rkelly/lib/rkelly/nodes/resolve_node.rb +19 -0
  61. data/vendor/rkelly/lib/rkelly/nodes/strict_equal_node.rb +6 -0
  62. data/vendor/rkelly/lib/rkelly/nodes/try_node.rb +13 -0
  63. data/vendor/rkelly/lib/rkelly/nodes/var_decl_node.rb +15 -0
  64. data/vendor/rkelly/lib/rkelly/nodes.rb +25 -0
  65. data/vendor/rkelly/lib/rkelly/parser.rb +104 -0
  66. data/vendor/rkelly/lib/rkelly/runtime/ruby_function.rb +13 -0
  67. data/vendor/rkelly/lib/rkelly/runtime/scope_chain.rb +57 -0
  68. data/vendor/rkelly/lib/rkelly/runtime.rb +36 -0
  69. data/vendor/rkelly/lib/rkelly/syntax_error.rb +4 -0
  70. data/vendor/rkelly/lib/rkelly/token.rb +15 -0
  71. data/vendor/rkelly/lib/rkelly/tokenizer.rb +122 -0
  72. data/vendor/rkelly/lib/rkelly/visitable.rb +16 -0
  73. data/vendor/rkelly/lib/rkelly/visitors/dot_visitor.rb +228 -0
  74. data/vendor/rkelly/lib/rkelly/visitors/ecma_visitor.rb +314 -0
  75. data/vendor/rkelly/lib/rkelly/visitors/enumerable_visitor.rb +18 -0
  76. data/vendor/rkelly/lib/rkelly/visitors/evaluation_visitor.rb +419 -0
  77. data/vendor/rkelly/lib/rkelly/visitors/function_visitor.rb +46 -0
  78. data/vendor/rkelly/lib/rkelly/visitors/pointcut_visitor.rb +31 -0
  79. data/vendor/rkelly/lib/rkelly/visitors/real_sexp_visitor.rb +16 -0
  80. data/vendor/rkelly/lib/rkelly/visitors/sexp_visitor.rb +373 -0
  81. data/vendor/rkelly/lib/rkelly/visitors/visitor.rb +136 -0
  82. data/vendor/rkelly/lib/rkelly/visitors.rb +4 -0
  83. data/vendor/rkelly/lib/rkelly.rb +14 -0
  84. data/vendor/rkelly/rkelly.gemspec +34 -0
  85. data/vendor/rkelly/test/ecma_script_test_case.rb +21 -0
  86. data/vendor/rkelly/test/execute_test_case.rb +16 -0
  87. data/vendor/rkelly/test/execution_contexts/test_10_1_3-1.rb +32 -0
  88. data/vendor/rkelly/test/expressions/test_11_3_1.rb +64 -0
  89. data/vendor/rkelly/test/expressions/test_11_3_2.rb +64 -0
  90. data/vendor/rkelly/test/expressions/test_11_4_2.rb +13 -0
  91. data/vendor/rkelly/test/expressions/test_11_4_3.rb +52 -0
  92. data/vendor/rkelly/test/expressions/test_11_4_4.rb +68 -0
  93. data/vendor/rkelly/test/expressions/test_11_4_5.rb +69 -0
  94. data/vendor/rkelly/test/expressions/test_11_4_6.rb +88 -0
  95. data/vendor/rkelly/test/expressions/test_11_4_8.rb +28 -0
  96. data/vendor/rkelly/test/expressions/test_11_4_9.rb +103 -0
  97. data/vendor/rkelly/test/expressions/test_11_5_1.rb +51 -0
  98. data/vendor/rkelly/test/expressions/test_11_5_2.rb +80 -0
  99. data/vendor/rkelly/test/expressions/test_11_5_3.rb +88 -0
  100. data/vendor/rkelly/test/expressions/test_11_6_1-1.rb +19 -0
  101. data/vendor/rkelly/test/expressions/test_11_9_1.rb +19 -0
  102. data/vendor/rkelly/test/function/test_15_3_1_1-1.rb +34 -0
  103. data/vendor/rkelly/test/global_object/test_15_1_1_1.rb +29 -0
  104. data/vendor/rkelly/test/global_object/test_15_1_1_2.rb +17 -0
  105. data/vendor/rkelly/test/global_object/test_15_1_1_3.rb +9 -0
  106. data/vendor/rkelly/test/helper.rb +5 -0
  107. data/vendor/rkelly/test/node_test_case.rb +11 -0
  108. data/vendor/rkelly/test/object/test_15_2_1_1.rb +257 -0
  109. data/vendor/rkelly/test/object/test_15_2_1_2.rb +21 -0
  110. data/vendor/rkelly/test/object/test_15_2_2_1.rb +52 -0
  111. data/vendor/rkelly/test/statements/test_12_5-1.rb +27 -0
  112. data/vendor/rkelly/test/test_add_node.rb +8 -0
  113. data/vendor/rkelly/test/test_arguments_node.rb +8 -0
  114. data/vendor/rkelly/test/test_array_node.rb +9 -0
  115. data/vendor/rkelly/test/test_assign_expr_node.rb +8 -0
  116. data/vendor/rkelly/test/test_automatic_semicolon_insertion.rb +137 -0
  117. data/vendor/rkelly/test/test_bit_and_node.rb +8 -0
  118. data/vendor/rkelly/test/test_bit_or_node.rb +8 -0
  119. data/vendor/rkelly/test/test_bit_x_or_node.rb +8 -0
  120. data/vendor/rkelly/test/test_bitwise_not_node.rb +8 -0
  121. data/vendor/rkelly/test/test_block_node.rb +14 -0
  122. data/vendor/rkelly/test/test_bracket_accessor_node.rb +16 -0
  123. data/vendor/rkelly/test/test_break_node.rb +11 -0
  124. data/vendor/rkelly/test/test_case_block_node.rb +11 -0
  125. data/vendor/rkelly/test/test_case_clause_node.rb +15 -0
  126. data/vendor/rkelly/test/test_comma_node.rb +13 -0
  127. data/vendor/rkelly/test/test_comments.rb +44 -0
  128. data/vendor/rkelly/test/test_conditional_node.rb +17 -0
  129. data/vendor/rkelly/test/test_const_statement_node.rb +14 -0
  130. data/vendor/rkelly/test/test_continue_node.rb +11 -0
  131. data/vendor/rkelly/test/test_delete_node.rb +8 -0
  132. data/vendor/rkelly/test/test_divide_node.rb +8 -0
  133. data/vendor/rkelly/test/test_do_while_node.rb +13 -0
  134. data/vendor/rkelly/test/test_dot_accessor_node.rb +9 -0
  135. data/vendor/rkelly/test/test_ecma_visitor.rb +192 -0
  136. data/vendor/rkelly/test/test_element_node.rb +8 -0
  137. data/vendor/rkelly/test/test_empty_statement_node.rb +8 -0
  138. data/vendor/rkelly/test/test_equal_node.rb +8 -0
  139. data/vendor/rkelly/test/test_evaluation_visitor.rb +66 -0
  140. data/vendor/rkelly/test/test_expression_statement_node.rb +10 -0
  141. data/vendor/rkelly/test/test_false_node.rb +8 -0
  142. data/vendor/rkelly/test/test_for_in_node.rb +17 -0
  143. data/vendor/rkelly/test/test_for_node.rb +24 -0
  144. data/vendor/rkelly/test/test_function_body_node.rb +8 -0
  145. data/vendor/rkelly/test/test_function_call_node.rb +10 -0
  146. data/vendor/rkelly/test/test_function_decl_node.rb +16 -0
  147. data/vendor/rkelly/test/test_function_expr_node.rb +16 -0
  148. data/vendor/rkelly/test/test_function_visitor.rb +26 -0
  149. data/vendor/rkelly/test/test_getter_property_node.rb +10 -0
  150. data/vendor/rkelly/test/test_global_object.rb +49 -0
  151. data/vendor/rkelly/test/test_greater_node.rb +8 -0
  152. data/vendor/rkelly/test/test_greater_or_equal_node.rb +8 -0
  153. data/vendor/rkelly/test/test_if_node.rb +17 -0
  154. data/vendor/rkelly/test/test_in_node.rb +8 -0
  155. data/vendor/rkelly/test/test_instance_of_node.rb +8 -0
  156. data/vendor/rkelly/test/test_label_node.rb +13 -0
  157. data/vendor/rkelly/test/test_left_shift_node.rb +8 -0
  158. data/vendor/rkelly/test/test_less_node.rb +8 -0
  159. data/vendor/rkelly/test/test_less_or_equal_node.rb +8 -0
  160. data/vendor/rkelly/test/test_line_number.rb +23 -0
  161. data/vendor/rkelly/test/test_logical_and_node.rb +8 -0
  162. data/vendor/rkelly/test/test_logical_not_node.rb +8 -0
  163. data/vendor/rkelly/test/test_logical_or_node.rb +8 -0
  164. data/vendor/rkelly/test/test_modulus_node.rb +8 -0
  165. data/vendor/rkelly/test/test_multiply_node.rb +8 -0
  166. data/vendor/rkelly/test/test_new_expr_node.rb +9 -0
  167. data/vendor/rkelly/test/test_not_equal_node.rb +8 -0
  168. data/vendor/rkelly/test/test_not_strict_equal_node.rb +8 -0
  169. data/vendor/rkelly/test/test_null_node.rb +8 -0
  170. data/vendor/rkelly/test/test_number_node.rb +8 -0
  171. data/vendor/rkelly/test/test_object_literal_node.rb +9 -0
  172. data/vendor/rkelly/test/test_op_and_equal_node.rb +10 -0
  173. data/vendor/rkelly/test/test_op_divide_equal_node.rb +10 -0
  174. data/vendor/rkelly/test/test_op_equal_node.rb +10 -0
  175. data/vendor/rkelly/test/test_op_l_shift_equal_node.rb +10 -0
  176. data/vendor/rkelly/test/test_op_minus_equal_node.rb +10 -0
  177. data/vendor/rkelly/test/test_op_mod_equal_node.rb +10 -0
  178. data/vendor/rkelly/test/test_op_multiply_equal_node.rb +10 -0
  179. data/vendor/rkelly/test/test_op_or_equal_node.rb +10 -0
  180. data/vendor/rkelly/test/test_op_plus_equal_node.rb +10 -0
  181. data/vendor/rkelly/test/test_op_r_shift_equal_node.rb +10 -0
  182. data/vendor/rkelly/test/test_op_u_r_shift_equal_node.rb +10 -0
  183. data/vendor/rkelly/test/test_op_x_or_equal_node.rb +10 -0
  184. data/vendor/rkelly/test/test_parameter_node.rb +8 -0
  185. data/vendor/rkelly/test/test_parser.rb +1361 -0
  186. data/vendor/rkelly/test/test_pointcut_visitor.rb +34 -0
  187. data/vendor/rkelly/test/test_postfix_node.rb +8 -0
  188. data/vendor/rkelly/test/test_prefix_node.rb +8 -0
  189. data/vendor/rkelly/test/test_property_node.rb +8 -0
  190. data/vendor/rkelly/test/test_regexp_node.rb +8 -0
  191. data/vendor/rkelly/test/test_resolve_node.rb +22 -0
  192. data/vendor/rkelly/test/test_return_node.rb +11 -0
  193. data/vendor/rkelly/test/test_right_shift_node.rb +8 -0
  194. data/vendor/rkelly/test/test_rkelly.rb +19 -0
  195. data/vendor/rkelly/test/test_runtime.rb +12 -0
  196. data/vendor/rkelly/test/test_scope_chain.rb +50 -0
  197. data/vendor/rkelly/test/test_setter_property_node.rb +10 -0
  198. data/vendor/rkelly/test/test_source_elements.rb +9 -0
  199. data/vendor/rkelly/test/test_strict_equal_node.rb +8 -0
  200. data/vendor/rkelly/test/test_string_node.rb +8 -0
  201. data/vendor/rkelly/test/test_subtract_node.rb +8 -0
  202. data/vendor/rkelly/test/test_switch_node.rb +12 -0
  203. data/vendor/rkelly/test/test_this_node.rb +8 -0
  204. data/vendor/rkelly/test/test_throw_node.rb +7 -0
  205. data/vendor/rkelly/test/test_tokenizer.rb +148 -0
  206. data/vendor/rkelly/test/test_true_node.rb +8 -0
  207. data/vendor/rkelly/test/test_try_node.rb +59 -0
  208. data/vendor/rkelly/test/test_type_of_node.rb +8 -0
  209. data/vendor/rkelly/test/test_unary_minus_node.rb +8 -0
  210. data/vendor/rkelly/test/test_unary_plus_node.rb +8 -0
  211. data/vendor/rkelly/test/test_unsigned_right_shift_node.rb +8 -0
  212. data/vendor/rkelly/test/test_var_decl_node.rb +21 -0
  213. data/vendor/rkelly/test/test_var_statement_node.rb +14 -0
  214. data/vendor/rkelly/test/test_void_node.rb +8 -0
  215. data/vendor/rkelly/test/test_while_node.rb +15 -0
  216. data/vendor/rkelly/test/test_with_node.rb +8 -0
  217. metadata +271 -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,314 @@
1
+ module RKelly
2
+ module Visitors
3
+ class ECMAVisitor < Visitor
4
+ def initialize
5
+ @indent = 0
6
+ end
7
+
8
+ def visit_SourceElementsNode(o)
9
+ o.value.map { |x| "#{indent}#{x.accept(self)}" }.join("\n")
10
+ end
11
+
12
+ def visit_VarStatementNode(o)
13
+ "var #{o.value.map { |x| x.accept(self) }.join(', ')};"
14
+ end
15
+
16
+ def visit_ConstStatementNode(o)
17
+ "const #{o.value.map { |x| x.accept(self) }.join(', ')};"
18
+ end
19
+
20
+ def visit_VarDeclNode(o)
21
+ "#{o.name}#{o.value ? o.value.accept(self) : nil}"
22
+ end
23
+
24
+ def visit_AssignExprNode(o)
25
+ " = #{o.value.accept(self)}"
26
+ end
27
+
28
+ def visit_NumberNode(o)
29
+ o.value.to_s
30
+ end
31
+
32
+ def visit_ForNode(o)
33
+ init = o.init ? o.init.accept(self) : ';'
34
+ test = o.test ? o.test.accept(self) : ''
35
+ counter = o.counter ? o.counter.accept(self) : ''
36
+ "for(#{init} #{test}; #{counter}) #{o.value.accept(self)}"
37
+ end
38
+
39
+ def visit_LessNode(o)
40
+ "#{o.left.accept(self)} < #{o.value.accept(self)}"
41
+ end
42
+
43
+ def visit_ResolveNode(o)
44
+ o.value
45
+ end
46
+
47
+ def visit_PostfixNode(o)
48
+ "#{o.operand.accept(self)}#{o.value}"
49
+ end
50
+
51
+ def visit_PrefixNode(o)
52
+ "#{o.value}#{o.operand.accept(self)}"
53
+ end
54
+
55
+ def visit_BlockNode(o)
56
+ @indent += 1
57
+ "{\n#{o.value.accept(self)}\n#{@indent -=1; indent}}"
58
+ end
59
+
60
+ def visit_ExpressionStatementNode(o)
61
+ "#{o.value.accept(self)};"
62
+ end
63
+
64
+ def visit_OpEqualNode(o)
65
+ "#{o.left.accept(self)} = #{o.value.accept(self)}"
66
+ end
67
+
68
+ def visit_FunctionCallNode(o)
69
+ "#{o.value.accept(self)}(#{o.arguments.accept(self)})"
70
+ end
71
+
72
+ def visit_ArgumentsNode(o)
73
+ o.value.map { |x| x.accept(self) }.join(', ')
74
+ end
75
+
76
+ def visit_StringNode(o)
77
+ o.value
78
+ end
79
+
80
+ def visit_NullNode(o)
81
+ "null"
82
+ end
83
+
84
+ def visit_FunctionDeclNode(o)
85
+ "#{indent}function #{o.value}(" +
86
+ "#{o.arguments.map { |x| x.accept(self) }.join(', ')})" +
87
+ "#{o.function_body.accept(self)}"
88
+ end
89
+
90
+ def visit_ParameterNode(o)
91
+ o.value
92
+ end
93
+
94
+ def visit_FunctionBodyNode(o)
95
+ @indent += 1
96
+ "{\n#{o.value.accept(self)}\n#{@indent -=1; indent}}"
97
+ end
98
+
99
+ def visit_BreakNode(o)
100
+ "break" + (o.value ? " #{o.value}" : '') + ';'
101
+ end
102
+
103
+ def visit_ContinueNode(o)
104
+ "continue" + (o.value ? " #{o.value}" : '') + ';'
105
+ end
106
+
107
+ def visit_TrueNode(o)
108
+ "true"
109
+ end
110
+
111
+ def visit_FalseNode(o)
112
+ "false"
113
+ end
114
+
115
+ def visit_EmptyStatementNode(o)
116
+ ';'
117
+ end
118
+
119
+ def visit_RegexpNode(o)
120
+ o.value
121
+ end
122
+
123
+ def visit_DotAccessorNode(o)
124
+ "#{o.value.accept(self)}.#{o.accessor}"
125
+ end
126
+
127
+ def visit_ThisNode(o)
128
+ "this"
129
+ end
130
+
131
+ def visit_BitwiseNotNode(o)
132
+ "~#{o.value.accept(self)}"
133
+ end
134
+
135
+ def visit_DeleteNode(o)
136
+ "delete #{o.value.accept(self)}"
137
+ end
138
+
139
+ def visit_ArrayNode(o)
140
+ "[#{o.value.map { |x| x ? x.accept(self) : '' }.join(', ')}]"
141
+ end
142
+
143
+ def visit_ElementNode(o)
144
+ o.value.accept(self)
145
+ end
146
+
147
+ def visit_LogicalNotNode(o)
148
+ "!#{o.value.accept(self)}"
149
+ end
150
+
151
+ def visit_UnaryMinusNode(o)
152
+ "-#{o.value.accept(self)}"
153
+ end
154
+
155
+ def visit_UnaryPlusNode(o)
156
+ "+#{o.value.accept(self)}"
157
+ end
158
+
159
+ def visit_ReturnNode(o)
160
+ "return" + (o.value ? " #{o.value.accept(self)}" : '') + ';'
161
+ end
162
+
163
+ def visit_ThrowNode(o)
164
+ "throw #{o.value.accept(self)};"
165
+ end
166
+
167
+ def visit_TypeOfNode(o)
168
+ "typeof #{o.value.accept(self)}"
169
+ end
170
+
171
+ def visit_VoidNode(o)
172
+ "void(#{o.value.accept(self)})"
173
+ end
174
+
175
+ [
176
+ [:Add, '+'],
177
+ [:BitAnd, '&'],
178
+ [:BitOr, '|'],
179
+ [:BitXOr, '^'],
180
+ [:Divide, '/'],
181
+ [:Equal, '=='],
182
+ [:Greater, '>'],
183
+ [:Greater, '>'],
184
+ [:GreaterOrEqual, '>='],
185
+ [:GreaterOrEqual, '>='],
186
+ [:In, 'in'],
187
+ [:InstanceOf, 'instanceof'],
188
+ [:LeftShift, '<<'],
189
+ [:LessOrEqual, '<='],
190
+ [:LogicalAnd, '&&'],
191
+ [:LogicalOr, '||'],
192
+ [:Modulus, '%'],
193
+ [:Multiply, '*'],
194
+ [:NotEqual, '!='],
195
+ [:NotStrictEqual, '!=='],
196
+ [:OpAndEqual, '&='],
197
+ [:OpDivideEqual, '/='],
198
+ [:OpLShiftEqual, '<<='],
199
+ [:OpMinusEqual, '-='],
200
+ [:OpModEqual, '%='],
201
+ [:OpMultiplyEqual, '*='],
202
+ [:OpOrEqual, '|='],
203
+ [:OpPlusEqual, '+='],
204
+ [:OpRShiftEqual, '>>='],
205
+ [:OpURShiftEqual, '>>>='],
206
+ [:OpXOrEqual, '^='],
207
+ [:RightShift, '>>'],
208
+ [:StrictEqual, '==='],
209
+ [:Subtract, '-'],
210
+ [:UnsignedRightShift, '>>>'],
211
+ ].each do |name,op|
212
+ define_method(:"visit_#{name}Node") do |o|
213
+ "#{o.left.accept(self)} #{op} #{o.value.accept(self)}"
214
+ end
215
+ end
216
+
217
+ def visit_WhileNode(o)
218
+ "while(#{o.left.accept(self)}) #{o.value.accept(self)}"
219
+ end
220
+
221
+ def visit_SwitchNode(o)
222
+ "switch(#{o.left.accept(self)}) #{o.value.accept(self)}"
223
+ end
224
+
225
+ def visit_CaseBlockNode(o)
226
+ @indent += 1
227
+ "{\n" + (o.value ? o.value.map { |x| x.accept(self) }.join('') : '') +
228
+ "#{@indent -=1; indent}}"
229
+ end
230
+
231
+ def visit_CaseClauseNode(o)
232
+ case_code = "#{indent}case #{o.left ? o.left.accept(self) : nil}:\n"
233
+ @indent += 1
234
+ case_code += "#{o.value.accept(self)}\n"
235
+ @indent -= 1
236
+ case_code
237
+ end
238
+
239
+ def visit_DoWhileNode(o)
240
+ "do #{o.left.accept(self)} while(#{o.value.accept(self)});"
241
+ end
242
+
243
+ def visit_WithNode(o)
244
+ "with(#{o.left.accept(self)}) #{o.value.accept(self)}"
245
+ end
246
+
247
+ def visit_LabelNode(o)
248
+ "#{o.name}: #{o.value.accept(self)}"
249
+ end
250
+
251
+ def visit_ObjectLiteralNode(o)
252
+ @indent += 1
253
+ lit = "{" + (o.value.length > 0 ? "\n" : ' ') +
254
+ o.value.map { |x| "#{indent}#{x.accept(self)}" }.join(",\n") +
255
+ (o.value.length > 0 ? "\n" : '') + '}'
256
+ @indent -= 1
257
+ lit
258
+ end
259
+
260
+ def visit_PropertyNode(o)
261
+ "#{o.name}: #{o.value.accept(self)}"
262
+ end
263
+
264
+ def visit_GetterPropertyNode(o)
265
+ "get #{o.name}#{o.value.accept(self)}"
266
+ end
267
+
268
+ def visit_SetterPropertyNode(o)
269
+ "set #{o.name}#{o.value.accept(self)}"
270
+ end
271
+
272
+ def visit_FunctionExprNode(o)
273
+ "#{o.value}(#{o.arguments.map { |x| x.accept(self) }.join(', ')}) " +
274
+ "#{o.function_body.accept(self)}"
275
+ end
276
+
277
+ def visit_CommaNode(o)
278
+ "#{o.left.accept(self)}, #{o.value.accept(self)}"
279
+ end
280
+
281
+ def visit_IfNode(o)
282
+ "if(#{o.conditions.accept(self)}) #{o.value.accept(self)}" +
283
+ (o.else ? " else #{o.else.accept(self)}" : '')
284
+ end
285
+
286
+ def visit_ConditionalNode(o)
287
+ "#{o.conditions.accept(self)} ? #{o.value.accept(self)} : " +
288
+ "#{o.else.accept(self)}"
289
+ end
290
+
291
+ def visit_ForInNode(o)
292
+ "for(#{o.left.accept(self)} in #{o.right.accept(self)}) " +
293
+ "#{o.value.accept(self)}"
294
+ end
295
+
296
+ def visit_TryNode(o)
297
+ "try #{o.value.accept(self)}" +
298
+ (o.catch_block ? " catch(#{o.catch_var}) #{o.catch_block.accept(self)}" : '') +
299
+ (o.finally_block ? " finally #{o.finally_block.accept(self)}" : '')
300
+ end
301
+
302
+ def visit_BracketAccessorNode(o)
303
+ "#{o.value.accept(self)}[#{o.accessor.accept(self)}]"
304
+ end
305
+
306
+ def visit_NewExprNode(o)
307
+ "new #{o.value.accept(self)}(#{o.arguments.accept(self)})"
308
+ end
309
+
310
+ private
311
+ def indent; ' ' * @indent * 2; end
312
+ end
313
+ end
314
+ 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