live_ast 0.6.3 → 0.7.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.
@@ -1,66 +1,32 @@
1
1
  module LiveAST
2
2
  module Evaler
3
3
  class << self
4
+ include Common
5
+
4
6
  def eval(parser_source, *args)
5
- evaler_source, bind, *location = handle_args(*args)
7
+ evaler_source, bind, *rest = handle_args(*args)
6
8
 
7
- file, line = handle_location(bind, *location)
8
- file = Linker.strip_token(file)
9
+ file, line = location_for_eval(bind, *rest)
10
+ file = LiveAST.strip_token(file)
9
11
 
10
12
  key, _ = Linker.new_cache_synced(parser_source, file, line, false)
11
13
 
12
14
  begin
13
15
  NATIVE_EVAL.call(evaler_source, bind, key, line)
14
16
  rescue Exception => ex
15
- fix_backtrace(ex.backtrace)
17
+ ex.backtrace.map! { |s| LiveAST.strip_token s }
16
18
  raise ex
17
19
  end
18
20
  end
19
21
 
20
- #
21
- # match eval's error messages
22
- #
23
22
  def handle_args(*args)
24
- unless (2..4).include? args.size
25
- raise ArgumentError,
26
- "wrong number of arguments (#{args.size} for 2..4)"
27
- end
28
- unless args[1].is_a? Binding
29
- raise TypeError,
30
- "wrong argument type #{args[1].class} (expected Binding)"
31
- end
32
- args[0] = arg_to_str(args[0])
33
- args[2] = arg_to_str(args[2]) unless args[2].nil?
34
- args
35
- end
36
-
37
- def arg_to_str(arg)
38
- begin
39
- arg.to_str
40
- rescue
41
- raise TypeError, "can't convert #{arg.class} into String"
23
+ args.tap do
24
+ check_arity(args, 2..4)
25
+ args[0] = arg_to_str(args[0])
26
+ check_type(args[1], Binding)
27
+ args[2] = arg_to_str(args[2]) if args[2]
42
28
  end
43
29
  end
44
-
45
- #
46
- # match eval's behavior
47
- #
48
- def handle_location(bind, *location)
49
- case location.size
50
- when 0
51
- NATIVE_EVAL.call("[__FILE__, __LINE__]", bind)
52
- when 1
53
- [location.first, 1]
54
- else
55
- location
56
- end
57
- end
58
-
59
- def fix_backtrace(backtrace)
60
- backtrace.map! { |line|
61
- LiveAST::Linker.strip_token line
62
- }
63
- end
64
30
  end
65
31
  end
66
32
  end
@@ -0,0 +1,2 @@
1
+ require 'live_ast'
2
+ require 'live_ast/replace_eval'
@@ -1,27 +1,33 @@
1
1
 
2
2
  module LiveAST
3
+ @history = nil
4
+
3
5
  module IRBSpy
4
- def self.code_at(line)
5
- unless defined?(@history)
6
- raise NotImplementedError,
7
- "LiveAST cannot access history for this IRB input method"
8
- end
9
- grow = 0
10
- begin
11
- code = @history[line..(line + grow)].join
12
- LiveAST.parser.new.parse(code) or raise "#{LiveAST.parser} error"
13
- rescue
14
- grow += 1
15
- retry if line + grow < @history.size
16
- raise
6
+ class << self
7
+ attr_writer :history
8
+
9
+ def code_at(line)
10
+ unless @history
11
+ raise NotImplementedError,
12
+ "LiveAST cannot access history for this IRB input method"
13
+ end
14
+ grow = 0
15
+ begin
16
+ code = @history[line..(line + grow)].join
17
+ LiveAST.parser.new.parse(code) or raise "#{LiveAST.parser} error"
18
+ rescue
19
+ grow += 1
20
+ retry if line + grow < @history.size
21
+ raise
22
+ end
23
+ code
17
24
  end
18
- code
19
25
  end
20
26
  end
21
27
  end
22
28
 
23
29
  [
24
- IRB::StdioInputMethod,
30
+ defined?(IRB::StdioInputMethod) ? IRB::StdioInputMethod : nil,
25
31
  defined?(IRB::ReadlineInputMethod) ? IRB::ReadlineInputMethod : nil,
26
32
  ].compact.each do |klass|
27
33
  klass.module_eval do
@@ -29,7 +35,7 @@ end
29
35
  def gets
