Class: CastOff::Compiler::Dependency
- Inherits:
-
Object
- Object
- CastOff::Compiler::Dependency
- Extended by:
- Util
- Includes:
- Util
- Defined in:
- lib/cast_off/compile/dependency.rb
Constant Summary collapse
- @@instance_method_dependency =
{}
- @@instance_method_dependency_initializers =
{}
- @@singleton_method_dependency =
{}
- @@singleton_method_dependency_initializers =
{}
- @@instance_method_strong_dependency =
{}
- @@singleton_method_strong_dependency =
{}
Class Method Summary collapse
- .copy(dst, src, singleton_p) ⇒ Object
- .get_class_or_module(km) ⇒ Object
- .hook(o) ⇒ Object
- .instance_method_depend(klass, mid, function_pointer_initializer) ⇒ Object
- .instance_method_depend?(klass, mid) ⇒ Boolean
- .instance_method_strongly_depend(klass, mid) ⇒ Object
- .instance_method_strongly_depend?(obj, mid) ⇒ Boolean
- .load(str) ⇒ Object
- .singleton_method_depend(klass, mid, function_pointer_initializer) ⇒ Object
- .singleton_method_depend?(obj, mid) ⇒ Boolean
- .singleton_method_strongly_depend(klass, mid) ⇒ Object
- .singleton_method_strongly_depend?(obj, mid) ⇒ Boolean
Instance Method Summary collapse
- #add(klass, mid, strong_p) ⇒ Object
- #check(configuration) ⇒ Object
- #check_failed(msg = '') ⇒ Object
- #dump(io) ⇒ Object
- #hook(function_pointer_initializer) ⇒ Object
-
#initialize ⇒ Dependency
constructor
A new instance of Dependency.
- #marshal_dump ⇒ Object
- #marshal_load(obj) ⇒ Object
Methods included from Util
Constructor Details
#initialize ⇒ Dependency
Returns a new instance of Dependency.
7 8 9 10 |
# File 'lib/cast_off/compile/dependency.rb', line 7 def initialize @dependency = {} @strong_dependency = [] end |
Class Method Details
.copy(dst, src, singleton_p) ⇒ Object
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/cast_off/compile/dependency.rb', line 165 def self.copy(dst, src, singleton_p) bug() unless dst.is_a?(Module) dst = ModuleWrapper.new(dst) deps = singleton_p ? @@singleton_method_dependency : @@instance_method_dependency funcs = singleton_p ? @@singleton_method_dependency_initializers : @@instance_method_dependency_initializers (deps[src] || []).each do |mid| finits = funcs[[src, mid]] if finits && !finits.empty? finits.each{|f| instance_method_depend(dst, mid, f)} else bug() unless singleton_p case mid when :singleton_method_added, :method_added, :include, :extend # nothing to do else bug() end end end end |
.get_class_or_module(km) ⇒ Object
19 20 21 22 23 24 25 26 27 28 |
# File 'lib/cast_off/compile/dependency.rb', line 19 def self.get_class_or_module(km) case km when ClassWrapper bug() if km.singleton? return km.contain_class when ModuleWrapper return km.contain_module end bug() end |
.hook(o) ⇒ Object
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/cast_off/compile/dependency.rb', line 186 def self.hook(o) s = class << o self end s.class_eval do def override_singleton_method(obj, mid, flag) CastOff.dlog("singleton method added #{obj}.#{mid}") CastOff.delete_original_singleton_method_iseq(self, mid) if initializers = Dependency.singleton_method_depend?(obj, mid) if Dependency.singleton_method_strongly_depend?(obj, mid) && !CastOff.method_replacing? raise(ExecutionError.new("Should not be override #{obj}.#{mid}")) end # TODO Array.each の上書きチェック initializers.each do |init| CastOff.dlog("update function pointer #{obj}.#{mid}") CastOff.__send__(init) end end end def override_method(obj, mid, flag) CastOff.dlog("method added #{obj}##{mid}") CastOff.delete_original_instance_method_iseq(self, mid) if initializers = Dependency.instance_method_depend?(obj, mid) if Dependency.instance_method_strongly_depend?(obj, mid) && !CastOff.method_replacing? raise(ExecutionError.new("Should not be override #{obj}##{mid}")) end # TODO Array.each の上書きチェック initializers.each do |init| CastOff.dlog("update function pointer #{obj}##{mid}") CastOff.__send__(init) end end end begin singleton_method_added = o.method(:singleton_method_added).unbind rescue NameError singleton_method_added = nil end begin method_added = o.method(:method_added).unbind rescue NameError method_added = nil end begin m_include = o.method(:include).unbind m_extend = o.method(:extend).unbind rescue NameError raise(ExecutionError.new("#{o}: include or extend not defined")) end define_method(:method_added) do |*args| ignore_overridden_p = Dependency.ignore_overridden? current_mid = CastOff.current_method_id case current_mid when :extend, :include mods = args extend_p = current_mid == :extend CastOff.dlog("#{self} #{extend_p ? 'extends' : 'includes'} #{mods}") bug() unless m_include && m_extend m = extend_p ? m_extend : m_include # include, extend の対象は self なので、self 以外が include, extend することはない。 m.bind(self).call(*mods) return unless o == self mods.each do |mod| next unless mod.is_a?(Module) Dependency.copy(mod, self, extend_p) Dependency.hook(mod) unless mod.singleton_methods(false).include?(:override_singleton_method) methods = mod.instance_methods(false) + mod.private_instance_methods(false) override_callback = extend_p ? :override_singleton_method : :override_method methods.each{|mid| o.__send__(override_callback, o, mid, extend_p ? :extend : :include)} end when :singleton_method_added mid = args.first CastOff.bug() unless mid.instance_of?(Symbol) if self == o && !ignore_overridden_p override_singleton_method(o, mid, :added) singleton_method_added.bind(self).call(mid) if singleton_method_added elsif o == Module && singleton_method_added singleton_method_added.bind(self).call(mid) end super(mid) rescue NoMethodError when :method_added mid = args.first CastOff.bug() unless mid.instance_of?(Symbol) if self == o && !ignore_overridden_p override_method(o, mid, :added) method_added.bind(self).call(mid) if method_added elsif o == Module && method_added method_added.bind(self).call(mid) end super(mid) rescue NoMethodError else raise(ExecutionError.new("CastOff expected include, extend, method_added or singleton_method_added but #{current_mid} was called")) end end alias extend method_added alias include method_added alias singleton_method_added method_added CastOff.dlog("hook #{o}") end @@singleton_method_dependency[o] ||= [] @@singleton_method_dependency[o] |= [:method_added, :singleton_method_added, :include, :extend] @@singleton_method_strong_dependency[o] ||= [] @@singleton_method_strong_dependency[o] |= [:method_added, :singleton_method_added, :include, :extend] end |
.instance_method_depend(klass, mid, function_pointer_initializer) ⇒ Object
30 31 32 33 34 35 36 |
# File 'lib/cast_off/compile/dependency.rb', line 30 def self.instance_method_depend(klass, mid, function_pointer_initializer) c = get_class_or_module(klass) a = (@@instance_method_dependency[c] ||= []) a << mid unless a.include?(mid) b = (@@instance_method_dependency_initializers[[c, mid]] ||= []) b << function_pointer_initializer unless b.include?(function_pointer_initializer) end |
.instance_method_depend?(klass, mid) ⇒ Boolean
45 46 47 48 49 50 51 52 |
# File 'lib/cast_off/compile/dependency.rb', line 45 def self.instance_method_depend?(klass, mid) bug() unless klass.instance_of?(Class) || klass.instance_of?(Module) dep = @@instance_method_dependency[klass] return false unless dep return false unless dep.include?(mid) bug() unless @@instance_method_dependency_initializers[[klass, mid]] @@instance_method_dependency_initializers[[klass, mid]] end |
.instance_method_strongly_depend(klass, mid) ⇒ Object
38 39 40 41 42 43 |
# File 'lib/cast_off/compile/dependency.rb', line 38 def self.instance_method_strongly_depend(klass, mid) c = get_class_or_module(klass) @@instance_method_strong_dependency[c] ||= [] a = @@instance_method_strong_dependency[c] a << mid unless a.include?(mid) end |
.instance_method_strongly_depend?(obj, mid) ⇒ Boolean
54 55 56 57 58 |
# File 'lib/cast_off/compile/dependency.rb', line 54 def self.instance_method_strongly_depend?(obj, mid) bug() unless obj.instance_of?(Class) || obj.instance_of?(Module) dep = @@instance_method_strong_dependency[obj] dep.instance_of?(Array) ? dep.include?(mid) : false end |
.load(str) ⇒ Object
115 116 117 118 119 |
# File 'lib/cast_off/compile/dependency.rb', line 115 def self.load(str) dep = Marshal.load(str) bug() unless dep.instance_of?(Dependency) dep end |
.singleton_method_depend(klass, mid, function_pointer_initializer) ⇒ Object
60 61 62 63 64 65 66 67 68 |
# File 'lib/cast_off/compile/dependency.rb', line 60 def self.singleton_method_depend(klass, mid, function_pointer_initializer) bug() unless klass.instance_of?(ClassWrapper) bug() unless klass.singleton? o = klass.contain_object a = (@@singleton_method_dependency[o] ||= []) a << mid unless a.include?(mid) b = (@@singleton_method_dependency_initializers[[o, mid]] ||= []) b << function_pointer_initializer unless b.include?(function_pointer_initializer) end |
.singleton_method_depend?(obj, mid) ⇒ Boolean
79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/cast_off/compile/dependency.rb', line 79 def self.singleton_method_depend?(obj, mid) bug() unless ClassWrapper.support?(obj, false) dep = @@singleton_method_dependency[obj] return false unless dep return false unless dep.include?(mid) unless @@singleton_method_dependency_initializers[[obj, mid]] if mid == :method_added || mid == :singleton_method_added return [] else bug() end end @@singleton_method_dependency_initializers[[obj, mid]] end |
.singleton_method_strongly_depend(klass, mid) ⇒ Object
70 71 72 73 74 75 76 77 |
# File 'lib/cast_off/compile/dependency.rb', line 70 def self.singleton_method_strongly_depend(klass, mid) bug() unless klass.instance_of?(ClassWrapper) bug() unless klass.singleton? o = klass.contain_object @@singleton_method_strong_dependency[o] ||= [] a = @@singleton_method_strong_dependency[o] a << mid unless a.include?(mid) end |
.singleton_method_strongly_depend?(obj, mid) ⇒ Boolean
94 95 96 97 98 |
# File 'lib/cast_off/compile/dependency.rb', line 94 def self.singleton_method_strongly_depend?(obj, mid) bug() unless ClassWrapper.support?(obj, false) dep = @@singleton_method_strong_dependency[obj] dep.instance_of?(Array) ? dep.include?(mid) : false end |
Instance Method Details
#add(klass, mid, strong_p) ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/cast_off/compile/dependency.rb', line 129 def add(klass, mid, strong_p) bug() unless klass.instance_of?(ClassWrapper) targets = [klass] klass.each_method_search_target(mid) do |cm| next if klass.singleton? ? (cm == klass) : (cm == klass.contain_class) case cm when Class targets << ClassWrapper.new(cm, true) when Module targets << ModuleWrapper.new(cm) when ClassWrapper bug() unless cm.singleton? targets << cm else bug() end end targets.each do |t| @dependency[t] ||= [] @dependency[t] |= [mid] @strong_dependency |= [[t, mid]] if strong_p end end |
#check(configuration) ⇒ Object
157 158 159 160 161 162 163 |
# File 'lib/cast_off/compile/dependency.rb', line 157 def check(configuration) @dependency.each do |(klass, mids)| bug() unless klass.instance_of?(ClassWrapper) || klass.instance_of?(ModuleWrapper) # TODO ブロックインライニングしたメソッドに対して # コンパイル時のメソッドと等しいものかどうかをチェック end end |
#check_failed(msg = '') ⇒ Object
153 154 155 |
# File 'lib/cast_off/compile/dependency.rb', line 153 def check_failed(msg = '') raise(LoadError.new("failed to check method dependency: #{msg}")) end |
#dump(io) ⇒ Object
100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
# File 'lib/cast_off/compile/dependency.rb', line 100 def dump(io) begin Marshal.dump(self, io) rescue TypeError => e raise(UnsupportedError.new(<<-EOS)) Failed to marshal dump method dependency. Dependency object should be able to marshal dump. Currently, CastOff doesn't support object, which cannot marshal dump (e.g. STDIN). --- Marshal.dump error message --- #{e.} EOS end end |
#hook(function_pointer_initializer) ⇒ Object
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 |
# File 'lib/cast_off/compile/dependency.rb', line 296 def hook(function_pointer_initializer) @dependency.keys.each do |klass| m = @dependency[klass] if klass.instance_of?(ClassWrapper) && klass.singleton? m.each{|mid| self.class.singleton_method_depend(klass, mid, function_pointer_initializer)} m.each{|mid| self.class.singleton_method_strongly_depend(klass, mid) if @strong_dependency.include?([klass, mid])} o = klass.contain_object bug() unless ClassWrapper.support?(o, false) else m.each{|mid| self.class.instance_method_depend(klass, mid, function_pointer_initializer)} m.each{|mid| self.class.instance_method_strongly_depend(klass, mid) if @strong_dependency.include?([klass, mid])} case klass when ClassWrapper o = klass.contain_class when ModuleWrapper o = klass.contain_module else bug() end end next if o.singleton_methods(false).include?(:override_singleton_method) Dependency.hook(o) end end |
#marshal_dump ⇒ Object
121 122 123 |
# File 'lib/cast_off/compile/dependency.rb', line 121 def marshal_dump() [@dependency, @strong_dependency] end |
#marshal_load(obj) ⇒ Object
125 126 127 |
# File 'lib/cast_off/compile/dependency.rb', line 125 def marshal_load(obj) @dependency, @strong_dependency = obj end |