Merge branch 'parfait'

This commit is contained in:
Torsten Rüger 2019-09-10 14:49:52 +03:00
commit c216d224ec
32 changed files with 312 additions and 270 deletions

View File

@ -8,7 +8,7 @@ PATH
remote: .
specs:
rubyx (0.6.0)
parser (~> 2.6.0)
parser (~> 2.5.0)
rx-file (~> 0.3)
GEM
@ -53,7 +53,7 @@ GEM
notiffany (0.1.3)
nenv (~> 0.1)
shellany (~> 0.0)
parser (2.6.3.0)
parser (2.5.3.0)
ast (~> 2.4.0)
pry (0.12.2)
coderay (~> 1.1.0)

View File

@ -34,7 +34,7 @@ module Mom
if(space_type.methods.nil?)
@compilers << compiler_for( space_type , Space , :main)
end
return @compilers
return @compilers
end
# TODO go through the virtual parfait layer and adjust function names
# to what they really are

View File

@ -7,18 +7,18 @@ module Parfait
def initialize
super()
instance_methods = List.new
@instance_methods = List.new
end
def methods
m = instance_methods
m = @instance_methods
return m if m
instance_methods = List.new
@instance_methods = List.new
end
def method_names
names = List.new
self.methods.each do |method|
methods.each do |method|
names.push method.name
end
names
@ -26,18 +26,19 @@ module Parfait
def add_instance_method( method )
raise "not implemented #{method.class} #{method.inspect}" unless method.is_a? VoolMethod
raise "HMM"
method
end
def remove_instance_method( method_name )
found = get_instance_method( method_name )
found ? self.methods.delete(found) : false
found ? methods.delete(found) : false
end
def get_instance_method( fname )
raise "get_instance_method #{fname}.#{fname.class}" unless fname.is_a?(Symbol)
#if we had a hash this would be easier. Detect or find would help too
self.instance_methods.find {|m| m.name == fname }
@instance_methods.find {|m| m.name == fname }
end
# get the method and if not found, try superclasses. raise error if not found
@ -46,7 +47,7 @@ module Parfait
method = get_instance_method(m_name)
return method if method
if( super_class_name && super_class_name != :Object )
method = self.super_class.resolve_method(m_name)
method = @super_class.resolve_method(m_name)
end
method
end

View File

@ -7,7 +7,7 @@ module Parfait
# and as the last code of each link is a jump to the next link.
#
class BinaryCode < Data32
attr :type, :next_code
attr_reader :next_code
def self.type_length
2 #type + next (could get from space, maybe later)
@ -27,11 +27,12 @@ module Parfait
def initialize(total_size)
super()
self.next_code = nil
@next_code = nil
extend_to(total_size )
(0 ... data_length).each{ |index| set_word(index , 0) }
set_last(0)
end
def extend_to(total_size)
return if total_size < data_length
extend_one() unless next_code
@ -39,7 +40,7 @@ module Parfait
end
def extend_one()
self.next_code = BinaryCode.new(1)
@next_code = BinaryCode.new(1)
Risc::Position.get(self).trigger_inserted if Risc::Position.set?(self)
end
@ -107,9 +108,9 @@ module Parfait
set_internal_word(word_index , char)
end
def total_byte_length(start = 0 )
start += self.byte_length
start += byte_length
return start unless self.next_code
self.next_code.total_byte_length(start)
@next_code.total_byte_length(start)
end
end
end

View File

@ -8,15 +8,16 @@
module Parfait
class CacheEntry < Object
attr :type, :cached_type, :cached_method
attr_reader :cached_type, :cached_method
def initialize(type , method)
self.cached_type = type
self.cached_method = method
super()
@cached_type = type
@cached_method = method
end
def to_s
"CacheEntry" + "#{cached_method&.name}"
"CacheEntry" + "#{@cached_method&.name}"
end
end
end

View File

@ -12,21 +12,24 @@ module Parfait
#
class Callable < Object
attr :type, :self_type , :arguments_type , :frame_type , :binary
attr :blocks , :name
attr :next_callable
attr_reader :self_type , :arguments_type , :frame_type , :binary
attr_reader :blocks , :name
attr_reader :next_callable
def self.type_length
8
end
def self.memory_size
8
end
def initialize( name , self_type , arguments_type , frame_type)
super()
raise "No class #{self}" unless self_type
raise "For type, not class #{self_type}" unless self_type.is_a?(Type)
raise "Mixup" unless name.is_a?(Symbol)
self.name = name
self.self_type = self_type
@name = name
@self_type = self_type
init(arguments_type, frame_type)
end
@ -38,25 +41,25 @@ module Parfait
def init(arguments_type, frame_type)
raise "Wrong argument type, expect Type not #{arguments_type.class}" unless arguments_type.is_a? Type
raise "Wrong frame type, expect Type not #{frame_type.class}" unless frame_type.is_a? Type
self.arguments_type = arguments_type
self.frame_type = frame_type
self.binary = BinaryCode.new(0)
@arguments_type = arguments_type
@frame_type = frame_type
@binary = BinaryCode.new(0)
end
# determine if method has a local variable or tmp (anonymous local) by given name
def has_local( name )
raise "has_local #{name}.#{name.class}" unless name.is_a? Symbol
frame_type.variable_index( name )
@frame_type.variable_index( name )
end
def add_local( name , type )
index = has_local( name )
return index if index
self.frame_type = frame_type.add_instance_variable(name,type)
@frame_type = @frame_type.add_instance_variable(name,type)
end
def each_binary( &block )
bin = binary
bin = @binary
while(bin) do
block.call( bin )
bin = bin.next_code
@ -64,7 +67,7 @@ module Parfait
end
def set_next( method )
self.next_callable = method
@next_callable = method
end
end