30
36
  live_ast_original_gets.tap do
31
37
  if defined?(@line)
32
- LiveAST::IRBSpy.instance_variable_set(:@history, @line)
38
+ LiveAST::IRBSpy.history = @line
33
39
  end
34
40
  end
35
41
  end
@@ -117,10 +117,6 @@ module LiveAST
117
117
  @caches.delete_if { |key, _| key.index REVISION_TOKEN }
118
118
  end
119
119
  end
120
-
121
- def strip_token(file)
122
- file.sub(/#{Regexp.quote REVISION_TOKEN}[a-z]+/, "")
123
- end
124
120
  end
125
121
  end
126
122
  end
@@ -0,0 +1,118 @@
1
+ require 'live_ast/base'
2
+ require 'boc'
3
+
4
+ module LiveAST
5
+ module ReplaceEval
6
+ class << self
7
+ def cache
8
+ Thread.current[:_live_ast_arg_cache] ||= {}
9
+ end
10
+
11
+ def handle_args(args)
12
+ if args.empty?
13
+ raise ArgumentError, "block not supplied"
14
+ end
15
+
16
+ args[0] = Common.arg_to_str(args[0])
17
+
18
+ unless (1..3).include? args.size
19
+ raise ArgumentError,
20
+ "wrong number of arguments: instance_eval(src) or instance_eval{..}"
21
+ end
22
+
23
+ args[1] = Common.arg_to_str(args[1]) if args[1]
24
+ end
25
+
26
+ def module_or_instance_eval(which, remote_self, bind, args)
27
+ handle_args(args)
28
+ begin
29
+ cache[:remote_self] = remote_self
30
+ cache[:args] = args
31
+
32
+ code = %{
33
+ ::LiveAST::ReplaceEval.cache[:remote_self].
34
+ live_ast_original_#{which}_eval %{
35
+ ::LiveAST.eval(
36
+ ::LiveAST::ReplaceEval.cache[:args][0],
37
+ binding,
38
+ *::LiveAST::ReplaceEval.cache[:args][1..-1])
39
+ }
40
+ }
41
+ live_ast_original_eval(code, bind)
42
+ ensure
43
+ cache.clear
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ module Kernel
51
+ private
52
+
53
+ alias_method :live_ast_original_eval, :eval
54
+
55
+ def eval(*args)
56
+ LiveAST::Common.check_arity(args, 1..4)
57
+ LiveAST.eval(
58
+ args[0],
59
+ args[1] || Boc.value,
60
+ *LiveAST::Common.location_for_eval(*args[1..3]))
61
+ end
62
+
63
+ class << self
64
+ alias_method :live_ast_original_singleton_eval, :eval
65
+
66
+ def eval(*args)
67
+ LiveAST::Common.check_arity(args, 1..4)
68
+ LiveAST.eval(
69
+ "::Kernel.live_ast_original_instance_eval do;" << args[0] << ";end",
70
+ args[1] || Boc.value,
71
+ *LiveAST::Common.location_for_eval(*args[1..3]))
72
+ end
73
+ end
74
+ end
75
+
76
+ class Binding
77
+ alias_method :live_ast_original_binding_eval, :eval
78
+
79
+ def eval(*args)
80
+ LiveAST.eval(args[0], self, *args[1..-1])
81
+ end
82
+ end
83
+
84
+ class BasicObject
85
+ alias_method :live_ast_original_instance_eval, :instance_eval
86
+
87
+ def instance_eval(*args, &block)
88
+ if block
89
+ live_ast_original_instance_eval(*args, &block)
90
+ else
91
+ ::LiveAST::ReplaceEval.module_or_instance_eval(
92
+ :instance, self, ::Boc.value, args)
93
+ end
94
+ end
95
+ end
96
+
97
+ class Module
98
+ alias_method :live_ast_original_module_eval, :module_eval
99
+
100
+ def module_eval(*args, &block)
101
+ if block
102
+ live_ast_original_module_eval(*args, &block)
103
+ else
104
+ LiveAST::ReplaceEval.module_or_instance_eval(
105
+ :module, self, Boc.value, args)
106
+ end
107
+ end
108
+ end
109
+
110
+ Boc.enable Kernel, :eval
111
+ Boc.enable Kernel.singleton_class, :eval
112
+ Boc.enable Module, :module_eval
113
+ Boc.enable BasicObject, :instance_eval
114
+
115
+ class Module
116
+ remove_method :class_eval
117
+ alias_method :class_eval, :module_eval
118
+ end
@@ -8,14 +8,11 @@ module Kernel
8
8
  def raise(*args)
