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,419 @@
1
+ module RKelly
2
+ module Visitors
3
+ class EvaluationVisitor < Visitor
4
+ attr_reader :scope_chain
5
+ def initialize(scope)
6
+ super()
7
+ @scope_chain = scope
8
+ @operand = []
9
+ end
10
+
11
+ def visit_SourceElementsNode(o)
12
+ o.value.each { |x|
13
+ next if scope_chain.returned?
14
+ x.accept(self)
15
+ }
16
+ end
17
+
18
+ def visit_FunctionDeclNode(o)
19
+ end
20
+
21
+ def visit_VarStatementNode(o)
22
+ o.value.each { |x| x.accept(self) }
23
+ end
24
+
25
+ def visit_VarDeclNode(o)
26
+ @operand << o.name
27
+ o.value.accept(self) if o.value
28
+ @operand.pop
29
+ end
30
+
31
+ def visit_IfNode(o)
32
+ truthiness = o.conditions.accept(self)
33
+ if truthiness.value && truthiness.value != 0
34
+ o.value.accept(self)
35
+ else
36
+ o.else && o.else.accept(self)
37
+ end
38
+ end
39
+
40
+ def visit_ResolveNode(o)
41
+ scope_chain[o.value]
42
+ end
43
+
44
+ def visit_ThisNode(o)
45
+ scope_chain.this
46
+ end
47
+
48
+ def visit_ExpressionStatementNode(o)
49
+ o.value.accept(self)
50
+ end
51
+
52
+ def visit_AddNode(o)
53
+ left = to_primitive(o.left.accept(self), 'Number')
54
+ right = to_primitive(o.value.accept(self), 'Number')
55
+
56
+ if left.value.is_a?(::String) || right.value.is_a?(::String)
57
+ RKelly::JS::Property.new(:add,
58
+ "#{left.value}#{right.value}"
59
+ )
60
+ else
61
+ additive_operator(:+, left, right)
62
+ end
63
+ end
64
+
65
+ def visit_SubtractNode(o)
66
+ RKelly::JS::Property.new(:subtract,
67
+ o.left.accept(self).value - o.value.accept(self).value
68
+ )
69
+ end
70
+
71
+ def visit_MultiplyNode(o)
72
+ left = to_number(o.left.accept(self)).value
73
+ right = to_number(o.value.accept(self)).value
74
+ return_val =
75
+ if [left, right].any? { |x| x.respond_to?(:nan?) && x.nan? }
76
+ RKelly::JS::NaN.new
77
+ else
78
+ [left, right].any? { |x|
79
+ x.respond_to?(:intinite?) && x.infinite?
80
+ } && [left, right].any? { |x| x == 0
81
+ } ? RKelly::JS::NaN.new : left * right
82
+ end
83
+ RKelly::JS::Property.new(:multiple, return_val)
84
+ end
85
+
86
+ def visit_DivideNode(o)
87
+ left = to_number(o.left.accept(self)).value
88
+ right = to_number(o.value.accept(self)).value
89
+ return_val =
90
+ if [left, right].any? { |x|
91
+ x.respond_to?(:nan?) && x.nan? ||
92
+ x.respond_to?(:intinite?) && x.infinite?
93
+ }
94
+ RKelly::JS::NaN.new
95
+ elsif [left, right].all? { |x| x == 0 }
96
+ RKelly::JS::NaN.new
97
+ elsif right == 0
98
+ left * (right.eql?(0) ? (1.0/0.0) : (-1.0/0.0))
99
+ else
100
+ left / right
101
+ end
102
+ RKelly::JS::Property.new(:divide, return_val)
103
+ end
104
+
105
+ def visit_ModulusNode(o)
106
+ left = to_number(o.left.accept(self)).value
107
+ right = to_number(o.value.accept(self)).value
108
+ return_val =
109
+ if [left, right].any? { |x| x.respond_to?(:nan?) && x.nan? }
110
+ RKelly::JS::NaN.new
111
+ elsif [left, right].all? { |x| x.respond_to?(:infinite?) && x.infinite? }
112
+ RKelly::JS::NaN.new
113
+ elsif right == 0
114
+ RKelly::JS::NaN.new
115
+ elsif left.respond_to?(:infinite?) && left.infinite?
116
+ RKelly::JS::NaN.new
117
+ elsif right.respond_to?(:infinite?) && right.infinite?
118
+ left
119
+ else
120
+ left % right
121
+ end
122
+ RKelly::JS::Property.new(:divide, return_val)
123
+ end
124
+
125
+ def visit_OpEqualNode(o)
126
+ left = o.left.accept(self)
127
+ right = o.value.accept(self)
128
+ left.value = right.value
129
+ left.function = right.function
130
+ left
131
+ end
132
+
133
+ def visit_OpPlusEqualNode(o)
134
+ o.left.accept(self).value += o.value.accept(self).value
135
+ end
136
+
137
+ def visit_AssignExprNode(o)
138
+ scope_chain[@operand.last] = o.value.accept(self)
139
+ end
140
+
141
+ def visit_NumberNode(o)
142
+ RKelly::JS::Property.new(o.value, o.value)
143
+ end
144
+
145
+ def visit_VoidNode(o)
146
+ o.value.accept(self)
147
+ RKelly::JS::Property.new(:undefined, :undefined)
148
+ end
149
+
150
+ def visit_NullNode(o)
151
+ RKelly::JS::Property.new(nil, nil)
152
+ end
153
+
154
+ def visit_TrueNode(o)
155
+ RKelly::JS::Property.new(true, true)
156
+ end
157
+
158
+ def visit_FalseNode(o)
159
+ RKelly::JS::Property.new(false, false)
160
+ end
161
+
162
+ def visit_StringNode(o)
163
+ RKelly::JS::Property.new(:string,
164
+ o.value.gsub(/\A['"]/, '').gsub(/['"]$/, '')
165
+ )
166
+ end
167
+
168
+ def visit_FunctionCallNode(o)
169
+ left = o.value.accept(self)
170
+ arguments = o.arguments.accept(self)
171
+ call_function(left, arguments)
172
+ end
173
+
174
+ def visit_NewExprNode(o)
175
+ visit_FunctionCallNode(o)
176
+ end
177
+
178
+ def visit_DotAccessorNode(o)
179
+ left = o.value.accept(self)
180
+ right = left.value[o.accessor]
181
+ right.binder = left.value
182
+ right
183
+ end
184
+
185
+ def visit_EqualNode(o)
186
+ left = o.left.accept(self)
187
+ right = o.value.accept(self)
188
+
189
+ RKelly::JS::Property.new(:equal_node, left.value == right.value)
190
+ end
191
+
192
+ def visit_BlockNode(o)
193
+ o.value.accept(self)
194
+ end
195
+
196
+ def visit_FunctionBodyNode(o)
197
+ o.value.accept(self)
198
+ scope_chain.return
199
+ end
200
+
201
+ def visit_ReturnNode(o)
202
+ scope_chain.return = o.value.accept(self)
203
+ end
204
+
205
+ def visit_BitwiseNotNode(o)
206
+ orig = o.value.accept(self)
207
+ number = to_int_32(orig)
208
+ RKelly::JS::Property.new(nil, ~number.value)
209
+ end
210
+
211
+ def visit_PostfixNode(o)
212
+ orig = o.operand.accept(self)
213
+ number = to_number(orig)
214
+ case o.value
215
+ when '++'
216
+ orig.value = number.value + 1
217
+ when '--'
218
+ orig.value = number.value - 1
219
+ end
220
+ number
221
+ end
222
+
223
+ def visit_PrefixNode(o)
224
+ orig = o.operand.accept(self)
225
+ number = to_number(orig)
226
+ case o.value
227
+ when '++'
228
+ orig.value = number.value + 1
229
+ when '--'
230
+ orig.value = number.value - 1
231
+ end
232
+ orig
233
+ end
234
+
235
+ def visit_LogicalNotNode(o)
236
+ bool = to_boolean(o.value.accept(self))
237
+ bool.value = !bool.value
238
+ bool
239
+ end
240
+
241
+ def visit_ArgumentsNode(o)
242
+ o.value.map { |x| x.accept(self) }
243
+ end
244
+
245
+ def visit_TypeOfNode(o)
246
+ val = o.value.accept(self)
247
+ return RKelly::JS::Property.new(:string, 'object') if val.value.nil?
248
+
249
+ case val.value
250
+ when String
251
+ RKelly::JS::Property.new(:string, 'string')
252
+ when Numeric
253
+ RKelly::JS::Property.new(:string, 'number')
254
+ when true
255
+ RKelly::JS::Property.new(:string, 'boolean')
256
+ when false
257
+ RKelly::JS::Property.new(:string, 'boolean')
258
+ when :undefined
259
+ RKelly::JS::Property.new(:string, 'undefined')
260
+ else
261
+ RKelly::JS::Property.new(:object, 'object')
262
+ end
263
+ end
264
+
265
+ def visit_UnaryPlusNode(o)
266
+ orig = o.value.accept(self)
267
+ to_number(orig)
268
+ end
269
+
270
+ def visit_UnaryMinusNode(o)
271
+ orig = o.value.accept(self)
272
+ v = to_number(orig)
273
+ v.value = v.value == 0 ? -0.0 : 0 - v.value
274
+ v
275
+ end
276
+
277
+ %w{
278
+ ArrayNode BitAndNode BitOrNode
279
+ BitXOrNode BracketAccessorNode BreakNode
280
+ CaseBlockNode CaseClauseNode CommaNode ConditionalNode
281
+ ConstStatementNode ContinueNode DeleteNode
282
+ DoWhileNode ElementNode EmptyStatementNode
283
+ ForInNode ForNode
284
+ FunctionExprNode GetterPropertyNode GreaterNode GreaterOrEqualNode
285
+ InNode InstanceOfNode LabelNode LeftShiftNode LessNode
286
+ LessOrEqualNode LogicalAndNode LogicalOrNode
287
+ NotEqualNode NotStrictEqualNode
288
+ ObjectLiteralNode OpAndEqualNode OpDivideEqualNode
289
+ OpLShiftEqualNode OpMinusEqualNode OpModEqualNode
290
+ OpMultiplyEqualNode OpOrEqualNode OpRShiftEqualNode
291
+ OpURShiftEqualNode OpXOrEqualNode ParameterNode
292
+ PropertyNode RegexpNode RightShiftNode
293
+ SetterPropertyNode StrictEqualNode
294
+ SwitchNode ThrowNode TryNode
295
+ UnsignedRightShiftNode
296
+ WhileNode WithNode
297
+ }.each do |type|
298
+ define_method(:"visit_#{type}") do |o|
299
+ raise "#{type} not defined"
300
+ end
301
+ end
302
+
303
+ private
304
+ def to_number(object)
305
+ return RKelly::JS::Property.new('0', 0) unless object.value
306
+
307
+ return_val =
308
+ case object.value
309
+ when :undefined
310
+ RKelly::JS::NaN.new
311
+ when false
312
+ 0
313
+ when true
314
+ 1
315
+ when Numeric
316
+ object.value
317
+ when ::String
318
+ s = object.value.gsub(/(\A[\s\xB\xA0]*|[\s\xB\xA0]*\Z)/, '')
319
+ if s.length == 0
320
+ 0
321
+ else
322
+ case s
323
+ when /^([+-])?Infinity/
324
+ $1 == '-' ? -1.0/0.0 : 1.0/0.0
325
+ when /\A[-+]?\d+\.\d*(?:[eE][-+]?\d+)?$|\A[-+]?\d+(?:\.\d*)?[eE][-+]?\d+$|\A[-+]?\.\d+(?:[eE][-+]?\d+)?$/, /\A[-+]?0[xX][\da-fA-F]+$|\A[+-]?0[0-7]*$|\A[+-]?\d+$/
326
+ s.gsub!(/\.(\D)/, '.0\1') if s =~ /\.\w/
327
+ s.gsub!(/\.$/, '.0') if s =~ /\.$/
328
+ s.gsub!(/^\./, '0.') if s =~ /^\./
329
+ s.gsub!(/^([+-])\./, '\10.') if s =~ /^[+-]\./
330
+ s = s.gsub(/^[0]*/, '') if /^0[1-9]+$/.match(s)
331
+ eval(s)
332
+ else
333
+ RKelly::JS::NaN.new
334
+ end
335
+ end
336
+ when RKelly::JS::Base
337
+ return to_number(to_primitive(object, 'Number'))
338
+ end
339
+ RKelly::JS::Property.new(nil, return_val)
340
+ end
341
+
342
+ def to_boolean(object)
343
+ return RKelly::JS::Property.new(false, false) unless object.value
344
+ value = object.value
345
+ boolean =
346
+ case value
347
+ when :undefined
348
+ false
349
+ when true
350
+ true
351
+ when Numeric
352
+ value == 0 || value.respond_to?(:nan?) && value.nan? ? false : true
353
+ when ::String
354
+ value.length == 0 ? false : true
355
+ when RKelly::JS::Base
356
+ true
357
+ else
358
+ raise
359
+ end
360
+ RKelly::JS::Property.new(boolean, boolean)
361
+ end
362
+
363
+ def to_int_32(object)
364
+ number = to_number(object)
365
+ value = number.value
366
+ return number if value == 0
367
+ if value.respond_to?(:nan?) && (value.nan? || value.infinite?)
368
+ RKelly::JS::Property.new(nil, 0)
369
+ end
370
+ value = ((value < 0 ? -1 : 1) * value.abs.floor) % (2 ** 32)
371
+ if value >= 2 ** 31
372
+ RKelly::JS::Property.new(nil, value - (2 ** 32))
373
+ else
374
+ RKelly::JS::Property.new(nil, value)
375
+ end
376
+ end
377
+
378
+ def to_primitive(object, preferred_type = nil)
379
+ return object unless object.value
380
+ case object.value
381
+ when false, true, :undefined, ::String, Numeric
382
+ RKelly::JS::Property.new(nil, object.value)
383
+ when RKelly::JS::Base
384
+ call_function(object.value.default_value(preferred_type))
385
+ end
386
+ end
387
+
388
+ def additive_operator(operator, left, right)
389
+ left, right = to_number(left).value, to_number(right).value
390
+
391
+ left = left.respond_to?(:nan?) && left.nan? ? 0.0/0.0 : left
392
+ right = right.respond_to?(:nan?) && right.nan? ? 0.0/0.0 : right
393
+
394
+ result = left.send(operator, right)
395
+ result = result.respond_to?(:nan?) && result.nan? ? JS::NaN.new : result
396
+
397
+ RKelly::JS::Property.new(operator, result)
398
+ end
399
+
400
+ def call_function(property, arguments = [])
401
+ function = property.function || property.value
402
+ case function
403
+ when RKelly::JS::Function
404
+ scope_chain.new_scope { |chain|
405
+ function.js_call(chain, *arguments)
406
+ }
407
+ when UnboundMethod
408
+ RKelly::JS::Property.new(:ruby,
409
+ function.bind(property.binder).call(*(arguments.map { |x| x.value}))
410
+ )
411
+ else
412
+ RKelly::JS::Property.new(:ruby,
413
+ function.call(*(arguments.map { |x| x.value }))
414
+ )
415
+ end
416
+ end
417
+ end
418
+ end
419
+ end
@@ -0,0 +1,46 @@
1
+ module RKelly
2
+ module Visitors
3
+ class FunctionVisitor < Visitor
4
+ attr_reader :scope_chain
5
+ def initialize(scope)
6
+ super()
7
+ @scope_chain = scope
8
+ end
9
+
10
+ def visit_SourceElementsNode(o)
11
+ o.value.each { |x| x.accept(self) }
12
+ end
13
+
14
+ def visit_FunctionDeclNode(o)
15
+ if o.value
16
+ scope_chain[o.value].value = RKelly::JS::Function.new(o.function_body, o.arguments)
17
+ end
18
+ end
19
+
20
+ %w{
21
+ AddNode ArgumentsNode ArrayNode AssignExprNode BitAndNode BitOrNode
22
+ BitXOrNode BitwiseNotNode BlockNode BracketAccessorNode BreakNode
23
+ CaseBlockNode CaseClauseNode CommaNode ConditionalNode
24
+ ConstStatementNode ContinueNode DeleteNode DivideNode
25
+ DoWhileNode DotAccessorNode ElementNode EmptyStatementNode EqualNode
26
+ ExpressionStatementNode FalseNode ForInNode ForNode FunctionBodyNode
27
+ FunctionExprNode GetterPropertyNode GreaterNode GreaterOrEqualNode
28
+ IfNode InNode InstanceOfNode LabelNode LeftShiftNode LessNode
29
+ LessOrEqualNode LogicalAndNode LogicalNotNode LogicalOrNode ModulusNode
30
+ MultiplyNode NewExprNode NotEqualNode NotStrictEqualNode NullNode
31
+ NumberNode ObjectLiteralNode OpAndEqualNode OpDivideEqualNode
32
+ OpEqualNode OpLShiftEqualNode OpMinusEqualNode OpModEqualNode
33
+ OpMultiplyEqualNode OpOrEqualNode OpPlusEqualNode OpRShiftEqualNode
34
+ OpURShiftEqualNode OpXOrEqualNode ParameterNode PostfixNode PrefixNode
35
+ PropertyNode RegexpNode ResolveNode ReturnNode RightShiftNode
36
+ SetterPropertyNode StrictEqualNode StringNode
37
+ SubtractNode SwitchNode ThisNode ThrowNode TrueNode TryNode TypeOfNode
38
+ UnaryMinusNode UnaryPlusNode UnsignedRightShiftNode VarDeclNode
39
+ VarStatementNode VoidNode WhileNode WithNode
40
+ }.each do |type|
41
+ define_method(:"visit_#{type}") do |o|
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,31 @@
1
+ module RKelly
2
+ module Visitors
3
+ class PointcutVisitor < Visitor
4
+ attr_reader :matches
5
+ def initialize(pattern, matches = [])
6
+ @pattern = pattern
7
+ @matches = matches
8
+ end
9
+
10
+ def >(pattern)
11
+ pattern =
12
+ case pattern
13
+ when Class
14
+ pattern.new(Object)
15
+ else
16
+ pattern
17
+ end
18
+ self.class.new(nil, @matches.map do |m|
19
+ m.pointcut(pattern).matches
20
+ end.flatten)
21
+ end
22
+
23
+ ALL_NODES.each do |type|
24
+ define_method(:"visit_#{type}Node") do |o|
25
+ @matches << o if @pattern === o
26
+ super
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ module RKelly
2
+ module Visitors
3
+ class RealSexpVisitor < Visitor
4
+ ALL_NODES.each do |type|
5
+ eval <<-RUBY
6
+ def visit_#{type}Node(o)
7
+ sexp = s(:#{type.scan(/[A-Z][a-z]+/).join('_').downcase}, *super(o))
8
+ sexp.line = o.line if o.line
9
+ sexp.file = o.filename
10
+ sexp
11
+ end
12
+ RUBY
13
+ end
14
+ end
15
+ end
16
+ end