View File

@ -14,32 +14,32 @@ module Parfait
def ==(other)
return false unless other.is_a?(CallableMethod)
return false if name != other.name
return false if @name != other.name
super
end
def rxf_reference_name
"Method: " + name.to_s
"Method: " + @name.to_s
end
def inspect
"#{self_type.object_class.name}:#{name}(#{arguments_type.inspect})"
"#{@self_type.object_class.name}:#{@name}(#{@arguments_type.inspect})"
end
def each_method( &block )
block.call( self )
next_callable.each_method( &block ) if next_callable
@next_callable.each_method( &block ) if @next_callable
end
def create_block(args , frame)
block_name = "#{name}_block".to_sym #TODO with id, to distinguish
add_block( Block.new(block_name , self_type , args , frame))
block_name = "#{@name}_block".to_sym #TODO with id, to distinguish
add_block( Block.new(block_name , @self_type , args , frame))
end
def add_block(bl)
was = blocks
bl.set_next(was) if(was)
self.blocks = bl
@blocks = bl
end
def has_block(block)
@ -47,7 +47,7 @@ module Parfait
false
end
def each_block(&bl)
blo = blocks
blo = @blocks
while( blo )
yield(blo)
blo = blo.next_callable

View File

@ -18,20 +18,23 @@ module Parfait
class Class < Object
include Behaviour
attr :type, :instance_type , :name , :instance_methods
attr :super_class_name , :meta_class
attr_reader :instance_type , :name , :instance_methods
attr_reader :super_class_name , :meta_class
def self.type_length
6
end
def self.memory_size
8
end
def initialize( name , superclass , instance_type)
super()
self.name = name
self.super_class_name = superclass
self.instance_methods = List.new
@name = name
@super_class_name = superclass
@instance_methods = List.new
set_instance_type( instance_type )
self.meta_class = MetaClass.new( self )
@meta_class = MetaClass.new( self )
end
def rxf_reference_name
@ -50,32 +53,32 @@ module Parfait
def add_method(method)
raise "Must be untyped method #{method}" unless method.is_a? Parfait::VoolMethod
instance_methods.push(method)
@instance_methods.push(method)
end
def get_method(name)
instance_methods.find{|m| m.name == name }
@instance_methods.find{|m| m.name == name }
end
# adding an instance changes the instance_type to include that variable
def add_instance_variable( name , type)
self.instance_type = instance_type.add_instance_variable( name , type )
@instance_type = @instance_type.add_instance_variable( name , type )
end
# setting the type generates all methods for this type
# (or will do, once we store the methods code to do that)
def set_instance_type( type )
raise "type must be type #{type}" unless type.is_a?(Type)
self.instance_type = type
@instance_type = type
end
# return the super class, but raise exception if either the super class name
# or the super classs is nil.
# Use only for non Object base class
def super_class!
raise "No super_class for class #{name}" unless super_class_name
raise "No super_class for class #{@name}" unless @super_class_name
s = super_class
raise "superclass not found for class #{name} (#{super_class_name})" unless s
raise "superclass not found for class #{@name} (#{@super_class_name})" unless s
s
end
@ -83,8 +86,8 @@ module Parfait
# we only store the name, and so have to resolve.
# Nil name means no superclass, and so nil is a valid return value
def super_class
return nil unless super_class_name
Parfait.object_space.get_class_by_name(super_class_name)
return nil unless @super_class_name
Parfait.object_space.get_class_by_name(@super_class_name)
end
# ruby 2.1 list (just for reference, keep at bottom)

View File

