Torsten Rüger
2dcb2a9a72
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)
85 lines
2.9 KiB
Ruby
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
|