ParseTree 2.2.0 → 3.0.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/.autotest +16 -0
- data/History.txt +48 -0
- data/Manifest.txt +3 -6
- data/Rakefile +8 -5
- data/lib/parse_tree.rb +67 -11
- data/lib/parse_tree_extensions.rb +69 -0
- data/lib/unified_ruby.rb +170 -42
- data/test/pt_testcase.rb +4240 -2399
- data/test/test_parse_tree.rb +52 -20
- data/test/test_parse_tree_extensions.rb +39 -0
- data/test/test_unified_ruby.rb +292 -234
- metadata +20 -11
- data/lib/composite_sexp_processor.rb +0 -49
- data/lib/sexp.rb +0 -282
- data/lib/sexp_processor.rb +0 -336
- data/test/test_composite_sexp_processor.rb +0 -70
- data/test/test_sexp.rb +0 -313
- data/test/test_sexp_processor.rb +0 -297
data/.autotest
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'autotest/restart'
|
4
|
+
|
5
|
+
Autotest.add_hook :initialize do |at|
|
6
|
+
at.libs << ":../../sexp_processor/dev/lib"
|
7
|
+
at.extra_files << "test/pt_testcase.rb"
|
8
|
+
|
9
|
+
%w(TestRawParseTree).each do |klass|
|
10
|
+
at.extra_class_map[klass] = "test/test_parse_tree.rb"
|
11
|
+
end
|
12
|
+
|
13
|
+
at.add_mapping(/pt_testcase/) do |f, _|
|
14
|
+
at.files_matching(/test_.*rb$/)
|
15
|
+
end
|
16
|
+
end
|
data/History.txt
CHANGED
@@ -1,3 +1,51 @@
|
|
1
|
+
=== 3.0.0 / 2008-10-22
|
2
|
+
|
3
|
+
* 3 major enhancements:
|
4
|
+
|
5
|
+
* Split out sexp_processor project.
|
6
|
+
* ParseTree#process outputs a UnifiedRuby parse tree.
|
7
|
+
* Switched all ParseTree tests to RawParseTree tests.
|
8
|
+
* Added ParseTree tests.
|
9
|
+
* Added UnifiedRuby#process.
|
10
|
+
|
11
|
+
* 28 minor enhancements:
|
12
|
+
|
13
|
+
* PTTC: Added a comprehensive suite of tests for every combo of defn args.
|
14
|
+
* PTTC: Added a ton of new tests.
|
15
|
+
* PTTC: Added extra tests for mri verbose flag testing (horrid horrid bug imhfo)
|
16
|
+
* PTTC: Don't generate tests if class has "TestCase" in the class name.
|
17
|
+
* PTTC: Made self.previous more overridable.
|
18
|
+
* PTTC: Now all tests that have "mri_verbose_flag" activate $VERBOSE
|
19
|
+
* PTTC: Officially added clone_same phase to generate_tests
|
20
|
+
* PTTC: Refactored test generation to make subclasses more flexible.
|
21
|
+
* PTTC: Refactored to use new add_tests. Much much cleaner.
|
22
|
+
* PTTC: Removed Unique from PTTC... subclasses need to deal with this
|
23
|
+
* PTTC: Removed some stupid tests.
|
24
|
+
* PTTC: Renamed a bunch of tests to be more uniform.
|
25
|
+
* UR: Added rewrite_attrasgn to normalize arg array into arglist.
|
26
|
+
* UR: Added rewrite_op_asgn1 to ensure the arglist is an arglist.
|
27
|
+
* UR: Flattened resbodies in rescue node.
|
28
|
+
* UR: Flattened super and yield args yet, deal with array arg properly.
|
29
|
+
* UR: Handle yield(*ary) properly.
|
30
|
+
* UR: Nuked argspush.
|
31
|
+
* UR: Removed begin node from unified sexps.
|
32
|
+
* UR: Removed block from rewritten resbody if only 1 element.
|
33
|
+
* UR: Removed dasgn, dasgn_curr, and dvar nodes.
|
34
|
+
* UR: Removed s(:block_arg, :block) in favor of :"&block"
|
35
|
+
* UR: Rewrote argscat to be a splat inside an array.
|
36
|
+
* UR: Rewrote block_pass into arglist of inner call/super.
|
37
|
+
* UR: Rewrote call to ALWAYS have an argslist (no more splat as arglist).
|
38
|
+
* UR: Rewrote rewrite_resbody from scratch... MUUCH cleaner.
|
39
|
+
* UR: zarray -> array
|
40
|
+
* Used Hoe#add_include_dirs to clean up rakefile.
|
41
|
+
* Moved PT dependent code from ruby2ruby to here (eg Proc#to_sexp & friends).
|
42
|
+
|
43
|
+
* 2 bug fixes:
|
44
|
+
|
45
|
+
* UR: Fixed a bug with resbody that starts with an lasgn.
|
46
|
+
* UR: Fixed args for attrset
|
47
|
+
* Fixed export of symbols to work across platforms.
|
48
|
+
|
1
49
|
=== 2.2.0 / 2008-06-09
|
2
50
|
|
3
51
|
* 18 minor enhancements:
|
data/Manifest.txt
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
.autotest
|
1
2
|
History.txt
|
2
3
|
Manifest.txt
|
3
4
|
README.txt
|
@@ -7,18 +8,14 @@ bin/parse_tree_audit
|
|
7
8
|
bin/parse_tree_deps
|
8
9
|
bin/parse_tree_show
|
9
10
|
demo/printer.rb
|
10
|
-
lib/composite_sexp_processor.rb
|
11
11
|
lib/parse_tree.rb
|
12
|
-
lib/
|
13
|
-
lib/sexp_processor.rb
|
12
|
+
lib/parse_tree_extensions.rb
|
14
13
|
lib/unified_ruby.rb
|
15
14
|
lib/unique.rb
|
16
15
|
test/pt_testcase.rb
|
17
16
|
test/something.rb
|
18
17
|
test/test_all.rb
|
19
|
-
test/test_composite_sexp_processor.rb
|
20
18
|
test/test_parse_tree.rb
|
21
|
-
test/
|
22
|
-
test/test_sexp_processor.rb
|
19
|
+
test/test_parse_tree_extensions.rb
|
23
20
|
test/test_unified_ruby.rb
|
24
21
|
validate.sh
|
data/Rakefile
CHANGED
@@ -3,7 +3,11 @@
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'hoe'
|
5
5
|
|
6
|
-
|
6
|
+
Hoe.add_include_dirs("../../RubyInline/dev/lib",
|
7
|
+
"../../sexp_processor/dev/lib",
|
8
|
+
"../../ZenTest/dev/lib",
|
9
|
+
"lib")
|
10
|
+
|
7
11
|
require './lib/parse_tree.rb'
|
8
12
|
|
9
13
|
Hoe.new("ParseTree", ParseTree::VERSION) do |pt|
|
@@ -12,14 +16,13 @@ Hoe.new("ParseTree", ParseTree::VERSION) do |pt|
|
|
12
16
|
pt.developer('Ryan Davis', 'ryand-ruby@zenspider.com')
|
13
17
|
|
14
18
|
pt.clean_globs << File.expand_path("~/.ruby_inline")
|
15
|
-
pt.extra_deps << ['RubyInline',
|
19
|
+
pt.extra_deps << ['RubyInline', '>= 3.7.0']
|
20
|
+
pt.extra_deps << ['SexpProcessor', '>= 3.0.0']
|
16
21
|
pt.spec_extras[:require_paths] = proc { |paths| paths << 'test' }
|
17
22
|
|
18
|
-
pt.multiruby_skip << "
|
23
|
+
pt.multiruby_skip << "mri_rel_1_9" << "rubinius" << "mri_trunk"
|
19
24
|
end
|
20
25
|
|
21
|
-
Hoe::RUBY_FLAGS.sub! /-I/, '-I../../RubyInline/dev/lib:test:'
|
22
|
-
|
23
26
|
desc 'Run in gdb'
|
24
27
|
task :debug do
|
25
28
|
puts "RUN: r -d #{Hoe::RUBY_FLAGS} test/test_all.rb #{Hoe::FILTER}"
|
data/lib/parse_tree.rb
CHANGED
@@ -7,6 +7,7 @@ raise LoadError, "ParseTree isn't needed with rubinius" if
|
|
7
7
|
|
8
8
|
require 'rubygems'
|
9
9
|
require 'inline'
|
10
|
+
require 'unified_ruby'
|
10
11
|
|
11
12
|
class Module
|
12
13
|
def modules
|
@@ -40,9 +41,9 @@ end
|
|
40
41
|
# [:args],
|
41
42
|
# [:return, [:call, [:lit, 1], "+", [:array, [:lit, 1]]]]]]]]]
|
42
43
|
|
43
|
-
class
|
44
|
+
class RawParseTree
|
44
45
|
|
45
|
-
VERSION = '
|
46
|
+
VERSION = '3.0.0'
|
46
47
|
|
47
48
|
##
|
48
49
|
# Front end translation method.
|
@@ -288,7 +289,7 @@ class ParseTree
|
|
288
289
|
# 1) Get me a login on your box so I can repro this and get it fixed.
|
289
290
|
# 2) Fix it and send me the patch
|
290
291
|
# 3) (quick, but dirty and bad), comment out the following line:
|
291
|
-
builder.add_compile_flags "-Werror"
|
292
|
+
builder.add_compile_flags "-Werror" unless RUBY_PLATFORM =~ /mswin/
|
292
293
|
|
293
294
|
builder.prefix %{
|
294
295
|
#define nd_3rd u3.node
|
@@ -350,7 +351,7 @@ void add_to_parse_tree(VALUE self, VALUE ary, NODE * n, ID * locals) {
|
|
350
351
|
static int masgn_level = 0;
|
351
352
|
|
352
353
|
if (NIL_P(node_names)) {
|
353
|
-
node_names = rb_const_get_at(rb_path2class("
|
354
|
+
node_names = rb_const_get_at(rb_path2class("RawParseTree"),rb_intern("NODE_NAMES"));
|
354
355
|
}
|
355
356
|
|
356
357
|
if (!node) return;
|
@@ -508,15 +509,27 @@ again:
|
|
508
509
|
|
509
510
|
case NODE_BREAK:
|
510
511
|
case NODE_NEXT:
|
512
|
+
if (node->nd_stts)
|
513
|
+
add_to_parse_tree(self, current, node->nd_stts, locals);
|
514
|
+
|
515
|
+
break;
|
516
|
+
|
511
517
|
case NODE_YIELD:
|
512
518
|
if (node->nd_stts)
|
513
519
|
add_to_parse_tree(self, current, node->nd_stts, locals);
|
520
|
+
|
521
|
+
if (node->nd_stts
|
522
|
+
&& (nd_type(node->nd_stts) == NODE_ARRAY
|
523
|
+
|| nd_type(node->nd_stts) == NODE_ZARRAY)
|
524
|
+
&& !node->nd_state)
|
525
|
+
rb_ary_push(current, Qtrue);
|
526
|
+
|
514
527
|
break;
|
515
528
|
|
516
529
|
case NODE_RESCUE:
|
517
|
-
|
518
|
-
|
519
|
-
|
530
|
+
add_to_parse_tree(self, current, node->nd_1st, locals);
|
531
|
+
add_to_parse_tree(self, current, node->nd_2nd, locals);
|
532
|
+
add_to_parse_tree(self, current, node->nd_3rd, locals);
|
520
533
|
break;
|
521
534
|
|
522
535
|
/*
|
@@ -665,15 +678,25 @@ again:
|
|
665
678
|
|
666
679
|
case NODE_MASGN:
|
667
680
|
masgn_level++;
|
668
|
-
|
681
|
+
if (node->nd_head) {
|
682
|
+
add_to_parse_tree(self, current, node->nd_head, locals);
|
683
|
+
} else {
|
684
|
+
rb_ary_push(current, Qnil);
|
685
|
+
}
|
669
686
|
if (node->nd_args) {
|
670
687
|
if (node->nd_args != (NODE *)-1) {
|
671
688
|
add_to_parse_tree(self, current, node->nd_args, locals);
|
672
689
|
} else {
|
673
690
|
rb_ary_push(current, wrap_into_node("splat", 0));
|
674
691
|
}
|
692
|
+
} else {
|
693
|
+
rb_ary_push(current, Qnil);
|
694
|
+
}
|
695
|
+
if (node->nd_value) {
|
696
|
+
add_to_parse_tree(self, current, node->nd_value, locals);
|
697
|
+
} else {
|
698
|
+
rb_ary_push(current, Qnil);
|
675
699
|
}
|
676
|
-
add_to_parse_tree(self, current, node->nd_value, locals);
|
677
700
|
masgn_level--;
|
678
701
|
break;
|
679
702
|
|
@@ -1051,9 +1074,12 @@ static VALUE parse_tree_for_meth(VALUE klass, VALUE method, VALUE is_cls_meth) {
|
|
1051
1074
|
}
|
1052
1075
|
}
|
1053
1076
|
|
1054
|
-
|
1077
|
+
extern_mode = RUBY_PLATFORM =~ /mswin/ ? 'RUBY_EXTERN' : 'extern'
|
1078
|
+
builder.prefix " #{extern_mode} NODE *ruby_eval_tree_begin; " \
|
1055
1079
|
if RUBY_VERSION < '1.9.0'
|
1056
1080
|
|
1081
|
+
# FIXME: ruby_in_eval is not properly exported across platforms
|
1082
|
+
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/13558
|
1057
1083
|
builder.c %Q{
|
1058
1084
|
static VALUE parse_tree_for_str(VALUE source, VALUE filename, VALUE line) {
|
1059
1085
|
VALUE tmp;
|
@@ -1094,4 +1120,34 @@ static VALUE parse_tree_for_str(VALUE source, VALUE filename, VALUE line) {
|
|
1094
1120
|
}
|
1095
1121
|
|
1096
1122
|
end # inline call
|
1097
|
-
end #
|
1123
|
+
end # RawParseTree class
|
1124
|
+
|
1125
|
+
class ParseTree < RawParseTree
|
1126
|
+
##
|
1127
|
+
# Initializes a ParseTree instance. Includes newline nodes if
|
1128
|
+
# +include_newlines+ which defaults to +$DEBUG+.
|
1129
|
+
|
1130
|
+
def initialize(include_newlines=$DEBUG)
|
1131
|
+
super
|
1132
|
+
@unifier = Unifier.new
|
1133
|
+
end
|
1134
|
+
|
1135
|
+
##
|
1136
|
+
# Main driver for ParseTree. Returns a Sexp instance containing the
|
1137
|
+
# AST representing the input given. This is a UnifiedRuby sexp, not
|
1138
|
+
# a raw sexp from ruby. If you want raw, use the old
|
1139
|
+
# parse_tree_for_xxx methods... Please tell me if/why you want raw,
|
1140
|
+
# I'd like to know so I can justify keeping the code around.
|
1141
|
+
|
1142
|
+
def process(input, verbose = nil, file = "(string)", line = -1)
|
1143
|
+
case input
|
1144
|
+
when Array then
|
1145
|
+
@unifier.process(input)
|
1146
|
+
when String then
|
1147
|
+
pt = self.parse_tree_for_string(input, file, line, verbose).first
|
1148
|
+
@unifier.process(pt)
|
1149
|
+
else
|
1150
|
+
raise ArgumentError, "Unknown input type #{input.inspect}"
|
1151
|
+
end
|
1152
|
+
end
|
1153
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class Method
|
2
|
+
def with_class_and_method_name
|
3
|
+
if self.inspect =~ /<Method: (.*)\#(.*)>/ then
|
4
|
+
klass = eval $1
|
5
|
+
method = $2.intern
|
6
|
+
raise "Couldn't determine class from #{self.inspect}" if klass.nil?
|
7
|
+
return yield(klass, method)
|
8
|
+
else
|
9
|
+
raise "Can't parse signature: #{self.inspect}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_sexp
|
14
|
+
require 'parse_tree'
|
15
|
+
require 'unified_ruby'
|
16
|
+
parser = ParseTree.new(false)
|
17
|
+
unifier = Unifier.new
|
18
|
+
with_class_and_method_name do |klass, method|
|
19
|
+
old_sexp = parser.parse_tree_for_method(klass, method)
|
20
|
+
unifier.process(old_sexp) # HACK
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_ruby
|
25
|
+
sexp = self.to_sexp
|
26
|
+
Ruby2Ruby.new.process sexp
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class ProcStoreTmp
|
31
|
+
@@n = 0
|
32
|
+
def self.new_name
|
33
|
+
@@n += 1
|
34
|
+
return :"myproc#{@@n}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class UnboundMethod
|
39
|
+
def to_ruby
|
40
|
+
name = ProcStoreTmp.new_name
|
41
|
+
ProcStoreTmp.send(:define_method, name, self)
|
42
|
+
m = ProcStoreTmp.new.method(name)
|
43
|
+
result = m.to_ruby.sub(/def #{name}(?:\(([^\)]*)\))?/,
|
44
|
+
'proc { |\1|').sub(/end\Z/, '}')
|
45
|
+
return result
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Proc
|
50
|
+
def to_method
|
51
|
+
name = ProcStoreTmp.new_name
|
52
|
+
ProcStoreTmp.send(:define_method, name, self)
|
53
|
+
ProcStoreTmp.new.method(name)
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_sexp
|
57
|
+
sexp = self.to_method.to_sexp
|
58
|
+
body = sexp.scope.block
|
59
|
+
args = sexp.args
|
60
|
+
args = nil if args.size == 1
|
61
|
+
body = body[1] if body.size == 2
|
62
|
+
|
63
|
+
s(:iter, s(:call, nil, :proc, s(:arglist)), args, body)
|
64
|
+
end
|
65
|
+
|
66
|
+
def to_ruby
|
67
|
+
Ruby2Ruby.new.process(self.to_sexp).sub(/^\Aproc do/, 'proc {').sub(/end\Z/, '}')
|
68
|
+
end
|
69
|
+
end
|
data/lib/unified_ruby.rb
CHANGED
@@ -1,17 +1,37 @@
|
|
1
|
+
require 'sexp_processor'
|
1
2
|
|
2
3
|
$TESTING ||= false
|
3
4
|
|
4
5
|
module UnifiedRuby
|
6
|
+
def process exp
|
7
|
+
exp = Sexp.from_array exp unless Sexp === exp or exp.nil?
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def rewrite_attrasgn(exp)
|
12
|
+
last = exp.last
|
13
|
+
|
14
|
+
if Sexp === last then
|
15
|
+
last[0] = :arglist if last[0] == :array
|
16
|
+
else
|
17
|
+
exp << s(:arglist)
|
18
|
+
end
|
19
|
+
|
20
|
+
exp
|
21
|
+
end
|
22
|
+
|
5
23
|
def rewrite_bmethod(exp)
|
6
24
|
exp[0] = :scope
|
7
25
|
|
26
|
+
has_splat = exp.masgn.array.splat.lasgn rescue false
|
27
|
+
|
8
28
|
args =
|
9
|
-
if
|
10
|
-
arg = exp.masgn(true).
|
29
|
+
if has_splat then
|
30
|
+
arg = exp.masgn(true).array.splat.lasgn.sexp_body
|
11
31
|
raise "nope: #{arg.size}" unless arg.size == 1
|
12
32
|
s(:args, :"*#{arg.last}")
|
13
33
|
else
|
14
|
-
args = exp.
|
34
|
+
args = exp.lasgn(true)
|
15
35
|
if args then
|
16
36
|
s(:args, *args.sexp_body)
|
17
37
|
else
|
@@ -27,6 +47,35 @@ module UnifiedRuby
|
|
27
47
|
exp
|
28
48
|
end
|
29
49
|
|
50
|
+
def rewrite_argscat exp
|
51
|
+
_, ary, val = exp
|
52
|
+
ary = s(:array, ary) unless ary.first == :array
|
53
|
+
ary << s(:splat, val)
|
54
|
+
end
|
55
|
+
|
56
|
+
def rewrite_argspush exp
|
57
|
+
exp[0] = :arglist
|
58
|
+
exp
|
59
|
+
end
|
60
|
+
|
61
|
+
def rewrite_block_pass exp
|
62
|
+
if exp.size == 3 then
|
63
|
+
_, block, recv = exp
|
64
|
+
case recv.first
|
65
|
+
when :super then
|
66
|
+
recv << s(:block_pass, block)
|
67
|
+
exp = recv
|
68
|
+
when :call then
|
69
|
+
recv.last << s(:block_pass, block)
|
70
|
+
exp = recv
|
71
|
+
else
|
72
|
+
raise "huh?: #{recv.inspect}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
exp
|
77
|
+
end
|
78
|
+
|
30
79
|
def rewrite_call(exp)
|
31
80
|
args = exp.last
|
32
81
|
case args
|
@@ -37,7 +86,7 @@ module UnifiedRuby
|
|
37
86
|
when :array, :arglist then
|
38
87
|
args[0] = :arglist
|
39
88
|
when :argscat, :splat then
|
40
|
-
|
89
|
+
exp[-1] = s(:arglist, args)
|
41
90
|
else
|
42
91
|
raise "unknown type in call #{args.first.inspect} in #{exp.inspect}"
|
43
92
|
end
|
@@ -49,6 +98,13 @@ module UnifiedRuby
|
|
49
98
|
exp
|
50
99
|
end
|
51
100
|
|
101
|
+
def rewrite_dasgn(exp)
|
102
|
+
exp[0] = :lasgn
|
103
|
+
exp
|
104
|
+
end
|
105
|
+
|
106
|
+
alias :rewrite_dasgn_curr :rewrite_dasgn
|
107
|
+
|
52
108
|
##
|
53
109
|
# :defn is one of the most complex of all the ASTs in ruby. We do
|
54
110
|
# one of 3 different translations:
|
@@ -91,10 +147,23 @@ module UnifiedRuby
|
|
91
147
|
|
92
148
|
# move block_arg up and in
|
93
149
|
block_arg = exp.scope.block.block_arg(true) rescue nil
|
94
|
-
|
150
|
+
if block_arg
|
151
|
+
block = args.block(true)
|
152
|
+
args << :"&#{block_arg.last}"
|
153
|
+
args << block if block
|
154
|
+
end
|
95
155
|
|
96
156
|
# patch up attr_accessor methods
|
97
|
-
|
157
|
+
if weirdo then
|
158
|
+
case
|
159
|
+
when exp.ivar then
|
160
|
+
exp.insert 2, s(:args)
|
161
|
+
when exp.attrset then
|
162
|
+
exp.insert 2, s(:args, :arg)
|
163
|
+
else
|
164
|
+
raise "unknown wierdo: #{wierdo.inpsect}"
|
165
|
+
end
|
166
|
+
end
|
98
167
|
|
99
168
|
exp
|
100
169
|
end
|
@@ -119,6 +188,11 @@ module UnifiedRuby
|
|
119
188
|
exp.shift # scope / block / body
|
120
189
|
end
|
121
190
|
|
191
|
+
def rewrite_dvar(exp)
|
192
|
+
exp[0] = :lvar
|
193
|
+
exp
|
194
|
+
end
|
195
|
+
|
122
196
|
def rewrite_fcall(exp)
|
123
197
|
exp[0] = :call
|
124
198
|
exp.insert 1, nil
|
@@ -127,55 +201,105 @@ module UnifiedRuby
|
|
127
201
|
rewrite_call(exp)
|
128
202
|
end
|
129
203
|
|
130
|
-
def
|
131
|
-
|
204
|
+
def rewrite_masgn(exp)
|
205
|
+
raise "wtf: #{exp}" unless exp.size == 4
|
132
206
|
|
133
|
-
|
134
|
-
while exp and exp.first == :resbody do
|
135
|
-
code << exp.shift
|
136
|
-
list = exp.shift || s(:array)
|
137
|
-
body = exp.empty? ? nil : exp.shift
|
138
|
-
exp = exp.empty? ? nil : exp.shift
|
207
|
+
t, lhs, lhs_splat, rhs = exp
|
139
208
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
list << body
|
147
|
-
body = nil
|
148
|
-
when :block then
|
149
|
-
# TODO: check that it is assigning $!
|
150
|
-
list << body.delete_at(1) if body[1].first == :lasgn
|
151
|
-
else
|
152
|
-
# do nothing (expression form)
|
153
|
-
end if body
|
209
|
+
lhs ||= s(:array)
|
210
|
+
|
211
|
+
if lhs_splat then
|
212
|
+
lhs_splat = s(:splat, lhs_splat) unless lhs_splat[0] == :splat
|
213
|
+
lhs << lhs_splat
|
214
|
+
end
|
154
215
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
216
|
+
s(t, lhs, rhs).compact
|
217
|
+
end
|
218
|
+
|
219
|
+
def rewrite_op_asgn1(exp)
|
220
|
+
exp[2][0] = :arglist # if exp[2][0] == :array
|
221
|
+
exp
|
222
|
+
end
|
223
|
+
|
224
|
+
def rewrite_rescue(exp)
|
225
|
+
# SKETCHY HACK return exp if exp.size > 4
|
226
|
+
ignored = exp.shift
|
227
|
+
body = exp.shift unless exp.first.first == :resbody
|
228
|
+
resbody = exp.shift
|
229
|
+
els = exp.shift unless exp.first.first == :resbody unless exp.empty?
|
230
|
+
rest = exp.empty? ? nil : exp # graceful re-rewriting (see rewrite_begin)
|
231
|
+
|
232
|
+
resbodies = []
|
233
|
+
|
234
|
+
unless rest then
|
235
|
+
while resbody do
|
236
|
+
resbodies << resbody
|
237
|
+
resbody = resbody.resbody(true)
|
238
|
+
end
|
239
|
+
|
240
|
+
resbodies.each do |resbody|
|
241
|
+
if resbody[2] && resbody[2][0] == :block && resbody[2].size == 2 then
|
242
|
+
resbody[2] = resbody[2][-1]
|
243
|
+
end
|
159
244
|
end
|
245
|
+
else
|
246
|
+
resbodies = [resbody] + rest
|
160
247
|
end
|
161
248
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
249
|
+
resbodies << els if els
|
250
|
+
|
251
|
+
s(:rescue, body, *resbodies).compact
|
252
|
+
end
|
253
|
+
|
254
|
+
def rewrite_resbody(exp)
|
255
|
+
exp[1] ||= s(:array) # no args
|
256
|
+
|
257
|
+
body = exp[2]
|
258
|
+
if body then
|
259
|
+
case body.first
|
260
|
+
when :lasgn, :iasgn then
|
261
|
+
exp[1] << exp.delete_at(2) if body[-1] == s(:gvar, :$!)
|
262
|
+
when :block then
|
263
|
+
exp[1] << body.delete_at(1) if [:lasgn, :iasgn].include?(body[1][0]) &&
|
264
|
+
body[1][-1] == s(:gvar, :$!)
|
265
|
+
end
|
170
266
|
end
|
171
267
|
|
172
|
-
|
268
|
+
exp << nil if exp.size == 2 # no body
|
269
|
+
|
270
|
+
exp
|
271
|
+
end
|
272
|
+
|
273
|
+
def rewrite_begin(exp)
|
274
|
+
raise "wtf: #{exp.inspect}" if exp.size > 2
|
275
|
+
exp.last
|
173
276
|
end
|
174
277
|
|
175
278
|
def rewrite_vcall(exp)
|
176
279
|
exp.push nil
|
177
280
|
rewrite_fcall(exp)
|
178
281
|
end
|
282
|
+
|
283
|
+
def rewrite_yield(exp)
|
284
|
+
# Literal array in yield, not args.
|
285
|
+
if exp.size == 3 and exp.pop == true then
|
286
|
+
# exp[1] = s(:arglist, exp[1])
|
287
|
+
elsif exp.size == 2 && exp.last.first == :array then
|
288
|
+
exp.push(*exp.pop[1..-1])
|
289
|
+
end
|
290
|
+
|
291
|
+
exp
|
292
|
+
end
|
293
|
+
|
294
|
+
def rewrite_super(exp)
|
295
|
+
exp.push(*exp.pop[1..-1]) if exp.size == 2 && exp.last.first == :array
|
296
|
+
exp
|
297
|
+
end
|
298
|
+
|
299
|
+
def rewrite_zarray(exp)
|
300
|
+
exp[0] = :array
|
301
|
+
exp
|
302
|
+
end
|
179
303
|
end
|
180
304
|
|
181
305
|
##
|
@@ -183,5 +307,9 @@ end
|
|
183
307
|
|
184
308
|
class Unifier < SexpProcessor
|
185
309
|
include UnifiedRuby
|
186
|
-
end
|
187
310
|
|
311
|
+
def initialize
|
312
|
+
super
|
313
|
+
@unsupported.delete :newline
|
314
|
+
end
|
315
|
+
end
|