@ -3,41 +3,44 @@
module Parfait
class Dictionary < Object
attr :type, :i_keys , :i_values
attr_reader :i_keys , :i_values
def self.type_length
3
end
def self.memory_size
8
end
# only empty initialization for now
#
# internally we store keys and values in lists, which means this does **not** scale well
def initialize
super()
self.i_keys = List.new()
self.i_values = List.new()
@i_keys = List.new()
@i_values = List.new()
end
def keys
i_keys.dup
@i_keys.dup
end
def values
i_values.dup
@i_values.dup
end
# are there any key/value items in the list
def empty?
i_keys.empty?
@i_keys.empty?
end
# How many key/value pairs there are
def length()
return i_keys.get_length()
return @i_keys.get_length()
end
def next_value(val)
return i_values.next_value(val)
return @i_values.next_value(val)
end
# get a value fot the given key
@ -46,7 +49,7 @@ module Parfait
def get(key)
index = key_index(key)
if( index )
i_values.get(index)
@i_values.get(index)
else
nil
end
@ -59,17 +62,17 @@ module Parfait
# private method
def key_index(key)
i_keys.index_of(key)
@i_keys.index_of(key)
end
# set key with value, returns value
def set(key , value)
index = key_index(key)
if( index )
i_values.set(index , value)
@i_values.set(index , value)
else
i_keys.push(key)
i_values.push(value)
@i_keys.push(key)
@i_values.push(value)
end
value
end
@ -82,9 +85,9 @@ module Parfait
# yield to each key value pair
def each
index = 0
while index < i_keys.get_length
key = i_keys.get(index)
value = i_values.get(index)
while index < @i_keys.get_length
key = @i_keys.get(index)
value = @i_values.get(index)
yield key , value
index = index + 1
end

View File

@ -14,15 +14,21 @@
module Parfait
class Factory < Object
attr :type , :for_type , :next_object , :reserve , :attribute_name , :page_size
attr_reader :for_type , :next_object , :reserve , :attribute_name , :page_size
def self.type_length
6
end
def self.memory_size
8
end
# initialize for a given type (for_type). The attribute that is used to create the
# list is the first that starts with next_ . "next" itself would have been nice and general
# but is a keyword, so no go.
def initialize(type , page)
self.for_type = type
self.attribute_name = type.names.find {|name| name.to_s.start_with?("next")}
self.page_size = page
@for_type = type
@attribute_name = type.names.find {|name| name.to_s.start_with?("next")}
@page_size = page
raise "No next found for #{type.class_name}" unless attribute_name
end
@ -32,7 +38,7 @@ module Parfait
# used, as it get's called from risc (or will)
def get_next_object
unless( next_object )
self.next_object = reserve
@next_object = reserve
get_more
end
get_head
@ -41,7 +47,7 @@ module Parfait
# this gets the head of the freelist, swaps it out agains the next and returns it
def get_head
nekst = next_object
self.next_object = get_next_for(nekst)
@next_object = get_next_for(nekst)
return nekst
end
@ -49,15 +55,15 @@ module Parfait
# and rebuilt the reserve (get_next already instantiates the reserve)
#
def get_more
self.reserve = get_chain
last_link = self.reserve
count = self.page_size / 100
@reserve = get_chain
last_link = @reserve
count = @page_size / 100
count = 15 if count < 15
while(count > 0)
last_link = get_next_for(last_link)
count -= 1
end
self.next_object = get_next_for(last_link)
@next_object = get_next_for(last_link)
set_next_for( last_link , nil )
self
end
@ -65,10 +71,10 @@ module Parfait
# this initiates the syscall to get more memory.
# it creates objects from the mem and link them into a chain
def get_chain
raise "type is nil" unless self.for_type
first = sys_mem( for_type , self.page_size)
raise "type is nil" unless @for_type
first = sys_mem( for_type , @page_size)
chain = first
counter = self.page_size
counter = @page_size
while( counter > 0)
nekst = get_next_raw( chain )
set_next_for(chain, nekst)
@ -87,7 +93,7 @@ module Parfait
# set the next_* attribute of the given object, with the value.
# the attribute name is determined in initialize
def set_next_for(object , value)
object.send("#{attribute_name}=".to_sym , value)
object.send("_set_#{attribute_name}".to_sym , value)
end
# Return the object _after the given one. In memory terms the next object starts

View File

@ -6,17 +6,7 @@
module Parfait
class Integer < Data4
attr :type, :next_integer
def initialize(value , next_i = nil)
super()
self.next_integer = next_i
set_internal_word(Integer.integer_index, value)
end
def value
get_internal_word(Integer.integer_index)
end
attr_reader :next_integer
def self.type_length
2 # 0 type, 1 next_i
@ -30,6 +20,16 @@ module Parfait
type_length
end
def initialize(value , next_i = nil)
super()
@next_integer = next_i
set_internal_word(Integer.integer_index, value)
end
def value
get_internal_word(Integer.integer_index)
end
def to_s
"Integer " + value.to_s
end
@ -39,6 +39,9 @@ module Parfait
set_internal_word(Integer.integer_index, value)
end
def _set_next_integer(nekst)
@next_integer = nekst
end
# :integer?, :odd?, :even?, :upto, :downto, :times, :succ, :next, :pred, :chr, :ord, :to_i, :to_int, :floor,
# :ceil, :truncate, :round, :gcd, :lcm, :gcdlcm, :numerator, :denominator, :to_r, :rationalize,
# :singleton_method_added, :coerce, :i, :+, :-, :fdiv, :div, :divmod, :%, :modulo, :remainder, :abs, :magnitude,

