opal 0.3.18 → 0.3.19
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 +1 -1
- data/Gemfile +1 -3
- data/README.md +472 -10
- data/Rakefile +10 -52
- data/core/array.rb +9 -14
- data/core/basic_object.rb +7 -10
- data/core/boolean.rb +5 -1
- data/core/class.rb +15 -38
- data/core/dir.rb +89 -0
- data/core/enumerable.rb +133 -57
- data/core/error.rb +15 -1
- data/core/file.rb +85 -0
- data/core/hash.rb +186 -32
- data/core/kernel.rb +30 -31
- data/core/load_order +4 -2
- data/core/module.rb +42 -62
- data/core/numeric.rb +7 -1
- data/core/object.rb +1 -1
- data/core/proc.rb +6 -2
- data/core/range.rb +16 -28
- data/core/regexp.rb +3 -3
- data/core/runtime.js +281 -350
- data/core/string.rb +100 -110
- data/docs/CNAME +1 -0
- data/docs/Rakefile +55 -0
- data/docs/css/styles.css +50 -0
- data/docs/css/syntax.css +63 -0
- data/docs/layout/post.html +3 -0
- data/docs/layout/pre.html +11 -0
- data/examples/dependencies/app.rb +3 -0
- data/lib/opal.rb +2 -1
- data/lib/opal/builder.rb +36 -10
- data/lib/opal/builder_task.rb +51 -24
- data/lib/opal/grammar.rb +2509 -2439
- data/lib/opal/grammar.y +38 -5
- data/lib/opal/lexer.rb +18 -2
- data/lib/opal/parser.rb +375 -349
- data/lib/opal/scope.rb +24 -2
- data/lib/opal/version.rb +1 -1
- data/spec/builder/build_order_spec.rb +20 -0
- data/spec/builder/lib_name_for_spec.rb +24 -0
- data/spec/grammar/call_spec.rb +9 -6
- data/spec/grammar/lambda_spec.rb +64 -0
- data/spec/grammar/sclass_spec.rb +5 -3
- data/{core/spec → test}/core/array/allocate_spec.rb +0 -0
- data/{core/spec → test}/core/array/append_spec.rb +0 -0
- data/{core/spec → test}/core/array/assoc_spec.rb +0 -0
- data/{core/spec → test}/core/array/at_spec.rb +0 -0
- data/{core/spec → test}/core/array/clear_spec.rb +0 -0
- data/{core/spec → test}/core/array/clone_spec.rb +0 -0
- data/{core/spec → test}/core/array/collect_spec.rb +0 -0
- data/{core/spec → test}/core/array/compact_spec.rb +0 -0
- data/{core/spec → test}/core/array/concat_spec.rb +0 -0
- data/{core/spec → test}/core/array/constructor_spec.rb +0 -0
- data/{core/spec → test}/core/array/count_spec.rb +0 -0
- data/{core/spec → test}/core/array/delete_at_spec.rb +0 -0
- data/{core/spec → test}/core/array/delete_if_spec.rb +0 -0
- data/{core/spec → test}/core/array/delete_spec.rb +0 -0
- data/{core/spec → test}/core/array/each_index_spec.rb +0 -0
- data/{core/spec → test}/core/array/each_spec.rb +0 -0
- data/{core/spec → test}/core/array/element_reference_spec.rb +0 -0
- data/{core/spec → test}/core/array/empty_spec.rb +0 -0
- data/{core/spec → test}/core/array/eql_spec.rb +0 -0
- data/{core/spec → test}/core/array/fetch_spec.rb +0 -0
- data/{core/spec → test}/core/array/first_spec.rb +0 -0
- data/{core/spec → test}/core/array/flatten_spec.rb +0 -0
- data/{core/spec → test}/core/array/include_spec.rb +0 -0
- data/{core/spec → test}/core/array/insert_spec.rb +0 -0
- data/{core/spec → test}/core/array/last_spec.rb +0 -0
- data/{core/spec → test}/core/array/length_spec.rb +0 -0
- data/{core/spec → test}/core/array/map_spec.rb +0 -0
- data/{core/spec → test}/core/array/plus_spec.rb +0 -0
- data/{core/spec → test}/core/array/pop_spec.rb +0 -0
- data/{core/spec → test}/core/array/push_spec.rb +0 -0
- data/{core/spec → test}/core/array/rassoc_spec.rb +0 -0
- data/{core/spec → test}/core/array/reject_spec.rb +0 -0
- data/{core/spec → test}/core/array/replace_spec.rb +0 -0
- data/{core/spec → test}/core/array/reverse_each_spec.rb +0 -0
- data/{core/spec → test}/core/array/reverse_spec.rb +0 -0
- data/{core/spec → test}/core/array/size_spec.rb +0 -0
- data/{core/spec → test}/core/array/to_ary_spec.rb +0 -0
- data/{core/spec → test}/core/array/uniq_spec.rb +0 -0
- data/{core/spec → test}/core/array/zip_spec.rb +0 -0
- data/test/core/class/fixtures/classes.rb +9 -0
- data/test/core/class/new_spec.rb +108 -0
- data/{core/spec → test}/core/enumerable/all_spec.rb +0 -0
- data/{core/spec → test}/core/enumerable/any_spec.rb +0 -0
- data/{core/spec → test}/core/enumerable/collect_spec.rb +0 -0
- data/{core/spec → test}/core/enumerable/count_spec.rb +0 -0
- data/test/core/enumerable/detect_spec.rb +48 -0
- data/test/core/enumerable/drop_spec.rb +17 -0
- data/test/core/enumerable/drop_while_spec.rb +24 -0
- data/test/core/enumerable/each_with_index_spec.rb +11 -0
- data/test/core/enumerable/each_with_object_spec.rb +17 -0
- data/test/core/enumerable/entries_spec.rb +6 -0
- data/test/core/enumerable/find_all_spec.rb +13 -0
- data/test/core/enumerable/find_index_spec.rb +45 -0
- data/test/core/enumerable/find_spec.rb +48 -0
- data/test/core/enumerable/first_spec.rb +40 -0
- data/{core/spec → test}/core/enumerable/fixtures/classes.rb +19 -0
- data/test/core/enumerable/grep_spec.rb +21 -0
- data/test/core/enumerable/take_spec.rb +40 -0
- data/test/core/enumerable/to_a_spec.rb +6 -0
- data/{core/spec → test}/core/false/and_spec.rb +0 -0
- data/{core/spec → test}/core/false/inspect_spec.rb +0 -0
- data/{core/spec → test}/core/false/or_spec.rb +0 -0
- data/{core/spec → test}/core/false/to_s_spec.rb +0 -0
- data/{core/spec → test}/core/false/xor_spec.rb +0 -0
- data/test/core/file/expand_path_spec.rb +20 -0
- data/{core/spec → test}/core/hash/allocate_spec.rb +0 -0
- data/{core/spec → test}/core/hash/assoc_spec.rb +0 -0
- data/{core/spec → test}/core/hash/clear_spec.rb +0 -0
- data/{core/spec → test}/core/hash/clone_spec.rb +0 -0
- data/test/core/hash/default_spec.rb +9 -0
- data/{core/spec → test}/core/hash/delete_if_spec.rb +0 -0
- data/test/core/hash/each_key_spec.rb +15 -0
- data/test/core/hash/each_pair_spec.rb +30 -0
- data/test/core/hash/each_spec.rb +30 -0
- data/test/core/hash/each_value_spec.rb +15 -0
- data/{core/spec → test}/core/hash/element_reference_spec.rb +14 -0
- data/{core/spec → test}/core/hash/element_set_spec.rb +1 -0
- data/test/core/hash/empty_spec.rb +10 -0
- data/test/core/hash/fetch_spec.rb +24 -0
- data/test/core/hash/flatten_spec.rb +46 -0
- data/test/core/hash/has_key_spec.rb +24 -0
- data/test/core/hash/has_value_spec.rb +12 -0
- data/test/core/hash/include_spec.rb +24 -0
- data/test/core/hash/index_spec.rb +13 -0
- data/test/core/hash/indexes_spec.rb +9 -0
- data/test/core/hash/indices_spec.rb +9 -0
- data/test/core/hash/invert_spec.rb +12 -0
- data/test/core/hash/keep_if_spec.rb +18 -0
- data/test/core/hash/key_spec.rb +24 -0
- data/test/core/hash/keys_spec.rb +10 -0
- data/test/core/hash/length_spec.rb +10 -0
- data/test/core/hash/member_spec.rb +24 -0
- data/{core/spec → test}/core/hash/merge_spec.rb +0 -0
- data/{core/spec → test}/core/hash/new_spec.rb +0 -0
- data/test/core/hash/rassoc_spec.rb +34 -0
- data/test/core/hash/replace_spec.rb +7 -0
- data/test/core/hash/select_spec.rb +52 -0
- data/test/core/hash/shift_spec.rb +19 -0
- data/test/core/hash/size_spec.rb +10 -0
- data/test/core/hash/update_spec.rb +17 -0
- data/test/core/hash/value_spec.rb +12 -0
- data/test/core/hash/values_at_spec.rb +9 -0
- data/test/core/hash/values_spec.rb +7 -0
- data/test/core/kernel/eql_spec.rb +15 -0
- data/test/core/kernel/equal_value_spec.rb +12 -0
- data/test/core/kernel/loop_spec.rb +23 -0
- data/test/core/kernel/nil_spec.rb +7 -0
- data/test/core/kernel/proc_spec.rb +9 -0
- data/test/core/kernel/rand_spec.rb +14 -0
- data/test/core/kernel/respond_to_spec.rb +24 -0
- data/test/core/kernel/send_spec.rb +56 -0
- data/test/core/kernel/tap_spec.rb +10 -0
- data/test/core/kernel/to_s_spec.rb +5 -0
- data/{core/spec → test}/core/matchdata/to_a_spec.rb +0 -0
- data/{core/spec → test}/core/nil/and_spec.rb +0 -0
- data/{core/spec → test}/core/nil/inspect_spec.rb +0 -0
- data/{core/spec → test}/core/nil/nil_spec.rb +0 -0
- data/{core/spec → test}/core/nil/or_spec.rb +0 -0
- data/{core/spec → test}/core/nil/to_a_spec.rb +0 -0
- data/{core/spec → test}/core/nil/to_f_spec.rb +0 -0
- data/{core/spec → test}/core/nil/to_i_spec.rb +0 -0
- data/{core/spec → test}/core/nil/to_s_spec.rb +0 -0
- data/{core/spec → test}/core/nil/xor_spec.rb +0 -0
- data/{core/spec → test}/core/numeric/equal_value_spec.rb +0 -0
- data/test/core/range/begin_spec.rb +9 -0
- data/test/core/range/case_compare_spec.rb +16 -0
- data/test/core/range/end_spec.rb +9 -0
- data/{core/spec → test}/core/regexp/match_spec.rb +0 -0
- data/test/core/string/capitalize_spec.rb +10 -0
- data/test/core/string/casecmp_spec.rb +16 -0
- data/test/core/string/chomp_spec.rb +43 -0
- data/test/core/string/chop_spec.rb +10 -0
- data/test/core/string/chr_spec.rb +13 -0
- data/test/core/string/comparison_spec.rb +13 -0
- data/test/core/string/downcase_spec.rb +6 -0
- data/test/core/string/element_reference_spec.rb +72 -0
- data/test/core/string/empty_spec.rb +8 -0
- data/test/core/string/end_with_spec.rb +12 -0
- data/test/core/string/fixtures/classes.rb +3 -0
- data/test/core/string/gsub_spec.rb +17 -0
- data/test/core/string/include_spec.rb +12 -0
- data/test/core/string/intern_spec.rb +9 -0
- data/test/core/string/length_spec.rb +9 -0
- data/test/core/string/lstrip_spec.rb +7 -0
- data/test/core/string/match_spec.rb +27 -0
- data/test/core/string/next_spec.rb +10 -0
- data/test/core/string/ord_spec.rb +9 -0
- data/test/core/string/partition_spec.rb +10 -0
- data/test/core/string/reverse_spec.rb +7 -0
- data/test/core/string/rstrip_spec.rb +7 -0
- data/test/core/string/size_spec.rb +9 -0
- data/test/core/string/slice_spec.rb +72 -0
- data/test/core/string/split_spec.rb +5 -0
- data/test/core/string/start_with_spec.rb +12 -0
- data/test/core/string/strip_spec.rb +6 -0
- data/test/core/string/sub_spec.rb +22 -0
- data/test/core/string/succ_spec.rb +10 -0
- data/test/core/string/sum_spec.rb +5 -0
- data/test/core/string/swapcase_spec.rb +18 -0
- data/test/core/string/to_a_spec.rb +9 -0
- data/test/core/string/to_f_spec.rb +14 -0
- data/test/core/string/to_i_spec.rb +25 -0
- data/test/core/string/to_s_spec.rb +13 -0
- data/test/core/string/to_str_spec.rb +13 -0
- data/test/core/string/to_sym_spec.rb +9 -0
- data/test/core/string/upcase_spec.rb +6 -0
- data/test/core/symbol/to_proc_spec.rb +12 -0
- data/{core/spec → test}/core/true/and_spec.rb +0 -0
- data/{core/spec → test}/core/true/inspect_spec.rb +0 -0
- data/{core/spec → test}/core/true/or_spec.rb +0 -0
- data/{core/spec → test}/core/true/to_s_spec.rb +0 -0
- data/{core/spec → test}/core/true/xor_spec.rb +0 -0
- data/test/index.html +11 -0
- data/{core/spec → test}/language/alias_spec.rb +4 -0
- data/{core/spec → test}/language/and_spec.rb +0 -0
- data/{core/spec → test}/language/array_spec.rb +0 -0
- data/{core/spec → test}/language/block_spec.rb +0 -0
- data/{core/spec → test}/language/break_spec.rb +0 -0
- data/{core/spec → test}/language/case_spec.rb +0 -0
- data/{core/spec → test}/language/defined_spec.rb +0 -0
- data/{core/spec → test}/language/ensure_spec.rb +0 -0
- data/test/language/fixtures/yield.rb +23 -0
- data/{core/spec → test}/language/hash_spec.rb +0 -0
- data/{core/spec → test}/language/if_spec.rb +0 -0
- data/test/language/literal_lambda_spec.rb +47 -0
- data/{core/spec → test}/language/loop_spec.rb +0 -0
- data/{core/spec → test}/language/metaclass_spec.rb +0 -0
- data/{core/spec → test}/language/next_spec.rb +0 -0
- data/{core/spec → test}/language/or_spec.rb +0 -0
- data/{core/spec → test}/language/predefined_spec.rb +0 -0
- data/{core/spec → test}/language/regexp_spec.rb +0 -0
- data/{core/spec → test}/language/send_spec.rb +0 -0
- data/{core/spec → test}/language/singleton_class_spec.rb +0 -0
- data/{core/spec → test}/language/super_spec.rb +0 -0
- data/{core/spec → test}/language/symbol_spec.rb +0 -0
- data/{core/spec → test}/language/undef_spec.rb +0 -0
- data/{core/spec → test}/language/unless_spec.rb +0 -0
- data/{core/spec → test}/language/until_spec.rb +0 -0
- data/{core/spec → test}/language/variables_spec.rb +0 -0
- data/{core/spec → test}/language/while_spec.rb +0 -0
- data/test/language/yield_spec.rb +100 -0
- data/test/opal/array/subclassing_spec.rb +32 -0
- data/test/opal/class/bridge_class_spec.rb +37 -0
- data/test/opal/exception/subclassing_spec.rb +17 -0
- data/test/opal/runtime/_methods_spec.rb +48 -0
- data/test/opal/runtime/class_hierarchy_spec.rb +22 -0
- data/test/opal/runtime/def_spec.rb +23 -0
- data/test/opal/string/subclassing_spec.rb +26 -0
- data/test/spec_helper.rb +3 -0
- metadata +437 -111
- data/core/spec/core/class/new_spec.rb +0 -16
- data/core/spec/core/hash/default_spec.rb +0 -4
- data/core/spec/core/symbol/to_proc_spec.rb +0 -6
- data/core/spec/index.html +0 -11
- data/spec/builder/build_source_spec.rb +0 -52
data/lib/opal/grammar.y
CHANGED
@@ -14,7 +14,7 @@ token CLASS MODULE DEF UNDEF BEGIN RESCUE ENSURE END IF UNLESS
|
|
14
14
|
'~' '%' '/' '+' '-' '<' '>' '|' '!' '^'
|
15
15
|
LCURLY '}' BACK_REF2 SYMBOL_BEG STRING_BEG XSTRING_BEG REGEXP_BEG
|
16
16
|
WORDS_BEG AWORDS_BEG STRING_DBEG STRING_DVAR STRING_END STRING
|
17
|
-
SYMBOL '\\n' '?' ':' ',' SPACE ';' LABEL
|
17
|
+
SYMBOL '\\n' '?' ':' ',' SPACE ';' LABEL LAMBDA LAMBEG DO_LAMBDA
|
18
18
|
|
19
19
|
prechigh
|
20
20
|
right '!' '~' '+@'
|
@@ -453,19 +453,19 @@ arg:
|
|
453
453
|
}
|
454
454
|
| arg '+' arg
|
455
455
|
{
|
456
|
-
result =
|
456
|
+
result = s(:operator, :"+", val[0], val[2])
|
457
457
|
}
|
458
458
|
| arg '-' arg
|
459
459
|
{
|
460
|
-
result =
|
460
|
+
result = s(:operator, :"-", val[0], val[2])
|
461
461
|
}
|
462
462
|
| arg '*' arg
|
463
463
|
{
|
464
|
-
result =
|
464
|
+
result = s(:operator, :"*", val[0], val[2])
|
465
465
|
}
|
466
466
|
| arg '/' arg
|
467
467
|
{
|
468
|
-
result =
|
468
|
+
result = s(:operator, :"/", val[0], val[2])
|
469
469
|
}
|
470
470
|
| arg '%' arg
|
471
471
|
{
|
@@ -784,6 +784,10 @@ primary:
|
|
784
784
|
result = val[1]
|
785
785
|
result[1] = val[0]
|
786
786
|
}
|
787
|
+
| LAMBDA lambda
|
788
|
+
{
|
789
|
+
result = val[1]
|
790
|
+
}
|
787
791
|
| IF expr_value then compstmt if_tail END
|
788
792
|
{
|
789
793
|
result = new_if val[1], val[3], val[4]
|
@@ -937,6 +941,35 @@ do:
|
|
937
941
|
| ':'
|
938
942
|
| DO_COND
|
939
943
|
|
944
|
+
lambda:
|
945
|
+
f_larglist lambda_body
|
946
|
+
{
|
947
|
+
call = new_call nil, :lambda, s(:arglist)
|
948
|
+
result = new_iter call, val[0], val[1]
|
949
|
+
}
|
950
|
+
|
951
|
+
f_larglist:
|
952
|
+
'(' block_var_args ')'
|
953
|
+
{
|
954
|
+
result = val[1]
|
955
|
+
}
|
956
|
+
| '(' ')'
|
957
|
+
{
|
958
|
+
result = nil
|
959
|
+
}
|
960
|
+
| block_var_args
|
961
|
+
| none
|
962
|
+
|
963
|
+
lambda_body:
|
964
|
+
LAMBEG compstmt '}'
|
965
|
+
{
|
966
|
+
result = val[1]
|
967
|
+
}
|
968
|
+
| DO_LAMBDA compstmt END
|
969
|
+
{
|
970
|
+
result = val[1]
|
971
|
+
}
|
972
|
+
|
940
973
|
if_tail:
|
941
974
|
opt_else
|
942
975
|
{
|
data/lib/opal/lexer.rb
CHANGED
@@ -617,6 +617,8 @@ module Opal
|
|
617
617
|
else
|
618
618
|
c = if scanner.scan(/n/)
|
619
619
|
"\n"
|
620
|
+
elsif scanner.scan(/r/)
|
621
|
+
"\r"
|
620
622
|
else
|
621
623
|
# escaped char doesnt need escaping, so just return it
|
622
624
|
scanner.scan(/./)
|
@@ -985,6 +987,11 @@ module Opal
|
|
985
987
|
return '>', '>'
|
986
988
|
end
|
987
989
|
|
990
|
+
elsif scanner.scan(/->/)
|
991
|
+
@lex_state = :expr_arg
|
992
|
+
@start_of_lambda = true
|
993
|
+
return [:LAMBDA, scanner.matched]
|
994
|
+
|
988
995
|
elsif scanner.scan(/[+-]/)
|
989
996
|
result = scanner.matched
|
990
997
|
sign = result + '@'
|
@@ -1110,7 +1117,12 @@ module Opal
|
|
1110
1117
|
return ',', scanner.matched
|
1111
1118
|
|
1112
1119
|
elsif scanner.scan(/\{/)
|
1113
|
-
if
|
1120
|
+
if @start_of_lambda
|
1121
|
+
@start_of_lambda = false
|
1122
|
+
@lex_state = :expr_beg
|
1123
|
+
return [:LAMBEG, scanner.matched]
|
1124
|
+
|
1125
|
+
elsif [:expr_end, :expr_arg, :expr_cmdarg].include? @lex_state
|
1114
1126
|
result = :LCURLY
|
1115
1127
|
elsif @lex_state == :expr_endarg
|
1116
1128
|
result = :LBRACE_ARG
|
@@ -1183,7 +1195,11 @@ module Opal
|
|
1183
1195
|
#puts cond?
|
1184
1196
|
#puts cmdarg?
|
1185
1197
|
#nputs @lex_state
|
1186
|
-
if
|
1198
|
+
if @start_of_lambda
|
1199
|
+
@start_of_lambda = false
|
1200
|
+
@lex_state = :expr_beg
|
1201
|
+
return [:DO_LAMBDA, scanner.matched]
|
1202
|
+
elsif cond?
|
1187
1203
|
@lex_state = :expr_beg
|
1188
1204
|
return :DO_COND, matched
|
1189
1205
|
elsif cmdarg? && @lex_state != :expr_cmdarg
|
data/lib/opal/parser.rb
CHANGED
@@ -13,16 +13,9 @@ module Opal
|
|
13
13
|
class Parser
|
14
14
|
INDENT = ' '
|
15
15
|
|
16
|
-
LEVEL = [:
|
16
|
+
LEVEL = [:stmt, :stmt_closure, :list, :expr, :recv]
|
17
17
|
|
18
|
-
|
19
|
-
MATH = %w(+ - / * %)
|
20
|
-
|
21
|
-
# Comparison operators
|
22
|
-
COMPARE = %w(< <= > >=)
|
23
|
-
|
24
|
-
# All Operators that can be optimized in method calls
|
25
|
-
CALL_OPERATORS = MATH + COMPARE
|
18
|
+
COMPARE = %w[< > <= >=]
|
26
19
|
|
27
20
|
# Reserved javascript keywords - we cannot create variables with the
|
28
21
|
# same name
|
@@ -60,25 +53,40 @@ module Opal
|
|
60
53
|
:** => 'pow'
|
61
54
|
}
|
62
55
|
|
63
|
-
# Type info for flags of objects. This helps identify the type of object
|
64
|
-
# being dealt with
|
65
|
-
TYPES = {
|
66
|
-
class: 0x0001,
|
67
|
-
module: 0x0002,
|
68
|
-
object: 0x0004,
|
69
|
-
boolean: 0x0008,
|
70
|
-
string: 0x0010,
|
71
|
-
array: 0x0020,
|
72
|
-
number: 0x0040,
|
73
|
-
proc: 0x0080,
|
74
|
-
hash: 0x0100,
|
75
|
-
range: 0x0200,
|
76
|
-
iclass: 0x0400,
|
77
|
-
singleton: 0x0800
|
78
|
-
}
|
79
|
-
|
80
56
|
STATEMENTS = [:xstr, :dxstr]
|
81
57
|
|
58
|
+
DEBUG_CODE = <<-CODE
|
59
|
+
var __const_get = function(const_table, id) {
|
60
|
+
if (const_table && const_table[id]) {
|
61
|
+
return const_table[id];
|
62
|
+
}
|
63
|
+
|
64
|
+
throw new Error('uninitialized constant ' + id);
|
65
|
+
};
|
66
|
+
|
67
|
+
var __send = function(recv, mid, jsid, block) {
|
68
|
+
var args = Array.prototype.slice.call(arguments, 4);
|
69
|
+
|
70
|
+
if (recv == null) {
|
71
|
+
throw new Error("cannot send '" + mid + "' to null");
|
72
|
+
}
|
73
|
+
|
74
|
+
var func = recv[jsid];
|
75
|
+
|
76
|
+
if (!func) {
|
77
|
+
throw new Error(recv + " does not respond to '" + mid + "'");
|
78
|
+
}
|
79
|
+
|
80
|
+
func._p = block;
|
81
|
+
|
82
|
+
return func.apply(recv, args);
|
83
|
+
};
|
84
|
+
|
85
|
+
var __send_splat = function(recv, mid, jsid, block, splat) {
|
86
|
+
return __send.apply(null, [recv, mid, jsid, block].concat(splat));
|
87
|
+
};
|
88
|
+
CODE
|
89
|
+
|
82
90
|
attr_reader :grammar
|
83
91
|
|
84
92
|
def self.parse(str)
|
@@ -90,13 +98,10 @@ module Opal
|
|
90
98
|
end
|
91
99
|
|
92
100
|
def parse(source, file = '(file)')
|
93
|
-
@file
|
94
|
-
@helpers
|
101
|
+
@file = file
|
102
|
+
@helpers = {
|
95
103
|
:breaker => true,
|
96
|
-
:klass => true,
|
97
|
-
:const_get => true,
|
98
104
|
:slice => true
|
99
|
-
# :nil => true
|
100
105
|
}
|
101
106
|
|
102
107
|
@grammar = Grammar.new
|
@@ -104,6 +109,14 @@ module Opal
|
|
104
109
|
top @grammar.parse(source, file)
|
105
110
|
end
|
106
111
|
|
112
|
+
def raise(msg)
|
113
|
+
super "#{msg} :#{@file}:#{@line}"
|
114
|
+
end
|
115
|
+
|
116
|
+
def parser_indent
|
117
|
+
@indent
|
118
|
+
end
|
119
|
+
|
107
120
|
def s(*parts)
|
108
121
|
sexp = parts
|
109
122
|
sexp.line = @line
|
@@ -126,7 +139,7 @@ module Opal
|
|
126
139
|
|
127
140
|
# guaranteed unique id per file..
|
128
141
|
def unique_temp
|
129
|
-
"
|
142
|
+
"TMP_#{@unique += 1}"
|
130
143
|
end
|
131
144
|
|
132
145
|
def top(sexp, options = {})
|
@@ -135,30 +148,30 @@ module Opal
|
|
135
148
|
|
136
149
|
in_scope(:top) do
|
137
150
|
indent {
|
138
|
-
code = @indent + process(s(:scope, sexp), :
|
151
|
+
code = @indent + process(s(:scope, sexp), :stmt)
|
139
152
|
}
|
140
153
|
|
141
|
-
vars << "
|
142
|
-
vars << "
|
143
|
-
|
144
|
-
|
145
|
-
vars.concat @helpers.keys.map { |h| "__#{h} = Opal.#{h}" }
|
154
|
+
vars << "__opal = Opal"
|
155
|
+
vars << "__scope = __opal"
|
156
|
+
vars << "nil = __opal.nil"
|
157
|
+
vars.concat @helpers.keys.map { |h| "__#{h} = __opal.#{h}" }
|
146
158
|
|
147
159
|
code = "var #{vars.join ', '};\n" + @scope.to_vars + "\n" + code
|
148
160
|
end
|
149
161
|
|
150
|
-
pre = "
|
162
|
+
pre = "function() {\n"
|
151
163
|
post = ""
|
152
164
|
|
165
|
+
pre += DEBUG_CODE if @debug
|
153
166
|
uniques = []
|
154
167
|
|
155
|
-
@unique.times { |i| uniques << "
|
168
|
+
@unique.times { |i| uniques << "TMP_#{i+1}" }
|
156
169
|
|
157
170
|
unless uniques.empty?
|
158
171
|
post += ";var #{uniques.join ', '};"
|
159
172
|
end
|
160
173
|
|
161
|
-
post += "\n}
|
174
|
+
post += "\n}"
|
162
175
|
|
163
176
|
pre + code + post
|
164
177
|
end
|
@@ -203,13 +216,11 @@ module Opal
|
|
203
216
|
end
|
204
217
|
|
205
218
|
def process(sexp, level)
|
206
|
-
# puts "PROCESS: (#{level})"
|
207
|
-
# puts " #{sexp.inspect}"
|
208
219
|
type = sexp.shift
|
220
|
+
meth = "process_#{type}"
|
221
|
+
raise "Unsupported sexp: #{type}" unless respond_to? meth
|
209
222
|
|
210
|
-
|
211
|
-
|
212
|
-
__send__ type, sexp, level
|
223
|
+
__send__ meth, sexp, level
|
213
224
|
end
|
214
225
|
|
215
226
|
def returns(sexp)
|
@@ -259,7 +270,7 @@ module Opal
|
|
259
270
|
!STATEMENTS.include?(sexp.first)
|
260
271
|
end
|
261
272
|
|
262
|
-
def
|
273
|
+
def process_block(sexp, level)
|
263
274
|
result = []
|
264
275
|
sexp << s(:nil) if sexp.empty?
|
265
276
|
|
@@ -273,58 +284,56 @@ module Opal
|
|
273
284
|
result.join "\n#@indent"
|
274
285
|
end
|
275
286
|
|
276
|
-
def
|
287
|
+
def process_scope(sexp, level)
|
277
288
|
stmt = sexp.shift
|
278
|
-
|
279
|
-
|
289
|
+
if stmt
|
290
|
+
stmt = returns stmt unless @scope.donates_methods
|
291
|
+
code = process stmt, :stmt
|
292
|
+
else
|
293
|
+
code = "nil"
|
294
|
+
end
|
280
295
|
|
281
296
|
code
|
282
297
|
end
|
283
298
|
|
284
299
|
# s(:js_return, sexp)
|
285
|
-
def
|
286
|
-
"return #{process sexp.shift, :
|
300
|
+
def process_js_return(sexp, level)
|
301
|
+
"return #{process sexp.shift, :expr}"
|
287
302
|
end
|
288
303
|
|
289
304
|
# s(:js_tmp, str)
|
290
|
-
def
|
305
|
+
def process_js_tmp(sexp, level)
|
291
306
|
sexp.shift.to_s
|
292
307
|
end
|
293
308
|
|
294
|
-
def
|
295
|
-
recv = sexp
|
296
|
-
meth = sexp[1]
|
297
|
-
arglist = sexp[2]
|
309
|
+
def process_operator(sexp, level)
|
310
|
+
meth, recv, arg = sexp
|
298
311
|
mid = mid_to_jsid meth.to_s
|
299
312
|
|
300
313
|
a = @scope.new_temp
|
301
314
|
b = @scope.new_temp
|
302
|
-
l = process recv, :
|
303
|
-
r = process
|
304
|
-
|
305
|
-
res = "(#{a} = #{l}, #{b} = #{r}, typeof(#{a}) === "
|
306
|
-
res += "'number' ? #{a} #{meth} #{b} : #{a}.#{mid}"
|
307
|
-
res += "(#{b}))"
|
315
|
+
l = process recv, :expr
|
316
|
+
r = process arg, :expr
|
308
317
|
|
309
318
|
@scope.queue_temp a
|
310
319
|
@scope.queue_temp b
|
311
320
|
|
312
|
-
|
321
|
+
"(%s = %s, %s = %s, typeof(%s) === 'number' ? %s %s %s : %s.%s(%s))" %
|
322
|
+
[a, l, b, r, a, a, meth.to_s, b, a, mid, b]
|
313
323
|
end
|
314
324
|
|
315
|
-
# s(:js_block_given)
|
316
325
|
def js_block_given(sexp, level)
|
317
326
|
@scope.uses_block!
|
318
|
-
"
|
327
|
+
"(#{@scope.block_name} !== nil)"
|
319
328
|
end
|
320
329
|
|
321
330
|
# s(:lit, 1)
|
322
331
|
# s(:lit, :foo)
|
323
|
-
def
|
332
|
+
def process_lit(sexp, level)
|
324
333
|
val = sexp.shift
|
325
334
|
case val
|
326
335
|
when Numeric
|
327
|
-
level == :
|
336
|
+
level == :recv ? "(#{val.inspect})" : val.inspect
|
328
337
|
when Symbol
|
329
338
|
val.to_s.inspect
|
330
339
|
when Regexp
|
@@ -337,32 +346,36 @@ module Opal
|
|
337
346
|
end
|
338
347
|
end
|
339
348
|
|
340
|
-
def
|
349
|
+
def process_dregx(sexp, level)
|
341
350
|
parts = sexp.map do |part|
|
342
351
|
if String === part
|
343
352
|
part.inspect
|
344
353
|
elsif part[0] == :str
|
345
|
-
process part, :
|
354
|
+
process part, :expr
|
346
355
|
else
|
347
|
-
process part[1], :
|
356
|
+
process part[1], :expr
|
348
357
|
end
|
349
358
|
end
|
350
359
|
|
351
360
|
"(new RegExp(#{parts.join ' + '}))"
|
352
361
|
end
|
353
362
|
|
354
|
-
def
|
363
|
+
def process_dot2(sexp, level)
|
364
|
+
lhs = process sexp[0], :expr
|
365
|
+
rhs = process sexp[1], :expr
|
355
366
|
@helpers[:range] = true
|
356
|
-
"__range(
|
367
|
+
"__range(%s, %s, false)" % [lhs, rhs]
|
357
368
|
end
|
358
369
|
|
359
|
-
def
|
370
|
+
def process_dot3(sexp, level)
|
371
|
+
lhs = process sexp[0], :expr
|
372
|
+
rhs = process sexp[1], :expr
|
360
373
|
@helpers[:range] = true
|
361
|
-
"__range(
|
374
|
+
"__range(%s, %s, true)" % [lhs, rhs]
|
362
375
|
end
|
363
376
|
|
364
377
|
# s(:str, "string")
|
365
|
-
def
|
378
|
+
def process_str(sexp, level)
|
366
379
|
str = sexp.shift
|
367
380
|
if str == @file
|
368
381
|
@uses_file = true
|
@@ -372,7 +385,7 @@ module Opal
|
|
372
385
|
end
|
373
386
|
end
|
374
387
|
|
375
|
-
def
|
388
|
+
def process_defined(sexp, level)
|
376
389
|
part = sexp[0]
|
377
390
|
case part[0]
|
378
391
|
when :self
|
@@ -385,7 +398,7 @@ module Opal
|
|
385
398
|
"false".inspect
|
386
399
|
when :call
|
387
400
|
mid = mid_to_jsid part[2].to_s
|
388
|
-
recv = part[1] ? process(part[1], :
|
401
|
+
recv = part[1] ? process(part[1], :expr) : 'this'
|
389
402
|
"(#{recv}.#{mid} ? 'method' : nil)"
|
390
403
|
else
|
391
404
|
raise "bad defined? part: #{part[0]}"
|
@@ -393,30 +406,18 @@ module Opal
|
|
393
406
|
end
|
394
407
|
|
395
408
|
# s(:not, sexp)
|
396
|
-
def
|
397
|
-
code = "!#{process sexp.shift, :
|
409
|
+
def process_not(sexp, level)
|
410
|
+
code = "!#{process sexp.shift, :expr}"
|
398
411
|
code
|
399
412
|
end
|
400
413
|
|
401
|
-
def
|
402
|
-
|
403
|
-
return "(#{pass} || function(){})"
|
404
|
-
tmp = @scope.new_temp
|
405
|
-
|
406
|
-
to_proc = process(s(:call, s(:js_tmp, tmp), :to_proc, s(:arglist)), :expression)
|
407
|
-
|
408
|
-
code = "(#{tmp} = #{pass}, (typeof(#{tmp}) === 'function' || #{tmp} == null ? #{tmp} : #{to_proc}))"
|
409
|
-
|
410
|
-
@scope.queue_temp tmp
|
411
|
-
|
412
|
-
code
|
414
|
+
def process_block_pass(exp, level)
|
415
|
+
process(s(:call, exp.shift, :to_proc, s(:arglist)), :expr)
|
413
416
|
end
|
414
417
|
|
415
418
|
# s(:iter, call, block_args [, body)
|
416
|
-
def
|
417
|
-
call = sexp
|
418
|
-
args = sexp[1]
|
419
|
-
body = sexp[2]
|
419
|
+
def process_iter(sexp, level)
|
420
|
+
call, args, body = sexp
|
420
421
|
|
421
422
|
body ||= s(:nil)
|
422
423
|
body = returns body
|
@@ -460,7 +461,7 @@ module Opal
|
|
460
461
|
code += "var #{block_arg} = _$ || nil, $context = #{block_arg}.$S;"
|
461
462
|
end
|
462
463
|
|
463
|
-
code += "\n#@indent" + process(body, :
|
464
|
+
code += "\n#@indent" + process(body, :stmt)
|
464
465
|
|
465
466
|
code = "\n#@indent#{@scope.to_vars}\n#@indent#{code}"
|
466
467
|
|
@@ -468,11 +469,17 @@ module Opal
|
|
468
469
|
end
|
469
470
|
end
|
470
471
|
|
472
|
+
tmp = @scope.new_temp
|
473
|
+
|
471
474
|
itercode = "function(#{params.join ', '}) {\n#{code}\n#@indent}"
|
472
475
|
itercode = "#{scope_name} = #{itercode}" if scope_name
|
473
|
-
call << itercode
|
474
476
|
|
475
|
-
|
477
|
+
call << ("(%s = %s, %s._s = this, %s)" % [tmp, itercode, tmp, tmp])
|
478
|
+
|
479
|
+
res = process call, level
|
480
|
+
@scope.queue_temp tmp
|
481
|
+
|
482
|
+
res
|
476
483
|
end
|
477
484
|
|
478
485
|
def js_block_args(sexp)
|
@@ -488,8 +495,7 @@ module Opal
|
|
488
495
|
# recv.mid = rhs
|
489
496
|
#
|
490
497
|
# s(recv, :mid=, s(:arglist, rhs))
|
491
|
-
|
492
|
-
def attrasgn(exp, level)
|
498
|
+
def process_attrasgn(exp, level)
|
493
499
|
recv = exp[0]
|
494
500
|
mid = exp[1]
|
495
501
|
arglist = exp[2]
|
@@ -497,35 +503,69 @@ module Opal
|
|
497
503
|
return process(s(:call, recv, mid, arglist), level)
|
498
504
|
end
|
499
505
|
|
500
|
-
#
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
506
|
+
# Used to generate optimized attr_reader, attr_writer and
|
507
|
+
# attr_accessor methods. These are optimized to avoid the added
|
508
|
+
# cost of converting the method id's into jsid's at runtime.
|
509
|
+
#
|
510
|
+
# This method will only be called if all the given ids are strings
|
511
|
+
# or symbols. Any dynamic arguments will default to being called
|
512
|
+
# using the Module#attr_* methods as expected.
|
513
|
+
#
|
514
|
+
# @param [Symbol] meth :attr_{reader,writer,accessor}
|
515
|
+
# @param [Array<Sexp>] attrs array of s(:lit) or s(:str)
|
516
|
+
# @return [String] precompiled attr methods
|
517
|
+
def attr_optimize(meth, attrs)
|
518
|
+
out = []
|
519
|
+
|
520
|
+
attrs.each do |attr|
|
521
|
+
ivar = attr[1].to_s
|
522
|
+
|
523
|
+
unless meth == :attr_writer
|
524
|
+
attr = mid_to_jsid ivar
|
525
|
+
check = "this.#{ivar} == null ? nil : this.#{ivar}"
|
526
|
+
out << "def.#{attr} = function() { return #{check}; }"
|
527
|
+
end
|
528
|
+
|
529
|
+
unless meth == :attr_reader
|
530
|
+
attr = mid_to_jsid "#{ivar}="
|
531
|
+
out << "def.#{attr} = function(val) { return this.#{ivar} = val }"
|
532
|
+
end
|
533
|
+
end
|
505
534
|
|
506
|
-
"
|
535
|
+
out.join ", \n#@indent"
|
507
536
|
end
|
508
537
|
|
509
538
|
# s(:call, recv, :mid, s(:arglist))
|
510
539
|
# s(:call, nil, :mid, s(:arglist))
|
511
|
-
def
|
512
|
-
recv = sexp
|
513
|
-
meth = sexp[1]
|
514
|
-
arglist = sexp[2]
|
515
|
-
iter = sexp[3]
|
516
|
-
|
540
|
+
def process_call(sexp, level)
|
541
|
+
recv, meth, arglist, iter = sexp
|
517
542
|
mid = mid_to_jsid meth.to_s
|
518
543
|
|
519
|
-
|
520
|
-
|
544
|
+
case meth
|
545
|
+
when :attr_reader, :attr_writer, :attr_accessor
|
546
|
+
attrs = arglist[1..-1]
|
547
|
+
if @scope.class_scope? && attrs.all? { |a| [:lit, :str].include? a.first }
|
548
|
+
return attr_optimize meth, attrs
|
549
|
+
end
|
550
|
+
when :block_given?
|
551
|
+
return js_block_given(sexp, level)
|
552
|
+
when :require
|
553
|
+
# path = arglist[1]
|
554
|
+
|
555
|
+
# if path and path[0] == :str
|
556
|
+
# path_name = path[1].sub(/^opal\//, '')
|
557
|
+
# @requires << path_name
|
558
|
+
# return "nil"
|
559
|
+
# else
|
560
|
+
# raise "Opal cannot do dynamic requires"
|
561
|
+
# end
|
562
|
+
end
|
521
563
|
|
522
564
|
splat = arglist[1..-1].any? { |a| a.first == :splat }
|
523
565
|
|
524
566
|
if Array === arglist.last and arglist.last.first == :block_pass
|
525
|
-
|
526
|
-
block = process s(:js_tmp, process(arglist.pop, :expression)), :expression
|
567
|
+
block = process s(:js_tmp, process(arglist.pop, :expr)), :expr
|
527
568
|
elsif iter
|
528
|
-
tmpmeth = @scope.new_temp
|
529
569
|
block = iter
|
530
570
|
end
|
531
571
|
|
@@ -537,22 +577,22 @@ module Opal
|
|
537
577
|
tmprecv = @scope.new_temp
|
538
578
|
end
|
539
579
|
|
540
|
-
recv_code = process recv, :
|
580
|
+
recv_code = process recv, :recv
|
541
581
|
args = ""
|
542
582
|
|
543
583
|
@scope.queue_temp tmprecv if tmprecv
|
544
|
-
@scope.queue_temp tmpmeth if tmpmeth
|
545
584
|
|
546
|
-
|
547
|
-
arglist.insert 1, s(:js_tmp, tmprecv)
|
548
|
-
end
|
585
|
+
args = process arglist, :expr
|
549
586
|
|
550
|
-
|
587
|
+
if block
|
588
|
+
dispatch = "(%s = %s, %s.%s._p = %s, %s.%s" %
|
589
|
+
[tmprecv, recv_code, tmprecv, mid, block, tmprecv, mid]
|
551
590
|
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
591
|
+
if splat
|
592
|
+
"%s.apply(%s, %s))" % [dispatch, tmprecv, args]
|
593
|
+
else
|
594
|
+
"%s(%s))" % [dispatch, args]
|
595
|
+
end
|
556
596
|
else
|
557
597
|
dispatch = tmprecv ? "(#{tmprecv} = #{recv_code}).#{mid}" : "#{recv_code}.#{mid}"
|
558
598
|
splat ? "#{dispatch}.apply(#{tmprecv || recv_code}, #{args})" : "#{dispatch}(#{args})"
|
@@ -560,18 +600,18 @@ module Opal
|
|
560
600
|
end
|
561
601
|
|
562
602
|
# s(:arglist, [arg [, arg ..]])
|
563
|
-
def
|
603
|
+
def process_arglist(sexp, level)
|
564
604
|
code = ''
|
565
605
|
work = []
|
566
606
|
|
567
607
|
until sexp.empty?
|
568
608
|
splat = sexp.first.first == :splat
|
569
|
-
arg = process sexp.shift, :
|
609
|
+
arg = process sexp.shift, :expr
|
570
610
|
|
571
611
|
if splat
|
572
612
|
if work.empty?
|
573
613
|
if code.empty?
|
574
|
-
code += arg
|
614
|
+
code += "[].concat(#{arg})"
|
575
615
|
else
|
576
616
|
code += ".concat(#{arg})"
|
577
617
|
end
|
@@ -596,75 +636,77 @@ module Opal
|
|
596
636
|
end
|
597
637
|
|
598
638
|
# s(:splat, sexp)
|
599
|
-
def
|
639
|
+
def process_splat(sexp, level)
|
600
640
|
return "[]" if sexp.first == [:nil]
|
601
|
-
return "[#{process sexp.first, :
|
602
|
-
process sexp.first, :
|
641
|
+
return "[#{process sexp.first, :expr}]" if sexp.first.first == :lit
|
642
|
+
process sexp.first, :recv
|
603
643
|
end
|
604
644
|
|
605
645
|
# s(:class, cid, super, body)
|
606
|
-
def
|
607
|
-
cid = sexp
|
608
|
-
|
609
|
-
body =
|
646
|
+
def process_class(sexp, level)
|
647
|
+
cid, sup, body = sexp
|
648
|
+
|
649
|
+
body[1] = s(:nil) unless body[1]
|
650
|
+
|
610
651
|
code = nil
|
652
|
+
@helpers[:klass] = @helpers[:donate] = true
|
611
653
|
|
612
654
|
if Symbol === cid or String === cid
|
613
|
-
donates_methods = (cid === :Object || cid === :BasicObject)
|
614
655
|
base = 'this'
|
615
656
|
name = cid.to_s.inspect
|
616
657
|
elsif cid[0] == :colon2
|
617
|
-
base = process(cid[1], :
|
658
|
+
base = process(cid[1], :expr)
|
618
659
|
name = cid[2].to_s.inspect
|
619
660
|
elsif cid[0] == :colon3
|
620
|
-
donates_methods = (cid[1] === :Object || cid[1] === :BasicObject)
|
621
661
|
base = 'Opal.Object'
|
622
662
|
name = cid[1].to_s.inspect
|
623
663
|
else
|
624
664
|
raise "Bad receiver in class"
|
625
665
|
end
|
626
666
|
|
627
|
-
sup = sup ? process(sup, :
|
667
|
+
sup = sup ? process(sup, :expr) : 'null'
|
628
668
|
|
629
669
|
indent do
|
630
670
|
in_scope(:class) do
|
631
|
-
@scope.donates_methods =
|
632
|
-
code = @indent + @scope.to_vars + "\n#@indent" + process(body, :
|
633
|
-
code += "\n#{@scope.to_donate_methods}"
|
671
|
+
@scope.donates_methods = true
|
672
|
+
code = @indent + @scope.to_vars + "\n#@indent" + process(body, :stmt)
|
673
|
+
code += "\n#{@scope.to_donate_methods}"
|
634
674
|
end
|
635
675
|
end
|
636
676
|
|
637
|
-
"__klass(#{base}, #{sup}, #{name}, function() {\n#{code}\n#@indent}
|
677
|
+
"__klass(#{base}, #{sup}, #{name}, function() {\n#{code}\n#@indent})"
|
638
678
|
end
|
639
679
|
|
640
680
|
# s(:sclass, recv, body)
|
641
|
-
def
|
681
|
+
def process_sclass(sexp, level)
|
642
682
|
recv = sexp[0]
|
643
683
|
body = sexp[1]
|
644
684
|
code = nil
|
645
|
-
base = process recv, :
|
685
|
+
base = process recv, :expr
|
686
|
+
@helpers[:sklass] = true
|
646
687
|
|
647
688
|
in_scope(:sclass) do
|
648
|
-
code = @scope.to_vars + process(body, :
|
689
|
+
code = @scope.to_vars + process(body, :stmt)
|
649
690
|
end
|
650
691
|
|
651
|
-
"
|
692
|
+
"__sklass(#{base}, function() {#{code}})"
|
652
693
|
end
|
653
694
|
|
654
695
|
# s(:module, cid, body)
|
655
|
-
def
|
696
|
+
def process_module(sexp, level)
|
656
697
|
cid = sexp[0]
|
657
698
|
body = sexp[1]
|
658
699
|
code = nil
|
700
|
+
@helpers[:module] = @helpers[:donate] = true
|
659
701
|
|
660
702
|
if Symbol === cid or String === cid
|
661
703
|
base = 'this'
|
662
704
|
name = cid.to_s.inspect
|
663
705
|
elsif cid[0] == :colon2
|
664
|
-
base = process(cid[1], :
|
706
|
+
base = process(cid[1], :expr)
|
665
707
|
name = cid[2].to_s.inspect
|
666
708
|
elsif cid[0] == :colon3
|
667
|
-
base = '
|
709
|
+
base = 'Opal.Object'
|
668
710
|
name = cid[1].to_s.inspect
|
669
711
|
else
|
670
712
|
raise "Bad receiver in class"
|
@@ -673,20 +715,26 @@ module Opal
|
|
673
715
|
indent do
|
674
716
|
in_scope(:module) do
|
675
717
|
@scope.donates_methods = true
|
676
|
-
code = @indent + @scope.to_vars + "\n#@indent" + process(body, :
|
718
|
+
code = @indent + @scope.to_vars + "\n#@indent" + process(body, :stmt) + "\n#@indent" + @scope.to_donate_methods
|
677
719
|
end
|
678
720
|
end
|
679
721
|
|
680
|
-
"
|
722
|
+
"__module(#{base}, #{name}, function() {\n#{code}\n#@indent})"
|
681
723
|
end
|
682
724
|
|
683
|
-
def
|
725
|
+
def process_undef(exp, level)
|
684
726
|
@helpers[:undef] = true
|
685
|
-
|
727
|
+
jsid = mid_to_jsid exp[0][1].to_s
|
728
|
+
|
729
|
+
# "__undef(this, #{jsid.inspect})"
|
730
|
+
# FIXME: maybe add this to donate(). it will be undefined, so
|
731
|
+
# when added to includees it will actually undefine methods there
|
732
|
+
# too.
|
733
|
+
"delete def.#{jsid}"
|
686
734
|
end
|
687
735
|
|
688
736
|
# s(:defn, mid, s(:args), s(:scope))
|
689
|
-
def
|
737
|
+
def process_defn(sexp, level)
|
690
738
|
mid = sexp[0]
|
691
739
|
args = sexp[1]
|
692
740
|
stmts = sexp[2]
|
@@ -694,7 +742,7 @@ module Opal
|
|
694
742
|
end
|
695
743
|
|
696
744
|
# s(:defs, recv, mid, s(:args), s(:scope))
|
697
|
-
def
|
745
|
+
def process_defs(sexp, level)
|
698
746
|
recv = sexp[0]
|
699
747
|
mid = sexp[1]
|
700
748
|
args = sexp[2]
|
@@ -706,11 +754,10 @@ module Opal
|
|
706
754
|
mid = mid_to_jsid mid.to_s
|
707
755
|
|
708
756
|
if recvr
|
709
|
-
@
|
710
|
-
|
711
|
-
recv = process(recvr, :expression)
|
757
|
+
@scope.defines_defs = true
|
758
|
+
recv = process(recvr, :expr)
|
712
759
|
else
|
713
|
-
|
760
|
+
@scope.defines_defn = true
|
714
761
|
recv = 'this'
|
715
762
|
end
|
716
763
|
|
@@ -750,25 +797,25 @@ module Opal
|
|
750
797
|
yielder = block_name || '__yield'
|
751
798
|
@scope.block_name = yielder
|
752
799
|
|
753
|
-
params = process args, :
|
800
|
+
params = process args, :expr
|
754
801
|
|
755
802
|
opt[1..-1].each do |o|
|
756
803
|
next if o[2][2] == :undefined
|
757
|
-
id = process s(:lvar, o[1]), :
|
758
|
-
code += "if (#{id} == null) {\n#@indent#{INDENT}#{process o, :
|
804
|
+
id = process s(:lvar, o[1]), :expr
|
805
|
+
code += "if (#{id} == null) {\n#@indent#{INDENT}#{process o, :expr};\n#@indent}"
|
759
806
|
end if opt
|
760
807
|
|
761
808
|
code += "#{splat} = __slice.call(arguments, #{len});" if splat
|
762
|
-
code += "\n#@indent" + process(stmts, :
|
809
|
+
code += "\n#@indent" + process(stmts, :stmt)
|
763
810
|
|
764
811
|
# Returns the identity name if identified, nil otherwise
|
765
812
|
scope_name = @scope.identity
|
766
813
|
|
767
814
|
if @scope.uses_block?
|
768
|
-
@scope.
|
769
|
-
@scope.
|
770
|
-
blk = "\n#{@indent}
|
771
|
-
blk += ";\n#{@indent
|
815
|
+
@scope.add_temp '__context'
|
816
|
+
@scope.add_temp yielder
|
817
|
+
blk = "\n#{@indent}#{yielder} = #{scope_name}._p || nil;\n#{@indent}__context = #{yielder}._s"
|
818
|
+
blk += ";\n#{@indent}#{scope_name}._p = null;\n#{@indent}"
|
772
819
|
code = blk + code
|
773
820
|
end
|
774
821
|
|
@@ -782,18 +829,21 @@ module Opal
|
|
782
829
|
|
783
830
|
defcode = "#{"#{scope_name} = " if scope_name}function(#{params}) {\n#{code}\n#@indent}"
|
784
831
|
|
785
|
-
if
|
786
|
-
|
787
|
-
|
788
|
-
"#{type}(#{recv}, '#{mid}', #{defcode})"
|
832
|
+
if recvr
|
833
|
+
# FIXME: need to donate()
|
834
|
+
"#{recv}.$singleton_class()._proto.#{mid} = #{defcode}"
|
789
835
|
elsif @scope.type == :class
|
790
|
-
@scope.methods << mid if @scope.donates_methods
|
836
|
+
@scope.methods << mid# if @scope.donates_methods
|
791
837
|
"def.#{mid} = #{defcode}"
|
792
838
|
elsif @scope.type == :module
|
793
839
|
@scope.methods << mid
|
794
840
|
"def.#{mid} = #{defcode}"
|
841
|
+
elsif @scope.type == :iter
|
842
|
+
# FIXME: this should also donate()
|
843
|
+
"def.#{mid} = #{defcode}"
|
795
844
|
else
|
796
|
-
|
845
|
+
# FIXME: this should also donate()
|
846
|
+
"def.#{mid} = #{defcode}"
|
797
847
|
end
|
798
848
|
end
|
799
849
|
|
@@ -813,7 +863,7 @@ module Opal
|
|
813
863
|
end
|
814
864
|
end
|
815
865
|
|
816
|
-
def
|
866
|
+
def process_args(exp, level)
|
817
867
|
args = []
|
818
868
|
|
819
869
|
until exp.empty?
|
@@ -827,24 +877,21 @@ module Opal
|
|
827
877
|
end
|
828
878
|
|
829
879
|
# s(:self) # => this
|
830
|
-
def
|
880
|
+
def process_self(sexp, level)
|
831
881
|
'this'
|
832
882
|
end
|
833
883
|
|
834
884
|
# s(:true) # => true
|
835
885
|
# s(:false) # => false
|
836
|
-
|
837
|
-
|
886
|
+
# s(:nil) # => nil
|
887
|
+
%w(true false nil).each do |name|
|
888
|
+
define_method "process_#{name}" do |exp, level|
|
838
889
|
name
|
839
890
|
end
|
840
891
|
end
|
841
892
|
|
842
|
-
def nil(*)
|
843
|
-
"nil"
|
844
|
-
end
|
845
|
-
|
846
893
|
# s(:array [, sexp [, sexp]])
|
847
|
-
def
|
894
|
+
def process_array(sexp, level)
|
848
895
|
return '[]' if sexp.empty?
|
849
896
|
|
850
897
|
code = ''
|
@@ -852,7 +899,7 @@ module Opal
|
|
852
899
|
|
853
900
|
until sexp.empty?
|
854
901
|
splat = sexp.first.first == :splat
|
855
|
-
part = process sexp.shift, :
|
902
|
+
part = process sexp.shift, :expr
|
856
903
|
|
857
904
|
if splat
|
858
905
|
if work.empty?
|
@@ -877,27 +924,28 @@ module Opal
|
|
877
924
|
end
|
878
925
|
|
879
926
|
# s(:hash, key1, val1, key2, val2...)
|
880
|
-
def
|
881
|
-
|
927
|
+
def process_hash(sexp, level)
|
928
|
+
@helpers[:hash] = true
|
929
|
+
"__hash(#{sexp.map { |p| process p, :expr }.join ', '})"
|
882
930
|
end
|
883
931
|
|
884
932
|
# s(:while, exp, block, true)
|
885
|
-
def
|
933
|
+
def process_while(sexp, level)
|
886
934
|
expr = sexp[0]
|
887
935
|
stmt = sexp[1]
|
888
936
|
redo_var = @scope.new_temp
|
889
|
-
stmt_level = if level == :
|
890
|
-
:
|
937
|
+
stmt_level = if level == :expr or level == :recv
|
938
|
+
:stmt_closure
|
891
939
|
else
|
892
|
-
:
|
940
|
+
:stmt
|
893
941
|
end
|
894
942
|
pre = "while ("
|
895
943
|
code = "#{js_truthy expr}){"
|
896
944
|
|
897
945
|
in_while do
|
898
|
-
@while_loop[:closure] = true if stmt_level == :
|
946
|
+
@while_loop[:closure] = true if stmt_level == :stmt_closure
|
899
947
|
@while_loop[:redo_var] = redo_var
|
900
|
-
body = process(stmt, :
|
948
|
+
body = process(stmt, :stmt)
|
901
949
|
|
902
950
|
if @while_loop[:use_redo]
|
903
951
|
pre = "#{redo_var}=false;" + pre + "#{redo_var} || "
|
@@ -911,29 +959,29 @@ module Opal
|
|
911
959
|
code = pre + code
|
912
960
|
@scope.queue_temp redo_var
|
913
961
|
|
914
|
-
if stmt_level == :
|
962
|
+
if stmt_level == :stmt_closure
|
915
963
|
code = "(function() {#{code}; return nil;}).call(this)"
|
916
964
|
end
|
917
965
|
|
918
966
|
code
|
919
967
|
end
|
920
968
|
|
921
|
-
def
|
969
|
+
def process_until(exp, level)
|
922
970
|
expr = exp[0]
|
923
971
|
stmt = exp[1]
|
924
972
|
redo_var = @scope.new_temp
|
925
|
-
stmt_level = if level == :
|
926
|
-
:
|
973
|
+
stmt_level = if level == :expr or level == :recv
|
974
|
+
:stmt_closure
|
927
975
|
else
|
928
|
-
:
|
976
|
+
:stmt
|
929
977
|
end
|
930
978
|
pre = "while (!("
|
931
979
|
code = "#{js_truthy expr})) {"
|
932
980
|
|
933
981
|
in_while do
|
934
|
-
@while_loop[:closure] = true if stmt_level == :
|
982
|
+
@while_loop[:closure] = true if stmt_level == :stmt_closure
|
935
983
|
@while_loop[:redo_var] = redo_var
|
936
|
-
body = process(stmt, :
|
984
|
+
body = process(stmt, :stmt)
|
937
985
|
|
938
986
|
if @while_loop[:use_redo]
|
939
987
|
pre = "#{redo_var}=false;" + pre + "#{redo_var} || "
|
@@ -947,7 +995,7 @@ module Opal
|
|
947
995
|
code = pre + code
|
948
996
|
@scope.queue_temp redo_var
|
949
997
|
|
950
|
-
if stmt_level == :
|
998
|
+
if stmt_level == :stmt_closure
|
951
999
|
code = "(function() {#{code}; return nil;}).call(this)"
|
952
1000
|
end
|
953
1001
|
|
@@ -958,14 +1006,16 @@ module Opal
|
|
958
1006
|
# alias foo bar
|
959
1007
|
#
|
960
1008
|
# s(:alias, s(:lit, :foo), s(:lit, :bar))
|
961
|
-
def
|
1009
|
+
def process_alias(exp, level)
|
962
1010
|
@helpers['alias'] = true
|
963
|
-
new = exp[0]
|
964
|
-
old = exp[1]
|
965
|
-
"__alias(this, #{
|
1011
|
+
new = mid_to_jsid exp[0][1].to_s
|
1012
|
+
old = mid_to_jsid exp[1][1].to_s
|
1013
|
+
# "__alias(this, #{new.inspect}, #{old.inspect})"
|
1014
|
+
@scope.methods << new
|
1015
|
+
"def.#{new} = def.#{old}"
|
966
1016
|
end
|
967
1017
|
|
968
|
-
def
|
1018
|
+
def process_masgn(sexp, level)
|
969
1019
|
lhs = sexp[0]
|
970
1020
|
rhs = sexp[1]
|
971
1021
|
tmp = @scope.new_temp
|
@@ -975,11 +1025,11 @@ module Opal
|
|
975
1025
|
lhs.shift
|
976
1026
|
if rhs[0] == :array
|
977
1027
|
len = rhs.length - 1 # we are guaranteed an array of this length
|
978
|
-
code = ["#{tmp} = #{process rhs, :
|
1028
|
+
code = ["#{tmp} = #{process rhs, :expr}"]
|
979
1029
|
elsif rhs[0] == :to_ary
|
980
|
-
code = ["#{tmp} = [#{process rhs[1], :
|
1030
|
+
code = ["#{tmp} = [#{process rhs[1], :expr}]"]
|
981
1031
|
elsif rhs[0] == :splat
|
982
|
-
code = ["#{tmp} = #{process rhs[1], :
|
1032
|
+
code = ["#{tmp} = #{process rhs[1], :expr}"]
|
983
1033
|
else
|
984
1034
|
raise "Unsupported mlhs type"
|
985
1035
|
end
|
@@ -989,14 +1039,14 @@ module Opal
|
|
989
1039
|
if l.first == :splat
|
990
1040
|
s = l[1]
|
991
1041
|
s << s(:js_tmp, "__slice.call(#{tmp}, #{idx})")
|
992
|
-
code << process(s, :
|
1042
|
+
code << process(s, :expr)
|
993
1043
|
else
|
994
1044
|
if idx >= len
|
995
1045
|
l << s(:js_tmp, "(#{tmp}[#{idx}] == null ? nil : #{tmp}[#{idx}])")
|
996
1046
|
else
|
997
1047
|
l << s(:js_tmp, "#{tmp}[#{idx}]")
|
998
1048
|
end
|
999
|
-
code << process(l, :
|
1049
|
+
code << process(l, :expr)
|
1000
1050
|
end
|
1001
1051
|
end
|
1002
1052
|
|
@@ -1004,38 +1054,38 @@ module Opal
|
|
1004
1054
|
code.join ', '
|
1005
1055
|
end
|
1006
1056
|
|
1007
|
-
def
|
1057
|
+
def process_svalue(sexp, level)
|
1008
1058
|
process sexp.shift, level
|
1009
1059
|
end
|
1010
1060
|
|
1011
1061
|
# s(:lasgn, :lvar, rhs)
|
1012
|
-
def
|
1062
|
+
def process_lasgn(sexp, level)
|
1013
1063
|
lvar = sexp[0]
|
1014
1064
|
rhs = sexp[1]
|
1015
1065
|
lvar = "#{lvar}$".intern if RESERVED.include? lvar.to_s
|
1016
1066
|
@scope.add_local lvar
|
1017
|
-
res = "#{lvar} = #{process rhs, :
|
1018
|
-
level == :
|
1067
|
+
res = "#{lvar} = #{process rhs, :expr}"
|
1068
|
+
level == :recv ? "(#{res})" : res
|
1019
1069
|
end
|
1020
1070
|
|
1021
1071
|
# s(:lvar, :lvar)
|
1022
|
-
def
|
1072
|
+
def process_lvar(exp, level)
|
1023
1073
|
lvar = exp.shift.to_s
|
1024
1074
|
lvar = "#{lvar}$" if RESERVED.include? lvar
|
1025
1075
|
lvar
|
1026
1076
|
end
|
1027
1077
|
|
1028
1078
|
# s(:iasgn, :ivar, rhs)
|
1029
|
-
def
|
1079
|
+
def process_iasgn(exp, level)
|
1030
1080
|
ivar = exp[0]
|
1031
1081
|
rhs = exp[1]
|
1032
1082
|
ivar = ivar.to_s[1..-1]
|
1033
1083
|
lhs = RESERVED.include?(ivar) ? "this['#{ivar}']" : "this.#{ivar}"
|
1034
|
-
"#{lhs} = #{process rhs, :
|
1084
|
+
"#{lhs} = #{process rhs, :expr}"
|
1035
1085
|
end
|
1036
1086
|
|
1037
1087
|
# s(:ivar, :ivar)
|
1038
|
-
def
|
1088
|
+
def process_ivar(exp, level)
|
1039
1089
|
ivar = exp.shift.to_s[1..-1]
|
1040
1090
|
part = RESERVED.include?(ivar) ? "['#{ivar}']" : ".#{ivar}"
|
1041
1091
|
@scope.add_ivar part
|
@@ -1043,63 +1093,58 @@ module Opal
|
|
1043
1093
|
end
|
1044
1094
|
|
1045
1095
|
# s(:gvar, gvar)
|
1046
|
-
def
|
1096
|
+
def process_gvar(sexp, level)
|
1047
1097
|
gvar = sexp.shift.to_s
|
1048
1098
|
@helpers['gvars'] = true
|
1049
1099
|
"__gvars[#{gvar.inspect}]"
|
1050
1100
|
end
|
1051
1101
|
|
1052
1102
|
# s(:gasgn, :gvar, rhs)
|
1053
|
-
def
|
1103
|
+
def process_gasgn(sexp, level)
|
1054
1104
|
gvar = sexp[0]
|
1055
1105
|
rhs = sexp[1]
|
1056
1106
|
@helpers['gvars'] = true
|
1057
|
-
"__gvars[#{gvar.to_s.inspect}] = #{process rhs, :
|
1107
|
+
"__gvars[#{gvar.to_s.inspect}] = #{process rhs, :expr}"
|
1058
1108
|
end
|
1059
1109
|
|
1060
1110
|
# s(:const, :const)
|
1061
|
-
def
|
1111
|
+
def process_const(sexp, level)
|
1062
1112
|
if @debug
|
1063
|
-
"
|
1113
|
+
"__const_get(__scope, #{sexp.shift.to_s.inspect})"
|
1064
1114
|
else
|
1065
1115
|
"__scope.#{sexp.shift}"
|
1066
1116
|
end
|
1067
1117
|
end
|
1068
1118
|
|
1069
1119
|
# s(:cdecl, :const, rhs)
|
1070
|
-
def
|
1120
|
+
def process_cdecl(sexp, level)
|
1071
1121
|
const = sexp[0]
|
1072
1122
|
rhs = sexp[1]
|
1073
|
-
"__scope.#{const} = #{process rhs, :
|
1123
|
+
"__scope.#{const} = #{process rhs, :expr}"
|
1074
1124
|
end
|
1075
1125
|
|
1076
1126
|
# s(:return [val])
|
1077
|
-
def
|
1078
|
-
val = process(sexp.shift || s(:nil), :
|
1127
|
+
def process_return(sexp, level)
|
1128
|
+
val = process(sexp.shift || s(:nil), :expr)
|
1079
1129
|
|
1080
|
-
|
1081
|
-
|
1082
|
-
else
|
1083
|
-
"$return(#{val})"
|
1084
|
-
end
|
1130
|
+
raise "Cannot return as an expression" unless level == :stmt
|
1131
|
+
"return #{val}"
|
1085
1132
|
end
|
1086
1133
|
|
1087
1134
|
# s(:xstr, content)
|
1088
|
-
def
|
1135
|
+
def process_xstr(sexp, level)
|
1089
1136
|
code = sexp.first.to_s
|
1090
|
-
code += ";" if level == :
|
1091
|
-
|
1092
|
-
|
1093
|
-
code
|
1137
|
+
code += ";" if level == :stmt and !code.include?(';')
|
1138
|
+
level == :recv ? "(#{code})" : code
|
1094
1139
|
end
|
1095
1140
|
|
1096
1141
|
# s(:dxstr, parts...)
|
1097
|
-
def
|
1142
|
+
def process_dxstr(sexp, level)
|
1098
1143
|
code = sexp.map do |p|
|
1099
1144
|
if String === p
|
1100
1145
|
p.to_s
|
1101
1146
|
elsif p.first == :evstr
|
1102
|
-
process p.last, :
|
1147
|
+
process p.last, :stmt
|
1103
1148
|
elsif p.first == :str
|
1104
1149
|
p.last.to_s
|
1105
1150
|
else
|
@@ -1107,18 +1152,18 @@ module Opal
|
|
1107
1152
|
end
|
1108
1153
|
end.join
|
1109
1154
|
|
1110
|
-
code += ";" if level == :
|
1111
|
-
code = "(#{code})" if level == :
|
1155
|
+
code += ";" if level == :stmt and !code.include?(';')
|
1156
|
+
code = "(#{code})" if level == :recv
|
1112
1157
|
code
|
1113
1158
|
end
|
1114
1159
|
|
1115
1160
|
# s(:dstr, parts..)
|
1116
|
-
def
|
1161
|
+
def process_dstr(sexp, level)
|
1117
1162
|
parts = sexp.map do |p|
|
1118
1163
|
if String === p
|
1119
1164
|
p.inspect
|
1120
1165
|
elsif p.first == :evstr
|
1121
|
-
process p.last, :
|
1166
|
+
process p.last, :expr
|
1122
1167
|
elsif p.first == :str
|
1123
1168
|
p.last.inspect
|
1124
1169
|
else
|
@@ -1127,15 +1172,15 @@ module Opal
|
|
1127
1172
|
end
|
1128
1173
|
|
1129
1174
|
res = parts.join ' + '
|
1130
|
-
level == :
|
1175
|
+
level == :recv ? "(#{res})" : res
|
1131
1176
|
end
|
1132
1177
|
|
1133
|
-
def
|
1178
|
+
def process_dsym(sexp, level)
|
1134
1179
|
parts = sexp.map do |p|
|
1135
1180
|
if String === p
|
1136
1181
|
p.inspect
|
1137
1182
|
elsif p.first == :evstr
|
1138
|
-
process(s(:call, p.last, :to_s, s(:arglist)), :
|
1183
|
+
process(s(:call, p.last, :to_s, s(:arglist)), :expr)
|
1139
1184
|
elsif p.first == :str
|
1140
1185
|
p.last.inspect
|
1141
1186
|
else
|
@@ -1147,22 +1192,21 @@ module Opal
|
|
1147
1192
|
end
|
1148
1193
|
|
1149
1194
|
# s(:if, test, truthy, falsy)
|
1150
|
-
def
|
1151
|
-
test
|
1152
|
-
|
1153
|
-
falsy = sexp[2]
|
1195
|
+
def process_if(sexp, level)
|
1196
|
+
test, truthy, falsy = sexp
|
1197
|
+
returnable = (level == :expr or level == :recv)
|
1154
1198
|
|
1155
|
-
if
|
1199
|
+
if returnable
|
1156
1200
|
truthy = returns(truthy || s(:nil))
|
1157
1201
|
falsy = returns(falsy || s(:nil))
|
1158
1202
|
end
|
1159
1203
|
|
1160
1204
|
code = "if (#{js_truthy test}) {\n"
|
1161
|
-
indent { code += @indent + process(truthy, :
|
1162
|
-
indent { code += "\n#@indent} else {\n#@indent#{process falsy, :
|
1205
|
+
indent { code += @indent + process(truthy, :stmt) } if truthy
|
1206
|
+
indent { code += "\n#@indent} else {\n#@indent#{process falsy, :stmt}" } if falsy
|
1163
1207
|
code += "\n#@indent}"
|
1164
1208
|
|
1165
|
-
code = "(function() { #{code}; return nil; }).call(this)" if
|
1209
|
+
code = "(function() { #{code}; return nil; }).call(this)" if returnable
|
1166
1210
|
|
1167
1211
|
code
|
1168
1212
|
end
|
@@ -1171,9 +1215,9 @@ module Opal
|
|
1171
1215
|
if sexp.first == :call
|
1172
1216
|
mid = sexp[2]
|
1173
1217
|
if mid == :block_given?
|
1174
|
-
return process sexp, :
|
1218
|
+
return process sexp, :expr
|
1175
1219
|
elsif COMPARE.include? mid.to_s
|
1176
|
-
return process sexp, :
|
1220
|
+
return process sexp, :expr
|
1177
1221
|
end
|
1178
1222
|
end
|
1179
1223
|
end
|
@@ -1184,89 +1228,72 @@ module Opal
|
|
1184
1228
|
end
|
1185
1229
|
|
1186
1230
|
tmp = @scope.new_temp
|
1187
|
-
code = "(#{tmp} = #{process sexp, :expression}) !== false && #{tmp} !== nil"
|
1188
1231
|
@scope.queue_temp tmp
|
1189
1232
|
|
1190
|
-
|
1233
|
+
"(%s = %s) !== false && %s !== nil" % [tmp, process(sexp, :expr), tmp]
|
1191
1234
|
end
|
1192
1235
|
|
1193
1236
|
# s(:and, lhs, rhs)
|
1194
|
-
def
|
1237
|
+
def process_and(sexp, level)
|
1195
1238
|
lhs = sexp[0]
|
1196
1239
|
rhs = sexp[1]
|
1197
1240
|
t = nil
|
1198
1241
|
tmp = @scope.new_temp
|
1199
1242
|
|
1200
1243
|
if t = js_truthy_optimize(lhs)
|
1201
|
-
return "(#{tmp} = #{t} ? #{process rhs, :
|
1244
|
+
return "(#{tmp} = #{t} ? #{process rhs, :expr} : #{tmp})".tap {
|
1202
1245
|
@scope.queue_temp tmp
|
1203
1246
|
}
|
1204
1247
|
end
|
1205
1248
|
|
1206
|
-
code = "((#{tmp} = #{process lhs, :expression}, #{tmp} !== false && "
|
1207
|
-
code += "#{tmp} !== nil) ? #{process rhs, :expression} : #{tmp})"
|
1208
1249
|
@scope.queue_temp tmp
|
1209
1250
|
|
1210
|
-
|
1251
|
+
"(%s = %s, %s !== false && %s !== nil ? %s : %s)" %
|
1252
|
+
[tmp, process(lhs, :expr), tmp, tmp, process(rhs, :expr), tmp]
|
1211
1253
|
end
|
1212
1254
|
|
1213
1255
|
# s(:or, lhs, rhs)
|
1214
|
-
def
|
1256
|
+
def process_or(sexp, level)
|
1215
1257
|
lhs = sexp[0]
|
1216
1258
|
rhs = sexp[1]
|
1217
1259
|
t = nil
|
1218
1260
|
tmp = @scope.new_temp
|
1219
1261
|
|
1220
1262
|
if t = js_truthy_optimize(lhs)
|
1221
|
-
return "(#{tmp} = #{t} ? #{tmp} : #{process rhs, :
|
1263
|
+
return "(#{tmp} = #{t} ? #{tmp} : #{process rhs, :expr})".tap {
|
1222
1264
|
@scope.queue_temp tmp
|
1223
1265
|
}
|
1224
1266
|
end
|
1225
1267
|
|
1226
|
-
code = "(#{tmp} = #{process lhs, :expression}, #{tmp} !== false && "
|
1227
|
-
code += "#{tmp} !== nil ? #{tmp} : #{process rhs, :expression})"
|
1228
1268
|
@scope.queue_temp tmp
|
1229
1269
|
|
1230
|
-
|
1270
|
+
"(%s = %s, %s !== false && %s !== nil ? %s : %s)" %
|
1271
|
+
[tmp, process(lhs, :expr), tmp, tmp, tmp, process(rhs, :expr)]
|
1231
1272
|
end
|
1232
1273
|
|
1233
1274
|
# s(:yield, arg1, arg2)
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1275
|
+
#
|
1276
|
+
# FIXME: yield as an expression (when used with js_return) should have the
|
1277
|
+
# right action. We should then warn when used as an expression in other cases
|
1278
|
+
# that we would need to use a try/catch/throw block (which is slow and bad
|
1279
|
+
# mmmkay).
|
1280
|
+
def process_yield(sexp, level)
|
1237
1281
|
@scope.uses_block!
|
1238
1282
|
splat = sexp.any? { |s| s.first == :splat }
|
1239
|
-
# sexp.unshift s(:js_tmp, 'null')
|
1240
1283
|
sexp.unshift s(:js_tmp, '__context') unless splat
|
1241
|
-
args =
|
1284
|
+
args = process_arglist(sexp, level)
|
1242
1285
|
|
1243
1286
|
yielder = @scope.block_name || '__yield'
|
1244
1287
|
|
1245
|
-
|
1246
|
-
|
1247
|
-
|
1248
|
-
|
1249
|
-
|
1250
|
-
|
1251
|
-
# FIXME: yield as an expression (when used with js_return) should have the
|
1252
|
-
# right action. We should then warn when used as an expression in other cases
|
1253
|
-
# that we would need to use a try/catch/throw block (which is slow and bad
|
1254
|
-
# mmmkay).
|
1255
|
-
|
1256
|
-
# if level == :receiver or level == :expression
|
1257
|
-
# tmp = @scope.new_temp
|
1258
|
-
# @scope.catches_break!
|
1259
|
-
# code = "((#{tmp} = #{call}) === __breaker ? #{tmp}.$t() : #{tmp})"
|
1260
|
-
# @scope.queue_temp tmp
|
1261
|
-
# else
|
1262
|
-
code = call
|
1263
|
-
# end
|
1264
|
-
|
1265
|
-
code
|
1288
|
+
if splat
|
1289
|
+
"#{yielder}.apply(__context, #{args})"
|
1290
|
+
else
|
1291
|
+
"#{yielder}.call(#{args})"
|
1292
|
+
end
|
1266
1293
|
end
|
1267
1294
|
|
1268
|
-
def
|
1269
|
-
val = exp.empty? ? 'nil' : process(exp.shift, :
|
1295
|
+
def process_break(exp, level)
|
1296
|
+
val = exp.empty? ? 'nil' : process(exp.shift, :expr)
|
1270
1297
|
if in_while?
|
1271
1298
|
if @while_loop[:closure]
|
1272
1299
|
"return #{val};"
|
@@ -1279,25 +1306,25 @@ module Opal
|
|
1279
1306
|
end
|
1280
1307
|
|
1281
1308
|
# s(:case, expr, when1, when2, ..)
|
1282
|
-
def
|
1309
|
+
def process_case(exp, level)
|
1283
1310
|
code = []
|
1284
1311
|
@scope.add_local "$case"
|
1285
|
-
expr = process exp.shift, :
|
1312
|
+
expr = process exp.shift, :expr
|
1286
1313
|
# are we inside a statement_closure
|
1287
|
-
returnable = level != :
|
1314
|
+
returnable = level != :stmt
|
1288
1315
|
done_else = false
|
1289
1316
|
|
1290
1317
|
until exp.empty?
|
1291
1318
|
wen = exp.shift
|
1292
1319
|
if wen and wen.first == :when
|
1293
1320
|
returns(wen) if returnable
|
1294
|
-
wen = process(wen, :
|
1321
|
+
wen = process(wen, :stmt)
|
1295
1322
|
wen = "else #{wen}" unless code.empty?
|
1296
1323
|
code << wen
|
1297
1324
|
elsif wen # s(:else)
|
1298
1325
|
done_else = true
|
1299
1326
|
wen = returns(wen) if returnable
|
1300
|
-
code << "else {#{process wen, :
|
1327
|
+
code << "else {#{process wen, :stmt}}"
|
1301
1328
|
end
|
1302
1329
|
end
|
1303
1330
|
|
@@ -1312,7 +1339,7 @@ module Opal
|
|
1312
1339
|
# bar
|
1313
1340
|
#
|
1314
1341
|
# s(:when, s(:array, foo), bar)
|
1315
|
-
def
|
1342
|
+
def process_when(exp, level)
|
1316
1343
|
arg = exp.shift[1..-1]
|
1317
1344
|
body = exp.shift
|
1318
1345
|
body = process body, level if body
|
@@ -1324,26 +1351,26 @@ module Opal
|
|
1324
1351
|
if a.first == :when # when inside another when means a splat of values
|
1325
1352
|
call = s(:call, s(:js_tmp, "$splt[i]"), :===, s(:arglist, s(:js_tmp, "$case")))
|
1326
1353
|
splt = "(function($splt) {for(var i = 0; i < $splt.length; i++) {"
|
1327
|
-
splt += "if (#{process call, :
|
1328
|
-
splt += "} return false; }).call(this, #{process a[1], :
|
1354
|
+
splt += "if (#{process call, :expr}) { return true; }"
|
1355
|
+
splt += "} return false; }).call(this, #{process a[1], :expr})"
|
1329
1356
|
|
1330
1357
|
test << splt
|
1331
1358
|
else
|
1332
1359
|
call = s(:call, a, :===, s(:arglist, s(:js_tmp, "$case")))
|
1333
|
-
call = process call, :
|
1360
|
+
call = process call, :expr
|
1334
1361
|
# call = "else " unless test.empty?
|
1335
1362
|
|
1336
1363
|
test << call
|
1337
1364
|
end
|
1338
1365
|
end
|
1339
1366
|
|
1340
|
-
"if (
|
1367
|
+
"if (%s) {\n%s\n}" % [test.join(' || '), body]
|
1341
1368
|
end
|
1342
1369
|
|
1343
1370
|
# lhs =~ rhs
|
1344
1371
|
#
|
1345
1372
|
# s(:match3, lhs, rhs)
|
1346
|
-
def
|
1373
|
+
def process_match3(sexp, level)
|
1347
1374
|
lhs = sexp[0]
|
1348
1375
|
rhs = sexp[1]
|
1349
1376
|
call = s(:call, lhs, :=~, s(:arglist, rhs))
|
@@ -1353,68 +1380,67 @@ module Opal
|
|
1353
1380
|
# @@class_variable
|
1354
1381
|
#
|
1355
1382
|
# s(:cvar, name)
|
1356
|
-
def
|
1383
|
+
def process_cvar(exp, level)
|
1357
1384
|
tmp = @scope.new_temp
|
1358
|
-
code = "((#{tmp} = Opal.cvars[#{exp.shift.to_s.inspect}]) == null ? null : #{tmp})"
|
1359
1385
|
@scope.queue_temp tmp
|
1360
|
-
|
1386
|
+
"((%s = Opal.cvars[%s]) == null ? nil : %s)" % [tmp, exp.shift.to_s.inspect, tmp]
|
1361
1387
|
end
|
1362
1388
|
|
1363
1389
|
# @@name = rhs
|
1364
1390
|
#
|
1365
1391
|
# s(:cvasgn, :@@name, rhs)
|
1366
|
-
def
|
1367
|
-
"(Opal.cvars[#{exp.shift.to_s.inspect}] = #{process exp.shift, :
|
1392
|
+
def process_cvasgn(exp, level)
|
1393
|
+
"(Opal.cvars[#{exp.shift.to_s.inspect}] = #{process exp.shift, :expr})"
|
1368
1394
|
end
|
1369
1395
|
|
1370
|
-
def
|
1371
|
-
"(Opal.cvars[#{exp.shift.to_s.inspect}] = #{process exp.shift, :
|
1396
|
+
def process_cvdecl(exp, level)
|
1397
|
+
"(Opal.cvars[#{exp.shift.to_s.inspect}] = #{process exp.shift, :expr})"
|
1372
1398
|
end
|
1373
1399
|
|
1374
1400
|
# BASE::NAME
|
1375
1401
|
#
|
1376
1402
|
# s(:colon2, base, :NAME)
|
1377
|
-
def
|
1403
|
+
def process_colon2(sexp, level)
|
1378
1404
|
base = sexp[0]
|
1379
1405
|
name = sexp[1]
|
1380
|
-
"
|
1406
|
+
"(%s)._scope.%s" % [process(base, :expr), name.to_s]
|
1381
1407
|
end
|
1382
1408
|
|
1383
|
-
def
|
1384
|
-
"
|
1409
|
+
def process_colon3(exp, level)
|
1410
|
+
"__opal.Object._scope.#{exp.shift.to_s}"
|
1385
1411
|
end
|
1386
1412
|
|
1387
1413
|
# super a, b, c
|
1388
1414
|
#
|
1389
1415
|
# s(:super, arg1, arg2, ...)
|
1390
|
-
def
|
1416
|
+
def process_super(sexp, level)
|
1391
1417
|
args = []
|
1392
1418
|
until sexp.empty?
|
1393
|
-
args << process(sexp.shift, :
|
1419
|
+
args << process(sexp.shift, :expr)
|
1394
1420
|
end
|
1395
1421
|
|
1396
|
-
# args.unshift 'null'
|
1397
|
-
|
1398
1422
|
js_super "[#{ args.join ', ' }]"
|
1399
1423
|
end
|
1400
1424
|
|
1401
1425
|
# super
|
1402
1426
|
#
|
1403
1427
|
# s(:zsuper)
|
1404
|
-
def
|
1405
|
-
|
1428
|
+
def process_zsuper(exp, level)
|
1406
1429
|
js_super "__slice.call(arguments)"
|
1407
1430
|
end
|
1408
1431
|
|
1409
1432
|
def js_super args
|
1410
1433
|
if @scope.type == :def
|
1411
|
-
mid = @scope.mid
|
1412
1434
|
identity = @scope.identify!
|
1413
|
-
|
1435
|
+
|
1436
|
+
# FIXME: only use `._proto` when inside normal def. remove it
|
1437
|
+
# for `def self.foo`.
|
1438
|
+
"__class._super._proto.#{@scope.mid}.apply(this, #{args})"
|
1414
1439
|
|
1415
1440
|
elsif @scope.type == :iter
|
1416
1441
|
chain, defn, mid = @scope.get_super_chain
|
1417
|
-
|
1442
|
+
trys = chain.map { |c| "#{c}._jsid" }.join ' || '
|
1443
|
+
"this._klass._super._proto[#{trys} || #{mid}].apply(this, #{args})"
|
1418
1444
|
|
1419
1445
|
else
|
1420
1446
|
raise "Cannot call super() from outside a method block"
|
@@ -1424,19 +1450,19 @@ module Opal
|
|
1424
1450
|
# a ||= rhs
|
1425
1451
|
#
|
1426
1452
|
# s(:op_asgn_or, s(:lvar, :a), s(:lasgn, :a, rhs))
|
1427
|
-
def
|
1428
|
-
process s(:or, exp.shift, exp.shift), :
|
1453
|
+
def process_op_asgn_or(exp, level)
|
1454
|
+
process s(:or, exp.shift, exp.shift), :expr
|
1429
1455
|
end
|
1430
1456
|
|
1431
|
-
def
|
1457
|
+
def process_op_asgn1(sexp, level)
|
1432
1458
|
"'FIXME(op_asgn1)'"
|
1433
1459
|
end
|
1434
1460
|
|
1435
1461
|
# lhs.b += rhs
|
1436
1462
|
#
|
1437
1463
|
# s(:op_asgn2, lhs, :b=, :+, rhs)
|
1438
|
-
def
|
1439
|
-
lhs = process exp.shift, :
|
1464
|
+
def process_op_asgn2(exp, level)
|
1465
|
+
lhs = process exp.shift, :expr
|
1440
1466
|
mid = exp.shift.to_s[0..-2]
|
1441
1467
|
op = exp.shift
|
1442
1468
|
rhs = exp.shift
|
@@ -1449,16 +1475,16 @@ module Opal
|
|
1449
1475
|
oper = s(:call, getr, op, s(:arglist, rhs))
|
1450
1476
|
asgn = s(:call, s(:js_tmp, temp), "#{mid}=", s(:arglist, oper))
|
1451
1477
|
|
1452
|
-
"(#{temp} = #{lhs}, #{process asgn, :
|
1478
|
+
"(#{temp} = #{lhs}, #{process asgn, :expr})".tap {
|
1453
1479
|
@scope.queue_temp temp
|
1454
1480
|
}
|
1455
1481
|
end
|
1456
1482
|
end
|
1457
1483
|
|
1458
1484
|
# s(:ensure, body, ensure)
|
1459
|
-
def
|
1485
|
+
def process_ensure(exp, level)
|
1460
1486
|
begn = exp.shift
|
1461
|
-
if level == :
|
1487
|
+
if level == :recv || level == :expr
|
1462
1488
|
retn = true
|
1463
1489
|
begn = returns begn
|
1464
1490
|
end
|
@@ -1473,7 +1499,7 @@ module Opal
|
|
1473
1499
|
res
|
1474
1500
|
end
|
1475
1501
|
|
1476
|
-
def
|
1502
|
+
def process_rescue(exp, level)
|
1477
1503
|
body = exp.first.first == :resbody ? s(:nil) : exp.shift
|
1478
1504
|
body = process body, level
|
1479
1505
|
|
@@ -1486,13 +1512,13 @@ module Opal
|
|
1486
1512
|
# if no rescue statement captures our error, we should rethrow
|
1487
1513
|
parts << "else { throw $err; }"
|
1488
1514
|
|
1489
|
-
code = "try {\n#{body}\n} catch ($err) {\n#{parts.join "\n"}\n}"
|
1490
|
-
code = "(function() { #{code} }).call(this)" if level == :
|
1515
|
+
code = "try {\n#@indent#{body}\n#@indent} catch ($err) {\n#@indent#{parts.join "\n"}\n}"
|
1516
|
+
code = "(function() { #{code} }).call(this)" if level == :expr
|
1491
1517
|
|
1492
1518
|
code
|
1493
1519
|
end
|
1494
1520
|
|
1495
|
-
def
|
1521
|
+
def process_resbody(exp, level)
|
1496
1522
|
args = exp[0]
|
1497
1523
|
body = exp[1]
|
1498
1524
|
body = process(body || s(:nil), level)
|
@@ -1500,7 +1526,7 @@ module Opal
|
|
1500
1526
|
|
1501
1527
|
err = types.map { |t|
|
1502
1528
|
call = s(:call, t, :===, s(:arglist, s(:js_tmp, "$err")))
|
1503
|
-
a = process call, :
|
1529
|
+
a = process call, :expr
|
1504
1530
|
#puts a
|
1505
1531
|
a
|
1506
1532
|
}.join ', '
|
@@ -1509,7 +1535,7 @@ module Opal
|
|
1509
1535
|
if Array === args.last and [:lasgn, :iasgn].include? args.last.first
|
1510
1536
|
val = args.last
|
1511
1537
|
val[2] = s(:js_tmp, "$err")
|
1512
|
-
val = process(val, :
|
1538
|
+
val = process(val, :expr) + ";"
|
1513
1539
|
end
|
1514
1540
|
|
1515
1541
|
"if (#{err}) {\n#{val}#{body}}"
|
@@ -1517,12 +1543,12 @@ module Opal
|
|
1517
1543
|
end
|
1518
1544
|
|
1519
1545
|
# FIXME: Hack.. grammar should remove top level begin.
|
1520
|
-
def
|
1546
|
+
def process_begin(exp, level)
|
1521
1547
|
process exp[0], level
|
1522
1548
|
end
|
1523
1549
|
|
1524
|
-
def
|
1525
|
-
val = exp.empty? ? 'nil' : process(exp.shift, :
|
1550
|
+
def process_next(exp, level)
|
1551
|
+
val = exp.empty? ? 'nil' : process(exp.shift, :expr)
|
1526
1552
|
if in_while?
|
1527
1553
|
"continue;"
|
1528
1554
|
else
|
@@ -1530,7 +1556,7 @@ module Opal
|
|
1530
1556
|
end
|
1531
1557
|
end
|
1532
1558
|
|
1533
|
-
def
|
1559
|
+
def process_redo(exp, level)
|
1534
1560
|
if in_while?
|
1535
1561
|
@while_loop[:use_redo] = true
|
1536
1562
|
"#{@while_loop[:redo_var]} = true"
|
@@ -1539,4 +1565,4 @@ module Opal
|
|
1539
1565
|
end
|
1540
1566
|
end
|
1541
1567
|
end
|
1542
|
-
end
|
1568
|
+
end
|