9
9
  ex = begin
10
10
  live_ast_original_raise(*args)
11
- rescue Exception => ex
12
- ex
11
+ rescue Exception => t
12
+ t
13
13
  end
14
-
15
14
  ex.backtrace.reject! { |line| line.index __FILE__ }
16
-
17
- LiveAST::Evaler.fix_backtrace ex.backtrace
18
-
15
+ ex.backtrace.map! { |line| LiveAST.strip_token line }
19
16
  live_ast_original_raise ex
20
17
  end
21
18
  end
@@ -1,3 +1,3 @@
1
1
  module LiveAST
2
- VERSION = "0.6.3"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -136,7 +136,7 @@ define_unsorted_test_case "BacktraceTest", RegularTest do
136
136
  orig_top = exception_backtrace { orig.call }.first
137
137
  live_top = exception_backtrace { live.call }.first
138
138
 
139
- assert_equal orig_top, LiveAST::Linker.strip_token(live_top)
139
+ assert_equal orig_top, LiveAST.strip_token(live_top)
140
140
 
141
141
  if will_succeed
142
142
  assert_equal orig_top, live_top
@@ -45,7 +45,7 @@ class AllEncodingTest < RegularTest
45
45
 
46
46
  def test_bad
47
47
  orig = assert_raises ArgumentError do
48
- require "./test/encoding_test/bad.rb"
48
+ live_ast_original_load "./test/encoding_test/bad.rb"
49
49
  end
50
50
  live = assert_raises ArgumentError do
51
51
  LiveAST.load "./test/encoding_test/bad.rb"
data/test/main.rb CHANGED
@@ -24,7 +24,7 @@ class JLMiniTest < MiniTest::Unit::TestCase
24
24
  if onlies.empty?
25
25
  default
26
26
  else
27
- puts "\n!!! NOTE: running ONLY *__only tests for #{self}"
27
+ puts "\nNOTE: running ONLY *__only tests for #{self}"
28
28
  onlies
29
29
  end
30
30
  end
@@ -48,26 +48,16 @@ class JLMiniTest < MiniTest::Unit::TestCase
48
48
  end
49
49
 
50
50
  def assert_nothing_raised
51
- assert_equal 3, 3
52
51
  yield
52
+ assert_nil nil
53
53
  rescue => ex
54
54
  raise MiniTest::Assertion,
55
55
  exception_details(ex, "Expected nothing raised, but got:")
56
56
  end
57
57
 
58
58
  %w[
59
- empty
60
- equal
61
- in_delta
62
- in_epsilon
63
- includes
64
- instance_of
65
- kind_of
66
- match
67
- nil
68
- operator
69
- respond_to
70
- same
59
+ empty equal in_delta in_epsilon includes instance_of
60
+ kind_of match nil operator respond_to same
71
61
  ].each { |name|
72
62
  alias_method "assert_not_#{name}", "refute_#{name}"
73
63
  }
@@ -122,3 +112,27 @@ class RegularTest < BaseTest
122
112
  require 'live_ast'
123
113
  end
124
114
  end
115
+
116
+ class ReplaceEvalTest < BaseTest
117
+ def initialize(*args)
118
+ super
119
+ ok = begin
120
+ require 'live_ast/full'
121
+ true
122
+ rescue LoadError
123
+ if RUBY_ENGINE == "ruby"
124
+ raise "need: gem install boc"
125
+ end
126
+ false
127
+ end
128
+
129
+ unless ok
130
+ self.class.class_eval do
131
+ instance_methods(false).each do |m|
132
+ remove_method(m)
133
+ define_method(m) { }
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end
data/test/readme_test.rb CHANGED
@@ -5,9 +5,9 @@ if LiveAST.parser::Test.respond_to?(:unified_sexp?) and
5
5
  LiveAST.parser::Test.unified_sexp?
6
6
  sections = [
7
7
  "Synopsis",
8
- "Loading Source",
9
- "Noninvasive Interface",
10
8
  "+to_ruby+",
9
+ "Noninvasive Interface",
10
+ "Pure Ruby and +ast_eval+",
11
11
  ]
12
12
 
13
13
  Levitate.doc_to_test("README.rdoc", *sections)