View File

@ -7,7 +7,7 @@
module Parfait
class List < Data16
attr :type, :indexed_length , :next_list
attr_reader :indexed_length , :next_list
def self.type_length
3 # 0 type , 1 length , 2 - next_list
@ -18,20 +18,20 @@ module Parfait
def initialize
super
self.indexed_length = 0
@indexed_length = 0
end
def data_length
self.class.data_length
end
def get_length
r = indexed_length
r = @indexed_length
r.nil? ? 0 : r
end
def ensure_next
self.next_list = List.new unless next_list
self.next_list
@next_list = List.new unless @next_list
@next_list
end
# set the value at index.
@ -43,7 +43,7 @@ module Parfait
end
if index >= data_length
ensure_next
next_list.set( index - data_length , value)
@next_list.set( index - data_length , value)
else
set_internal_word( index + self.class.type_length, value)
end
@ -54,8 +54,8 @@ module Parfait
def get( index )
raise "Only positive indexes, #{index}" if index < 0
if index >= data_length
return nil unless next_list
return next_list.get( index - data_length)
return nil unless @next_list
return @next_list.get( index - data_length)
else
ret = nil
if(index < get_length)
@ -273,7 +273,7 @@ module Parfait
end
private
def internal_set_length( i )
self.indexed_length = i
@indexed_length = i
end
end

View File

@ -11,22 +11,15 @@
module Parfait
class Message < Object
# :next_message => :Message, :receiver => :Object, :frame => :NamedList ,
# :return_address => :Integer, :return_value => :Integer,
# :caller => :Message , :name => :Word , :arguments => :NamedList
attr :type, :next_message
attr :receiver
attr :return_address, :return_value
attr :caller , :method
attr :arguments_given
attr :arg1 , :arg2, :arg3, :arg4, :arg5, :arg6
attr :locals_used
attr :local1 , :local2, :local3, :local4, :local5, :local6 ,:local7,:local8
attr :local9 ,:local10, :local11 , :local12, :local13, :local14
attr_reader :next_message, :receiver
attr_reader :return_address, :return_value
attr_reader :caller , :method
attr_reader :arguments_given, :arg1 , :arg2, :arg3, :arg4, :arg5, :arg6
attr_reader :locals_used, :local1 , :local2, :local3, :local4, :local5, :local6 ,:local7
attr_reader :local8 , :local9 ,:local10, :local11 , :local12, :local13, :local14
def self.type_length
31
30
end
def self.memory_size
32
@ -40,25 +33,38 @@ module Parfait
def initialize( )
super()
self.locals_used = Parfait::Integer.new(0)
self.arguments_given = Parfait::Integer.new(0)
@locals_used = Parfait::Integer.new(0)
@arguments_given = Parfait::Integer.new(0)
end
public :initialize
def set_receiver(rec)
self.receiver = rec
@receiver = rec
end
def set_caller(caller)
caller = caller
@caller = caller
end
def get_type_for(name)
index = type.get_index(name)
index = @type.get_index(name)
get_at(index)
end
def method_name
return "" unless @method
return "" unless @method == NilClass
@method.name
end
def to_s
"Message:#{method&.name}(#{arguments_given})"
"Message:#{method_name}(#{@arguments_given})"
end
def _set_next_message(nekst)
@next_message = nekst
end
def _set_caller(prev)
@caller = prev
end
end
end

View File

@ -20,25 +20,28 @@ module Parfait
class MetaClass < Object
include Behaviour
attr :type, :instance_type , :instance_methods , :clazz
attr_reader :instance_type , :instance_methods , :clazz
def self.type_length
4
end
def self.memory_size
8
end
def initialize( clazz )
super()
self.clazz = clazz
self.instance_methods = List.new
@clazz = clazz
@instance_methods = List.new
set_instance_type( clazz.get_type() )
end
def rxf_reference_name
clazz.name
@clazz.name
end
def inspect
"MetaClass(#{clazz.name})"
"MetaClass(#{@clazz.name})"
end
def add_method_for(name , type , frame , body )
@ -49,23 +52,23 @@ module Parfait
def add_method(method)
raise "Must be untyped method #{method}" unless method.is_a? Parfait::VoolMethod
instance_methods.push(method)
@instance_methods.push(method)
end
def get_method(name)
instance_methods.find{|m| m.name == name }
@instance_methods.find{|m| m.name == name }
end
# adding an instance changes the instance_type to include that variable
def add_instance_variable( name , type)
self.instance_type = instance_type.add_instance_variable( name , type )
@instance_type = @instance_type.add_instance_variable( name , type )
end
# setting the type generates all methods for this type
# (or will do, once we store the methods code to do that)
def set_instance_type( type )
raise "type must be type #{type}" unless type.is_a?(Type)
self.instance_type = type
raise "type must be type #{type.class}:#{type}" unless type.is_a?(Type)
@instance_type = type
end
# Nil name means no superclass, and so nil returned

