opal 0.2.2 → 0.3.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 (325) hide show
  1. data/.gitignore +5 -10
  2. data/LICENSE +75 -0
  3. data/README.md +55 -3
  4. data/Rakefile +62 -139
  5. data/bin/opal +7 -10
  6. data/gems/core/README.md +5 -0
  7. data/gems/core/Rakefile +7 -0
  8. data/gems/core/core.gemspec +13 -0
  9. data/gems/core/lib/core.rb +33 -0
  10. data/gems/core/lib/core/array.rb +1470 -0
  11. data/gems/core/lib/core/basic_object.rb +15 -0
  12. data/gems/core/lib/core/class.rb +31 -0
  13. data/gems/core/lib/core/dir.rb +26 -0
  14. data/gems/core/lib/core/error.rb +43 -0
  15. data/gems/core/lib/core/false_class.rb +21 -0
  16. data/gems/core/lib/core/file.rb +54 -0
  17. data/gems/core/lib/core/hash.rb +725 -0
  18. data/gems/core/lib/core/kernel.rb +240 -0
  19. data/gems/core/lib/core/module.rb +98 -0
  20. data/gems/core/lib/core/nil_class.rb +41 -0
  21. data/gems/core/lib/core/numeric.rb +370 -0
  22. data/gems/core/lib/core/proc.rb +11 -0
  23. data/gems/core/lib/core/range.rb +17 -0
  24. data/gems/core/lib/core/regexp.rb +18 -0
  25. data/gems/core/lib/core/string.rb +328 -0
  26. data/gems/core/lib/core/symbol.rb +15 -0
  27. data/gems/core/lib/core/top_self.rb +8 -0
  28. data/gems/core/lib/core/true_class.rb +20 -0
  29. data/gems/core/lib/core/vm.rb +16 -0
  30. data/{opals/opal/opal → gems/core}/spec/core/array/append_spec.rb +0 -0
  31. data/{opals/opal/opal → gems/core}/spec/core/array/assoc_spec.rb +0 -0
  32. data/{opals/opal/opal → gems/core}/spec/core/array/at_spec.rb +0 -0
  33. data/{opals/opal/opal → gems/core}/spec/core/array/clear_spec.rb +1 -1
  34. data/{opals/opal/opal → gems/core}/spec/core/array/collect_bang_spec.rb +0 -0
  35. data/{opals/opal/opal → gems/core}/spec/core/array/collect_spec.rb +0 -0
  36. data/gems/core/spec/core/array/compact_spec.rb +41 -0
  37. data/{opals/opal/opal → gems/core}/spec/core/array/concat_spec.rb +0 -0
  38. data/{opals/opal/opal → gems/core}/spec/core/array/constructor_spec.rb +0 -0
  39. data/{opals/opal/opal → gems/core}/spec/core/array/each_spec.rb +0 -0
  40. data/{opals/opal/opal → gems/core}/spec/core/array/element_reference_spec.rb +0 -0
  41. data/{opals/opal/opal → gems/core}/spec/core/array/first_spec.rb +1 -1
  42. data/{opals/opal/opal → gems/core}/spec/core/array/include_spec.rb +0 -0
  43. data/gems/core/spec/core/array/join_spec.rb +6 -0
  44. data/gems/core/spec/core/array/last_spec.rb +51 -0
  45. data/gems/core/spec/core/array/length_spec.rb +6 -0
  46. data/{opals/opal/opal → gems/core}/spec/core/array/map_spec.rb +2 -0
  47. data/gems/core/spec/core/array/reverse_spec.rb +6 -0
  48. data/{opals/opal/opal → gems/core}/spec/core/builtin_constants/builtin_constants_spec.rb +0 -0
  49. data/{opals/opal/opal → gems/core}/spec/core/false/and_spec.rb +0 -0
  50. data/{opals/opal/opal → gems/core}/spec/core/false/inspect_spec.rb +0 -0
  51. data/{opals/opal/opal → gems/core}/spec/core/false/or_spec.rb +0 -0
  52. data/{opals/opal/opal → gems/core}/spec/core/false/to_s_spec.rb +0 -0
  53. data/{opals/opal/opal → gems/core}/spec/core/false/xor_spec.rb +0 -0
  54. data/{opals/opal/opal → gems/core}/spec/core/file/join_spec.rb +1 -1
  55. data/gems/core/spec/core/hash/assoc_spec.rb +32 -0
  56. data/{opals/opal/opal → gems/core}/spec/core/kernel/instance_eval_spec.rb +0 -0
  57. data/{opals/opal/opal → gems/core}/spec/core/kernel/loop_spec.rb +0 -0
  58. data/{opals/opal/opal → gems/core}/spec/core/kernel/raise_spec.rb +0 -0
  59. data/{opals/opal/opal → gems/core}/spec/core/module/attr_accessor_spec.rb +0 -0
  60. data/{opals/opal/opal → gems/core}/spec/core/number/lt_spec.rb +0 -0
  61. data/gems/core/spec/core/string/sub_spec.rb +24 -0
  62. data/{opals/opal/opal → gems/core}/spec/core/true/and_spec.rb +0 -0
  63. data/{opals/opal/opal → gems/core}/spec/core/true/inspect_spec.rb +0 -0
  64. data/{opals/opal/opal → gems/core}/spec/core/true/or_spec.rb +0 -0
  65. data/{opals/opal/opal → gems/core}/spec/core/true/to_s_spec.rb +0 -0
  66. data/{opals/opal/opal → gems/core}/spec/core/true/xor_spec.rb +0 -0
  67. data/{opals/opal/opal → gems/core}/spec/language/and_spec.rb +2 -3
  68. data/{opals/opal/opal → gems/core}/spec/language/array_spec.rb +21 -5
  69. data/gems/core/spec/language/block_spec.rb +38 -0
  70. data/{opals/opal/opal → gems/core}/spec/language/break_spec.rb +0 -0
  71. data/gems/core/spec/language/case_spec.rb +103 -0
  72. data/{opals/opal/opal → gems/core}/spec/language/def_spec.rb +11 -1
  73. data/{opals/opal/opal → gems/core}/spec/language/eigenclass_spec.rb +0 -0
  74. data/gems/core/spec/language/file_spec.rb +13 -0
  75. data/gems/core/spec/language/fixtures/block.rb +21 -0
  76. data/gems/core/spec/language/fixtures/super.rb +293 -0
  77. data/{opals/opal/opal → gems/core}/spec/language/hash_spec.rb +0 -0
  78. data/{opals/opal/opal → gems/core}/spec/language/if_spec.rb +0 -0
  79. data/{opals/opal/opal → gems/core}/spec/language/loop_spec.rb +0 -0
  80. data/gems/core/spec/language/metaclass_spec.rb +21 -0
  81. data/{opals/opal/opal → gems/core}/spec/language/method_spec.rb +60 -0
  82. data/{opals/opal/opal → gems/core}/spec/language/next_spec.rb +0 -0
  83. data/{opals/opal/opal → gems/core}/spec/language/or_spec.rb +0 -0
  84. data/{opals/opal/opal → gems/core}/spec/language/redo_spec.rb +0 -0
  85. data/gems/core/spec/language/regexp_spec.rb +26 -0
  86. data/{opals/opal/opal → gems/core}/spec/language/rescue_spec.rb +0 -0
  87. data/{opals/opal/opal → gems/core}/spec/language/return_spec.rb +0 -0
  88. data/{opals/opal/opal → gems/core}/spec/language/string_spec.rb +0 -0
  89. data/gems/core/spec/language/super_spec.rb +32 -0
  90. data/{opals/opal/opal → gems/core}/spec/language/until_spec.rb +47 -47
  91. data/gems/core/spec/language/variables_spec.rb +155 -0
  92. data/{opals/opal/opal → gems/core}/spec/language/while_spec.rb +47 -47
  93. data/{opals/opal/opal → gems/core}/spec/spec_helper.rb +1 -1
  94. data/gems/core_fs/README.md +19 -0
  95. data/gems/dev/Rakefile +5 -0
  96. data/gems/dev/lib/dev.js +99 -0
  97. data/gems/dev/lib/dev/generator.js +1264 -0
  98. data/gems/dev/lib/dev/parser.js +979 -0
  99. data/gems/dev/lib/dev/ruby_parser.js +1088 -0
  100. data/gems/dev/lib/dev/ruby_parser.y +1267 -0
  101. data/gems/dev/lib/dev/string_scanner.js +38 -0
  102. data/gems/dev/tools/racc2js/README.md +39 -0
  103. data/gems/dev/tools/racc2js/math_parser.js +222 -0
  104. data/gems/dev/tools/racc2js/math_parser.rb +133 -0
  105. data/gems/dev/tools/racc2js/math_parser.y +28 -0
  106. data/gems/dev/tools/racc2js/parser.js +218 -0
  107. data/gems/dev/tools/racc2js/racc2js.rb +153 -0
  108. data/gems/json/README.md +4 -0
  109. data/gems/json/json.gemspec +14 -0
  110. data/gems/json/lib/json.rb +64 -0
  111. data/gems/json/lib/json/ext.rb +51 -0
  112. data/{opals/opal/browser/lib/browser/json_parse.js → gems/json/lib/json/json2.js} +197 -37
  113. data/gems/ospec/README.md +0 -0
  114. data/gems/ospec/lib/ospec.rb +6 -0
  115. data/gems/ospec/lib/ospec/autorun.rb +3 -0
  116. data/gems/ospec/lib/ospec/dsl.rb +15 -0
  117. data/gems/ospec/lib/ospec/example.rb +11 -0
  118. data/gems/ospec/lib/ospec/example/before_and_after_hooks.rb +56 -0
  119. data/gems/ospec/lib/ospec/example/errors.rb +17 -0
  120. data/gems/ospec/lib/ospec/example/example_group.rb +12 -0
  121. data/gems/ospec/lib/ospec/example/example_group_factory.rb +21 -0
  122. data/gems/ospec/lib/ospec/example/example_group_hierarchy.rb +20 -0
  123. data/{opals/opal/spec/lib/spec → gems/ospec/lib/ospec}/example/example_group_methods.rb +26 -68
  124. data/gems/ospec/lib/ospec/example/example_group_proxy.rb +14 -0
  125. data/gems/ospec/lib/ospec/example/example_methods.rb +46 -0
  126. data/gems/ospec/lib/ospec/example/example_proxy.rb +18 -0
  127. data/gems/ospec/lib/ospec/expectations.rb +19 -0
  128. data/gems/ospec/lib/ospec/expectations/errors.rb +8 -0
  129. data/gems/ospec/lib/ospec/expectations/fail_with.rb +8 -0
  130. data/gems/ospec/lib/ospec/expectations/handler.rb +27 -0
  131. data/gems/ospec/lib/ospec/matchers.rb +24 -0
  132. data/{opals/opal/Rakefile → gems/ospec/lib/ospec/matchers/be.rb} +0 -0
  133. data/gems/ospec/lib/ospec/matchers/generated_descriptions.rb +20 -0
  134. data/gems/ospec/lib/ospec/matchers/operator_matcher.rb +52 -0
  135. data/gems/ospec/lib/ospec/runner.rb +40 -0
  136. data/gems/ospec/lib/ospec/runner/example_group_runner.rb +44 -0
  137. data/{opals/opal/spec/lib/spec → gems/ospec/lib/ospec}/runner/formatter/html_formatter.rb +31 -40
  138. data/gems/ospec/lib/ospec/runner/formatter/terminal_formatter.rb +48 -0
  139. data/gems/ospec/lib/ospec/runner/options.rb +36 -0
  140. data/{opals/opal/spec/lib/spec → gems/ospec/lib/ospec}/runner/reporter.rb +23 -55
  141. data/gems/ospec/ospec.gemspec +0 -0
  142. data/gems/rquery/README.md +9 -0
  143. data/gems/rquery/lib/rquery.rb +10 -0
  144. data/gems/rquery/lib/rquery/ajax.rb +4 -0
  145. data/gems/rquery/lib/rquery/css.rb +96 -0
  146. data/gems/rquery/lib/rquery/document.rb +25 -0
  147. data/gems/rquery/lib/rquery/element.rb +292 -0
  148. data/gems/rquery/lib/rquery/event.rb +108 -0
  149. data/gems/rquery/lib/rquery/jquery.js +8177 -0
  150. data/gems/rquery/lib/rquery/request.rb +138 -0
  151. data/gems/rquery/lib/rquery/response.rb +49 -0
  152. data/gems/rquery/rquery.gemspec +16 -0
  153. data/lib/opal.js +1597 -0
  154. data/lib/opal.rb +6 -69
  155. data/lib/opal/builder.rb +115 -0
  156. data/lib/opal/bundle.rb +131 -0
  157. data/lib/opal/command.rb +11 -0
  158. data/lib/opal/context.rb +69 -0
  159. data/lib/opal/context/console.rb +12 -0
  160. data/lib/opal/context/file_system.rb +19 -0
  161. data/lib/opal/context/loader.rb +117 -0
  162. data/lib/opal/gem.rb +153 -0
  163. data/lib/opal/ruby/nodes.rb +1302 -0
  164. data/lib/opal/ruby/parser.rb +780 -0
  165. data/lib/opal/ruby/ruby_parser.rb +5170 -0
  166. data/lib/opal/ruby/ruby_parser.y +1298 -0
  167. data/opal.gemspec +11 -256
  168. metadata +179 -240
  169. data/.gitmodules +0 -6
  170. data/Opalfile +0 -384
  171. data/VERSION +0 -1
  172. data/demos/apps/browser_demo/index.html +0 -11
  173. data/demos/apps/browser_demo/lib/browser_demo.rb +0 -31
  174. data/demos/apps/simple_opal/Opalfile +0 -13
  175. data/demos/apps/simple_opal/index.html +0 -11
  176. data/demos/apps/simple_opal/lib/app_controller.rb +0 -62
  177. data/demos/apps/simple_opal/lib/main_window.rb +0 -146
  178. data/demos/browser/request/index.html +0 -52
  179. data/demos/browser/request/request.rb +0 -48
  180. data/gen/browser/__PROJECT_NAME__/Rakefile +0 -12
  181. data/gen/browser/__PROJECT_NAME__/index.html +0 -11
  182. data/gen/browser/__PROJECT_NAME__/javascripts/opal.debug.js +0 -4687
  183. data/gen/browser/__PROJECT_NAME__/javascripts/opal.min.js +0 -175
  184. data/gen/browser/__PROJECT_NAME__/lib/__PROJECT_NAME__.rb +0 -1
  185. data/lib/opal/builders/base.rb +0 -50
  186. data/lib/opal/builders/css.rb +0 -46
  187. data/lib/opal/builders/javascript.rb +0 -44
  188. data/lib/opal/builders/opal.rb +0 -79
  189. data/lib/opal/builders/ruby.rb +0 -50
  190. data/lib/opal/builders/ruby/generate.rb +0 -1851
  191. data/lib/opal/builders/ruby/nodes.rb +0 -210
  192. data/lib/opal/builders/ruby/ruby.rb +0 -916
  193. data/lib/opal/builders/ruby/ruby_parser.rb +0 -6008
  194. data/lib/opal/builders/ruby/ruby_parser.rb.y +0 -1451
  195. data/lib/opal/models/build_item.rb +0 -104
  196. data/lib/opal/models/hash_struct.rb +0 -40
  197. data/lib/opal/models/project.rb +0 -252
  198. data/lib/opal/models/struct_accessors.rb +0 -58
  199. data/lib/opal/models/target.rb +0 -176
  200. data/lib/opal/opal/build.rb +0 -169
  201. data/lib/opal/opal/env/console.rb +0 -66
  202. data/lib/opal/opal/env/fs.rb +0 -98
  203. data/lib/opal/opal/env/object.rb +0 -48
  204. data/lib/opal/opal/environment.rb +0 -139
  205. data/lib/opal/opal/gen.rb +0 -62
  206. data/lib/opal/opal/opal.rb +0 -75
  207. data/lib/opal/opal/repl.rb +0 -38
  208. data/lib/opal/opalfile/dsl.rb +0 -62
  209. data/lib/opal/opalfile/opalfile.rb +0 -133
  210. data/lib/opal/opalfile/task.rb +0 -96
  211. data/lib/opal/opalfile/task_manager.rb +0 -63
  212. data/lib/opal/opalfile/task_scope.rb +0 -52
  213. data/lib/opal/rack/app_server.rb +0 -119
  214. data/lib/opal/rake/opal_task.rb +0 -34
  215. data/opals/opal/README.md +0 -37
  216. data/opals/opal/browser/Opalfile +0 -11
  217. data/opals/opal/browser/README.md +0 -146
  218. data/opals/opal/browser/SIZZLE_LICESNSE.txt +0 -148
  219. data/opals/opal/browser/lib/browser.rb +0 -118
  220. data/opals/opal/browser/lib/browser/builder.rb +0 -41
  221. data/opals/opal/browser/lib/browser/canvas_context.rb +0 -115
  222. data/opals/opal/browser/lib/browser/dimensions.rb +0 -50
  223. data/opals/opal/browser/lib/browser/document.rb +0 -146
  224. data/opals/opal/browser/lib/browser/element.rb +0 -487
  225. data/opals/opal/browser/lib/browser/element/attributes.rb +0 -88
  226. data/opals/opal/browser/lib/browser/element/css.rb +0 -290
  227. data/opals/opal/browser/lib/browser/element/form.rb +0 -146
  228. data/opals/opal/browser/lib/browser/event/dom_events.rb +0 -81
  229. data/opals/opal/browser/lib/browser/event/event.rb +0 -177
  230. data/opals/opal/browser/lib/browser/event/trigger_events.rb +0 -53
  231. data/opals/opal/browser/lib/browser/geometry.rb +0 -97
  232. data/opals/opal/browser/lib/browser/json.rb +0 -32
  233. data/opals/opal/browser/lib/browser/request/request.rb +0 -201
  234. data/opals/opal/browser/lib/browser/sizzle.js +0 -1068
  235. data/opals/opal/browser/lib/browser/string.rb +0 -42
  236. data/opals/opal/browser/lib/browser/touch.rb +0 -37
  237. data/opals/opal/browser/lib/browser/vml_context.js +0 -33
  238. data/opals/opal/browser/lib/browser/window.rb +0 -36
  239. data/opals/opal/browser/spec/browser/browser_detection_spec.rb +0 -7
  240. data/opals/opal/browser/spec/document/aref_spec.rb +0 -110
  241. data/opals/opal/browser/spec/document/ready_spec.rb +0 -16
  242. data/opals/opal/browser/spec/element/body_spec.rb +0 -11
  243. data/opals/opal/browser/spec/element/clear_spec.rb +0 -26
  244. data/opals/opal/browser/spec/element/empty_spec.rb +0 -29
  245. data/opals/opal/browser/spec/element/has_class_spec.rb +0 -40
  246. data/opals/opal/browser/spec/element/hidden_spec.rb +0 -23
  247. data/opals/opal/browser/spec/element/hide_spec.rb +0 -31
  248. data/opals/opal/browser/spec/element/remove_spec.rb +0 -25
  249. data/opals/opal/browser/spec/element/show_spec.rb +0 -31
  250. data/opals/opal/browser/spec/element/style_spec.rb +0 -69
  251. data/opals/opal/browser/spec/element/toggle_spec.rb +0 -31
  252. data/opals/opal/browser/spec/element/visible_spec.rb +0 -23
  253. data/opals/opal/browser/spec/spec_helper.rb +0 -1
  254. data/opals/opal/opal/Opalfile +0 -14
  255. data/opals/opal/opal/spec/core/array/compact_spec.rb +0 -15
  256. data/opals/opal/opal/spec/fixtures/super.rb +0 -70
  257. data/opals/opal/opal/spec/language/____temp_remove_this.rb +0 -12
  258. data/opals/opal/opal/spec/language/block_spec.rb +0 -18
  259. data/opals/opal/opal/spec/language/case_spec.rb +0 -103
  260. data/opals/opal/opal/spec/language/metaclass_spec.rb +0 -21
  261. data/opals/opal/opal/spec/language/super_spec.rb +0 -26
  262. data/opals/opal/runtime/Opalfile +0 -78
  263. data/opals/opal/runtime/README.md +0 -12
  264. data/opals/opal/runtime/docs/debugging.md +0 -51
  265. data/opals/opal/runtime/lib/array.rb +0 -1516
  266. data/opals/opal/runtime/lib/basic_object.rb +0 -49
  267. data/opals/opal/runtime/lib/class.rb +0 -54
  268. data/opals/opal/runtime/lib/dir.rb +0 -36
  269. data/opals/opal/runtime/lib/error.rb +0 -49
  270. data/opals/opal/runtime/lib/false_class.rb +0 -52
  271. data/opals/opal/runtime/lib/file.rb +0 -79
  272. data/opals/opal/runtime/lib/hash.rb +0 -791
  273. data/opals/opal/runtime/lib/io.rb +0 -39
  274. data/opals/opal/runtime/lib/kernel.rb +0 -288
  275. data/opals/opal/runtime/lib/match_data.rb +0 -36
  276. data/opals/opal/runtime/lib/module.rb +0 -109
  277. data/opals/opal/runtime/lib/nil_class.rb +0 -69
  278. data/opals/opal/runtime/lib/number.rb +0 -398
  279. data/opals/opal/runtime/lib/proc.rb +0 -77
  280. data/opals/opal/runtime/lib/range.rb +0 -63
  281. data/opals/opal/runtime/lib/regexp.rb +0 -111
  282. data/opals/opal/runtime/lib/ruby.rb +0 -30
  283. data/opals/opal/runtime/lib/string.rb +0 -328
  284. data/opals/opal/runtime/lib/symbol.rb +0 -40
  285. data/opals/opal/runtime/lib/top_self.rb +0 -33
  286. data/opals/opal/runtime/lib/true_class.rb +0 -45
  287. data/opals/opal/runtime/runtime/browser.js +0 -287
  288. data/opals/opal/runtime/runtime/debug.js +0 -180
  289. data/opals/opal/runtime/runtime/opal.js +0 -1008
  290. data/opals/opal/runtime/runtime/post_opal.js +0 -1
  291. data/opals/opal/runtime/runtime/pre_opal.js +0 -2
  292. data/opals/opal/runtime/runtime/server_side.js +0 -50
  293. data/opals/opal/spec/LICENSE.txt +0 -26
  294. data/opals/opal/spec/Opalfile +0 -5
  295. data/opals/opal/spec/bin/spec.rb +0 -43
  296. data/opals/opal/spec/lib/spec.rb +0 -33
  297. data/opals/opal/spec/lib/spec/dsl.rb +0 -41
  298. data/opals/opal/spec/lib/spec/example.rb +0 -35
  299. data/opals/opal/spec/lib/spec/example/before_and_after_hooks.rb +0 -81
  300. data/opals/opal/spec/lib/spec/example/errors.rb +0 -42
  301. data/opals/opal/spec/lib/spec/example/example_group.rb +0 -37
  302. data/opals/opal/spec/lib/spec/example/example_group_factory.rb +0 -43
  303. data/opals/opal/spec/lib/spec/example/example_group_hierarchy.rb +0 -45
  304. data/opals/opal/spec/lib/spec/example/example_group_proxy.rb +0 -41
  305. data/opals/opal/spec/lib/spec/example/example_methods.rb +0 -73
  306. data/opals/opal/spec/lib/spec/example/example_proxy.rb +0 -48
  307. data/opals/opal/spec/lib/spec/expectations.rb +0 -46
  308. data/opals/opal/spec/lib/spec/expectations/errors.rb +0 -35
  309. data/opals/opal/spec/lib/spec/expectations/fail_with.rb +0 -37
  310. data/opals/opal/spec/lib/spec/expectations/handler.rb +0 -48
  311. data/opals/opal/spec/lib/spec/matchers.rb +0 -50
  312. data/opals/opal/spec/lib/spec/matchers/be.rb +0 -26
  313. data/opals/opal/spec/lib/spec/matchers/generated_descriptions.rb +0 -47
  314. data/opals/opal/spec/lib/spec/matchers/operator_matcher.rb +0 -66
  315. data/opals/opal/spec/lib/spec/runner.rb +0 -48
  316. data/opals/opal/spec/lib/spec/runner/example_group_runner.rb +0 -71
  317. data/opals/opal/spec/lib/spec/runner/formatter/terminal_formatter.rb +0 -82
  318. data/opals/opal/spec/lib/spec/runner/options.rb +0 -63
  319. data/opals/opal/spec/resources/index.html +0 -25
  320. data/opals/opal/spec/resources/spec.css +0 -132
  321. data/spec/cherry_kit/iseq_spec.rb +0 -38
  322. data/spec/spec_helper.rb +0 -16
  323. data/spec/vienna_spec.rb +0 -7
  324. data/yard/index.html +0 -43
  325. data/yard/style.css +0 -765
