rubybreaker 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/NEWS +6 -0
- data/VERSION +1 -1
- data/bin/rubybreaker +3 -3
- data/lib/rubybreaker.rb +15 -11
- data/lib/rubybreaker/doc/rdoc.rb +1 -1
- data/lib/rubybreaker/runtime/monitor.rb +8 -6
- data/lib/rubybreaker/runtime/object_wrapper.rb +38 -16
- data/lib/rubybreaker/runtime/overrides.rb +42 -30
- data/lib/rubybreaker/runtime/type_system.rb +45 -14
- data/lib/rubybreaker/type/type_unparser.rb +4 -8
- data/lib/rubybreaker/typing/subtyping.rb +1 -0
- data/test/integrated/tc_original_behavior.rb +38 -0
- data/test/integrated/tc_simple1.rb +20 -0
- data/test/integrated/tc_simple_algorithms.rb +135 -0
- data/test/runtime/tc_obj_wrapper.rb +3 -3
- data/test/ts_integrated.rb +1 -0
- data/test/type/tc_parser.rb +24 -0
- data/webpage/rdoc/Object.html +0 -2
- data/webpage/rdoc/Rake.html +0 -2
- data/webpage/rdoc/Rake/RubyBreakerTestTask.html +0 -2
- data/webpage/rdoc/RubyBreaker.html +1 -3
- data/webpage/rdoc/RubyBreaker/Breakable.html +0 -2
- data/webpage/rdoc/RubyBreaker/Broken.html +0 -2
- data/webpage/rdoc/RubyBreaker/Context.html +0 -2
- data/webpage/rdoc/RubyBreaker/Errors.html +0 -2
- data/webpage/rdoc/RubyBreaker/Errors/ArgumentTypeError.html +0 -2
- data/webpage/rdoc/RubyBreaker/Errors/ArityError.html +0 -2
- data/webpage/rdoc/RubyBreaker/Errors/InternalError.html +0 -2
- data/webpage/rdoc/RubyBreaker/Errors/InvalidSubtypeCheck.html +0 -2
- data/webpage/rdoc/RubyBreaker/Errors/InvalidTypeConstruction.html +0 -2
- data/webpage/rdoc/RubyBreaker/Errors/ReturnTypeError.html +0 -2
- data/webpage/rdoc/RubyBreaker/Errors/TypeError.html +0 -2
- data/webpage/rdoc/RubyBreaker/Errors/UserError.html +0 -2
- data/webpage/rdoc/RubyBreaker/ObjectPosition.html +0 -2
- data/webpage/rdoc/RubyBreaker/Position.html +0 -2
- data/webpage/rdoc/RubyBreaker/RubyTypeUtils.html +0 -2
- data/webpage/rdoc/RubyBreaker/Runtime.html +7 -3
- data/webpage/rdoc/RubyBreaker/Runtime/Inspector.html +0 -2
- data/webpage/rdoc/RubyBreaker/Runtime/MethodInfo.html +0 -2
- data/webpage/rdoc/RubyBreaker/Runtime/Monitor.html +12 -13
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorInstaller.html +6 -7
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorSwitch.html +4 -6
- data/webpage/rdoc/RubyBreaker/Runtime/ObjectWrapper.html +21 -19
- data/webpage/rdoc/RubyBreaker/Runtime/Pluggable.html +0 -2
- data/webpage/rdoc/RubyBreaker/Runtime/TypeSigParser.html +0 -2
- data/webpage/rdoc/RubyBreaker/Runtime/TypeSigUnparser.html +0 -2
- data/webpage/rdoc/RubyBreaker/Runtime/TypeSystem.html +52 -23
- data/webpage/rdoc/RubyBreaker/TypeComparer.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeDefs.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeDefs/AnyType.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeDefs/BlockType.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeDefs/DuckType.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeDefs/FusionType.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeDefs/MethodListType.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeDefs/MethodType.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeDefs/NilType.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeDefs/NominalType.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeDefs/OptionalType.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeDefs/OrType.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeDefs/SelfType.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeDefs/Type.html +2 -4
- data/webpage/rdoc/RubyBreaker/TypeDefs/VarLengthType.html +0 -2
- data/webpage/rdoc/RubyBreaker/TypeUnparser.html +1 -3
- data/webpage/rdoc/RubyBreaker/Typing.html +1 -3
- data/webpage/rdoc/RubyBreaker/Util.html +0 -2
- data/webpage/rdoc/Test.html +0 -2
- data/webpage/rdoc/Test/Unit.html +0 -2
- data/webpage/rdoc/created.rid +10 -10
- data/webpage/rdoc/index.html +0 -2
- data/webpage/rdoc/js/search_index.js +1 -1
- data/webpage/rdoc/table_of_contents.html +31 -38
- metadata +3 -3
- data/webpage/rdoc/RubyBreaker/RDocSupport.html +0 -328
data/NEWS
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.9
|
data/bin/rubybreaker
CHANGED
@@ -9,10 +9,10 @@ module RubyBreaker
|
|
9
9
|
exit(1)
|
10
10
|
end
|
11
11
|
|
12
|
-
# This method prepares
|
12
|
+
# This method prepares the command mode execution of RubyBreaker.
|
13
13
|
def self.main()
|
14
14
|
RubyBreaker.setup_logger()
|
15
|
-
RubyBreaker.verbose("Running RubyBreaker in
|
15
|
+
RubyBreaker.verbose("Running RubyBreaker in the command mode")
|
16
16
|
|
17
17
|
# parse the command-line arguments
|
18
18
|
OPTION_PARSER.parse!
|
@@ -60,7 +60,7 @@ module RubyBreaker
|
|
60
60
|
self.verbose("Done importing #{lib}")
|
61
61
|
end
|
62
62
|
|
63
|
-
#
|
63
|
+
# Runs the main library code at this point
|
64
64
|
RubyBreaker.run()
|
65
65
|
|
66
66
|
# Run the program file!
|
data/lib/rubybreaker.rb
CHANGED
@@ -133,18 +133,22 @@ module RubyBreaker
|
|
133
133
|
if fname && OPTIONS[:save_output]
|
134
134
|
# Check if the file already exists--that is, if it was used for input
|
135
135
|
io_exist = File.exists?(fname)
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
136
|
+
if File.writable?(fname)
|
137
|
+
RubyBreaker.verbose("Saving it to #{fname}")
|
138
|
+
# Append the result to the input file (or create a new file)
|
139
|
+
fmode = OPTIONS[:append] ? "a" : "w"
|
140
|
+
open(fname, fmode) do |f|
|
141
|
+
# When append, do not write the header
|
142
|
+
unless OPTIONS[:append]
|
143
|
+
f.puts "# This file is auto-generated by RubyBreaker"
|
144
|
+
end
|
145
|
+
# But time stamp always
|
146
|
+
f.puts "# Last modified: #{Time.now}"
|
147
|
+
f.puts "require \"rubybreaker\"" unless OPTIONS[:append]
|
148
|
+
f.print code
|
143
149
|
end
|
144
|
-
|
145
|
-
|
146
|
-
f.puts "require \"rubybreaker\"" unless OPTIONS[:append]
|
147
|
-
f.print code
|
150
|
+
else
|
151
|
+
RubyBreaker.verbose("Cannot write to #{fname}.")
|
148
152
|
end
|
149
153
|
end
|
150
154
|
|
data/lib/rubybreaker/doc/rdoc.rb
CHANGED
@@ -94,14 +94,13 @@ module RubyBreaker
|
|
94
94
|
mm.check_before_method(obj, meth_info)
|
95
95
|
end
|
96
96
|
rescue ::Exception => e
|
97
|
+
RubyBreaker.log("Exception #{e.class} has been raised.", :debug, CONTEXT)
|
97
98
|
# Trap it, turn on the global monitor and then re-raise the
|
98
99
|
# exception
|
99
100
|
GLOBAL_MONITOR_SWITCH.turn_on()
|
100
101
|
raise e
|
101
102
|
end
|
102
103
|
|
103
|
-
RubyBreaker.log("break_before_method ended")
|
104
|
-
|
105
104
|
# we are going to turn the switch back on
|
106
105
|
GLOBAL_MONITOR_SWITCH.turn_on()
|
107
106
|
|
@@ -109,9 +108,10 @@ module RubyBreaker
|
|
109
108
|
retval = obj.send(stub_meth_name.to_sym, *meth_info.args,
|
110
109
|
&meth_info.blk)
|
111
110
|
|
112
|
-
# turn
|
111
|
+
# turn the switch off again
|
113
112
|
GLOBAL_MONITOR_SWITCH.turn_off()
|
114
113
|
|
114
|
+
# Remember the return value in the method info object.
|
115
115
|
meth_info.ret = retval
|
116
116
|
|
117
117
|
begin
|
@@ -124,6 +124,7 @@ module RubyBreaker
|
|
124
124
|
rescue ::Exception => e
|
125
125
|
# Trap it, turn on the global monitor and then re-raise the
|
126
126
|
# exception
|
127
|
+
RubyBreaker.log("Exception #{e.class} has been raised.", :debug, CONTEXT)
|
127
128
|
GLOBAL_MONITOR_SWITCH.turn_on()
|
128
129
|
raise e
|
129
130
|
end
|
@@ -143,7 +144,7 @@ module RubyBreaker
|
|
143
144
|
|
144
145
|
# This method returns the alternative (renamed) method name
|
145
146
|
def self.get_alt_meth_name(meth_name)
|
146
|
-
return "
|
147
|
+
return "__rubybreaker_#{meth_name}"
|
147
148
|
end
|
148
149
|
|
149
150
|
# This method returns the original method name
|
@@ -237,11 +238,11 @@ module RubyBreaker
|
|
237
238
|
# Installs an module (class) monitor to the object.
|
238
239
|
def self.install_monitor(monitor_type, mod)
|
239
240
|
|
240
|
-
RubyBreaker.log("Installing
|
241
|
+
RubyBreaker.log("Installing #{monitor_type} monitor for #{mod} started.")
|
241
242
|
|
242
243
|
# Do not re-install monitor if already done so.
|
243
244
|
if MONITOR_MAP[mod]
|
244
|
-
RubyBreaker.log("
|
245
|
+
RubyBreaker.log("#{mod} already has a monitor installed.")
|
245
246
|
return
|
246
247
|
end
|
247
248
|
|
@@ -266,6 +267,7 @@ module RubyBreaker
|
|
266
267
|
end
|
267
268
|
end
|
268
269
|
|
270
|
+
RubyBreaker.log("Installing #{monitor_type} monitor for #{mod} ended.")
|
269
271
|
end
|
270
272
|
|
271
273
|
end
|
@@ -35,13 +35,25 @@ module RubyBreaker
|
|
35
35
|
return @__rubybreaker_type
|
36
36
|
end
|
37
37
|
|
38
|
+
# This method computes the wrap level of any given wrapped object. In
|
39
|
+
# theory, this should always be 1.
|
40
|
+
#
|
41
|
+
# Used for internal debugging purpose only
|
42
|
+
def __rubybreaker_wrap_level() #:nodoc:
|
43
|
+
val = 1
|
44
|
+
if @__rubybreaker_obj.respond_to?(WRAPPED_INDICATOR)
|
45
|
+
val += @__rubybreaker_obj.__rubybreaker_wrap_level
|
46
|
+
end
|
47
|
+
return val
|
48
|
+
end
|
49
|
+
|
38
50
|
#--
|
39
51
|
# The following code generates the "serious problem" warning which is
|
40
52
|
# suppressed by the hack using $VERBOSE. This is ok. This meta
|
41
53
|
# programming code block re-defines BasicObject's methods to redirect
|
42
54
|
# to the actual object.
|
43
55
|
[:"!", :"!=", :"==", :"equal?", :"eql?", :"__id__", :"object_id",
|
44
|
-
:"send", :"__send__", :"instance_eval",
|
56
|
+
:"send", :"__send__", :"instance_eval", :class,
|
45
57
|
:"instance_exec"].each do |meth|
|
46
58
|
|
47
59
|
orig_verbose = $VERBOSE
|
@@ -65,14 +77,20 @@ module RubyBreaker
|
|
65
77
|
return true if mname.to_sym == WRAPPED_INDICATOR
|
66
78
|
return @__rubybreaker_obj.respond_to?(mname)
|
67
79
|
end
|
80
|
+
|
81
|
+
# # Keep track of methods that MUST NOT take wrapped arguments.
|
82
|
+
# WRAP_BLACKLIST = {
|
83
|
+
# ::Array => [:[], :[]=],
|
84
|
+
# ::Hash => [:[], :[]=],
|
85
|
+
# }
|
68
86
|
|
69
87
|
# This method missing method redirects all other method calls.
|
70
88
|
def method_missing(mname,*args,&blk)
|
71
|
-
::RubyBreaker.log("Method_missing for #{mname}")
|
72
89
|
if GLOBAL_MONITOR_SWITCH.switch
|
73
90
|
|
74
91
|
# Be safe and turn the switch off
|
75
92
|
GLOBAL_MONITOR_SWITCH.turn_off
|
93
|
+
::RubyBreaker.log("Object wrapper method_missing for #{mname} started")
|
76
94
|
|
77
95
|
# Must handle send method specially (do not track them)
|
78
96
|
if [:"__send__", :send].include?(mname)
|
@@ -88,16 +106,18 @@ module RubyBreaker
|
|
88
106
|
is_obj_mod = (obj.class == ::Class or obj.class == ::Module)
|
89
107
|
mod = is_obj_mod ? Runtime.eigen_class(obj) : obj.class
|
90
108
|
|
91
|
-
#
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
end
|
109
|
+
# # There are certain methods that should not take wrapped
|
110
|
+
# # argument(s) whatsoever. Use WRAP_BLACKLIST for these.
|
111
|
+
# if !MONITOR_MAP[mod] && WRAP_BLACKLIST[mod] &&
|
112
|
+
# WRAP_BLACKLIST[mod].include?(mname)
|
113
|
+
# args.map! do |arg|
|
114
|
+
# if arg.respond_to?(WRAPPED_INDICATOR)
|
115
|
+
# arg.__rubybreaker_obj
|
116
|
+
# else
|
117
|
+
# arg
|
118
|
+
# end
|
119
|
+
# end
|
120
|
+
# end
|
101
121
|
|
102
122
|
# Turn on the global switch again
|
103
123
|
GLOBAL_MONITOR_SWITCH.turn_on
|
@@ -105,13 +125,15 @@ module RubyBreaker
|
|
105
125
|
# And call the original method
|
106
126
|
retval = @__rubybreaker_obj.send(mname, *args, &blk)
|
107
127
|
|
108
|
-
# No need to wrap the object again...if it's wrapped already
|
109
|
-
unless retval.respond_to?(WRAPPED_INDICATOR)
|
110
|
-
|
111
|
-
end
|
128
|
+
# # No need to wrap the object again...if it's wrapped already
|
129
|
+
# unless retval.respond_to?(WRAPPED_INDICATOR)
|
130
|
+
# retval = ObjectWrapper.new(retval)
|
131
|
+
# end
|
112
132
|
else
|
133
|
+
::RubyBreaker.log("Object wrapper method_missing for #{mname} started")
|
113
134
|
retval = @__rubybreaker_obj.send(mname, *args, &blk)
|
114
135
|
end
|
136
|
+
::RubyBreaker.log("Object wrapper method_missing for #{mname} ended")
|
115
137
|
return retval
|
116
138
|
end
|
117
139
|
end
|
@@ -19,19 +19,31 @@ module RubyBreaker
|
|
19
19
|
# indicate overridden methods.
|
20
20
|
OVERRIDE_PREFIX = "__rubybreaker"
|
21
21
|
|
22
|
-
# Prohibit these module/class+method from being overriden
|
22
|
+
# Prohibit these module/class+method from being overriden.
|
23
23
|
BLACKLIST = {
|
24
24
|
String => [:to_s, :<<, :concat, :gsub],
|
25
25
|
}
|
26
26
|
|
27
|
+
# Allow certain methods of these classes/modules to be overrriden. That
|
28
|
+
# is, they will take unwrapped arguments whatsoever.
|
29
|
+
WHITELIST = {
|
30
|
+
Kernel => [:puts, :putc, :gets, :print, :printf, :raise],
|
31
|
+
IO => [:getc, :gets, :putc, :puts, :print, :printf,
|
32
|
+
:readlines, :readline, :read],
|
33
|
+
Object => [:"==", :equal?, :eql?, :"!="],
|
34
|
+
Enumerable => [:"==", :equal?, :eql?, :"!="],
|
35
|
+
Array => [:"==", :equal?, :eql?, :"!=", :[], :[]=],
|
36
|
+
Hash => [:"==", :equal?, :eql?, :"!=", :[], :[]=],
|
37
|
+
}
|
38
|
+
|
27
39
|
end
|
28
40
|
|
29
41
|
end
|
30
42
|
|
31
43
|
# TODO: More IO related stuff need to be overriden!
|
32
|
-
|
44
|
+
RubyBreaker::Runtime::WHITELIST.each_pair do |mod, mlist|
|
33
45
|
|
34
|
-
|
46
|
+
mlist.each do |meth_name|
|
35
47
|
|
36
48
|
mod.module_eval <<-EOS
|
37
49
|
|
@@ -58,7 +70,7 @@ end
|
|
58
70
|
|
59
71
|
end
|
60
72
|
|
61
|
-
[Symbol, Numeric, Fixnum, Float, Integer, Bignum, String].each do |mod|
|
73
|
+
[Exception, StandardError, ArgumentError, Symbol, Numeric, Fixnum, Float, Integer, Bignum, String].each do |mod|
|
62
74
|
mod.instance_methods(false).each do |meth_name|
|
63
75
|
black_list = RubyBreaker::Runtime::BLACKLIST
|
64
76
|
next if black_list[mod] && black_list[mod].include?(meth_name)
|
@@ -83,32 +95,32 @@ end
|
|
83
95
|
end
|
84
96
|
end
|
85
97
|
|
86
|
-
# TODO: add more modules here as necessary!
|
87
|
-
[Object, Enumerable, Array, Hash].each do |mod|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
end
|
98
|
+
# # TODO: add more modules here as necessary!
|
99
|
+
# [Object, Enumerable, Array, Hash].each do |mod|
|
100
|
+
#
|
101
|
+
# [:"==", :equal?, :eql?, :"!="].each do |meth_name|
|
102
|
+
#
|
103
|
+
# # Create a unique alias name for each module. (It causes some issue when
|
104
|
+
# # not done this way.)
|
105
|
+
# alias_name = "RubyBreaker::Runtime::OVERRIDE_PREFIX_#{mod.object_id}" +
|
106
|
+
# "_#{meth_name}"
|
107
|
+
#
|
108
|
+
# mod.module_eval <<-EOS
|
109
|
+
#
|
110
|
+
# alias :"#{alias_name}" :"#{meth_name}"
|
111
|
+
#
|
112
|
+
# def #{meth_name}(other)
|
113
|
+
# if other.respond_to?(RubyBreaker::Runtime::WRAPPED_INDICATOR)
|
114
|
+
# other = other.__rubybreaker_obj
|
115
|
+
# end
|
116
|
+
# return self.send(:"#{alias_name}",other)
|
117
|
+
# end
|
118
|
+
#
|
119
|
+
# EOS
|
120
|
+
#
|
121
|
+
# end
|
122
|
+
#
|
123
|
+
# end
|
112
124
|
|
113
125
|
|
114
126
|
|
@@ -41,21 +41,31 @@ module RubyBreaker
|
|
41
41
|
# most restrictive for the given test cases.
|
42
42
|
arg_types = []
|
43
43
|
|
44
|
+
# Resolve the argument types first.
|
44
45
|
exist_meth_type.arg_types.each_with_index do |exist_arg_type, i|
|
45
46
|
arg_type = nil
|
46
47
|
new_arg_type = new_meth_type.arg_types[i]
|
47
48
|
if !exist_arg_type
|
48
|
-
# nil means there hasn't been any type observed
|
49
|
+
# nil means there hasn't been any type observed so use the new
|
50
|
+
# argument type as "resolved".
|
49
51
|
arg_type = new_arg_type
|
50
52
|
elsif new_arg_type.subtype_of?(exist_arg_type)
|
53
|
+
# Pick the subtype argument since we are resolving in
|
54
|
+
# contra-variance
|
55
|
+
arg_type = new_arg_type
|
56
|
+
elsif exist_arg_type.subtype_of?(new_arg_type)
|
57
|
+
# Pick the subtype argument since we are resolving in
|
58
|
+
# contra-variance
|
51
59
|
arg_type = exist_arg_type
|
52
|
-
|
53
|
-
# No subtype relation between them, so OR them
|
60
|
+
else
|
61
|
+
# No subtype relation between them, so OR them.
|
54
62
|
arg_type = OrType.new([new_arg_type, exist_arg_type])
|
55
63
|
end
|
56
64
|
arg_types << arg_type
|
57
65
|
end
|
58
66
|
|
67
|
+
# Now, resolve the return type
|
68
|
+
|
59
69
|
new_ret_type = new_meth_type.ret_type
|
60
70
|
exist_ret_type = exist_meth_type.ret_type
|
61
71
|
|
@@ -63,10 +73,12 @@ module RubyBreaker
|
|
63
73
|
ret_type = new_ret_type
|
64
74
|
resolved = true
|
65
75
|
elsif exist_ret_type.subtype_of?(new_ret_type)
|
66
|
-
|
76
|
+
# Co-variance
|
77
|
+
ret_type = new_ret_type
|
67
78
|
resolved = true
|
68
79
|
elsif new_ret_type.subtype_of?(exist_ret_type)
|
69
|
-
|
80
|
+
# Co-variance
|
81
|
+
ret_type = exist_ret_type
|
70
82
|
resolved = true
|
71
83
|
else
|
72
84
|
resolved = false
|
@@ -213,6 +225,8 @@ module RubyBreaker
|
|
213
225
|
args = meth_info.args
|
214
226
|
# blk = meth_info.blk
|
215
227
|
|
228
|
+
RubyBreaker.log("check_before_method #{mod}##{meth_name} started")
|
229
|
+
|
216
230
|
# Get the registered method type for this method
|
217
231
|
meth_type = meth_type_map[meth_name]
|
218
232
|
|
@@ -263,6 +277,7 @@ module RubyBreaker
|
|
263
277
|
end
|
264
278
|
end
|
265
279
|
|
280
|
+
RubyBreaker.log("check_before_method #{mod}##{meth_name} ended")
|
266
281
|
end
|
267
282
|
|
268
283
|
# This method is invoked after the original method is executed.
|
@@ -270,13 +285,16 @@ module RubyBreaker
|
|
270
285
|
is_obj_mod = (obj.class == Class or obj.class == Module)
|
271
286
|
mod = is_obj_mod ? Runtime.eigen_class(obj) : obj.class
|
272
287
|
|
288
|
+
# Get the method type map for the module/class from the global map.
|
273
289
|
meth_type_map = TYPE_MAP[mod]
|
274
|
-
return unless meth_type_map
|
290
|
+
return unless meth_type_map
|
275
291
|
|
276
292
|
# Let's take things out of the MethodInfo object
|
277
293
|
meth_name = meth_info.meth_name
|
278
294
|
ret = meth_info.ret
|
279
295
|
|
296
|
+
RubyBreaker.log("check_after_method #{mod}##{meth_name} started")
|
297
|
+
|
280
298
|
# Get the registered method type for this method
|
281
299
|
meth_type = meth_type_map[meth_name]
|
282
300
|
|
@@ -286,6 +304,8 @@ module RubyBreaker
|
|
286
304
|
" return value does not have type #{ret_type.unparse()}."
|
287
305
|
raise Errors::ReturnTypeError.new(msg)
|
288
306
|
end
|
307
|
+
|
308
|
+
RubyBreaker.log("check_after_method #{mod}##{meth_name} started")
|
289
309
|
end
|
290
310
|
|
291
311
|
# This method occurs before every call to a "monitored" method in a
|
@@ -298,30 +318,37 @@ module RubyBreaker
|
|
298
318
|
is_obj_mod = (obj.class == Class or obj.class == Module)
|
299
319
|
mod = is_obj_mod ? Runtime.eigen_class(obj) : obj.class
|
300
320
|
|
301
|
-
meth_type_map = TYPE_MAP[mod]
|
302
|
-
|
303
321
|
# Let's take things out of the MethodInfo object
|
304
322
|
meth_name = meth_info.meth_name
|
305
323
|
args = meth_info.args
|
306
324
|
blk = meth_info.blk
|
307
325
|
ret = meth_info.ret
|
308
326
|
|
327
|
+
RubyBreaker.log("break_before_method #{mod}##{meth_name} started")
|
328
|
+
|
309
329
|
args = args.map do |arg|
|
310
330
|
if arg == nil || arg.kind_of?(TrueClass) || arg.kind_of?(FalseClass)
|
311
331
|
# XXX: would overrides resolve this issue?
|
312
332
|
arg
|
333
|
+
elsif arg.respond_to?(WRAPPED_INDICATOR)
|
334
|
+
# Don't need to wrap an object that is already wrapped
|
335
|
+
arg
|
313
336
|
else
|
314
337
|
ObjectWrapper.new(arg)
|
315
338
|
end
|
316
339
|
end
|
317
340
|
|
318
|
-
|
319
|
-
|
341
|
+
# Using this module object, retrieve the method type map which
|
342
|
+
# maps method names to method types.
|
343
|
+
meth_type_map = TYPE_MAP[mod]
|
344
|
+
|
345
|
+
# Using the method name, get the type of this method from the map.
|
320
346
|
meth_type = meth_type_map[meth_name]
|
321
347
|
|
322
348
|
if meth_type
|
323
349
|
# This means the method type has been created previously.
|
324
|
-
unless
|
350
|
+
unless !meth_type.instance_of?(MethodType) ||
|
351
|
+
(blk == nil && meth_type.blk_type == nil) &&
|
325
352
|
(!blk || blk.arity == meth_type.blk_type.arg_types.length)
|
326
353
|
raise Errors::TypeError.new("Block usage is inconsistent")
|
327
354
|
end
|
@@ -349,6 +376,8 @@ module RubyBreaker
|
|
349
376
|
|
350
377
|
meth_info.args = args
|
351
378
|
|
379
|
+
RubyBreaker.log("break_before_method #{mod}##{meth_name} ended")
|
380
|
+
|
352
381
|
end
|
353
382
|
|
354
383
|
# This method occurs after every call to a "monitored" method call of
|
@@ -359,16 +388,16 @@ module RubyBreaker
|
|
359
388
|
is_obj_mod = (obj.class == Class or obj.class == Module)
|
360
389
|
mod = is_obj_mod ? Runtime.eigen_class(obj) : obj.class
|
361
390
|
|
362
|
-
# Take things out
|
391
|
+
# Take things out of the method info object
|
363
392
|
meth_name = meth_info.meth_name
|
364
393
|
retval = meth_info.ret
|
365
394
|
args = meth_info.args
|
366
395
|
blk = meth_info.blk
|
367
396
|
|
368
|
-
RubyBreaker.log("
|
397
|
+
RubyBreaker.log("break_after_method #{mod}##{meth_name} started")
|
369
398
|
|
370
399
|
# Compute the least upper bound
|
371
|
-
lub(obj, TYPE_MAP[mod],meth_name,retval
|
400
|
+
lub(obj, TYPE_MAP[mod], meth_name, retval, *args, &blk)
|
372
401
|
|
373
402
|
if obj == retval
|
374
403
|
# It is possible that the method receiver is a wrapped object if
|
@@ -378,6 +407,8 @@ module RubyBreaker
|
|
378
407
|
meth_info.ret = obj
|
379
408
|
end
|
380
409
|
|
410
|
+
RubyBreaker.log("break_after_method #{mod}##{meth_name} ended")
|
411
|
+
|
381
412
|
end
|
382
413
|
|
383
414
|
end
|