View File

@ -23,8 +23,6 @@
module Parfait
class NamedList < Object
attr :type
def self.memory_size
16
end

View File

@ -14,7 +14,18 @@
module Parfait
class Object
attr :type
attr_reader :type
def self.type_length
1
end
def self.memory_size
4
end
def type=(t)
set_type( t )
end
def == other
self.object_id == other.object_id
@ -34,38 +45,39 @@ module Parfait
# private
def set_type(typ)
raise "not type" + typ.class.to_s + "in " + object_id.to_s(16) unless typ.is_a?(Type)
self.type = typ
@type = typ
end
# so we can keep the raise in get_type
def has_type?
! type.nil?
! @type.nil?
end
def get_type()
raise "No type " + self.object_id.to_s(16) + ":" + self.class.name unless has_type?
type
@type
end
def get_instance_variables
type.names
@type.names
end
def get_instance_variable( name )
index = instance_variable_defined(name)
#puts "getting #{name} at #{index}"
#raise "at :#{name}:" if name.to_s[0] == "@"
return nil if index == nil
return get_internal_word(index)
end
def set_instance_variable( name , value )
index = instance_variable_defined(name)
#puts "setting #{name} at #{index}"
return nil if index == nil
return set_internal_word(index , value)
end
def instance_variable_defined( name )
type.variable_index(name)
@type.variable_index(name)
end
# objects only come in lengths of multiple of 8 words / 32 bytes
@ -81,7 +93,7 @@ module Parfait
end
def padded_length
Object.padded_words( type.instance_length )
Object.padded_words( @type.instance_length )
end
# parfait versions are deliberately called different, so we "relay"
@ -90,13 +102,5 @@ module Parfait
get_instance_variables.to_a.collect{ |n| n.to_s.to_sym }
end
# name comes in as a ruby var name
def instance_variable_ged( name )
#TODO the [] shoud be a range, but currenly that is not processed in RubyCompiler
var = get_instance_variable name.to_s[1 , name.to_s.length - 1].to_sym
#puts "getting #{name} #{var}"
var
end
end
end

View File

@ -30,16 +30,22 @@ module Parfait
class Space < Object
attr :type, :classes , :types , :factories
attr :true_object , :false_object , :nil_object
attr_reader :classes , :types , :factories
attr_reader :true_object , :false_object , :nil_object
def self.type_length
7
end
def self.memory_size
8
end
def initialize( classes , pages)
self.classes = classes
self.types = Dictionary.new
@classes = classes
@types = Dictionary.new
classes.each do |name , cl|
add_type(cl.instance_type)
end
self.factories = Dictionary.new
@factories = Dictionary.new
[:Integer , :ReturnAddress , :Message].each do |fact_name|
for_type = classes[fact_name].instance_type
page_size = pages[fact_name] || 1024
@ -49,23 +55,16 @@ module Parfait
end
init_message_chain( factories[ :Message ].reserve )
init_message_chain( factories[ :Message ].next_object )
self.true_object = Parfait::TrueClass.new
self.false_object = Parfait::FalseClass.new
self.nil_object = Parfait::NilClass.new
end
def self.type_length
12
end
def self.memory_size
16
@true_object = Parfait::TrueClass.new
@false_object = Parfait::FalseClass.new
@nil_object = Parfait::NilClass.new
end
def init_message_chain( message )
prev = nil
while(message)
message.initialize
message.caller = prev if prev
message._set_caller(prev) if prev
prev = message
message = message.next_message
end
@ -73,18 +72,18 @@ module Parfait
# return the factory for the given type
# or more exactly the type that has a class_name "name"
def get_factory_for(name)
factories[name]
@factories[name]
end
# use the factory of given name to generate next_object
# just a shortcut basically
def get_next_for(name)
factories[name].get_next_object
@factories[name].get_next_object
end
# yield each type in the space
def each_type
types.values.each do |type|
@types.values.each do |type|
yield(type)
end
end
@ -100,7 +99,7 @@ module Parfait
# get a type by the type hash (the hash is what uniquely identifies the type)
def get_type_for( hash )
types[hash]
@types[hash]
end
# all methods form all types
@ -137,7 +136,7 @@ module Parfait
# return nili if no such class. Use bang version if create should be implicit
def get_class_by_name( name )
raise "get_class_by_name #{name}.#{name.class}" unless name.is_a?(Symbol)
c = classes[name]
c = @classes[name]
#puts "MISS, no class #{name} #{name.class}" unless c # " #{classes}"
#puts "CLAZZ, #{name} #{c.get_type.get_length}" if c
c
@ -159,7 +158,7 @@ module Parfait
raise "create_class #{superclass.class}" unless superclass.is_a? Symbol
type = get_type_by_class_name(superclass)
c = Class.new(name , superclass , type )
classes[name] = c
@classes[name] = c
end
def rxf_reference_name

