Created
March 30, 2020 08:25
-
-
Save ellcs/37644987d2166d51808996d0c64a24a4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'contracts' | |
# https://ruby-doc.org/core-2.6/RubyVM/InstructionSequence.html | |
module B | |
def c; end | |
end | |
def global_method; end | |
class A | |
include B | |
include Contracts::Core | |
def self.klass_method; end | |
def foo; end | |
Contract Integer => Integer | |
def ret_int(q) | |
q | |
end | |
def third | |
klass_method | |
c | |
ret_int.a | |
foo | |
global_method | |
asdf | |
end | |
end | |
class ISeqParser | |
attr_reader :m | |
attr_reader :iseq | |
def self.for(m) | |
new(m, RubyVM::InstructionSequence.of(m)) | |
end | |
def initialize(m, iseq) | |
@m = m | |
@iseq = iseq | |
@array = iseq.to_a | |
end | |
[:magic, | |
:major_version, | |
:minor_version, | |
:format_type, | |
:misc, | |
:label, | |
:path, | |
:absolute_path, | |
:first_lineno, | |
:type, | |
:locals, | |
:params, | |
:catch_type, | |
:bytecode].each.with_index do |m, index| | |
define_method(m) do | |
@array[index] | |
end | |
end | |
def arg_size | |
misc[:arg_size] | |
end | |
def local_size | |
misc[:local_size] | |
end | |
def stack_max | |
misc[:stack_max] | |
end | |
# packed by lines | |
def packed_bytecode | |
bytecode.reduce([]) do |accu, elem| | |
if elem.is_a?(Integer) | |
accu.push([elem]) | |
else | |
accu.last << elem | |
end | |
accu | |
end | |
end | |
def sat_calls2 | |
errors = [] | |
packed_bytecode.each do |pb| | |
owner = if pb.include?([:putself]) | |
@m.owner | |
else | |
raise "not sapport yet" | |
end | |
pb.select do |(k, e)| | |
if k == :opt_send_without_block | |
unless object.private_methods.include?(mc) || | |
owner.instance_methods.include?(mc) || | |
owner.methods.include?(mc) | |
errors << "#{owner}##{@m.name} doesn't know #{mc}." | |
end | |
Contracts::Engine.fetch_from(owner) | |
end | |
end | |
end | |
end | |
# returns new owner | |
def sat_call(owner, method) | |
end | |
def method_calls | |
calls = [] | |
binding.pry | |
packed_bytecode.each do |instruction_line| | |
index = instruction_line.flatten.find_index(:opt_send_without_block) | |
if index | |
calls << instruction_line.flatten[index+1][:mid] | |
end | |
end | |
calls | |
end | |
def sat_calls | |
owner = @m.owner | |
errors = [] | |
method_calls.each do |mc| | |
unless object.private_methods.include?(mc) || | |
owner.instance_methods.include?(mc) || | |
owner.methods.include?(mc) | |
errors << "#{owner}##{@m.name} doesn't know #{mc}." | |
end | |
end | |
errors | |
end | |
end | |
i = ISeqParser.for(A.instance_method(:third)) | |
require 'pry';binding.pry | |
check(method(:third)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment