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.
- data/.gitignore +5 -10
- data/LICENSE +75 -0
- data/README.md +55 -3
- data/Rakefile +62 -139
- data/bin/opal +7 -10
- data/gems/core/README.md +5 -0
- data/gems/core/Rakefile +7 -0
- data/gems/core/core.gemspec +13 -0
- data/gems/core/lib/core.rb +33 -0
- data/gems/core/lib/core/array.rb +1470 -0
- data/gems/core/lib/core/basic_object.rb +15 -0
- data/gems/core/lib/core/class.rb +31 -0
- data/gems/core/lib/core/dir.rb +26 -0
- data/gems/core/lib/core/error.rb +43 -0
- data/gems/core/lib/core/false_class.rb +21 -0
- data/gems/core/lib/core/file.rb +54 -0
- data/gems/core/lib/core/hash.rb +725 -0
- data/gems/core/lib/core/kernel.rb +240 -0
- data/gems/core/lib/core/module.rb +98 -0
- data/gems/core/lib/core/nil_class.rb +41 -0
- data/gems/core/lib/core/numeric.rb +370 -0
- data/gems/core/lib/core/proc.rb +11 -0
- data/gems/core/lib/core/range.rb +17 -0
- data/gems/core/lib/core/regexp.rb +18 -0
- data/gems/core/lib/core/string.rb +328 -0
- data/gems/core/lib/core/symbol.rb +15 -0
- data/gems/core/lib/core/top_self.rb +8 -0
- data/gems/core/lib/core/true_class.rb +20 -0
- data/gems/core/lib/core/vm.rb +16 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/append_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/assoc_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/at_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/clear_spec.rb +1 -1
- data/{opals/opal/opal → gems/core}/spec/core/array/collect_bang_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/collect_spec.rb +0 -0
- data/gems/core/spec/core/array/compact_spec.rb +41 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/concat_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/constructor_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/each_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/element_reference_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/first_spec.rb +1 -1
- data/{opals/opal/opal → gems/core}/spec/core/array/include_spec.rb +0 -0
- data/gems/core/spec/core/array/join_spec.rb +6 -0
- data/gems/core/spec/core/array/last_spec.rb +51 -0
- data/gems/core/spec/core/array/length_spec.rb +6 -0
- data/{opals/opal/opal → gems/core}/spec/core/array/map_spec.rb +2 -0
- data/gems/core/spec/core/array/reverse_spec.rb +6 -0
- data/{opals/opal/opal → gems/core}/spec/core/builtin_constants/builtin_constants_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/false/and_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/false/inspect_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/false/or_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/false/to_s_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/false/xor_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/file/join_spec.rb +1 -1
- data/gems/core/spec/core/hash/assoc_spec.rb +32 -0
- data/{opals/opal/opal → gems/core}/spec/core/kernel/instance_eval_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/kernel/loop_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/kernel/raise_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/module/attr_accessor_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/number/lt_spec.rb +0 -0
- data/gems/core/spec/core/string/sub_spec.rb +24 -0
- data/{opals/opal/opal → gems/core}/spec/core/true/and_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/true/inspect_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/true/or_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/true/to_s_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/core/true/xor_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/and_spec.rb +2 -3
- data/{opals/opal/opal → gems/core}/spec/language/array_spec.rb +21 -5
- data/gems/core/spec/language/block_spec.rb +38 -0
- data/{opals/opal/opal → gems/core}/spec/language/break_spec.rb +0 -0
- data/gems/core/spec/language/case_spec.rb +103 -0
- data/{opals/opal/opal → gems/core}/spec/language/def_spec.rb +11 -1
- data/{opals/opal/opal → gems/core}/spec/language/eigenclass_spec.rb +0 -0
- data/gems/core/spec/language/file_spec.rb +13 -0
- data/gems/core/spec/language/fixtures/block.rb +21 -0
- data/gems/core/spec/language/fixtures/super.rb +293 -0
- data/{opals/opal/opal → gems/core}/spec/language/hash_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/if_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/loop_spec.rb +0 -0
- data/gems/core/spec/language/metaclass_spec.rb +21 -0
- data/{opals/opal/opal → gems/core}/spec/language/method_spec.rb +60 -0
- data/{opals/opal/opal → gems/core}/spec/language/next_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/or_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/redo_spec.rb +0 -0
- data/gems/core/spec/language/regexp_spec.rb +26 -0
- data/{opals/opal/opal → gems/core}/spec/language/rescue_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/return_spec.rb +0 -0
- data/{opals/opal/opal → gems/core}/spec/language/string_spec.rb +0 -0
- data/gems/core/spec/language/super_spec.rb +32 -0
- data/{opals/opal/opal → gems/core}/spec/language/until_spec.rb +47 -47
- data/gems/core/spec/language/variables_spec.rb +155 -0
- data/{opals/opal/opal → gems/core}/spec/language/while_spec.rb +47 -47
- data/{opals/opal/opal → gems/core}/spec/spec_helper.rb +1 -1
- data/gems/core_fs/README.md +19 -0
- data/gems/dev/Rakefile +5 -0
- data/gems/dev/lib/dev.js +99 -0
- data/gems/dev/lib/dev/generator.js +1264 -0
- data/gems/dev/lib/dev/parser.js +979 -0
- data/gems/dev/lib/dev/ruby_parser.js +1088 -0
- data/gems/dev/lib/dev/ruby_parser.y +1267 -0
- data/gems/dev/lib/dev/string_scanner.js +38 -0
- data/gems/dev/tools/racc2js/README.md +39 -0
- data/gems/dev/tools/racc2js/math_parser.js +222 -0
- data/gems/dev/tools/racc2js/math_parser.rb +133 -0
- data/gems/dev/tools/racc2js/math_parser.y +28 -0
- data/gems/dev/tools/racc2js/parser.js +218 -0
- data/gems/dev/tools/racc2js/racc2js.rb +153 -0
- data/gems/json/README.md +4 -0
- data/gems/json/json.gemspec +14 -0
- data/gems/json/lib/json.rb +64 -0
- data/gems/json/lib/json/ext.rb +51 -0
- data/{opals/opal/browser/lib/browser/json_parse.js → gems/json/lib/json/json2.js} +197 -37
- data/gems/ospec/README.md +0 -0
- data/gems/ospec/lib/ospec.rb +6 -0
- data/gems/ospec/lib/ospec/autorun.rb +3 -0
- data/gems/ospec/lib/ospec/dsl.rb +15 -0
- data/gems/ospec/lib/ospec/example.rb +11 -0
- data/gems/ospec/lib/ospec/example/before_and_after_hooks.rb +56 -0
- data/gems/ospec/lib/ospec/example/errors.rb +17 -0
- data/gems/ospec/lib/ospec/example/example_group.rb +12 -0
- data/gems/ospec/lib/ospec/example/example_group_factory.rb +21 -0
- data/gems/ospec/lib/ospec/example/example_group_hierarchy.rb +20 -0
- data/{opals/opal/spec/lib/spec → gems/ospec/lib/ospec}/example/example_group_methods.rb +26 -68
- data/gems/ospec/lib/ospec/example/example_group_proxy.rb +14 -0
- data/gems/ospec/lib/ospec/example/example_methods.rb +46 -0
- data/gems/ospec/lib/ospec/example/example_proxy.rb +18 -0
- data/gems/ospec/lib/ospec/expectations.rb +19 -0
- data/gems/ospec/lib/ospec/expectations/errors.rb +8 -0
- data/gems/ospec/lib/ospec/expectations/fail_with.rb +8 -0
- data/gems/ospec/lib/ospec/expectations/handler.rb +27 -0
- data/gems/ospec/lib/ospec/matchers.rb +24 -0
- data/{opals/opal/Rakefile → gems/ospec/lib/ospec/matchers/be.rb} +0 -0
- data/gems/ospec/lib/ospec/matchers/generated_descriptions.rb +20 -0
- data/gems/ospec/lib/ospec/matchers/operator_matcher.rb +52 -0
- data/gems/ospec/lib/ospec/runner.rb +40 -0
- data/gems/ospec/lib/ospec/runner/example_group_runner.rb +44 -0
- data/{opals/opal/spec/lib/spec → gems/ospec/lib/ospec}/runner/formatter/html_formatter.rb +31 -40
- data/gems/ospec/lib/ospec/runner/formatter/terminal_formatter.rb +48 -0
- data/gems/ospec/lib/ospec/runner/options.rb +36 -0
- data/{opals/opal/spec/lib/spec → gems/ospec/lib/ospec}/runner/reporter.rb +23 -55
- data/gems/ospec/ospec.gemspec +0 -0
- data/gems/rquery/README.md +9 -0
- data/gems/rquery/lib/rquery.rb +10 -0
- data/gems/rquery/lib/rquery/ajax.rb +4 -0
- data/gems/rquery/lib/rquery/css.rb +96 -0
- data/gems/rquery/lib/rquery/document.rb +25 -0
- data/gems/rquery/lib/rquery/element.rb +292 -0
- data/gems/rquery/lib/rquery/event.rb +108 -0
- data/gems/rquery/lib/rquery/jquery.js +8177 -0
- data/gems/rquery/lib/rquery/request.rb +138 -0
- data/gems/rquery/lib/rquery/response.rb +49 -0
- data/gems/rquery/rquery.gemspec +16 -0
- data/lib/opal.js +1597 -0
- data/lib/opal.rb +6 -69
- data/lib/opal/builder.rb +115 -0
- data/lib/opal/bundle.rb +131 -0
- data/lib/opal/command.rb +11 -0
- data/lib/opal/context.rb +69 -0
- data/lib/opal/context/console.rb +12 -0
- data/lib/opal/context/file_system.rb +19 -0
- data/lib/opal/context/loader.rb +117 -0
- data/lib/opal/gem.rb +153 -0
- data/lib/opal/ruby/nodes.rb +1302 -0
- data/lib/opal/ruby/parser.rb +780 -0
- data/lib/opal/ruby/ruby_parser.rb +5170 -0
- data/lib/opal/ruby/ruby_parser.y +1298 -0
- data/opal.gemspec +11 -256
- metadata +179 -240
- data/.gitmodules +0 -6
- data/Opalfile +0 -384
- data/VERSION +0 -1
- data/demos/apps/browser_demo/index.html +0 -11
- data/demos/apps/browser_demo/lib/browser_demo.rb +0 -31
- data/demos/apps/simple_opal/Opalfile +0 -13
- data/demos/apps/simple_opal/index.html +0 -11
- data/demos/apps/simple_opal/lib/app_controller.rb +0 -62
- data/demos/apps/simple_opal/lib/main_window.rb +0 -146
- data/demos/browser/request/index.html +0 -52
- data/demos/browser/request/request.rb +0 -48
- data/gen/browser/__PROJECT_NAME__/Rakefile +0 -12
- data/gen/browser/__PROJECT_NAME__/index.html +0 -11
- data/gen/browser/__PROJECT_NAME__/javascripts/opal.debug.js +0 -4687
- data/gen/browser/__PROJECT_NAME__/javascripts/opal.min.js +0 -175
- data/gen/browser/__PROJECT_NAME__/lib/__PROJECT_NAME__.rb +0 -1
- data/lib/opal/builders/base.rb +0 -50
- data/lib/opal/builders/css.rb +0 -46
- data/lib/opal/builders/javascript.rb +0 -44
- data/lib/opal/builders/opal.rb +0 -79
- data/lib/opal/builders/ruby.rb +0 -50
- data/lib/opal/builders/ruby/generate.rb +0 -1851
- data/lib/opal/builders/ruby/nodes.rb +0 -210
- data/lib/opal/builders/ruby/ruby.rb +0 -916
- data/lib/opal/builders/ruby/ruby_parser.rb +0 -6008
- data/lib/opal/builders/ruby/ruby_parser.rb.y +0 -1451
- data/lib/opal/models/build_item.rb +0 -104
- data/lib/opal/models/hash_struct.rb +0 -40
- data/lib/opal/models/project.rb +0 -252
- data/lib/opal/models/struct_accessors.rb +0 -58
- data/lib/opal/models/target.rb +0 -176
- data/lib/opal/opal/build.rb +0 -169
- data/lib/opal/opal/env/console.rb +0 -66
- data/lib/opal/opal/env/fs.rb +0 -98
- data/lib/opal/opal/env/object.rb +0 -48
- data/lib/opal/opal/environment.rb +0 -139
- data/lib/opal/opal/gen.rb +0 -62
- data/lib/opal/opal/opal.rb +0 -75
- data/lib/opal/opal/repl.rb +0 -38
- data/lib/opal/opalfile/dsl.rb +0 -62
- data/lib/opal/opalfile/opalfile.rb +0 -133
- data/lib/opal/opalfile/task.rb +0 -96
- data/lib/opal/opalfile/task_manager.rb +0 -63
- data/lib/opal/opalfile/task_scope.rb +0 -52
- data/lib/opal/rack/app_server.rb +0 -119
- data/lib/opal/rake/opal_task.rb +0 -34
- data/opals/opal/README.md +0 -37
- data/opals/opal/browser/Opalfile +0 -11
- data/opals/opal/browser/README.md +0 -146
- data/opals/opal/browser/SIZZLE_LICESNSE.txt +0 -148
- data/opals/opal/browser/lib/browser.rb +0 -118
- data/opals/opal/browser/lib/browser/builder.rb +0 -41
- data/opals/opal/browser/lib/browser/canvas_context.rb +0 -115
- data/opals/opal/browser/lib/browser/dimensions.rb +0 -50
- data/opals/opal/browser/lib/browser/document.rb +0 -146
- data/opals/opal/browser/lib/browser/element.rb +0 -487
- data/opals/opal/browser/lib/browser/element/attributes.rb +0 -88
- data/opals/opal/browser/lib/browser/element/css.rb +0 -290
- data/opals/opal/browser/lib/browser/element/form.rb +0 -146
- data/opals/opal/browser/lib/browser/event/dom_events.rb +0 -81
- data/opals/opal/browser/lib/browser/event/event.rb +0 -177
- data/opals/opal/browser/lib/browser/event/trigger_events.rb +0 -53
- data/opals/opal/browser/lib/browser/geometry.rb +0 -97
- data/opals/opal/browser/lib/browser/json.rb +0 -32
- data/opals/opal/browser/lib/browser/request/request.rb +0 -201
- data/opals/opal/browser/lib/browser/sizzle.js +0 -1068
- data/opals/opal/browser/lib/browser/string.rb +0 -42
- data/opals/opal/browser/lib/browser/touch.rb +0 -37
- data/opals/opal/browser/lib/browser/vml_context.js +0 -33
- data/opals/opal/browser/lib/browser/window.rb +0 -36
- data/opals/opal/browser/spec/browser/browser_detection_spec.rb +0 -7
- data/opals/opal/browser/spec/document/aref_spec.rb +0 -110
- data/opals/opal/browser/spec/document/ready_spec.rb +0 -16
- data/opals/opal/browser/spec/element/body_spec.rb +0 -11
- data/opals/opal/browser/spec/element/clear_spec.rb +0 -26
- data/opals/opal/browser/spec/element/empty_spec.rb +0 -29
- data/opals/opal/browser/spec/element/has_class_spec.rb +0 -40
- data/opals/opal/browser/spec/element/hidden_spec.rb +0 -23
- data/opals/opal/browser/spec/element/hide_spec.rb +0 -31
- data/opals/opal/browser/spec/element/remove_spec.rb +0 -25
- data/opals/opal/browser/spec/element/show_spec.rb +0 -31
- data/opals/opal/browser/spec/element/style_spec.rb +0 -69
- data/opals/opal/browser/spec/element/toggle_spec.rb +0 -31
- data/opals/opal/browser/spec/element/visible_spec.rb +0 -23
- data/opals/opal/browser/spec/spec_helper.rb +0 -1
- data/opals/opal/opal/Opalfile +0 -14
- data/opals/opal/opal/spec/core/array/compact_spec.rb +0 -15
- data/opals/opal/opal/spec/fixtures/super.rb +0 -70
- data/opals/opal/opal/spec/language/____temp_remove_this.rb +0 -12
- data/opals/opal/opal/spec/language/block_spec.rb +0 -18
- data/opals/opal/opal/spec/language/case_spec.rb +0 -103
- data/opals/opal/opal/spec/language/metaclass_spec.rb +0 -21
- data/opals/opal/opal/spec/language/super_spec.rb +0 -26
- data/opals/opal/runtime/Opalfile +0 -78
- data/opals/opal/runtime/README.md +0 -12
- data/opals/opal/runtime/docs/debugging.md +0 -51
- data/opals/opal/runtime/lib/array.rb +0 -1516
- data/opals/opal/runtime/lib/basic_object.rb +0 -49
- data/opals/opal/runtime/lib/class.rb +0 -54
- data/opals/opal/runtime/lib/dir.rb +0 -36
- data/opals/opal/runtime/lib/error.rb +0 -49
- data/opals/opal/runtime/lib/false_class.rb +0 -52
- data/opals/opal/runtime/lib/file.rb +0 -79
- data/opals/opal/runtime/lib/hash.rb +0 -791
- data/opals/opal/runtime/lib/io.rb +0 -39
- data/opals/opal/runtime/lib/kernel.rb +0 -288
- data/opals/opal/runtime/lib/match_data.rb +0 -36
- data/opals/opal/runtime/lib/module.rb +0 -109
- data/opals/opal/runtime/lib/nil_class.rb +0 -69
- data/opals/opal/runtime/lib/number.rb +0 -398
- data/opals/opal/runtime/lib/proc.rb +0 -77
- data/opals/opal/runtime/lib/range.rb +0 -63
- data/opals/opal/runtime/lib/regexp.rb +0 -111
- data/opals/opal/runtime/lib/ruby.rb +0 -30
- data/opals/opal/runtime/lib/string.rb +0 -328
- data/opals/opal/runtime/lib/symbol.rb +0 -40
- data/opals/opal/runtime/lib/top_self.rb +0 -33
- data/opals/opal/runtime/lib/true_class.rb +0 -45
- data/opals/opal/runtime/runtime/browser.js +0 -287
- data/opals/opal/runtime/runtime/debug.js +0 -180
- data/opals/opal/runtime/runtime/opal.js +0 -1008
- data/opals/opal/runtime/runtime/post_opal.js +0 -1
- data/opals/opal/runtime/runtime/pre_opal.js +0 -2
- data/opals/opal/runtime/runtime/server_side.js +0 -50
- data/opals/opal/spec/LICENSE.txt +0 -26
- data/opals/opal/spec/Opalfile +0 -5
- data/opals/opal/spec/bin/spec.rb +0 -43
- data/opals/opal/spec/lib/spec.rb +0 -33
- data/opals/opal/spec/lib/spec/dsl.rb +0 -41
- data/opals/opal/spec/lib/spec/example.rb +0 -35
- data/opals/opal/spec/lib/spec/example/before_and_after_hooks.rb +0 -81
- data/opals/opal/spec/lib/spec/example/errors.rb +0 -42
- data/opals/opal/spec/lib/spec/example/example_group.rb +0 -37
- data/opals/opal/spec/lib/spec/example/example_group_factory.rb +0 -43
- data/opals/opal/spec/lib/spec/example/example_group_hierarchy.rb +0 -45
- data/opals/opal/spec/lib/spec/example/example_group_proxy.rb +0 -41
- data/opals/opal/spec/lib/spec/example/example_methods.rb +0 -73
- data/opals/opal/spec/lib/spec/example/example_proxy.rb +0 -48
- data/opals/opal/spec/lib/spec/expectations.rb +0 -46
- data/opals/opal/spec/lib/spec/expectations/errors.rb +0 -35
- data/opals/opal/spec/lib/spec/expectations/fail_with.rb +0 -37
- data/opals/opal/spec/lib/spec/expectations/handler.rb +0 -48
- data/opals/opal/spec/lib/spec/matchers.rb +0 -50
- data/opals/opal/spec/lib/spec/matchers/be.rb +0 -26
- data/opals/opal/spec/lib/spec/matchers/generated_descriptions.rb +0 -47
- data/opals/opal/spec/lib/spec/matchers/operator_matcher.rb +0 -66
- data/opals/opal/spec/lib/spec/runner.rb +0 -48
- data/opals/opal/spec/lib/spec/runner/example_group_runner.rb +0 -71
- data/opals/opal/spec/lib/spec/runner/formatter/terminal_formatter.rb +0 -82
- data/opals/opal/spec/lib/spec/runner/options.rb +0 -63
- data/opals/opal/spec/resources/index.html +0 -25
- data/opals/opal/spec/resources/spec.css +0 -132
- data/spec/cherry_kit/iseq_spec.rb +0 -38
- data/spec/spec_helper.rb +0 -16
- data/spec/vienna_spec.rb +0 -7
- data/yard/index.html +0 -43
- data/yard/style.css +0 -765
data/gems/dev/Rakefile
ADDED
data/gems/dev/lib/dev.js
ADDED
|
@@ -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
|
+
|