rubyx/lib/risc/collector.rb
Torsten Rüger 2dcb2a9a72 Introduce singleton types
Just for future, as this gives us a way to know immediately in the type, which represent normal, and which singleton classes
Also instantiate singleton class lazily (with singleton type)
This makes the type of class single, ie unique, immediately when it is used, ie methods or variables defined.
Fixes a design mistake, where all singletonn classes shared the same type, and thus unique methods per class were impossible
(Also some misc in commit)
2019-10-01 19:42:16 +03:00

85 lines
2.9 KiB
Ruby

module Risc
# collect anything that is in the space and reachable (linker constants)
#
# The place we collect in is the position map in Position class
module Collector
# Collect all object that need to be added to the binary
# This means the object_space and aby constants the linker has
# we call keep on each object, see there for details
# return all positions
def self.collect_space(linker)
keep Parfait.object_space
linker.constants.each do |obj|
keep(obj)
end
Position.positions
end
# keep "collects" the object for "keeping". Such objects get written to binary
# keeping used to be done by adding to a hash, but now the object is
# given a position, and the Position class has a hash of all positions
# (the same hash has all objects, off course)
def self.keep( object)
collection = []
mark_1k( object , 0 , collection)
collection.each do |obj|
keep(obj)
end
end
# marking object that make up the binary.
# "Only" up to 1k stack depth, collect object that make up the "border"
#
# Collection is an empty arry that is passed on. Objects below 1k get added
# So basically it "should" be a return, but then we would keep creating and adding
# arrays, most of which would be empty
def self.mark_1k(object , depth , collection)
return if object.nil?
if depth > 1000
collection << object
return
end
return unless position!( object )
return unless object.respond_to? :has_type?
type = object.get_type
mark_1k(type , depth + 1 , collection)
return if object.is_a? Symbol
type.names.each do |name|
mark_1k(name , depth + 1, collection)
inst = object.get_instance_variable name
mark_1k(inst , depth + 1, collection)
end
if object.is_a? Parfait::List
object.each do |item|
mark_1k(item , depth + 1, collection)
end
end
end
# Give the object a position. Position class keeps a list of all positions
# and associated objects. The actual position is determined later, here a
# Position object is assigned.
#
# All Objects that end up in the binary must have a Position.
#
# return if the position was assigned (true) or had been assigned already (false)
def self.position!( objekt )
return false if Position.set?(objekt)
return true if objekt.is_a? ::Integer
return true if objekt.is_a? ::NilClass
return true if objekt.is_a? ::TrueClass
return true if objekt.is_a? ::FalseClass
return true if objekt.is_a?( Risc::Label)
#puts "ADD #{objekt.class.name}"
unless objekt.is_a?( Parfait::Object) or objekt.is_a?( Symbol)
raise "adding non parfait #{objekt.class}:#{objekt}"
end
#raise "Method #{objekt.name}" if objekt.is_a? Parfait::CallableMethod
Position.get_or_create(objekt)
true
end
end
end