virtual_keywords 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. data/lib/parsetree/History.txt +477 -0
  2. data/lib/parsetree/Manifest.txt +19 -0
  3. data/lib/parsetree/README.txt +97 -0
  4. data/lib/parsetree/Rakefile +37 -0
  5. data/lib/parsetree/bin/parse_tree_abc +89 -0
  6. data/lib/parsetree/bin/parse_tree_audit +28 -0
  7. data/lib/parsetree/bin/parse_tree_deps +62 -0
  8. data/lib/parsetree/bin/parse_tree_show +63 -0
  9. data/lib/parsetree/demo/printer.rb +20 -0
  10. data/lib/parsetree/lib/gauntlet_parsetree.rb +121 -0
  11. data/lib/parsetree/lib/parse_tree.rb +1202 -0
  12. data/lib/parsetree/lib/parse_tree_extensions.rb +59 -0
  13. data/lib/parsetree/lib/unified_ruby.rb +421 -0
  14. data/lib/parsetree/test/something.rb +53 -0
  15. data/lib/parsetree/test/test_parse_tree.rb +2567 -0
  16. data/lib/parsetree/test/test_parse_tree_extensions.rb +107 -0
  17. data/lib/parsetree/test/test_unified_ruby.rb +57 -0
  18. data/lib/parsetree/validate.sh +31 -0
  19. data/lib/sexps/{count_to_ten_sexp.txt → count_to_ten_sexp.rb} +0 -0
  20. data/lib/sexps/{sexps_and.txt → sexps_and.rb} +0 -0
  21. data/lib/sexps/{sexps_case_when.txt → sexps_case_when.rb} +0 -0
  22. data/lib/sexps/{sexps_greet.txt → sexps_greet.rb} +0 -0
  23. data/lib/sexps/sexps_not.rb +24 -0
  24. data/lib/sexps/{sexps_rewritten_keywords.txt → sexps_rewritten_keywords.rb} +0 -0
  25. data/lib/sexps/{sexps_symbolic_and.txt → sexps_symbolic_and.rb} +0 -0
  26. data/lib/sexps/sexps_until.rb +60 -0
  27. data/lib/sexps/{sexps_while.txt → sexps_while.rb} +0 -0
  28. data/lib/spec/class_reflection_spec.rb +64 -0
  29. data/lib/spec/keyword_rewriter_spec.rb +7 -54
  30. data/lib/spec/not_rewriter_spec.rb +25 -0
  31. data/lib/spec/parser_strategy_spec.rb +23 -0
  32. data/lib/spec/sexp_stringifier_spec.rb +19 -0
  33. data/lib/spec/spec_helper.rb +61 -307
  34. data/lib/spec/until_rewriter_spec.rb +26 -0
  35. data/lib/spec/virtualizees/and_user.rb +17 -0
  36. data/lib/spec/virtualizees/case_when_user.rb +20 -0
  37. data/lib/spec/virtualizees/fizzbuzzer.rb +15 -0
  38. data/lib/spec/virtualizees/greeter.rb +127 -0
  39. data/lib/spec/virtualizees/not_user.rb +9 -0
  40. data/lib/spec/virtualizees/operator_user.rb +15 -0
  41. data/lib/spec/virtualizees/or_user.rb +17 -0
  42. data/lib/spec/virtualizees/parents.rb +8 -0
  43. data/lib/spec/virtualizees/until_user.rb +16 -0
  44. data/lib/spec/virtualizees/while_user.rb +16 -0
  45. data/lib/spec/virtualizer_spec.rb +46 -83
  46. data/lib/virtual_keywords/class_reflection.rb +88 -0
  47. data/lib/virtual_keywords/deep_copy_array.rb +12 -0
  48. data/lib/virtual_keywords/keyword_rewriter.rb +54 -0
  49. data/lib/virtual_keywords/parser_strategy.rb +40 -0
  50. data/lib/virtual_keywords/rewritten_keywords.rb +15 -0
  51. data/lib/virtual_keywords/sexp_stringifier.rb +1 -5
  52. data/lib/virtual_keywords/version.rb +1 -1
  53. data/lib/virtual_keywords/virtualizer.rb +30 -115
  54. data/lib/virtual_keywords.rb +31 -5
  55. metadata +117 -90
  56. data/lib/spec/class_mirrorer_spec.rb +0 -18
  57. data/lib/virtual_keywords/class_mirrorer.rb +0 -39