@@ -0,0 +1,5 @@
1
+ desc "Rebuild parser for dev"
2
+ task :parser do
3
+ system "./tools/racc2js/racc2js.rb ./packages/opal_dev/lib/opal_dev/ruby_parser.y"
4
+ end
5
+
@@ -0,0 +1,99 @@
1
+ console.log("in opal dev, boom!");
2
+
3
+ /*
4
+ * Browser dev wraps all the dev tools, for compiling etc, but adds some functionality
5
+ * in-browser. It will automatically pick out text/ruby script tags and execute their
6
+ * content. opal.js does not do this as the compiler is required. opal_dev.js should
7
+ * only be used in development mode, so overhead in checking/compiling ruby code
8
+ * in the browser will not affect production level environments.
9
+ */
10
+
11
+ var dev_tools = require('opal_dev/parser');
12
+
13
+ for (var prop in dev_tools) {
14
+ exports[prop] = dev_tools[prop];
15
+ };
16
+
17
+ /**
18
+ Exposes an on screen repl session.
19
+ */
20
+ exports.browser_repl = function() {
21
+ browser_register_ready_listener(function() {
22
+ // wrapping div
23
+ var repl_element = document.createElement('div');
24
+
25
+ // text input
26
+ var input = document.createElement('input');
27
+ input.type = 'text';
28
+ repl_element.appendChild(input);
29
+
30
+ document.body.appendChild(repl_element);
31
+
32
+ input.onkeydown = function() {
33
+ console.log("key down..");
34
+ };
35
+ });
36
+ };
37
+
38
+ /*
39
+ * Document ready listener can take callbacks that are fired when the document
40
+ * and/or window are ready to run. If already loaded then the callback is just
41
+ * called immediately.
42
+ */
43
+ var browser_register_ready_listener = function(callback) {
44
+ if (browser_is_ready) return callback();
45
+
46
+ (function() {
47
+ // w3c - chrome, safari, ff
48
+ if (document.addEventListener) {
49
+ document.addEventListener('DOMContentLoaded', callback, false);
50
+ }
51
+ // IE
52
+ else {
53
+ (function() {
54
+ try {
55
+ document.documentElement.doScroll('left');
56
+ } catch (e) {
57
+ setTimeout(arguments.callee, 0);
58
+ return;
59
+ }
60
+ callback();
61
+ })();
62
+ }
63
+ })();
64
+ };
65
+
66
+ /*
67
+ * Document is not ready yet...
68
+ */
69
+ var browser_is_ready = false;
70
+
71
+ /*
72
+ * Find all script tags and run them.
73
+ */
74
+ browser_register_ready_listener(function() {
75
+ browser_is_ready = true;
76
+
77
+ var tags = document.getElementsByTagName('script'), tag;
78
+
79
+ for (var i = 0; i < tags.length; i++) {
80
+ tag = tags[i];
81
+
82
+ if (tag.type == 'text/ruby') {
83
+ // src property - load by ajax, then run
84
+ if (tag.src) {
85
+
86
+ }
87
+ // no src, so just run inner contents
88
+ else {
89
+ console.log('need to run content:');
90
+ console.log(tag.innerHTML);
91
+ var result = Opal.compile(tag.innerHTML);
92
+ console.log(result);
93
+ eval(result);
94
+ }
95
+ }
96
+ }
97
+ });
98
+
99
+
@@ -0,0 +1,1264 @@
1
+ // Inheritence for nodes
2
+ var extend = function(subclass, superclass) {
3
+ for (var key in superclass) {
4
+ if (superclass.hasOwnProperty(key)) {
5
+ subclass[key] = superclass[key];
6
+ }
7
+ }
8
+
9
+ var cons = function() {};
10
+ cons.prototype = superclass.prototype;
11
+ subclass.prototype = new cons();
12
+ subclass.__super__ = superclass.prototype;
13
+ return subclass;
14
+ };
15
+
16
+ // Indent for generated code scopes; 2 spaces, never use tabs.
17
+ var INDENT = ' ';
18
+
19
+ var LEVEL_TOP = 0; // normal top level statements
20
+ var LEVEL_TOP_CLOSURE = 1; // normal top level, but wrapped ina closure - return needs to throw, etc
21
+ var LEVEL_LIST = 2;
22
+ var LEVEL_EXPR = 3;
23
+
24
+ // Base node. All other nodes inherit from this.
25
+ var BaseNode = function() {
26
+ return this;
27
+ };
28
+
29
+ // Generate the code for this node. MUST override in subclasses.
30
+ BaseNode.prototype.generate = function() {
31
+ return '';
32
+ };
33
+
34
+ // Makes the node return its value. Overriden by various subclasses.
35
+ // This is not for use with the ruby return statement, this just means that
36
+ // the generated scope requires us to return wihin javascript. The return stmt
37
+ // in ruby uses another method for returning.
38
+ BaseNode.prototype.returns = function() {
39
+ // this is not a VM return, it just means return out of func
40
+ return new FuncReturnNode(this);
41
+ };
42
+
43
+ // By default all nodes are expressions (';' to finish them). Statements override
44
+ // this to be false.
45
+ BaseNode.prototype.isExpression = function() {
46
+ return true;
47
+ };
48
+
49
+ // processes the node which generates it. By default, process will also fix the
50
+ // line number etc. Some nodes override this as they need a slightly different
51
+ // approach. This will also set the level for indentation?? To generate, but not
52
+ // indent or fix line number, you may call .generate() directly. Note that this
53
+ // relies on the level. If the level is LEVEL_LIST, for example, then a node will
54
+ // not correct its line number or indentation.
55
+ BaseNode.prototype.process = function(opts, level) {
56
+ if (level <= LEVEL_LIST) {
57
+ return this.fixLineNumber(opts) + this.generate(opts, level);
58
+ } else {
59
+ return this.generate(opts, level);
60
+ }
61
+ };
62
+
63
+ // Fix the line number for nodes that want to (calls etc)
64
+ BaseNode.prototype.fixLineNumber = function(opts, line) {
65
+ var code = '';
66
+ // make sure we are at the right line.
67
+ var targetLine = (line || this.line), currentLine = opts.top.line;
68
+ // console.log(targetLine + " ... " + currentLine);
69
+ if (currentLine < targetLine) {
70
+ for (var j = (targetLine - currentLine); j > 0; j--) {
71
+ opts.top.line++;
72
+ code += '\n';
73
+ }
74
+
75
+ code += opts.indent;
76
+ // console.log(currentLine - targetLine);
77
+ }
78
+ return code;
79
+ };
80
+
81
+ // Scoped nodes - all scope nodes inherit from this: method, class, def, etc.
82
+ var ScopeNode = function(parent, statements) {
83
+ this.parent = parent;
84
+ this.statements = statements;
85
+ // all variables - arg, temps, params etc
86
+ this.variables = [];
87
+ // all vars for scope and temp
88
+ this.scopeVars = [];
89
+ // temps
90
+ this.temp_current = {};
91
+ this.temp_queue = {};
92
+ // ivars.. we need to make sure these exist (make sure they are nil if new)
93
+ this.ivars = [];
94
+
95
+ this.temp_queue = [];
96
+ this.temp_current = 'a';
97
+ };
98
+
99
+ extend(ScopeNode, BaseNode);
100
+
101
+ ScopeNode.prototype.ensureIvar = function(name) {
102
+ this.ivars.push(name);
103
+ };
104
+
105
+ ScopeNode.prototype.paramVariable = function(name) {
106
+ this.variables.push(name);
107
+ };
108
+
109
+ ScopeNode.prototype.ensureVariable = function(name) {
110
+ var variable;
111
+
112
+ if (variable = this.findVariable(name)) {
113
+ return variable;
114
+ }
115
+
116
+ // does not exist in scope
117
+ this.scopeVars.push(name);
118
+ return this.variables.push(name);
119
+ };
120
+
121
+ ScopeNode.prototype.findVariable = function(name) {
122
+ var scope = this;
123
+
124
+ while (scope) {
125
+
126
+ if (scope.variables.indexOf(name) != -1) {
127
+ return name;
128
+ }
129
+
130
+ if ((scope instanceof BlockNode) && scope.parent) {
131
+ scope = scope.parent;
132
+ } else {
133
+ break;
134
+ }
135
+ }
136
+
137
+ return null;
138
+ };
139
+
140
+ ScopeNode.prototype.temp_local = function() {
141
+ if (this.temp_queue.length) {
142
+ return this.temp_queue.pop();
143
+ }
144
+
145
+ var name = '__' + this.temp_current;
146
+ this.scopeVars.push(name);
147
+ this.temp_current = String.fromCharCode(this.temp_current.charCodeAt(0) + 1);
148
+ return name;
149
+ };
150
+
151
+ ScopeNode.prototype.queue_temp = function(temp) {
152
+ this.temp_queue.push(temp);
153
+ };
154
+
155
+ ScopeNode.prototype.set_uses_block = function() {
156
+ if (this._block_arg_name) {
157
+ return this._block_arg_name;
158
+ }
159
+
160
+ this._block_arg_name = '__block__';
161
+ return this._block_arg_name;
162
+ };
163
+
164
+ ScopeNode.prototype.generate = function(opts, level) {
165
+ var stmts = this.statements.generate(opts, level);
166
+ var vars = '';
167
+
168
+ return vars + stmts;
169
+ };
170
+
171
+ // Top level scope. This also manages things like line numbers etc. All opts will
172
+ // be passed a .top property that references this root scope (instead of manually
173
+ // traversing it each time)
174
+ var TopScopeNode = exports.TopScopeNode = function(statements) {
175
+ ScopeNode.call(this, null, statements);
176
+ // helpers we need at top of file
177
+ this.file_helpers = [];
178
+ // keep track of the line number
179
+ this.line = 1;
180
+ return this;
181
+ };
182
+
183
+ extend(TopScopeNode, ScopeNode);
184
+
185
+ TopScopeNode.prototype.generate = function(opts, level) {
186
+ var code = [];
187
+ // super()
188
+ code.push(ScopeNode.prototype.generate.call(this, opts, level));
189
+
190
+ // pre
191
+ var pre_code = '';
192
+
193
+ pre_code += ('var Opal = $opal, self = Opal.top, nil = Opal.Qnil');
194
+ pre_code += (', $class = Opal.dc, $def = Opal.dm, $symbol = Opal.Y');
195
+ pre_code += (', $hash = Opal.H, $block = Opal.P;');
196
+
197
+ if (this.scopeVars.length != 0) {
198
+ pre_code = 'var ' + this.scopeVars.join(', ') + ';' + pre_code;
199
+ }
200
+
201
+ return pre_code + code.join('');
202
+ };
203
+
204
+ // Statements - represents any chain of statements
205
+ var StatementsNode = exports.StatementsNode = function(nodes) {
206
+ this.nodes = nodes || [];
207
+ return this;
208
+ };
209
+
210
+ extend(StatementsNode, BaseNode);
211
+
212
+ StatementsNode.prototype.returns = function() {
213
+ if (this.nodes.length > 0) {
214
+ // this.nodes[this.nodes.length - 1] = new ReturnNode({line: this.line}, [[this.nodes[this.nodes.length - 1]]]);
215
+ this.nodes[this.nodes.length - 1] = this.nodes[this.nodes.length - 1].returns();
216
+ } else {
217
+ this.nodes[0] = (new FuncReturnNode(new NilNode({})));
218
+ }
219
+ };
220
+
221
+ StatementsNode.prototype.generate = function(opts, level) {
222
+ var code = [], node;
223
+ for (var i = 0; i < this.nodes.length; i++) {
224
+ node = this.nodes[i];
225
+
226
+
227
+ var nodeCode = this.nodes[i].process(opts, LEVEL_TOP);
228
+ // console.log("LEVEL is " + level);
229
+ if (level <= LEVEL_TOP_CLOSURE) {
230
+ // to prevent lots of trailing whitespace when we generate statements on new lines,
231
+ // we only insert indent if we dont have a newline marker straight away.
232
+ if (nodeCode.charAt(0) == '\n') {
233
+ code.push(nodeCode);
234
+ } else {
235
+ code.push(opts.indent + nodeCode);
236
+ }
237
+ // if expression, add ';' .. statements dont need ';'
238
+ // we MUST call this after we generate it, as some stmts may determine themselves
239
+ // during compilation. for example, IfNode does depending on whether it needs to
240
+ // generate as a level_top or a level_top_closure
241
+ if (node.isExpression()) { code.push(';'); }
242
+
243
+ } else {
244
+ code.push(nodeCode);
245
+ }
246
+ // indent? we should add it here if the LEVEL is top level.. (or normal stmt
247
+ // level)... currently no indentation
248
+ }
249
+ return code.join('');
250
+ };
251
+
252
+
253
+ // Push more statements onto end
254
+ StatementsNode.prototype.push = function(node) {
255
+ this.nodes.push(node);
256
+ return this;
257
+ };
258
+
259
+ // Generate statements for the top level - generally used for files
260
+ StatementsNode.prototype.generateTop = function(opts) {
261
+ opts = opts || {};
262
+ var scope = new TopScopeNode(this);
263
+ opts.scope = scope;
264
+ opts.indent = '';
265
+ opts.top = scope;
266
+ return scope.generate(opts, LEVEL_TOP);
267
+ // return "shake sgake boom";
268
+ };
269
+
270
+ var NumericNode = exports.NumericNode = function(val) {
271
+ this.value = val.value;
272
+ this.line = val.line;
273
+ return this;
274
+ };
275
+
276
+ extend(NumericNode, BaseNode);
277
+
278
+ NumericNode.prototype.generate = function(opts) {
279
+ return this.value;
280
+ };
281
+
282
+ var SymbolNode = exports.SymbolNode = function(val) {
283
+ this.val = val.value;
284
+ this.line = val.line;
285
+ return this;
286
+ };
287
+
288
+ extend(SymbolNode, BaseNode);
289
+
290
+ SymbolNode.prototype.generate = function(opts) {
291
+ return '$symbol("' + this.val + '")';
292
+ };
293
+
294
+ var CallNode = exports.CallNode = function(recv, mid, args) {
295
+ this.recv = recv;
296
+ this.mid = mid.value;
297
+ this.args = args;
298
+ // our initial line is where our receiver's line starts. method name might be
299
+ // on a subsiquint line, e.g. calling the result of an IF stmt
300
+ this.line = recv ? recv.line : mid.line;
301
+ return this;
302
+ };
303
+
304
+ extend(CallNode, BaseNode);
305
+
306
+ CallNode.prototype.mid_to_jsid = function(id) {
307
+ id = 'm$' + id;
308
+
309
+ if(/[\!\=\?\+\-\*\/\^\&\%\@\|\[\]\<\>\~]/.exec(id)) {
310
+ return '["' + id + '"]';
311
+ }
312
+ return '.' + id;
313
+ };
314
+
315
+ CallNode.prototype.generate = function(opts) {
316
+ // var code = this.fixLineNumber(opts);
317
+ var code = '', arg_res = [], recv, mid;
318
+
319
+ // recv
320
+ if (this.recv instanceof NumericNode) {
321
+ recv = ('(' + this.recv.process(opts, LEVEL_EXPR) + ')');
322
+ } else if (this.recv) {
323
+ recv = this.recv.process(opts, LEVEL_EXPR);
324
+ } else {
325
+ recv = (new SelfNode({}).generate(opts));
326
+ }
327
+
328
+ // mid
329
+ mid = this.mid_to_jsid(this.mid);
330
+
331
+ // args
332
+ var args = this.args;
333
+ // norm
334
+ if (args[0]) {
335
+ for (var i = 0; i < args[0].length; i++) {
336
+ arg_res.push(args[0][i].generate(opts, LEVEL_EXPR));
337
+ }
338
+ }
339
+
340
+ if (this.block) {
341
+ // tmp self
342
+ var tmp_self = opts.scope.temp_local();
343
+ var tmp_args = opts.scope.temp_local();
344
+ // var scope = { indent: opts.indent + INDENT, top: opts.top, scope: this };
345
+ var BLOCK = this.block.generate(opts, LEVEL_TOP);
346
+
347
+
348
+ code += ('(' + tmp_self + ' = ' + recv + ', ' + tmp_args + ' = ' + '[' + arg_res.join(', ') + ']');
349
+ code += (', ($block.p = ' + BLOCK + ').$self = ' + (new SelfNode({})).generate(opts));
350
+ code += (', ($block.f = ' + tmp_self + mid + ').apply(' + tmp_self + ', ' + tmp_args + '))');
351
+ // code
352
+
353
+ // code += ('(($block.p = ' + BLOCK + ').$self = (' + tmp_self + ' = ' + recv);
354
+ // code += ('), $block.f = ' + tmp_self + mid +')');
355
+ // code += '.call';
356
+
357
+ // arg_res.push(tmp_self);
358
+
359
+ opts.scope.queue_temp(tmp_self);
360
+ opts.scope.queue_temp(tmp_args);
361
+
362
+ return code;
363
+
364
+ // &to_proc. Note: this must NOT reassign the $self for the proc... we are just
365
+ // passing an existing block on.
366
+ } else if (args[3]) {
367
+ var tmp_self = opts.scope.temp_local();
368
+ var tmp_args = opts.scope.temp_local();
369
+
370
+ code += ('(' + tmp_self + ' = ' + recv + ', ' + tmp_args + ' = ' + '[' + arg_res.join(', ') + ']');
371
+ code += (', ($block.p = ' + args[3].process(opts, LEVEL_LIST) + ')');
372
+ code += (', ($block.f = ' + tmp_self + mid + ').apply(' + tmp_self + ', ' + tmp_args + '))');
373
+
374
+ opts.scope.queue_temp(tmp_self);
375
+ opts.scope.queue_temp(tmp_args);
376
+ return code;
377
+
378
+ // no block..
379
+ } else {
380
+
381
+ // splat args
382
+ if (args[1]) {
383
+ var splat = args[1].generate(opts);
384
+ return recv + mid + '.apply' + '(' + recv + ', [' + arg_res.join(', ') + '].concat(' + splat + '))';
385
+ } else {
386
+ return recv + mid + '(' + arg_res.join(', ') + ')';
387
+ }
388
+ // code += (recv + mid);
389
+ }
390
+
391
+ // return code + '(' + arg_res.join(', ') + ')';
392
+ };
393
+
394
+ var SelfNode = exports.SelfNode = function(val) {
395
+ this.line = val.line;
396
+ return this;
397
+ };
398
+
399
+ extend(SelfNode, BaseNode);
400
+
401
+ SelfNode.prototype.generate = function(opts) {
402
+ return 'self';
403
+ };
404
+
405
+ var NilNode = exports.NilNode = function(val) {
406
+ this.line = val.line;
407
+ return this;
408
+ };
409
+
410
+ extend(NilNode, BaseNode);
411
+
412
+ NilNode.prototype.generate = function(opts) {
413
+ return 'nil';
414
+ };
415
+
416
+ var ModuleNode = exports.ModuleNode = function(mod, path, body, end) {
417
+ ScopeNode.call(this, null, body);
418
+ this.line = mod.line;
419
+ this.base = path[0];
420
+ this.clsName = path[1].value;
421
+ this.endLine = end.line;
422
+ return this;
423
+ };
424
+
425
+ extend(ModuleNode, BaseNode);
426
+
427
+ ModuleNode.prototype.generate = function(opts) {
428
+ var code = '$class(';
429
+
430
+ // base
431
+ if (this.base == null) {
432
+ code += (new SelfNode({})).generate(opts);
433
+ } else {
434
+ code += "w";
435
+ }
436
+
437
+ code += ', ';
438
+
439
+ // superclass
440
+ code += ((new NilNode({})).generate(opts) + ', ');
441
+
442
+ // module name
443
+ code += ('"' + this.clsName + '", ');
444
+
445
+ // scope
446
+
447
+ var scope = { indent: opts.indent + INDENT, top: opts.top, scope: this };
448
+ var stmt = this.statements.generate(scope, LEVEL_TOP);
449
+ code += "function() {";
450
+
451
+ code += 'var self = this;';
452
+
453
+ code += stmt;
454
+
455
+ // fix ending line number
456
+ var currentLine = opts.top.line, targetLine = this.endLine;
457
+ for (var i = (targetLine - currentLine); i > 0; i--) {
458
+ opts.top.line++;
459
+ code += '\n';
460
+ }
461
+
462
+ code += opts.indent + '}, 2)';
463
+
464
+ return code;
465
+ };
466
+
467
+ var ClassNode = exports.ClassNode = function(cls, path, sup, body, end) {
468
+ ScopeNode.call(this, null, body);
469
+ this.scopeVars.push('self = this');
470
+ this.line = cls.line;
471
+ this.base = path[0];
472
+ this.clsName = path[1];
473
+ this.sup = sup;
474
+ // we keep the end line number as its useful for keeping the generated '})'
475
+ // on the matching line to the source
476
+ this.endLine = end.line;
477
+ };
478
+
479
+ extend(ClassNode, ScopeNode);
480
+
481
+ ClassNode.prototype.generate = function(opts) {
482
+ var code = '$class(';
483
+
484
+ // base
485
+ if(this.base == null) {
486
+ code += (new SelfNode({})).generate(opts);
487
+ } else {
488
+ code += "w";
489
+ }
490
+
491
+ code += ', ';
492
+
493
+ // superclass
494
+ if (this.sup) {
495
+ code += this.sup.generate(opts);
496
+ } else {
497
+ code += (new NilNode({})).generate(opts);
498
+ }
499
+
500
+ code += ', ';
501
+
502
+ // class name
503
+ code += ('"' + this.clsName.value + '", ');
504
+
505
+ // generate scope?
506
+ var scope = { indent: opts.indent + INDENT, top: opts.top, scope: this };
507
+ var stmt = this.statements.generate(scope, LEVEL_TOP);
508
+ code += "function() {";
509
+ code += ('var ' + this.scopeVars.join(', ') + ';');
510
+ code += stmt;
511
+
512
+ // fix ending line number
513
+ var currentLine = opts.top.line, targetLine = this.endLine;
514
+ for (var i = (targetLine - currentLine); i > 0; i--) {
515
+ opts.top.line++;
516
+ code += '\n';
517
+ }
518
+
519
+ code += opts.indent + '}, 0)'
520
+
521
+ return code;
522
+ };
523
+
524
+ var DefNode = exports.DefNode = function(def, singleton, fname, args, body, end) {
525
+ ScopeNode.call(this, null, body);
526
+ // do this early..
527
+ this.scopeVars.unshift('self = this');
528
+ this.line = def.line;
529
+ this.singleton = singleton;
530
+ this.fname = fname;
531
+ this.args = args;
532
+ this.body = body;
533
+ this.endLine = end.line;
534
+ return this;
535
+ };
536
+
537
+ extend(DefNode, ScopeNode);
538
+
539
+ DefNode.prototype.generate = function(opts) {
540
+ var code = '$def(';
541
+
542
+ // singleton
543
+ if (this.singleton) {
544
+ code += this.singleton.generate(opts);
545
+ } else {
546
+ code += (new SelfNode({})).generate(opts);
547
+ }
548
+
549
+ code += ', ';
550
+
551
+ // method id
552
+ code += '"' + this.fname.value + '", ';
553
+
554
+ // all method arg names to be placed in function arg list
555
+ var method_args = [];
556
+ // all pre code - opt arg fixing, rest args, tmp variable names, and norm variable names.
557
+ // This will also include the block capture for the function, and an initial try { expr
558
+ // if we need to catch any errors within the method itself... all in all, lots goes in
559
+ // here. Tmp var names must be inserted (or appear before) opt arg fixing, as that might
560
+ // require the use of tmp variables.
561
+ var pre_code = '';
562
+
563
+ // stmt code
564
+ var scope = { indent: opts.indent + INDENT, top: opts.top, scope: this };
565
+ // generate args, method fixes etc. we do this before the body as it simply
566
+ // means that we are creating stataments on the fly and unshifting them onto
567
+ // the current statements... magical!
568
+ var args = this.args;
569
+ // norm
570
+ for (var i = 0; i < args[0].length; i++) {
571
+ // this.push_arg(args[0].value);
572
+ this.paramVariable(args[0][i].value);
573
+ method_args.push(args[0][i].value);
574
+ }
575
+
576
+ // opt
577
+ for (i = 0; i < args[1].length; i++) {
578
+ this.paramVariable(args[1][i][0].value);
579
+ method_args.push(args[1][i][0].value);
580
+ }
581
+
582
+ // rest
583
+ if (args[2]) {
584
+ this.paramVariable(args[2].value);
585
+ method_args.push(args[2].value);
586
+ pre_code += (args[2].value + ' = [].slice.call(arguments, ' + (method_args.length - 1) + ');');
587
+ }
588
+
589
+ if (args[3]) {
590
+ this.paramVariable(args[3].value);
591
+ this._block_arg_name = args[3].value;
592
+ }
593
+
594
+ this.body.returns();
595
+ var stmt = this.body.generate(scope, LEVEL_TOP);
596
+ code += "function(";
597
+ // need to insert all args, local vars, opt_arg fixes and ivar fixes
598
+ code += method_args.join(', ');
599
+ code += ") { ";
600
+ // dont put pre_code on new line.. keep it on def line to maintain correct lines. Its
601
+ // better to clog up end of def line as its unimportant, and all pre_code is boring
602
+ // boilerplate stuff which the user shouldnt/doesnt need to care about.
603
+
604
+ pre_code = ('var ' + this.scopeVars.join(', ') + ';') + pre_code;
605
+
606
+ // ivars
607
+ for (var i = 0; i < this.ivars.length; i++) {
608
+ pre_code += ('if (self["' + this.ivars[i] + '"] == undefined) {self["' + this.ivars[i] + '"] = nil;}');
609
+ }
610
+
611
+ // block arg
612
+ if (this._block_arg_name) {
613
+ pre_code += (' var ' + this._block_arg_name + ' = ($block.f == arguments.callee)'
614
+ + ' ? $block.p : nil; $block.p = $block.f = nil;');
615
+ }
616
+ code += pre_code;
617
+ code += stmt;
618
+
619
+ // fix trailing }) as well as 0/1 for normal/singleton
620
+ code += (this.fixLineNumber(opts, this.endLine) + '}, ' + (this.singleton ? '1' : '0') + ')');
621
+
622
+ return code;
623
+ };
624
+
625
+ var BodyStatementsNode = exports.BodyStatementsNode = function(stmt, rescue, optelse, optensure) {
626
+ // StatementsNode.call(this, stmt.statements);
627
+ this.statements = stmt;
628
+ this.opt_rescue = rescue;
629
+ this.opt_else = optelse;
630
+ this.opt_ensure = optensure;
631
+ };
632
+
633
+ extend(BodyStatementsNode, BaseNode);
634
+
635
+ BodyStatementsNode.prototype.returns = function() {
636
+ return this.statements.returns();
637
+ };
638
+
639
+
640
+ BodyStatementsNode.prototype.generate = function(opts, level) {
641
+ return this.statements.generate(opts, level);
642
+ };
643
+
644
+ var OrNode = exports.OrNode = function(node, lhs, rhs) {
645
+ this.line = node.line;
646
+ this.lhs = lhs;
647
+ this.rhs = rhs;
648
+ };
649
+
650
+ extend(OrNode, BaseNode);
651
+
652
+ OrNode.prototype.generate = function(opts) {
653
+ var res = '((';
654
+ var tmp = opts.scope.temp_local();
655
+ res += (tmp + ' = ' + this.lhs.generate(opts, LEVEL_LIST) + ').$r ? ');
656
+ res += (tmp + ' : ' + this.rhs.generate(opts, LEVEL_LIST) + ')');
657
+ // queue tmp
658
+ opts.scope.queue_temp(tmp);
659
+ return res;
660
+ };
661
+
662
+ var AndNode = exports.AndNode = function(node, lhs, rhs) {
663
+ this.line = node.line;
664
+ this.lhs = lhs;
665
+ this.rhs = rhs;
666
+ };
667
+
668
+ extend(AndNode, BaseNode);
669
+
670
+ AndNode.prototype.generate = function(opts) {
671
+ var res = '((';
672
+ var tmp = opts.scope.temp_local();
673
+ res += (tmp + ' = ' + this.lhs.generate(opts, LEVEL_LIST) + ').$r ? ');
674
+ res += (this.rhs.generate(opts, LEVEL_LIST) + ' : ' + tmp + ')');
675
+ // queue tmp
676
+ opts.scope.queue_temp(tmp);
677
+ return res;
678
+ };
679
+
680
+ var ArrayNode = exports.ArrayNode = function(parts, begin, end) {
681
+ this.line = begin.line;
682
+ this.endLine = end.line;
683
+ this.args = parts;
684
+ return this;
685
+ };
686
+
687
+ extend(ArrayNode, BaseNode);
688
+
689
+ ArrayNode.prototype.generate = function(opts) {
690
+ var code = '', old_indent = opts.indent;
691
+
692
+ opts.indent += INDENT;
693
+
694
+ for (var i = 0 ; i < this.args[0].length; i++) {
695
+ if (i > 0) code += ', ';
696
+ code += this.args[0][i].process(opts, LEVEL_LIST);
697
+ }
698
+
699
+ opts.indent = old_indent;
700
+ return '[' + code + this.fixLineNumber(opts, this.endLine) + ']';
701
+ };
702
+
703
+ var HashNode = exports.HashNode = function(parts, begin, end) {
704
+ this.line = begin.line;
705
+ this.endLine = end.line;
706
+ this.parts = parts;
707
+ return this;
708
+ };
709
+
710
+ extend(HashNode, BaseNode);
711
+
712
+ HashNode.prototype.generate = function(opts) {
713
+ var code = '', part, old_indent = opts.indent;
714
+
715
+ opts.indent += INDENT;
716
+
717
+ for (var i = 0; i < this.parts.length; i++) {
718
+ part = this.parts[i];
719
+ if (i > 0) code += ', ';
720
+ code += part[0].process(opts, LEVEL_LIST);
721
+ code += ', ';
722
+ code += part[1].process(opts, LEVEL_LIST);
723
+ }
724
+
725
+ opts.indent = old_indent;
726
+
727
+ code = '$hash(' + code;
728
+
729
+ return code + this.fixLineNumber(opts, this.endLine) + ')';
730
+
731
+ // return '$hash(' + code + ')';
732
+ };
733
+
734
+ var IfNode = exports.IfNode = function(beg, expr, stmt, tail, end) {
735
+ this.line = beg.line;
736
+ this.expr = expr;
737
+ this.stmt = stmt;
738
+ this.tail = tail;
739
+ this.endLine = end.line;
740
+ };
741
+
742
+ extend(IfNode, BaseNode);
743
+
744
+ IfNode.prototype.returns = function() {
745
+ this.stmt.returns();
746
+
747
+ for (var i = 0; i < this.tail.length; i++) {
748
+ var tail = this.tail[i];
749
+
750
+ if (tail[0].value == 'elsif') {
751
+ tail[2].returns();
752
+ } else {
753
+ // else
754
+ tail[1].returns();
755
+ }
756
+ }
757
+ return this;
758
+ };
759
+
760
+ IfNode.prototype.isExpression = function() {
761
+ return this._exprLevel;
762
+ };
763
+
764
+ IfNode.prototype.generate = function(opts, level) {
765
+ var code = '', done_else = false, old_indent = opts.indent, tail;
766
+
767
+ opts.indent += INDENT;
768
+
769
+ // stmt_level is level_top, unless we are an expression.. then it is level_top_closure
770
+ var stmt_level = level === LEVEL_EXPR ? LEVEL_TOP_CLOSURE : LEVEL_TOP;
771
+
772
+ if (stmt_level === LEVEL_TOP_CLOSURE) {
773
+ this.returns();
774
+ this._exprLevel = true;
775
+ }
776
+
777
+ code += 'if (' + this.expr.generate(opts) + '.$r) {';
778
+
779
+ code += this.stmt.process(opts, stmt_level);
780
+
781
+ for (var i = 0; i < this.tail.length; i++) {
782
+ tail = this.tail[i];
783
+ opts.indent = old_indent;
784
+
785
+ code += this.fixLineNumber(opts, tail[0].line);
786
+
787
+ if (tail[0].value == 'elsif') {
788
+ code += '} else if (' + tail[1].generate(opts) + '.$r) {';
789
+ opts.indent += INDENT;
790
+ code += tail[2].process(opts, stmt_level);
791
+
792
+ } else {
793
+ done_else = true;
794
+ code += '} else {';
795
+ opts.indent += INDENT;
796
+ code += tail[1].process(opts, stmt_level);
797
+ }
798
+ }
799
+
800
+ if (this.forceElse) {
801
+ // generate an else statement if we MUST have one. If, for example, we set
802
+ // the result of ourselves to a variable, we must have an else part which
803
+ // simply returns nil.
804
+ }
805
+
806
+ opts.indent = old_indent;
807
+
808
+ code += (this.fixLineNumber(opts, this.endLine) + '}');
809
+
810
+ // if we are an expression, we need to wrap ourself as a closure..
811
+ if (level === LEVEL_EXPR) {
812
+ code = '(function() {' + code + '})()';
813
+ }
814
+
815
+ return code;
816
+ };
817
+
818
+ var ConstantNode = exports.ConstantNode = function(name) {
819
+ this.line = name.line;
820
+ this.name = name.value;
821
+ return this;
822
+ };
823
+
824
+ extend(ConstantNode, BaseNode);
825
+
826
+ ConstantNode.prototype.generate = function(opts) {
827
+ return 'rb_vm_cg(' + (new SelfNode({})).generate(opts) + ', "' + this.name + '")';
828
+ };
829
+
830
+ var Colon2Node = exports.Colon2Node = function(lhs, name) {
831
+ this.lhs = lhs;
832
+ this.line = name.line;
833
+ this.name = name.value;
834
+ };
835
+
836
+ extend(Colon2Node, BaseNode);
837
+
838
+ Colon2Node.prototype.generate = function(opts) {
839
+ return 'rb_vm_cg(' + this.lhs.generate(opts) + ', "' + this.name + '")';
840
+ };
841
+
842
+ var AssignNode = exports.AssignNode = function(lhs, rhs, assign) {
843
+ this.line = lhs.line;
844
+ this.lhs = lhs;
845
+ this.rhs = rhs;
846
+ return this;
847
+ };
848
+
849
+ extend(AssignNode, BaseNode);
850
+
851
+ AssignNode.prototype.generate = function(opts, level) {
852
+ var code = '';
853
+
854
+ if (this.lhs instanceof IvarNode) {
855
+ return (new SelfNode({})).generate(opts) + '["' + this.lhs.name + '"] = ' + this.rhs.generate(opts, LEVEL_EXPR);
856
+ } else if (this.lhs instanceof IdentifierNode) {
857
+ opts.scope.ensureVariable(this.lhs.name);
858
+ return this.lhs.name + ' = ' + this.rhs.generate(opts, LEVEL_EXPR);
859
+ } else if (this.lhs instanceof CallNode) {
860
+ return (new CallNode(
861
+ this.lhs.recv,
862
+ { value: this.lhs.mid + '=', line: this.line },
863
+ [[this.rhs]])
864
+ ).generate(opts);
865
+
866
+ } else if (this.lhs instanceof ConstantNode) {
867
+ return 'rb_vm_cs(self, "' + this.lhs.name + '", ' + this.rhs.generate(opts, LEVEL_EXPR) + ')';
868
+
869
+ } else if (this.lhs instanceof ArefNode) {
870
+ return (new AsetNode(this.lhs.recv, this.lhs.arefs, this.rhs)).process(opts, level);
871
+ } else {
872
+ console.log(this.lhs);
873
+ throw new Error("line " + this.line + ": bad lhs for assign");
874
+ }
875
+ };
876
+
877
+ var OpAsgnNode = exports.OpAsgnNode = function(asgn, lhs, rhs) {
878
+ this.lhs = lhs;
879
+ this.rhs = rhs;
880
+ this.line = asgn.line;
881
+ this.asgn = asgn;
882
+ };
883
+
884
+ extend(OpAsgnNode, BaseNode);
885
+
886
+ OpAsgnNode.prototype.generate = function(opts) {
887
+ var assign;
888
+ if (this.asgn.value == '||') {
889
+ assign = new OrNode({value: '||', line: this.line }, this.lhs, new AssignNode(this.lhs, this.rhs));
890
+ } else if (['+', '-', '/', '*'].indexOf(this.asgn.value) != -1) {
891
+ assign = new AssignNode(this.lhs, new CallNode(this.lhs, this.asgn, [[this.rhs]]));
892
+ } else {
893
+ console.log(this.asgn);
894
+ throw new Error("bad asgn type for opasgn");
895
+ }
896
+ return assign.generate(opts);
897
+ };
898
+
899
+ var IvarNode = exports.IvarNode = function(name) {
900
+ this.line = name.line;
901
+ this.name = name.value;
902
+ };
903
+
904
+ extend(IvarNode, BaseNode);
905
+
906
+ IvarNode.prototype.generate = function(opts) {
907
+ opts.scope.ensureIvar(this.name);
908
+ return (new SelfNode({})).generate(opts) + '["' + this.name + '"]';
909
+ };
910
+
911
+ var IdentifierNode = exports.IdentifierNode= function(name) {
912
+ this.line = name.line;
913
+ this.name = name.value;
914
+ };
915
+
916
+ extend(IdentifierNode, BaseNode);
917
+
918
+ IdentifierNode.prototype.generate = function(opts) {
919
+ // for now assume it is an identifier
920
+ if (opts.scope.findVariable(this.name)) {
921
+ return this.name;
922
+ } else {
923
+ return (new CallNode(null, {value: this.name, line: this.line}, [[]])).generate(opts);
924
+ }
925
+ };
926
+
927
+ var BeginNode = exports.BeginNode = function(begin, body, end) {
928
+ this.line = begin.line;
929
+ this.body = body;
930
+ this.endLine = end.line;
931
+ };
932
+
933
+ extend(BeginNode, BaseNode);
934
+
935
+ BeginNode.prototype.generate = function(opts) {
936
+ var code = 'try {', old_indent = opts.indent;
937
+ opts.indent += INDENT;
938
+
939
+ code += this.body.process(opts, LEVEL_TOP);
940
+ code += '} catch(__err__) {';
941
+
942
+ // console.log(this.body.opt_rescue);
943
+ for (var i = 0; i < this.body.opt_rescue.length; i++) {
944
+ var rescue = this.body.opt_rescue[i];
945
+
946
+ // need to comapre error types
947
+ code += (this.fixLineNumber(opts, rescue[0].line) + 'if (true) {');
948
+ opts.indent += INDENT;
949
+ code += (rescue[3].process(opts, LEVEL_TOP) + '}');
950
+ opts.indent = old_indent + INDENT;
951
+ }
952
+
953
+ opts.indent = old_indent;
954
+ code += (this.fixLineNumber(opts, this.endLine) + '}');
955
+ return code;
956
+ };
957
+
958
+ var ReturnNode = exports.ReturnNode = function(ret, val) {
959
+ this.line = ret.line;
960
+ this.val = val;
961
+ };
962
+
963
+ extend(ReturnNode, BaseNode);
964
+
965
+ ReturnNode.prototype.returns = function() {
966
+ return this;
967
+ };
968
+
969
+ ReturnNode.prototype.generate = function(opts, level) {
970
+ var code = '';
971
+
972
+ if (this.val[0].length === 0) {
973
+ code = (new NilNode({})).generate(opts);
974
+ } else if (this.val[0].length === 1) {
975
+ code = this.val[0][0].generate(opts);
976
+ } else {
977
+ code = (new NilNode({})).generate(opts);
978
+ }
979
+
980
+ // if we are in block, we need to throw return to the nearest method
981
+ if (!(opts.scope instanceof DefNode)) {
982
+ var return_func = '__return_func';
983
+ return '$return(' + code + ', ' + return_func + ')';
984
+ }
985
+ // level top, we are running full statements, so just return normally
986
+ else if (level == LEVEL_TOP) {
987
+ return 'return ' + code;
988
+ } else {
989
+ return '$return(' + code + ')';
990
+ }
991
+ };
992
+
993
+ // just return out of js scope
994
+ var FuncReturnNode = function(val) {
995
+ this.val = val;
996
+ this.line = val.line;
997
+ };
998
+
999
+ extend(FuncReturnNode, BaseNode);
1000
+
1001
+ FuncReturnNode.prototype.generate = function(opts) {
1002
+ return 'return ' + this.val.generate(opts);
1003
+ };
1004
+
1005
+ var StringNode = exports.StringNode = function(parts, end) {
1006
+ this.line = end.line;
1007
+ this.parts = parts;
1008
+ this.join = end.value;
1009
+ };
1010
+
1011
+ extend(StringNode, BaseNode);
1012
+
1013
+ StringNode.prototype.generate = function(opts) {
1014
+ var code = '';
1015
+ if (this.parts.length == 0) return '""';
1016
+
1017
+ if (this.parts.length == 1) {
1018
+ if (this.parts[0][0] == 'string_content') {
1019
+ return this.join + this.parts[0][1].value + this.join;
1020
+ }
1021
+ } else {
1022
+ code = '(';
1023
+ var part;
1024
+ for (var i = 0; i < this.parts.length; i++) {
1025
+ part = this.parts[i];
1026
+ if (i > 0) code += ' + ';
1027
+
1028
+ if (part[0] == 'string_content') {
1029
+ code += (this.join + part[1].value + this.join);
1030
+ } else if (part[0] == 'string_dbegin') {
1031
+ code += (new CallNode(part[1], { value:'to_s', line:0}, [[]])).generate(opts);
1032
+ }
1033
+ }
1034
+ code += ')'
1035
+ }
1036
+
1037
+ return code;
1038
+ };
1039
+
1040
+ var TrueNode = exports.TrueNode = function(val) {
1041
+ this.line = val.line;
1042
+ };
1043
+
1044
+ extend(TrueNode, BaseNode);
1045
+
1046
+ TrueNode.prototype.generate = function(opts) {
1047
+ return 'Qtrue';
1048
+ };
1049
+
1050
+
1051
+ var FalseNode = exports.FalseNode = function(val) {
1052
+ this.line = val.line;
1053
+ };
1054
+
1055
+ extend(FalseNode, BaseNode);
1056
+
1057
+ FalseNode.prototype.generate = function(opts) {
1058
+ return 'Qfalse';
1059
+ };
1060
+
1061
+ var BlockNode = exports.BlockNode = function(start, vars, stmt, end) {
1062
+ ScopeNode.call(this, null, stmt);
1063
+ // block uses self
1064
+ this.scopeVars.push('self = this');
1065
+ this.line = start.line;
1066
+ this.args = vars;
1067
+ this.stmt = stmt;
1068
+ this.endLine = end.line;
1069
+ };
1070
+
1071
+ extend(BlockNode, ScopeNode);
1072
+
1073
+ BlockNode.prototype.generate = function(opts) {
1074
+ this.parent = opts.scope;
1075
+
1076
+ var pre_code = '';
1077
+
1078
+ var code = '';
1079
+
1080
+
1081
+ var scope = { scope: this, top: opts.top, indent: opts.indent + INDENT };
1082
+
1083
+ var args = this.args[0], method_args = [];
1084
+
1085
+ if (args) {
1086
+ // norm
1087
+ if (args[0]) {
1088
+ // console.log(args[0]);
1089
+ // console.log("length is " + args[0].length);
1090
+ for (var i = 0; i < args[0].length; i++) {
1091
+ // console.log(args[0][i]);
1092
+ // this.push_arg(args[0].value);
1093
+ this.paramVariable(args[0][i].value);
1094
+ method_args.push(args[0][i].value);
1095
+ }
1096
+ }
1097
+
1098
+ // opt
1099
+ if (args[1]) {
1100
+ for (i = 0; i < args[1].length; i++) {
1101
+ method_args.push(args[1][i][0].value);
1102
+ }
1103
+ }
1104
+
1105
+ // rest
1106
+ if (args[2]) {
1107
+ method_args.push(args[2].value);
1108
+ pre_code += (args[2].value + ' = [].slice.call(arguments, ' + (method_args.length - 1) + ');');
1109
+ }
1110
+
1111
+ }
1112
+
1113
+ var stmt = this.stmt.process(scope, LEVEL_TOP);
1114
+
1115
+ code += 'function(';
1116
+ code += method_args.join(', ');
1117
+ code += ') {';
1118
+
1119
+ code += ('var ' + this.scopeVars.join(', ') + ';');
1120
+
1121
+
1122
+ code += stmt;
1123
+
1124
+ code += (this.fixLineNumber(opts, this.endLine) + '}');
1125
+
1126
+ return code;
1127
+ };
1128
+
1129
+ var XStringNode = exports.XStringNode = function(beg, parts, end) {
1130
+ this.line = beg.line;
1131
+ this.parts = parts;
1132
+ this.endLine = end.line;
1133
+ };
1134
+
1135
+ extend(XStringNode, BaseNode);
1136
+
1137
+ XStringNode.prototype.returns = function() {
1138
+ // we dont return.. or do we?
1139
+ return this;
1140
+ };
1141
+
1142
+ // treat ourself like an expression. All XString code should add their own
1143
+ // semi-colons etc, so we can include for, if, return statements etc.
1144
+ XStringNode.prototype.isExpression = function() {
1145
+ return false;
1146
+ };
1147
+
1148
+ XStringNode.prototype.generate = function(opts) {
1149
+ var code = '', part;
1150
+
1151
+ for (var i = 0; i < this.parts.length; i++) {
1152
+ part = this.parts[i];
1153
+
1154
+ if (part[0] == 'string_content') {
1155
+ code += part[1].value;
1156
+ } else if (part[0] == 'string_dbegin') {
1157
+ code += part[1].generate(opts);
1158
+ }
1159
+ }
1160
+
1161
+ code += this.fixLineNumber(opts, this.endLine);
1162
+ return code;
1163
+ };
1164
+
1165
+ var YieldNode = exports.YieldNode = function(start, args) {
1166
+ this.line = start.line;
1167
+ this.args = args;
1168
+ };
1169
+
1170
+ extend(YieldNode, BaseNode);
1171
+
1172
+ YieldNode.prototype.generate = function(opts) {
1173
+ // need to get block from nearet method
1174
+ var block = opts.scope.set_uses_block();
1175
+ var code = '';
1176
+
1177
+ var arg_res = [block + '.$self'], args = this.args;
1178
+
1179
+ if (args[0]) {
1180
+ for (var i = 0; i < args[0].length; i++) {
1181
+ arg_res.push(args[0][i].generate(opts));
1182
+ }
1183
+ }
1184
+
1185
+ return block + '.call(' + arg_res.join(', ') + ')';
1186
+ };
1187
+
1188
+ var BlockGivenNode = exports.BlockGivenNode = function(given) {
1189
+ this.line = given.line;
1190
+ };
1191
+
1192
+ extend(BlockGivenNode, BaseNode);
1193
+
1194
+ BlockGivenNode.prototype.generate = function(opts) {
1195
+ var name = opts.scope.set_uses_block();
1196
+ return '(' + name + ' !== nil ? Qtrue : Qfalse)';
1197
+ };
1198
+
1199
+ var IfModNode = exports.IfModNode = function(type, expr, stmt) {
1200
+ this.line = type.line;
1201
+ this.type = type.value;
1202
+ this.expr = expr;
1203
+ this.stmt = stmt;
1204
+ };
1205
+
1206
+ extend(IfModNode, BaseNode);
1207
+
1208
+ IfModNode.prototype.generate = function(opts, level) {
1209
+ var code = '';
1210
+ code += ('if (' + (this.type == 'if' ? '' : '!') + this.expr.generate(opts, LEVEL_EXPR) + '.$r) {');
1211
+ code += (this.stmt.process(opts, level) + '}');
1212
+ return code;
1213
+ };
1214
+
1215
+ var ArefNode = exports.ArefNode = function(recv, arefs) {
1216
+ this.line = recv.line;
1217
+ this.recv = recv;
1218
+ this.arefs = arefs;
1219
+ }
1220
+
1221
+ extend(ArefNode, BaseNode);
1222
+
1223
+ ArefNode.prototype.generate = function(opts) {
1224
+ return this.recv.generate(opts);
1225
+ };
1226
+
1227
+ var AsetNode = exports.AsetNode = function(recv, arefs, val) {
1228
+ this.line = recv.line;
1229
+ this.recv = recv;
1230
+ this.arefs = arefs;
1231
+ this.val = val;
1232
+ };
1233
+
1234
+ extend(AsetNode, BaseNode);
1235
+
1236
+ AsetNode.prototype.generate = function(opts) {
1237
+ this.arefs[0].push(this.val);
1238
+ return (new CallNode(this.recv, {value: '[]='}, this.arefs)).generate(opts);
1239
+ // return this.recv.generate(opts);
1240
+ };
1241
+
1242
+ var ParenNode = exports.ParenNode = function(opening, parts, closing) {
1243
+ this.line = opening.line;
1244
+ this.parts = parts;
1245
+ this.endLine = closing.line;
1246
+ }
1247
+
1248
+ extend(ParenNode, BaseNode);
1249
+
1250
+ ParenNode.prototype.generate = function(opts) {
1251
+ var parts = [];
1252
+
1253
+ for (var i = 0; i < this.parts.nodes.length; i++) {
1254
+ parts.push(this.parts.nodes[i].generate(opts));
1255
+ }
1256
+
1257
+ // empty paren list
1258
+ if (parts.length == 0) {
1259
+ parts.push('nil');
1260
+ }
1261
+
1262
+ return '(' + parts.join(', ') + ')';
1263
+ };
1264
+