View File

@ -36,7 +36,7 @@ module Parfait
class Type < Object
attr :type, :object_class , :names , :types , :methods
attr_reader :object_class , :names , :types , :methods
def self.type_length
5
@ -57,18 +57,18 @@ module Parfait
# this part of the init is seperate because at boot time we can not use normal new
# new is overloaded to grab the type from space, and before boot, that is not set up
def init_lists(hash)
self.methods = nil
self.names = List.new
self.types = List.new
@methods = nil
@names = List.new
@types = List.new
raise "No type Type in #{hash}" unless hash[:type]
private_add_instance_variable(:type , hash[:type]) #first
hash.each do |name , type|
private_add_instance_variable(name , type) unless name == :type
hash.keys.each do |name |
private_add_instance_variable(name , hash[name]) unless name == :type
end
end
def class_name
object_class.name
@object_class.name
end
def to_s
@ -87,8 +87,8 @@ module Parfait
def method_names
names = List.new
return names unless methods
methods.each_method do |method|
return names unless @methods
@methods.each_method do |method|
names.push method.name
end
names
@ -118,19 +118,19 @@ module Parfait
if get_method( method.name )
remove_method(method.name)
end
method.set_next( methods )
self.methods = method
method.set_next( @methods )
@methods = method
#puts "#{self.name} add #{method.name}"
method
end
def remove_method( method_name )
raise "No such method #{method_name} in #{self.name}" unless methods
if( methods.name == method_name)
self.methods = methods.next_callable
raise "No such method #{method_name} in #{self.name}" unless @methods
if( @methods.name == method_name)
@methods = @methods.next_callable
return true
end
method = methods
method = @methods
while(method && method.next_callable)
if( method.next_callable.name == method_name)
method.set_next( method.next_callable.next_callable )
@ -144,8 +144,8 @@ module Parfait
def get_method( fname )
raise "get_method #{fname}.#{fname.class}" unless fname.is_a?(Symbol)
return nil unless methods
methods.each_method do |m|
return nil unless @methods
@methods.each_method do |m|
return m if(m.name == fname )
end
nil
@ -167,9 +167,9 @@ module Parfait
end
def methods_length
return 0 unless methods
return 0 unless @methods
len = 0
methods.each_method { len += 1}
@methods.each_method { len += 1}
return len
end
@ -190,33 +190,33 @@ module Parfait
def set_object_class(oc)
raise "object class should be a class, not #{oc.class}" unless oc.is_a?(Class)
self.object_class = oc
@object_class = oc
end
def instance_length
names.get_length()
@names.get_length()
end
# index of the variable when using get_internal_word
# (get_internal_word is 0 based and 0 is always the type)
def variable_index( name )
has = names.index_of(name)
has = @names.index_of(name)
return nil unless has
raise "internal error #{name}:#{has}" if has < 0
has
end
def get_length()
names.get_length()
@names.get_length()
end
def name_at( index )
raise "No names #{index}" unless names
names.get(index)
raise "No names #{index}" unless @names
@names.get(index)
end
def type_at( index )
types.get(index)
@types.get(index)
end
def type_for( name )
@ -226,11 +226,11 @@ module Parfait
end
def inspect
"Type[#{names.inspect}]"
"Type[#{@names.inspect}]"
end
def rxf_reference_name
"#{object_class.name}_Type"
"#{@object_class.name}_Type"
end
alias :name :rxf_reference_name
@ -243,9 +243,10 @@ module Parfait
end
def each_method(&block)
return unless methods
methods.each_method(&block)
return unless @methods
@methods.each_method(&block)
end
def to_hash
hash = {}
each do |name , type|
@ -284,8 +285,8 @@ module Parfait
def private_add_instance_variable( name , type)
raise "Name shouldn't be nil" unless name
raise "Value Type shouldn't be nil" unless type
names.push(name)
types.push(type)
@names.push(name)
@types.push(type)
end
end

View File

@ -12,13 +12,13 @@ module Parfait
#
class VoolMethod < Object
attr :type, :name , :args_type , :frame_type
attr_reader :name , :args_type , :frame_type
attr_reader :source
def initialize(name , args_type , frame_type , source )
self.name = name
self.args_type = args_type
self.frame_type = frame_type
@name = name
@args_type = args_type
@frame_type = frame_type
@source = source
raise "Name must be symbol" unless name.is_a?(Symbol)
raise "args_type must be type" unless args_type.is_a?(Parfait::Type)
@ -27,13 +27,13 @@ module Parfait
raise "Empty bod" if(@source.is_a?(Vool::Statements) and @source.empty?)
end
def create_callable_method( type )
def create_callable_method_for( type )
raise "create_method #{type.inspect} is not a Type" unless type.is_a? Parfait::Type
type.create_method( name , args_type , frame_type)
type.create_method( @name , @args_type , @frame_type)
end
def compiler_for(self_type)
callable_method = create_callable_method(self_type)
callable_method = create_callable_method_for(self_type)
compiler = Mom::MethodCompiler.new( callable_method )
head = @source.to_mom( compiler )
compiler.add_code(head)

