live_ast 0.2.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/CHANGES.rdoc +6 -0
- data/MANIFEST +54 -0
- data/README.rdoc +388 -0
- data/Rakefile +19 -0
- data/devel/jumpstart.rb +983 -0
- data/lib/live_ast/ast_eval.rb +13 -0
- data/lib/live_ast/ast_load.rb +15 -0
- data/lib/live_ast/base.rb +56 -0
- data/lib/live_ast/cache.rb +14 -0
- data/lib/live_ast/error.rb +30 -0
- data/lib/live_ast/evaler.rb +66 -0
- data/lib/live_ast/linker.rb +107 -0
- data/lib/live_ast/loader.rb +69 -0
- data/lib/live_ast/parser.rb +48 -0
- data/lib/live_ast/replace_load.rb +14 -0
- data/lib/live_ast/replace_raise.rb +21 -0
- data/lib/live_ast/to_ast.rb +17 -0
- data/lib/live_ast/to_ruby.rb +12 -0
- data/lib/live_ast/version.rb +3 -0
- data/lib/live_ast.rb +4 -0
- data/test/ast_eval_feature_test.rb +11 -0
- data/test/ast_load_feature_test.rb +11 -0
- data/test/backtrace_test.rb +159 -0
- data/test/covert_define_method_test.rb +23 -0
- data/test/def_test.rb +35 -0
- data/test/define_method_test.rb +41 -0
- data/test/define_singleton_method_test.rb +15 -0
- data/test/encoding_test/bad.rb +1 -0
- data/test/encoding_test/cp932.rb +6 -0
- data/test/encoding_test/default.rb +5 -0
- data/test/encoding_test/eucjp.rb +6 -0
- data/test/encoding_test/koi8.rb +6 -0
- data/test/encoding_test/koi8_shebang.rb +7 -0
- data/test/encoding_test/usascii.rb +6 -0
- data/test/encoding_test/utf8.rb +6 -0
- data/test/encoding_test.rb +51 -0
- data/test/error_test.rb +115 -0
- data/test/eval_test.rb +269 -0
- data/test/flush_cache_test.rb +98 -0
- data/test/lambda_test.rb +56 -0
- data/test/load_path_test.rb +84 -0
- data/test/load_test.rb +85 -0
- data/test/noninvasive_test.rb +51 -0
- data/test/readme_test.rb +11 -0
- data/test/recursive_eval_test.rb +52 -0
- data/test/redefine_method_test.rb +83 -0
- data/test/reload_test.rb +108 -0
- data/test/shared/ast_generators.rb +124 -0
- data/test/shared/main.rb +110 -0
- data/test/stdlib_test.rb +11 -0
- data/test/thread_test.rb +44 -0
- data/test/to_ast_feature_test.rb +15 -0
- data/test/to_ruby_feature_test.rb +15 -0
- data/test/to_ruby_test.rb +86 -0
- metadata +223 -0
data/test/lambda_test.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
class LambdaTest < RegularTest
|
4
|
+
def test_block_braces_multiline
|
5
|
+
block = return_block { |x, y|
|
6
|
+
x + y
|
7
|
+
}
|
8
|
+
|
9
|
+
expected = binop_block(:return_block, :+)
|
10
|
+
assert_equal expected, block.to_ast
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_block_do_end_multiline
|
14
|
+
block = return_block do |x, y|
|
15
|
+
x * y
|
16
|
+
end
|
17
|
+
|
18
|
+
expected = binop_block(:return_block, :*)
|
19
|
+
assert_equal expected, block.to_ast
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_lambda
|
23
|
+
a = lambda { |x, y| x - y }
|
24
|
+
|
25
|
+
expected = binop_block(:lambda, :-)
|
26
|
+
assert_equal expected, a.to_ast
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_proc
|
30
|
+
a = proc { |x, y| x / y }
|
31
|
+
|
32
|
+
expected = binop_block(:proc, :/)
|
33
|
+
assert_equal expected, a.to_ast
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_proc_new
|
37
|
+
a = Proc.new { |x, y| x + y }
|
38
|
+
|
39
|
+
expected = binop_proc_new(:+)
|
40
|
+
assert_equal expected, a.to_ast
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_block_braces_one_line
|
44
|
+
block = return_block { |x, y| x * y }
|
45
|
+
|
46
|
+
expected = binop_block(:return_block, :*)
|
47
|
+
assert_equal expected, block.to_ast
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_block_do_end_one_line
|
51
|
+
block = return_block do |x, y| x - y end
|
52
|
+
|
53
|
+
expected = binop_block(:return_block, :-)
|
54
|
+
assert_equal expected, block.to_ast
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
class AAA_LoadPathTest < BaseTest
|
4
|
+
include FileUtils
|
5
|
+
|
6
|
+
def test_load_path
|
7
|
+
$LOAD_PATH.unshift DATA_DIR
|
8
|
+
begin
|
9
|
+
check_load
|
10
|
+
check_errors
|
11
|
+
temp_file "foo.rb" do
|
12
|
+
Dir.chdir(DATA_DIR) do
|
13
|
+
compare_load_errors("/foo.rb")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
ensure
|
17
|
+
$LOAD_PATH.shift
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_chdir
|
22
|
+
mkdir DATA_DIR, :verbose => false rescue nil
|
23
|
+
Dir.chdir(DATA_DIR) do
|
24
|
+
check_load
|
25
|
+
check_errors
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def check_load
|
30
|
+
code_1 = %{
|
31
|
+
def hello
|
32
|
+
"password"
|
33
|
+
end
|
34
|
+
}
|
35
|
+
|
36
|
+
code_2 = %{
|
37
|
+
def goodbye
|
38
|
+
"bubbleboy"
|
39
|
+
end
|
40
|
+
}
|
41
|
+
|
42
|
+
temp_file "foo.rb" do |path|
|
43
|
+
write_file(path, code_1)
|
44
|
+
|
45
|
+
Object.send(:remove_method, :hello) rescue nil
|
46
|
+
load "foo.rb"
|
47
|
+
assert_equal "password", hello
|
48
|
+
|
49
|
+
write_file path, code_2
|
50
|
+
|
51
|
+
Object.send(:remove_method, :goodbye) rescue nil
|
52
|
+
LiveAST.load "foo.rb"
|
53
|
+
assert_equal "bubbleboy", goodbye
|
54
|
+
end
|
55
|
+
ensure
|
56
|
+
Object.send(:remove_method, :hello) rescue nil
|
57
|
+
Object.send(:remove_method, :goodbye) rescue nil
|
58
|
+
end
|
59
|
+
|
60
|
+
def compare_load_errors(file)
|
61
|
+
orig = assert_raise LoadError do
|
62
|
+
load file
|
63
|
+
end
|
64
|
+
live = assert_raise LoadError do
|
65
|
+
LiveAST.load file
|
66
|
+
end
|
67
|
+
assert_equal orig.message, live.message
|
68
|
+
end
|
69
|
+
|
70
|
+
def check_errors
|
71
|
+
temp_file "foo.rb" do |path|
|
72
|
+
touch path, :verbose => false
|
73
|
+
[
|
74
|
+
"foo",
|
75
|
+
"",
|
76
|
+
"/usr",
|
77
|
+
".",
|
78
|
+
"..",
|
79
|
+
].each do |file|
|
80
|
+
compare_load_errors(file)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/test/load_test.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
class AAA_LoadFileTest < BaseTest
|
4
|
+
class << self
|
5
|
+
attr_accessor :flag
|
6
|
+
end
|
7
|
+
|
8
|
+
def test_a_no_locals_created
|
9
|
+
code = %{
|
10
|
+
AAA_LoadFileTest.flag = :code_a
|
11
|
+
FOO = 77
|
12
|
+
x = 33
|
13
|
+
y = 99
|
14
|
+
}
|
15
|
+
|
16
|
+
temp_file do |file|
|
17
|
+
write_file file, code
|
18
|
+
|
19
|
+
ret = LiveAST.load file
|
20
|
+
assert_equal true, ret
|
21
|
+
assert_equal :code_a, AAA_LoadFileTest.flag
|
22
|
+
|
23
|
+
assert_raise NameError do
|
24
|
+
eval("x", TOPLEVEL_BINDING)
|
25
|
+
end
|
26
|
+
|
27
|
+
assert_equal 77, ::FOO
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_b_no_locals_modified
|
32
|
+
code = %{
|
33
|
+
AAA_LoadFileTest.flag = :code_b
|
34
|
+
r = 55
|
35
|
+
}
|
36
|
+
|
37
|
+
temp_file do |file|
|
38
|
+
eval("r = 66", TOPLEVEL_BINDING)
|
39
|
+
|
40
|
+
write_file file, code
|
41
|
+
|
42
|
+
ret = LiveAST.load file
|
43
|
+
assert_equal true, ret
|
44
|
+
assert_equal :code_b, AAA_LoadFileTest.flag
|
45
|
+
|
46
|
+
actual = eval("r", TOPLEVEL_BINDING)
|
47
|
+
assert_equal 66, actual
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_c_wrap
|
52
|
+
code = %{
|
53
|
+
AAA_LoadFileTest.flag = :code_c
|
54
|
+
ZOOM = 111
|
55
|
+
}
|
56
|
+
|
57
|
+
temp_file do |file|
|
58
|
+
write_file file, code
|
59
|
+
|
60
|
+
ret = LiveAST.load file, true
|
61
|
+
assert_equal true, ret
|
62
|
+
assert_equal :code_c, AAA_LoadFileTest.flag
|
63
|
+
|
64
|
+
assert_raises NameError do
|
65
|
+
ZOOM
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.from_d
|
71
|
+
self.flag = :code_d
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_d_empty_locals_list
|
75
|
+
code = %{
|
76
|
+
AAA_LoadFileTest.from_d
|
77
|
+
}
|
78
|
+
|
79
|
+
temp_file do |file|
|
80
|
+
write_file file, code
|
81
|
+
LiveAST.load file
|
82
|
+
assert_equal :code_d, AAA_LoadFileTest.flag
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
class AAA_NoninvasiveTest < BaseTest
|
4
|
+
def test_no_clutter
|
5
|
+
[Method, UnboundMethod, Proc].each do |klass|
|
6
|
+
assert !klass.instance_methods.include?(:to_ast)
|
7
|
+
assert !klass.instance_methods.include?(:to_ruby)
|
8
|
+
end
|
9
|
+
|
10
|
+
assert !respond_to?(:ast_eval)
|
11
|
+
assert !Kernel.respond_to?(:ast_eval)
|
12
|
+
assert !respond_to?(:ast_load)
|
13
|
+
assert !Kernel.respond_to?(:ast_load)
|
14
|
+
end
|
15
|
+
|
16
|
+
DEFINE_A = lambda do
|
17
|
+
class A
|
18
|
+
def f
|
19
|
+
"A#f"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_method
|
25
|
+
DEFINE_A.call
|
26
|
+
|
27
|
+
expected = no_arg_def(:f, "A#f")
|
28
|
+
assert_equal expected, LiveAST.ast(A.instance_method(:f))
|
29
|
+
assert_equal expected, LiveAST.ast(A.new.method(:f))
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_lambda
|
33
|
+
a = lambda { |x, y| x ** y }
|
34
|
+
|
35
|
+
assert_equal binop_block(:lambda, :**), LiveAST.ast(a)
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_ast_eval
|
39
|
+
code = %{ lambda { |x, y| x / y } }
|
40
|
+
|
41
|
+
expected = binop_block(:lambda, :/)
|
42
|
+
result = LiveAST.ast(LiveAST.eval(code, binding))
|
43
|
+
assert_equal expected, result
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_bogus
|
47
|
+
assert_raises TypeError do
|
48
|
+
LiveAST.ast(99)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/test/readme_test.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
class RecursiveEvalTest < RegularTest
|
4
|
+
DEFINE = lambda do
|
5
|
+
ast_eval %{
|
6
|
+
class A
|
7
|
+
ast_eval %{
|
8
|
+
def f
|
9
|
+
"A#f"
|
10
|
+
end
|
11
|
+
}, binding
|
12
|
+
|
13
|
+
ast_eval %{
|
14
|
+
ast_eval %{
|
15
|
+
remove_method :f
|
16
|
+
def f(x, y)
|
17
|
+
x + y
|
18
|
+
end
|
19
|
+
|
20
|
+
def g
|
21
|
+
"A#g"
|
22
|
+
end
|
23
|
+
}, binding
|
24
|
+
|
25
|
+
LAMBDA = ast_eval %{
|
26
|
+
lambda { |x, y| x * y }
|
27
|
+
}, binding
|
28
|
+
}, binding
|
29
|
+
end
|
30
|
+
}, binding
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_method
|
34
|
+
defined?(A) or DEFINE.call
|
35
|
+
assert_equal "#{self.class}::A", A.name
|
36
|
+
|
37
|
+
assert_equal binop_def(:f, :+),
|
38
|
+
A.instance_method(:f).to_ast
|
39
|
+
|
40
|
+
assert_equal no_arg_def(:g, "A#g"),
|
41
|
+
A.instance_method(:g).to_ast
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_lambda
|
45
|
+
defined?(A) or DEFINE.call
|
46
|
+
assert_equal "#{self.class}::A", A.name
|
47
|
+
|
48
|
+
assert_equal binop_block(:lambda, :*),
|
49
|
+
A::LAMBDA.to_ast
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
class RedefineMethodTest < RegularTest
|
4
|
+
DEFINE_A = lambda do
|
5
|
+
class A
|
6
|
+
def f
|
7
|
+
"old A#f"
|
8
|
+
end
|
9
|
+
|
10
|
+
PREVIOUS_Af = instance_method(:f)
|
11
|
+
remove_method :f
|
12
|
+
|
13
|
+
def f(x, y)
|
14
|
+
x * y
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_inclass_redef
|
20
|
+
DEFINE_A.call
|
21
|
+
|
22
|
+
assert_equal binop_def(:f, :*),
|
23
|
+
A.instance_method(:f).to_ast
|
24
|
+
|
25
|
+
assert_equal no_arg_def(:f, "old A#f"),
|
26
|
+
A::PREVIOUS_Af.to_ast
|
27
|
+
end
|
28
|
+
|
29
|
+
DEFINE_B = lambda do
|
30
|
+
class B
|
31
|
+
def f
|
32
|
+
"old B#f"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_dynamic_redef
|
38
|
+
DEFINE_B.call
|
39
|
+
|
40
|
+
assert_equal "old B#f", B.new.f
|
41
|
+
assert_equal no_arg_def(:f, "old B#f"), B.instance_method(:f).to_ast
|
42
|
+
|
43
|
+
B.class_eval do
|
44
|
+
remove_method :f
|
45
|
+
define_method :f do |x, y|
|
46
|
+
x - y
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
assert_equal 11, B.new.f(44, 33)
|
51
|
+
|
52
|
+
assert_equal binop_define_method(:f, :-),
|
53
|
+
B.instance_method(:f).to_ast
|
54
|
+
end
|
55
|
+
|
56
|
+
DEFINE_C = lambda do
|
57
|
+
class C
|
58
|
+
def f
|
59
|
+
"old C#f"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_dynamic_redef_with_eval
|
65
|
+
DEFINE_C.call
|
66
|
+
|
67
|
+
assert_equal "old C#f", C.new.f
|
68
|
+
|
69
|
+
C.class_eval do
|
70
|
+
ast_eval %{
|
71
|
+
remove_method :f
|
72
|
+
define_method :f do |x, y|
|
73
|
+
x * y
|
74
|
+
end
|
75
|
+
}, binding
|
76
|
+
end
|
77
|
+
|
78
|
+
assert_equal 12, C.new.f(3, 4)
|
79
|
+
|
80
|
+
assert_equal binop_define_method(:f, :*),
|
81
|
+
C.instance_method(:f).to_ast
|
82
|
+
end
|
83
|
+
end
|
data/test/reload_test.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
require_relative 'shared/main'
|
2
|
+
|
3
|
+
class AAB_ReloadTest < BaseTest
|
4
|
+
include FileUtils
|
5
|
+
|
6
|
+
def test_reloading
|
7
|
+
raw_reload
|
8
|
+
require 'live_ast/ast_load'
|
9
|
+
noninvasive_ast_reload
|
10
|
+
require 'live_ast/replace_load'
|
11
|
+
ast_reload
|
12
|
+
end
|
13
|
+
|
14
|
+
def raw_reload
|
15
|
+
code_1 = %{
|
16
|
+
class AAB_ReloadTest::A
|
17
|
+
def f
|
18
|
+
"first A#f"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
}
|
22
|
+
|
23
|
+
code_2 = %{
|
24
|
+
class AAB_ReloadTest::A
|
25
|
+
def f
|
26
|
+
"second A#f"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
}
|
30
|
+
|
31
|
+
temp_file do |file|
|
32
|
+
write_file file, code_1
|
33
|
+
load file
|
34
|
+
|
35
|
+
LiveAST.ast(A.instance_method(:f))
|
36
|
+
|
37
|
+
write_file file, code_2
|
38
|
+
load file
|
39
|
+
|
40
|
+
# forced a raw-reload inconsistency -- verify bogus
|
41
|
+
|
42
|
+
assert_equal no_arg_def(:f, "first A#f"),
|
43
|
+
LiveAST.ast(A.instance_method(:f))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def noninvasive_ast_reload
|
48
|
+
code_1 = %{
|
49
|
+
class AAB_ReloadTest::B
|
50
|
+
def f
|
51
|
+
"first B#f"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
}
|
55
|
+
|
56
|
+
code_2 = %{
|
57
|
+
class AAB_ReloadTest::B
|
58
|
+
def f
|
59
|
+
"second B#f"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
}
|
63
|
+
|
64
|
+
temp_file do |file|
|
65
|
+
write_file file, code_1
|
66
|
+
load file
|
67
|
+
|
68
|
+
LiveAST.ast(B.instance_method(:f))
|
69
|
+
|
70
|
+
write_file file, code_2
|
71
|
+
ast_load file
|
72
|
+
|
73
|
+
assert_equal no_arg_def(:f, "second B#f"),
|
74
|
+
LiveAST.ast(B.instance_method(:f))
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def ast_reload
|
79
|
+
code_1 = %{
|
80
|
+
class AAB_ReloadTest::C
|
81
|
+
def f
|
82
|
+
"first C#f"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
}
|
86
|
+
|
87
|
+
code_2 = %{
|
88
|
+
class AAB_ReloadTest::C
|
89
|
+
def f
|
90
|
+
"second C#f"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
}
|
94
|
+
|
95
|
+
temp_file do |file|
|
96
|
+
write_file file, code_1
|
97
|
+
load file
|
98
|
+
|
99
|
+
LiveAST.ast(C.instance_method(:f))
|
100
|
+
|
101
|
+
write_file file, code_2
|
102
|
+
load file
|
103
|
+
|
104
|
+
assert_equal no_arg_def(:f, "second C#f"),
|
105
|
+
LiveAST.ast(C.instance_method(:f))
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module ASTGenerators
|
2
|
+
#
|
3
|
+
# no_arg_def(:f, "A#f") returns the ast of
|
4
|
+
#
|
5
|
+
# def f
|
6
|
+
# "A#f"
|
7
|
+
# end
|
8
|
+
#
|
9
|
+
def no_arg_def(name, ret)
|
10
|
+
s(:defn, name, s(:args), s(:scope, s(:block, s(:str, ret))))
|
11
|
+
end
|
12
|
+
|
13
|
+
#
|
14
|
+
# no_arg_def_return(no_arg_def(:f, "A#f")) == "A#f"
|
15
|
+
#
|
16
|
+
def no_arg_def_return(ast)
|
17
|
+
ast[3][1][1][1]
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
# binop_def(:f, :+) returns the ast of
|
22
|
+
#
|
23
|
+
# def f(x, y)
|
24
|
+
# x + y
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
def binop_def(name, op)
|
28
|
+
s(:defn,
|
29
|
+
name,
|
30
|
+
s(:args, :x, :y),
|
31
|
+
s(:scope,
|
32
|
+
s(:block, s(:call, s(:lvar, :x), op, s(:arglist, s(:lvar, :y))))))
|
33
|
+
end
|
34
|
+
|
35
|
+
#
|
36
|
+
# binop_define_method(:f, :*) returns the ast of
|
37
|
+
#
|
38
|
+
# define_method :f do |x, y|
|
39
|
+
# x * y
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
def binop_define_method(name, op)
|
43
|
+
s(:iter,
|
44
|
+
s(:call, nil, :define_method, s(:arglist, s(:lit, name))),
|
45
|
+
s(:masgn, s(:array, s(:lasgn, :x), s(:lasgn, :y))),
|
46
|
+
s(:call, s(:lvar, :x), op, s(:arglist, s(:lvar, :y))))
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# binop_covert_define_method(:f, :-, :my_def) returns the ast of
|
51
|
+
#
|
52
|
+
# my_def :f do |x, y|
|
53
|
+
# x - y
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
def binop_covert_define_method(name, op, covert_name)
|
57
|
+
s(:iter,
|
58
|
+
s(:call, nil, covert_name, s(:arglist, s(:lit, name))),
|
59
|
+
s(:masgn, s(:array, s(:lasgn, :x), s(:lasgn, :y))),
|
60
|
+
s(:call, s(:lvar, :x), op, s(:arglist, s(:lvar, :y))))
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
# binop_define_method_with_var(:method_name, :/) returns the ast of
|
65
|
+
#
|
66
|
+
# define_method method_name do |x, y|
|
67
|
+
# x / y
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
def binop_define_method_with_var(name, op)
|
71
|
+
s(:iter,
|
72
|
+
s(:call, nil, :define_method, s(:arglist, s(:lvar, name))),
|
73
|
+
s(:masgn, s(:array, s(:lasgn, :x), s(:lasgn, :y))),
|
74
|
+
s(:call, s(:lvar, :x), op, s(:arglist, s(:lvar, :y))))
|
75
|
+
end
|
76
|
+
|
77
|
+
#
|
78
|
+
# binop_define_singleton_method(:f, :+, :a) returns the ast of
|
79
|
+
#
|
80
|
+
# a.define_singleton_method :f do |x, y|
|
81
|
+
# x + y
|
82
|
+
# end
|
83
|
+
#
|
84
|
+
def binop_define_singleton_method(name, op, receiver)
|
85
|
+
s(:iter,
|
86
|
+
s(:call, s(:lvar, receiver), :define_singleton_method,
|
87
|
+
s(:arglist, s(:lit, name))),
|
88
|
+
s(:masgn, s(:array, s(:lasgn, :x), s(:lasgn, :y))),
|
89
|
+
s(:call, s(:lvar, :x), op, s(:arglist, s(:lvar, :y))))
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# no_arg_block(:foo, "bar") returns the ast of
|
94
|
+
#
|
95
|
+
# foo { "bar" }
|
96
|
+
#
|
97
|
+
def no_arg_block(name, ret)
|
98
|
+
s(:iter, s(:call, nil, name, s(:arglist)), nil, s(:str, ret))
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# binop_block(:foo, :+) returns the ast of
|
103
|
+
#
|
104
|
+
# foo { |x, y| x + y }
|
105
|
+
#
|
106
|
+
def binop_block(name, op, receiver = nil, args = [])
|
107
|
+
s(:iter,
|
108
|
+
s(:call, receiver, name, s(:arglist, *args)),
|
109
|
+
s(:masgn, s(:array, s(:lasgn, :x), s(:lasgn, :y))),
|
110
|
+
s(:call, s(:lvar, :x), op, s(:arglist, s(:lvar, :y))))
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# binop_proc_new(:*) returns the ast of
|
115
|
+
#
|
116
|
+
# Proc.new { |x, y| x * y }
|
117
|
+
#
|
118
|
+
def binop_proc_new(op)
|
119
|
+
s(:iter,
|
120
|
+
s(:call, s(:const, :Proc), :new, s(:arglist)),
|
121
|
+
s(:masgn, s(:array, s(:lasgn, :x), s(:lasgn, :y))),
|
122
|
+
s(:call, s(:lvar, :x), op, s(:arglist, s(:lvar, :y))))
|
123
|
+
end
|
124
|
+
end
|