2015-12-01 18:17:45 +01:00
|
|
|
require_relative '../helper'
|
2017-01-19 08:08:59 +01:00
|
|
|
require "risc/interpreter"
|
2015-12-01 18:17:45 +01:00
|
|
|
require "parser/ruby22"
|
|
|
|
require "yaml"
|
|
|
|
|
2017-01-19 08:02:29 +01:00
|
|
|
# An experiment to find out how much ruby there is to achieve bootstrap
|
|
|
|
#
|
2017-01-19 08:08:59 +01:00
|
|
|
# currently (jan/2017) just under 150 classes, 1.5k methods , 10k sends, only 10 yields
|
|
|
|
# 1 retry and redo (to be avoided), 4 ensure , 5 rescue
|
|
|
|
#
|
2015-12-01 18:17:45 +01:00
|
|
|
class Walker < AST::Processor
|
|
|
|
def initialize collector
|
|
|
|
@collector = collector
|
|
|
|
end
|
|
|
|
|
|
|
|
def on_send node
|
|
|
|
_ , method , file_node = *node
|
|
|
|
if method == :require
|
2016-12-08 14:19:37 +01:00
|
|
|
file = file_node.children[0]
|
|
|
|
@collector.load("#{file}.rb") unless file.include?("parslet")
|
2015-12-01 18:17:45 +01:00
|
|
|
end
|
|
|
|
if method == :require_relative
|
|
|
|
@collector.load File.dirname(@collector.current) + "/" + file_node.children[0] + ".rb"
|
|
|
|
end
|
2016-02-25 21:03:11 +01:00
|
|
|
if method.to_s.include?("eval")
|
|
|
|
@collector.evals << method
|
|
|
|
end
|
2015-12-01 18:17:45 +01:00
|
|
|
handler_missing(node)
|
|
|
|
end
|
|
|
|
|
2016-02-25 21:03:11 +01:00
|
|
|
def on_class node
|
|
|
|
@collector.class_defs << node.children[0].children[1]
|
|
|
|
handler_missing(node)
|
|
|
|
end
|
|
|
|
def on_const node
|
|
|
|
@collector.const_uses[node.children[1]] += 1
|
|
|
|
handler_missing(node)
|
|
|
|
end
|
2015-12-01 18:17:45 +01:00
|
|
|
def handler_missing node
|
|
|
|
type = node.type
|
|
|
|
@collector.types[type] += 1
|
|
|
|
node.children.each do |kid|
|
|
|
|
process(kid) if kid.is_a? AST::Node
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
class Collector
|
|
|
|
|
|
|
|
def initialize
|
|
|
|
@parser = Parser::Ruby22
|
|
|
|
@paths = Bundler.load.specs.collect { |s| s.gem_dir + "/lib/" }
|
2016-02-25 21:03:11 +01:00
|
|
|
@class_defs = []
|
|
|
|
@const_uses = Hash.new(0)
|
2015-12-01 18:17:45 +01:00
|
|
|
@types = Hash.new(0)
|
|
|
|
@not_found = []
|
|
|
|
@walker = Walker.new(self)
|
|
|
|
@files = []
|
2016-02-25 21:03:11 +01:00
|
|
|
@evals = []
|
2015-12-01 18:17:45 +01:00
|
|
|
@current = nil
|
|
|
|
end
|
2016-02-25 21:03:11 +01:00
|
|
|
attr_reader :class_defs , :const_uses , :types , :current , :evals
|
2015-12-01 18:17:45 +01:00
|
|
|
|
|
|
|
def file_content file_name
|
|
|
|
return nil if @files.include? file_name
|
|
|
|
@paths.each do |name|
|
|
|
|
next unless File.exist? name + file_name
|
|
|
|
@files << file_name
|
|
|
|
return File.open(name + file_name).read
|
|
|
|
end
|
|
|
|
nil
|
|
|
|
end
|
|
|
|
|
|
|
|
def run
|
2017-01-19 08:08:59 +01:00
|
|
|
load "rubyx.rb"
|
2015-12-01 18:17:45 +01:00
|
|
|
load "parser/ruby22.rb"
|
2016-12-08 14:19:37 +01:00
|
|
|
# load "../../../.rbenv/versions/2.2.3/lib/ruby/2.2.0/racc/parser.rb"
|
2015-12-01 18:17:45 +01:00
|
|
|
print
|
|
|
|
end
|
|
|
|
|
|
|
|
def load file
|
|
|
|
str = file_content(file)
|
|
|
|
return @not_found.push(file) unless str
|
|
|
|
ast = @parser.parse str
|
|
|
|
was = @current
|
|
|
|
@current = file
|
|
|
|
@walker.process ast
|
|
|
|
@current = was
|
|
|
|
end
|
|
|
|
def print
|
2016-02-25 21:03:11 +01:00
|
|
|
@class_defs.uniq!
|
|
|
|
@files.uniq!
|
|
|
|
puts "Types #{@types.to_yaml}"
|
2016-12-08 14:19:37 +01:00
|
|
|
puts "Class defs #{@class_defs.length}"
|
|
|
|
puts "Class defs #{@class_defs}"
|
2016-02-25 21:03:11 +01:00
|
|
|
puts "evals=#{@evals.length} #{@evals.uniq}"
|
2016-12-08 14:19:37 +01:00
|
|
|
puts "Not found #{@not_found.length} #{@not_found}"
|
2015-12-01 18:17:45 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
Collector.new.run
|