View File

@ -13,7 +13,7 @@ module Parfait
# Object length is measured in non-type cells though
class Word < Data8
attr :type, :char_length
attr_reader :char_length
def self.type_length
2 # 0 type , 1 char_length
@ -26,7 +26,7 @@ module Parfait
# Risc provides methods to create Parfait objects from ruby
def initialize( len )
super()
self.char_length = 0
@char_length = 0
raise "Must init with int, not #{len.class}" unless len.kind_of? ::Integer
raise "Must init with positive, not #{len}" if len < 0
fill_to( len , 32 ) unless len == 0 #32 being ascii space
@ -36,10 +36,10 @@ module Parfait
# return a copy of self
def copy
cop = Word.new( self.length )
cop = Word.new( @char_length )
index = 0
while( index < self.length )
cop.set_char(index , self.get_char(index))
while( index < @char_length )
cop.set_char(index , get_char(index))
index = index + 1
end
cop
@ -47,8 +47,7 @@ module Parfait
# return the number of characters
def length()
obj_len = char_length
return obj_len
@char_length
end
# make every char equal the given one
@ -57,7 +56,7 @@ module Parfait
end
def fill_from_with( from , char )
len = self.length()
len = @char_length
return if from < 0
while( from < len)
set_char( from , char)
@ -68,16 +67,16 @@ module Parfait
# true if no characters
def empty?
return self.length == 0
return @char_length == 0
end
# pad the string with the given character to the given length
#
def fill_to(len , fill_char)
return if len <= 0
old = char_length
old = @char_length
return if old >= len
self.char_length = len
@char_length = len
check_length
fill_from_with( old , fill_char )
end
@ -170,7 +169,7 @@ module Parfait
string = ""
index = 0
#puts "Length = #{char_length}"
while( index < char_length)
while( index < @char_length)
char = get_char(index)
string += char ? char.chr : "*"
index = index + 1
@ -184,12 +183,12 @@ module Parfait
end
def padded_length
Object.padded( 4 * get_type().instance_length + char_length )
Object.padded( 4 * get_type().instance_length + @char_length )
end
private
def check_length
raise "Length out of bounds #{char_length}" if char_length > 1000
raise "Length out of bounds #{char_length}" if @char_length > 1000
end
end

View File

@ -43,6 +43,10 @@ module Risc
@register = register
end
attr_reader :register
def to_s
class_source( register.to_s)
end
end
# A Dynamic yield is very much like a DynamicJump, especially in it's idea

View File

@ -52,6 +52,7 @@ module Risc
raise "Not int #{pos}" unless pos.is_a? Numeric
position = Position.at(pos)
raise "No position at 0x#{pos.to_s(16)}" unless position
log.debug ""
log.debug "Setting Position #{clock}-#{position}, "
set_instruction( position.object )
@clock += 1
@ -60,7 +61,7 @@ module Risc
def set_instruction( instruction )
raise "set to same instruction #{instruction}:#{instruction.class} at #{clock}" if @instruction == instruction
log.debug "Setting Instruction #{instruction.class}"
#log.debug "Setting Instruction #{instruction.class}"
old = @instruction
@instruction = instruction
trigger(:instruction_changed, old , instruction)
@ -121,6 +122,7 @@ module Risc
end
def execute_Branch
label = @instruction.label
log.debug "Branch to Label: #{@instruction.label}"
pos = Position.get(label).at
pos += Parfait::BinaryCode.byte_offset if label.is_a?(Parfait::BinaryCode)
set_pc( pos )
@ -169,6 +171,8 @@ module Risc
raise "error #{@instruction} retrieves nil"
else
value = object.get_internal_word( index )
#log.debug "Getting #{index} from #{object} value=#{value}"
#log.debug "type=#{object.type} get_type=#{object.get_type} intern=#{object.get_internal_word(0)}"
end
log.debug "#{@instruction} == #{object}(#{Position.get(object)}) (#{value}|#{index})"
set_register( @instruction.register , value )

View File