@@ -0,0 +1,107 @@
1
+ require 'minitest/autorun'
2
+ require 'parse_tree'
3
+ require 'parse_tree_extensions'
4
+ require 'tmpdir'
5
+
6
+ $: << "../../ruby2ruby/1.3.1/lib" # unoffical dependency - user responsibility
7
+ require 'ruby2ruby'
8
+
9
+ class R2RTestCase < MiniTest::Unit::TestCase
10
+ def test_proc_to_ruby
11
+ util_setup_inline
12
+ block = proc { puts "something" }
13
+ assert_equal 'proc { puts("something") }', block.to_ruby
14
+ end
15
+
16
+ # TODO: bus error
17
+ # def test_proc_to_ruby_args_0
18
+ # util_setup_inline
19
+ # block = proc { || puts 42 }
20
+ # assert_equal 'proc { || puts(42) }', block.to_ruby
21
+ # end
22
+
23
+ def test_proc_to_ruby_args_1
24
+ util_setup_inline
25
+ block = proc { |x| puts x }
26
+ assert_equal 'proc { |x| puts(x) }', block.to_ruby
27
+ end
28
+
29
+ def test_proc_to_ruby_args_n
30
+ util_setup_inline
31
+ block = proc { |x| puts x }
32
+ assert_equal 'proc { |x| puts(x) }', block.to_ruby
33
+ end
34
+
35
+ def test_proc_to_sexp
36
+ util_setup_inline
37
+ p = proc { 1 + 1 }
38
+ s = s(:iter,
39
+ s(:call, nil, :proc, s(:arglist)),
40
+ nil,
41
+ s(:call, s(:lit, 1), :+, s(:arglist, s(:lit, 1))))
42
+ assert_equal s, p.to_sexp
43
+ end
44
+
45
+ # TODO: bus error
46
+ # def test_proc_to_sexp_args_0
47
+ # util_setup_inline
48
+ # p = proc { || 1 + 1 }
49
+ # s = s(:iter,
50
+ # s(:call, nil, :proc, s(:arglist)),
51
+ # nil,
52
+ # s(:call, s(:lit, 1), :+, s(:arglist, s(:lit, 1))))
53
+ # assert_equal s, p.to_sexp
54
+ # end
55
+
56
+ def test_proc_to_sexp_args_1
57
+ util_setup_inline
58
+ p = proc {|x| puts x }
59
+ s = s(:iter,
60
+ s(:call, nil, :proc, s(:arglist)),
61
+ s(:lasgn, :x),
62
+ s(:call, nil, :puts, s(:arglist, s(:lvar, :x))))
63
+
64
+ assert_equal s, p.to_sexp
65
+ end
66
+
67
+ def test_proc_to_sexp_args_n
68
+ util_setup_inline
69
+ p = proc {|x, y| puts x + y }
70
+ s = s(:iter,
71
+ s(:call, nil, :proc, s(:arglist)),
72
+ s(:masgn, s(:array, s(:lasgn, :x), s(:lasgn, :y))),
73
+ s(:call, nil, :puts,
74
+ s(:arglist, s(:call, s(:lvar, :x), :+, s(:arglist, s(:lvar, :y))))))
75
+
76
+ assert_equal s, p.to_sexp
77
+ end
78
+
79
+ def test_parse_tree_for_proc # TODO: move?
80
+ p = proc {|a, b, c|}
81
+ s = s(:iter,
82
+ s(:call, nil, :proc, s(:arglist)),
83
+ s(:masgn, s(:array, s(:lasgn, :a), s(:lasgn, :b), s(:lasgn, :c))))
84
+
85
+ pt = ParseTree.new(false)
86
+ u = Unifier.new
87
+ sexp = pt.parse_tree_for_proc p
88
+
89
+ sexp = u.process(sexp)
90
+
91
+ assert_equal s, sexp
92
+ end
93
+
94
+ def test_unbound_method_to_ruby
95
+ util_setup_inline
96
+ r = "proc { ||\n util_setup_inline\n p = proc { (1 + 1) }\n s = s(:iter, s(:call, nil, :proc, s(:arglist)), nil, s(:call, s(:lit, 1), :+, s(:arglist, s(:lit, 1))))\n assert_equal(s, p.to_sexp)\n}"
97
+ m = self.class.instance_method(:test_proc_to_sexp)
98
+
99
+ assert_equal r, m.to_ruby
100
+ end
101
+
102
+ def util_setup_inline
103
+ @rootdir = File.join(Dir.tmpdir, "test_ruby_to_ruby.#{$$}")
104
+ Dir.mkdir @rootdir, 0700 unless test ?d, @rootdir
105
+ ENV['INLINEDIR'] = @rootdir
106
+ end
107
+ end
@@ -0,0 +1,57 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ $TESTING = true
4
+
5
+ require 'minitest/autorun' if $0 == __FILE__ unless defined? $ZENTEST and $ZENTEST
6
+ require 'test/unit/testcase'
7
+ require 'sexp'
8
+ require 'sexp_processor'
9
+ require 'unified_ruby'
10
+
11
+ class TestUnifier < MiniTest::Unit::TestCase
12
+ def test_pre_fcall
13
+ u = PreUnifier.new
14
+
15
+ input = [:fcall, :block_given?]
16
+ expect = s(:fcall, :block_given?, s(:arglist))
17
+
18
+ assert_equal expect, u.process(input)
19
+
20
+ input = [:fcall, :m, [:array, [:lit, 42]]]
21
+ expect = s(:fcall, :m, s(:arglist, s(:lit, 42)))
22
+
23
+ assert_equal expect, u.process(input)
24
+ end
25
+
26
+ def test_pre_call
27
+ u = PreUnifier.new
28
+
29
+ input = [:call, [:self], :method]
30
+ expect = s(:call, s(:self), :method, s(:arglist))
31
+
32
+ assert_equal expect, u.process(input)
33
+
34
+ input = [:fcall, :m, [:array, [:lit, 42]]]
35
+ expect = s(:fcall, :m, s(:arglist, s(:lit, 42)))
36
+
37
+ assert_equal expect, u.process(input)
38
+ end
39
+
40
+ def test_process_bmethod
41
+ u = Unifier.new
42
+
43
+ raw = [:defn, :myproc3,
44
+ [:bmethod,
45
+ [:masgn, [:array,
46
+ [:dasgn_curr, :a],
47
+ [:dasgn_curr, :b],
48
+ [:dasgn_curr, :c]],
49
+ nil, nil]]]
50
+
51
+ s = s(:defn, :myproc3,
52
+ s(:args, :a, :b, :c),
53
+ s(:scope, s(:block)))
54
+
55
+ assert_equal s, u.process(raw)
56
+ end
57
+ end
@@ -0,0 +1,31 @@
1
+ #!/bin/bash
2
+
3
+ # set -xv
4
+
5
+ trap "exit 1" 1 2 3 15
6
+
7
+ DIRS="-I../../metaruby/dev/tests/builtin -I../../metaruby/dev/tests -Ilib"
8
+ for d in $(ls -d ../../*/dev); do
9
+ DIRS="-I$d $DIRS"
10
+ done
11
+
12
+ if [ -f rb.bad.txt ]; then
13
+ mv rb.bad.txt rb.files.txt
14
+ else
15
+ find ../../*/dev /usr/local/lib/ruby/1.8/ -name \*.rb > rb.files.txt
16
+ fi
17
+
18
+ total_count=$(wc -l rb.files.txt | awk '{print $1}')
19
+ curr_count=0
20
+ for f in $(cat rb.files.txt); do
21
+ curr_count=$(($curr_count + 1))
22
+ if GEM_SKIP=ParseTree ruby $DIRS ./bin/parse_tree_show -q $f > /dev/null 2> rb.err.txt < /dev/null; then
23
+ echo $f >> rb.good.txt
24
+ status=pass
25
+ else
26
+ echo $f >> rb.bad.txt
27
+ status=fail
28
+ fi
29
+ fname=`basename $f`
30
+ printf "%4d/%4d: %s %s\n" $curr_count $total_count $status $fname
31
+ done
File without changes
File without changes
@@ -0,0 +1,24 @@
1
+ # Before
2
+ s(:defn, :negate,
3
+ s(:scope,
4
+ s(:block, s(:args),
5
+ s(:not, s(:ivar, :@value))
6
+ )
7
+ )
8
+ )
9
+
10
+ # After
11
+ s(:defn, :negate_result,
12
+ s(:scope,
13
+ s(:block, s(:args),
14
+ s(:fcall, :my_not,
15
+ s(:array,
16
+ s(:iter,
17
+ s(:fcall, :lambda), nil,
18
+ s(:ivar, :@value)
19
+ )
20
+ )
21
+ )
22
+ )
23
+ )
24
+ )
@@ -0,0 +1,60 @@
1
+ # Before
2
+ s(:defn, :until_count_to_value,
3
+ s(:scope,
4
+ s(:block, s(:args),
5
+ s(:until,
6
+ # Condition
7
+ s(:call, s(:ivar, :@i), :>,
8
+ s(:array, s(:ivar, :@value))
9
+ ),
10
+ # Body
11
+ s(:block,
12
+ s(:call, s(:ivar, :@counts), :<<,
13
+ s(:array, s(:ivar, :@i))
14
+ ),
15
+ s(:iasgn, :@i,
16
+ s(:call, s(:ivar, :@i), :+,
17
+ s(:array, s(:lit, 1))
18
+ )
19
+ )
20
+ ),
21
+ # TODO Again, I'm not sure what this true is for
22
+ true
23
+ ),
24
+ s(:ivar, :@counts)
25
+ )
26
+ )
27
+ )
28
+
29
+ # After
30
+ s(:defn, :until_result,
31
+ s(:scope,
32
+ s(:block, s(:args),
33
+ s(:fcall, :my_until,
34
+ s(:array,
35
+ s(:iter,
36
+ s(:fcall, :lambda), nil,
37
+ # Condition
38
+ s(:call, s(:ivar, :@i), :>,
39
+ s(:array, s(:ivar, :@value))
40
+ )
41
+ ),
42
+ s(:iter,
43
+ s(:fcall, :lambda), nil,
44
+ # Body
45
+ s(:block,
46
+ s(:call, s(:ivar, :@counts), :<<,
47
+ s(:array, s(:ivar, :@i))
48
+ ),
49
+ s(:iasgn, :@i,
50
+ s(:call, s(:ivar, :@i), :+,
51
+ s(:array, s(:lit, 1)))
52
+ )
53
+ )
54
+ )
55
+ )
56
+ ),
57
+ s(:ivar, :@counts)
58
+ )
59
+ )
60
+ )
File without changes
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'ClassReflection' do
4
+ before :each do
5
+ class MyClass
6
+ def foo
7
+ :hello
8
+ end
9
+ end
10
+ @object = MyClass.new
11
+ @object2 = MyClass.new
12
+
13
+ @reflection = VirtualKeywords::ClassReflection.new
14
+ end
15
+
16
+ it 'retrieves the instance methods of a class' do
17
+ method_names = @reflection.instance_methods_of(Fizzbuzzer).keys
18
+ method_names.should include :fizzbuzz
19
+ end
20
+
21
+ it 'finds the subclasses of classes and flattens the result' do
22
+ rails_classes = [ActiveRecord::Base, ApplicationController]
23
+ subclasses = @reflection.subclasses_of_classes rails_classes
24
+
25
+ subclasses.should include Fizzbuzzer
26
+ subclasses.should include Greeter
27
+ end
28
+
29
+ it 'installs methods on classes' do
30
+ @reflection.install_method_on_class(MyClass, 'def foo; :goodbye; end')
31
+ @object.foo.should eql :goodbye
32
+ end
33
+
34
+ it 'installs methods that change instance fields' do
35
+ class MyClass
36
+ def foo
37
+ :hello
38
+ end
39
+ end
40
+ @reflection.install_method_on_class(
41
+ MyClass, 'def foo; @bar = :bar; :goodbye; end')
42
+ @reflection.install_method_on_class(
43
+ MyClass, 'def bar; @bar; end')
44
+
45
+ @object.foo.should eql :goodbye
46
+ @object.bar.should eql :bar
47
+ end
48
+
49
+ it 'installs methods that mutate globals' do
50
+ $thing = :old
51
+ @reflection.install_method_on_class(
52
+ MyClass, 'def foo; $thing = :new; end')
53
+
54
+ @object.foo
55
+ $thing.should eql :new
56
+ end
57
+
58
+ it 'installs methods on specific instances' do
59
+ @reflection.install_method_on_instance(
60
+ @object, 'def foo; :goodbye; end')
61
+ @object.foo.should eql :goodbye
62
+ @object2.foo.should eql :hello
63
+ end
64
+ end
@@ -2,60 +2,13 @@ require 'spec_helper'
2
2
 
3
3
  describe 'KeywordRewriter' do
4
4
  before :each do
5
- #@while_count_sexp = method_to_sexp(WhileUser, :while_count_to_value)
6
- #@while_result_sexp = method_to_sexp(WhileUser, :while_result)
5
+ #@not = method_to_sexp(NotUser, :negate)
6
+ #@not_result = method_to_sexp(NotUser, :negate_result)
7
7
  end
8
8
 
9
- # These two "specs" produce sexps that I used to figure out how
10
- # to do the rewrite. Their outputs are in sexps_greet.txt and
11
- # count_to_ten_sexp.txt
12
-
13
- #it 'compares sexps of manually translated if' do
14
- #puts 'before translation'
15
- #p @greet_if_else_sexp
16
- #puts ''
17
-
18
- #puts 'after translation'
19
- #p @greet_changed_sexp
20
- #puts ''
21
- #end
22
-
23
- #it 'turns a method with block code into a sexp' do
24
- #count_sexp = method_to_sexp(Greeter, :count_to_ten)
25
- #p count_sexp
26
- #end
27
-
28
- # Spec used to see how "and" should be translated
29
- #it 'compares sexps of manually translated and' do
30
- #puts 'before'
31
- #p @method_with_and_sexp
32
- #puts ''
33
-
34
- #puts 'after'
35
- #p @method_with_and_result_sexp
36
- #puts ''
37
- #end
38
-
39
- # Spec used to see how && should be translated
40
- # Looks like it uses :and same as the other one
41
- # Aren't they different semantically though?
42
- #it 'compares sexps of manually translated &&' do
43
- #puts 'before'
44
- #p @symbolic_and_sexp
45
- #puts ''
46
-
47
- #puts 'after'
48
- #p @symbolic_and_result_sexp
49
- #puts ''
50
- #end
51
-
52
- #it 'turns a case-when into a sexp' do
53
- #p @describe_value_sexp
54
- #end
55
-
56
- #it 'turns a while into a sexp' do
57
- #p @while_count_sexp
58
- #puts ''
59
- #p @while_result_sexp
60
- #end
9
+ it 'turns a not into a sexp' do
10
+ #p @not
11
+ #puts ""
12
+ #p @not_result
13
+ end
61
14
  end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'NotRewriter' do
4
+ include TrackNots, DoRewrite
5
+
6
+ before :each do
7
+ @not_user = NotUser.new true
8
+ @methods = sexpify_instance_methods NotUser
9
+ @not_rewriter = VirtualKeywords::NotRewriter.new
10
+
11
+ @my_not_calls = 0
12
+
13
+ VirtualKeywords::REWRITTEN_KEYWORDS.register_lambda_for_object(
14
+ @not_user, :not, my_not)
15
+ end
16
+
17
+ def rewriters
18
+ [@not_rewriter]
19
+ end
20
+
21
+ it 'rewrites "not" expressions' do
22
+ do_rewrite(:negate, @not_user)
23
+ @my_not_calls.should eql 1
24
+ end
25
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'ParseTreeStrategy' do
4
+ before :each do
5
+ @parse_tree = double 'ParseTree'
6
+ @sexp_processor = double 'SexpProcessor'
7
+
8
+ @strategy = VirtualKeywords::ParseTreeStrategy.new(
9
+ @parse_tree, @sexp_processor)
10
+ end
11
+
12
+ it 'runs the ParseTree parser, then converts the result into a sexp' do
13
+ klass = :foo
14
+ method_name = :bar
15
+ parse_result = :parsed
16
+ result = :sexp
17
+ @parse_tree.should_receive(:translate).with(klass, method_name).
18
+ and_return parse_result
19
+ @sexp_processor.should_receive(:process).with(parse_result).
20
+ and_return result
21
+ @strategy.translate_instance_method(klass, method_name).should eql result
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ describe 'SexpStringifier' do
2
+ before :each do
3
+ @stub_unifier = double 'Unifier'
4
+ @stub_ruby2ruby = double 'Ruby2Ruby'
5
+ @stringifier = VirtualKeywords::SexpStringifier.new(
6
+ @stub_unifier, @stub_ruby2ruby)
7
+ end
8
+
9
+ it 'stringifies sexps using unifier and ruby2ruby' do
10
+ sexp = :fake_sexp
11
+ unifier_result = :unified
12
+ final_result = :final
13
+ @stub_unifier.should_receive(:process).with(sexp).
14
+ and_return unifier_result
15
+ @stub_ruby2ruby.should_receive(:process).with(unifier_result).
16
+ and_return final_result
17
+ @stringifier.stringify(sexp).should eql final_result
18
+ end
19
+ end