@ -1,31 +1,43 @@
require_relative "fake_memory"
module Parfait
class Object
module Parfait
class Object ; end
class DataObject < Object
def self.allocate
r = super
r.instance_variable_set(:@memory , Risc::FakeMemory.new(r ,self.type_length , self.memory_size))
r
end
# 0 -based index
def get_internal_word(index)
@memory[index]
return super(index) if index < self.class.type_length
@memory[ index ]
end
# 0 -based index
def set_internal_word(index , value)
@memory[index] = value
value
return super(index,value) if index < self.class.type_length
@memory[ index ] = value
end
end
class Object
# 0 -based index
def get_internal_word(index)
return @type if index == Parfait::TYPE_INDEX
name = Parfait.name_for_index(self , index)
return nil unless name
instance_eval("@#{name}")
end
def self.attr( *attributes )
attributes = [attributes] unless attributes.is_a?(Array)
attributes.each do |name|
define_getter(name)
define_setter(name)
end
# 0 -based index
def set_internal_word(index , value)
name = Parfait.name_for_index(self , index)
raise "no string #{name.class}" unless name.is_a?(Symbol)
instance_eval("@#{name}=value" )
value
end
def self.variable_index( name)
@ -39,22 +51,6 @@ module Parfait
i + 1
end
def self.define_getter(name)
index = variable_index(name)
define_method(name) do
#puts "GETTING #{name} for #{self.class.name} in #{object_id.to_s(16)}"
@memory._get(index)
end
end
def self.define_setter(name)
index = variable_index(name)
define_method("#{name}=".to_sym ) do |value|
#puts "SETTING #{name}= for #{self.class.name} in #{object_id.to_s(16)}"
@memory._set(index , value)
end
end
def self.cattr( *names )
names.each do |ca|
class_eval "@@#{ca} = 0"

View File

@ -181,4 +181,13 @@ module Parfait
Word: {char_length: :Integer , next_word: :Word} ,
}
end
def self.name_for_index(object , index)
return :type if index == 0
clazz = object.class.name.split("::").last.to_sym
cl = self.type_names[clazz]
keys = cl.keys
keys[index - 1] # -1 because type is excluded in the lists (FIX)
# FIXME Now that we use instance variables in parfait, they should be parsed
# and the type_names generated automatically
end
end

View File

@ -13,6 +13,6 @@ Gem::Specification.new do |s|
s.require_paths = ['lib']
s.summary = 'RubyX is a native object vm without any c, one day possibly a ruby vm'
s.add_dependency "parser" , "~> 2.6.0"
s.add_dependency "parser" , "~> 2.5.0"
s.add_dependency "rx-file" , "~> 0.3"
end

View File

@ -39,11 +39,6 @@ module Risc
produced = produce_body
assert_equal Parfait::NilClass , produced.next(5).constant.class
end
def est_nil_check
produced = produce_body
assert_equal Label , produced.next(4).label.class
assert_equal produced.next(12) , produced.next(4).label
end
def test_true_label
produced = produce_body
assert produced.next(8).name.start_with?("true_label")

View File

@ -19,7 +19,7 @@ module Parfait
assert_nil @mess.method
end
def test_message_next_set
@mess.next_message = :next_message
@mess._set_next_message :next_message
assert_equal :next_message , @mess.next_message
end
def test_message_type_set
@ -27,7 +27,7 @@ module Parfait
assert_equal @type , @mess.get_type
end
def test_attribute_index
@mess.next_message = :message
@mess._set_next_message :message
assert_equal Parfait::Type , @mess.get_type.class
end

View File

@ -68,7 +68,8 @@ module Parfait
end
def test_one_set1
assert_equal 2 , @list.set(0,2)
assert_equal 1 , @list.get_internal_word(1)
# assert_equal 1 , @list.get_internal_word(1)
assert_equal 1 , @list.get_length
assert_equal 2 , @list.get_internal_word(List.type_length)
end
def test_set1_len

View File

@ -46,7 +46,7 @@ module Parfait
assert_equal classes.length , @space.classes.length , @space.classes.keys.inspect
end
def test_types
assert @space.instance_variable_ged("@types").is_a? Parfait::Dictionary
assert @space.types.is_a? Parfait::Dictionary
end
def test_types_attr
assert @space.types.is_a? Parfait::Dictionary
@ -57,7 +57,7 @@ module Parfait
end
end
def test_types_hashes
types = @space.instance_variable_ged("@types")
types = @space.types
types.each do |has , type|
assert has.is_a?(::Integer) , has.inspect
end

View File

@ -5,7 +5,7 @@ module Parfait
def setup
super
@types = @space.instance_variable_ged("@types")
@types = @space.types
@first = @types.values.first
end

View File

@ -38,8 +38,10 @@ module Risc
def test_integer_positions
objects = Collector.collect_space(@linker)
int = Parfait.object_space.get_next_for(:Integer)
count = 0
while(int)
assert Position.set?(int) , "INt #{int.object_id}"
count += 1
assert Position.set?(int) , "INT #{int.object_id.to_s(16)} , count #{count}"
int = int.next_integer
end
end
@ -66,7 +68,7 @@ module Risc
count = 0
while(int)
count += 1
assert Position.set?(int) , "INT #{int.object_id} , count #{count}"
assert Position.set?(int) , "INT #{int.object_id.to_s(16)} , count #{count}"
int = int.next_integer
end
end

View File

@ -15,7 +15,7 @@ module Risc
mains = @linker.assemblers.find_all{|asm| asm.callable.name == :main }
assert_equal 1 , mains.length
end
def est_assembler_num
def test_assembler_num
assert_equal 22 , @linker.assemblers.length
end
end