move parfait adapter into parfait ruby

in the future parfait will be coded in some and translated back into
ruby to “adapt”
until then, all ruby code is the adapter
This commit is contained in:
Torsten Ruger 2015-11-18 11:55:29 +02:00
parent aa30864fcb
commit 40d81681b5
16 changed files with 155 additions and 208 deletions

View File

@ -14,3 +14,4 @@ require "parfait/layout"
require "parfait/message"
require "parfait/frame"
require "parfait/space"
require "parfait/symbol_adapter"

View File

@ -84,14 +84,8 @@ module Parfait
self
end
# :rehash, :to_hash, :to_h, :to_a, :[], :fetch, :[]=, :store, :default, :default=, :default_proc, :default_proc=,
# :key, :index, :size, :length, :empty?, :each_value, :each_key, :each_pair, :each, :keys, :values,
# :values_at, :shift, :delete, :delete_if, :keep_if, :select, :select!, :reject, :reject!, :clear, :invert,
# :update, :replace, :merge!, :merge, :assoc, :rassoc, :flatten, :include?, :member?, :has_key?, :has_value?,
# :key?, :value?, :compare_by_identity, :compare_by_identity?, :entries, :sort, :sort_by, :grep, :count, :find,
# :detect, :find_index, :find_all, :collect, :map, :flat_map, :collect_concat, :inject, :reduce, :partition,
# :group_by, :first, :all?, :any?, :one?, :none?, :min, :max, :minmax, :min_by, :max_by, :minmax_by, :each_with_index,
# :reverse_each, :each_entry, :each_slice, :each_cons, :each_with_object, :zip, :take, :take_while, :drop, :drop_while,
# :cycle, :chunk, :slice_before, :lazy
def to_sof_node(writer , level , ref)
Sof.hash_to_sof_node( self , writer , level , ref)
end
end
end

View File

@ -23,18 +23,30 @@ module Parfait
alias :[] :get
#ruby 2.1 list (just for reference, keep at bottom)
# :at, :fetch, :first, :last, :concat, :<<, :push, :pop, :shift, :unshift, :insert, :each, :each_index, :reverse_each,
# :length, :size, :empty?, :find_index, :index, :rindex, :join, :reverse, :reverse!, :rotate, :rotate!,
# :sort, :sort!, :sort_by!, :collect, :collect!, :map, :map!, :select, :select!, :keep_if,
# :values_at, :delete, :delete_at, :delete_if, :reject, :reject!, :zip, :transpose, :replace, :clear,
# :fill, :include?, :slice, :slice!, :assoc, :rassoc, :+, :*, :-, :&, :|, :uniq, :uniq!, :compact, :compact!,
# :flatten, :flatten!, :count, :shuffle!, :shuffle, :sample, :cycle, :permutation, :combination,
# :repeated_permutation, :repeated_combination, :product, :take, :take_while, :drop, :drop_while,
# :bsearch, :pack, :entries, :sort_by, :grep, :find, :detect, :find_all, :flat_map, :collect_concat,
# :inject, :reduce, :partition, :group_by, :all?, :any?, :one?, :none?,
# :min, :max, :minmax, :min_by, :max_by, :minmax_by, :member?, :each_with_index, :each_entry,
# :each_slice, :each_cons, :each_with_object, :chunk, :slice_before, :lazy
def to_sof_node(writer , level , ref )
Sof.array_to_sof_node(self , writer , level , ref )
end
def to_a
array = []
index = 1
while( index <= self.get_length)
array[index - 1] = get(index)
index = index + 1
end
array
end
end
# new list from ruby array to be precise
def self.new_list array
list = Parfait::List.new
list.set_length array.length
index = 1
while index <= array.length do
list.set(index , array[index - 1])
index = index + 1
end
list
end
end

View File

@ -32,7 +32,8 @@ module Parfait
self.locals = List.new
end
attributes [:name , :source , :instructions , :binary ,:arguments , :for_class, :locals ]
# not part of the parfait model, hence ruby accessor
attr_accessor :source
# determine whether this method has an argument by the name
def has_arg name

View File

@ -28,6 +28,30 @@ module Parfait
object
end
# Objects memory functions. Object memory is 1 based
# but we implement it with ruby array (0 based) and don't use 0
# These are the same functions that Builtin implements for run-time
include Padding
include Positioned
def fake_init
@memory = Array.new(16)
@position = nil
self # for chaining
end
# 1 -based index
def get_internal(index)
@memory[index]
end
# 1 -based index
def set_internal(index , value)
raise "failed init for #{self.class}" unless @memory
raise "Word[#{index}] = " if((self.class == Parfait::Word) and value.nil? )
@memory[index] = value
value
end
def self.attributes names
names.each{|name| attribute(name) }
end
@ -101,15 +125,17 @@ module Parfait
padded_words( get_layout().instance_length )
end
# Object
# :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint,
# :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods,
# :private_methods, :public_methods, :get_instance_variables, :get_instance_variable, :set_instance_variable, :instance_variable_defined?,
# :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?,
# :extend, :display, :method, :public_method, :singleton_method, :define_singleton_method,
# :object_id, :to_enum, :enum_for
#
# BasicObject
# :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__
# parfait versions are deliberately called different, so we "relay"
# have to put the "@" on the names for sof to take them off again
def instance_variables
get_instance_variables.to_a.collect{ |n| "@#{n}".to_sym }
end
# name comes in as a ruby @var name
def instance_variable_get name
var = get_instance_variable name.to_s[1 .. -1].to_sym
#puts "getting #{name} #{var}"
var
end
end
end

View File

@ -0,0 +1,43 @@
class Symbol
include Positioned
include Padding
def has_layout?
true
end
def get_layout
l = Register.machine.space.classes[:Word].object_layout
#puts "LL #{l.class}"
l
end
def padded_length
padded to_s.length + 4
end
# not the prettiest addition to the game, but it wasn't me who decided symbols are frozen in 2.x
def cache_positions
unless defined?(@@symbol_positions)
@@symbol_positions = {}
end
@@symbol_positions
end
def position
pos = cache_positions[self]
if pos == nil
str = "position accessed but not set, "
str += "Machine has object=#{Register.machine.objects.has_key?(self.object_id)} "
raise str + " for Symbol:#{self}"
end
pos
end
def position= pos
# resetting of position used to be error, but since relink and dynamic instruction size it is ok.
# in measures (of 32)
old = cache_positions[self]
if old != nil and ((old - pos).abs > 20000)
raise "position set again #{pos}!=#{old} for #{self}"
end
cache_positions[self] = pos
end
end

View File

@ -147,6 +147,26 @@ module Parfait
return true
end
def == other
return false unless other.is_a?(String) or other.is_a?(Word)
as_string = self.to_string
unless other.is_a? String
other = other.to_string
end
as_string == other
end
def to_string
string = ""
index = 1
while( index <= self.char_length)
char = get_char(index)
string += char ? char.chr : "*"
index = index + 1
end
string
end
# as we answered is_value? with true, sof will create a basic node with this string
def to_sof
"'" + to_s + "'"
@ -161,4 +181,15 @@ module Parfait
raise "Length out of bounds #{self.char_length}" if self.char_length > 1000
end
end
# Word from string
def self.new_word( string )
string = string.to_s if string.is_a? Symbol
word = Parfait::Word.new( string.length )
string.codepoints.each_with_index do |code , index |
word.set_char(index + 1 , code)
end
word
end
end

View File

@ -1,9 +1,7 @@
require "register/padding"
require "register/positioned"
require "parfait"
require "register/machine"
#if we are in the ruby run-time / generating an executable
require "register/positioned"
require "register/padding"
require "register/parfait_adapter"
require "soml/compiler"

View File

@ -1,159 +0,0 @@
# Below we define functions (in different classes) that are not part of the run-time
# They are used for the boot process, ie when this codes executes in the vm that builds salama
# To stay sane, we use the same classes that we use later, but "adapt" them to work in ruby
# This affects mainly memory layout
module Register
def self.new_list array
list = Parfait::List.new
list.set_length array.length
index = 1
while index <= array.length do
list.set(index , array[index - 1])
index = index + 1
end
list
end
# Functions to generate parfait objects
def self.new_word( string )
string = string.to_s if string.is_a? Symbol
word = Parfait::Word.new( string.length )
string.codepoints.each_with_index do |code , index |
word.set_char(index + 1 , code)
end
word
end
end
class Symbol
include Positioned
include Padding
def has_layout?
true
end
def get_layout
l = Register.machine.space.classes[:Word].object_layout
#puts "LL #{l.class}"
l
end
def padded_length
padded to_s.length + 4
end
# not the prettiest addition to the game, but it wasn't me who decided symbols are frozen in 2.x
def cache_positions
unless defined?(@@symbol_positions)
@@symbol_positions = {}
end
@@symbol_positions
end
def position
pos = cache_positions[self]
if pos == nil
str = "position accessed but not set, "
str += "Machine has object=#{Register.machine.objects.has_key?(self.object_id)} "
raise str + " for Symbol:#{self}"
end
pos
end
def position= pos
# resetting of position used to be error, but since relink and dynamic instruction size it is ok.
# in measures (of 32)
old = cache_positions[self]
if old != nil and ((old - pos).abs > 20000)
raise "position set again #{pos}!=#{old} for #{self}"
end
cache_positions[self] = pos
end
end
module Parfait
# Objects memory functions. Object memory is 1 based
# but we implement it with ruby array (0 based) and don't use 0
# These are the same functions that Builtin implements for run-time
class Object
include Padding
include Positioned
def fake_init
@memory = Array.new(16)
@position = nil
self # for chaining
end
# 1 -based index
def get_internal(index)
@memory[index]
end
# 1 -based index
def set_internal(index , value)
raise "failed init for #{self.class}" unless @memory
raise "Word[#{index}] = " if((self.class == Parfait::Word) and value.nil? )
@memory[index] = value
value
end
end
class List
def to_sof_node(writer , level , ref )
Sof.array_to_sof_node(self , writer , level , ref )
end
def to_a
array = []
index = 1
while( index <= self.get_length)
array[index - 1] = get(index)
index = index + 1
end
array
end
end
class Dictionary
def to_sof_node(writer , level , ref)
Sof.hash_to_sof_node( self , writer , level , ref)
end
end
class Method
attr_accessor :source
end
class Word
def == other
return false unless other.is_a?(String) or other.is_a?(Word)
as_string = self.to_string
unless other.is_a? String
other = other.to_string
end
as_string == other
end
def to_string
string = ""
index = 1
while( index <= self.char_length)
char = get_char(index)
string += char ? char.chr : "*"
index = index + 1
end
string
end
end
## sof related stuff
class Object
# parfait versions are deliberately called different, so we "relay"
# have to put the "@" on the names for sof to take them off again
def instance_variables
get_instance_variables.to_a.collect{ |n| "@#{n}".to_sym }
end
# name comes in as a ruby @var name
def instance_variable_get name
var = get_instance_variable name.to_s[1 .. -1].to_sym
#puts "getting #{name} #{var}"
var
end
end
end

View File

@ -74,7 +74,7 @@ module Soml
end
arguments << arg
end
@method = clazz.create_instance_method( method_name , Register.new_list(arguments))
@method = clazz.create_instance_method( method_name , Parfait.new_list(arguments))
self
end

View File

@ -36,7 +36,7 @@ module Soml
end
def on_string expression
value = Register.new_word expression.first.to_sym
value = Parfait.new_word expression.first.to_sym
reg = use_reg :Word
Register.machine.constants << value
add_code Register::LoadConstant.new( expression, value , reg )

View File

@ -8,7 +8,7 @@ class TestClass < MiniTest::Test
end
def foo_method for_class = :Try
args = Register.new_list [ Parfait::Variable.new(:Integer , :bar )]
args = Parfait.new_list [ Parfait::Variable.new(:Integer , :bar )]
::Parfait::Method.new @space.get_class_by_name(for_class) , :foo , args
end
@ -42,7 +42,7 @@ class TestClass < MiniTest::Test
end
end
def test_create_method
@try.create_instance_method :bar, Register.new_list( [ Parfait::Variable.new(:Integer , :bar )])
@try.create_instance_method :bar, Parfait.new_list( [ Parfait::Variable.new(:Integer , :bar )])
assert_equal ":bar" , @try.method_names.inspect
end
def test_method_get

View File

@ -8,7 +8,7 @@ class TestMeta < MiniTest::Test
end
def foo_method for_class = :Try
args = Register.new_list [ Parfait::Variable.new(:Integer , :bar )]
args = Parfait.new_list [ Parfait::Variable.new(:Integer , :bar )]
::Parfait::Method.new @space.get_class_by_name(for_class) , :foo , args
end
@ -24,7 +24,7 @@ class TestMeta < MiniTest::Test
end
def test_create_method
@try.create_instance_method :bar, Register.new_list( [ Parfait::Variable.new(:Integer , :bar )])
@try.create_instance_method :bar, Parfait.new_list( [ Parfait::Variable.new(:Integer , :bar )])
assert_equal ":bar" , @try.method_names.inspect
end
def test_add_method

View File

@ -4,7 +4,7 @@ class TestMethod < MiniTest::Test
def setup
obj = Register.machine.boot.space.get_class_by_name(:Object)
args = Register.new_list [ Parfait::Variable.new(:Integer , :bar )]
args = Parfait.new_list [ Parfait::Variable.new(:Integer , :bar )]
@method = ::Parfait::Method.new obj , :foo , args
end

View File

@ -9,14 +9,14 @@ class TestCompat < MiniTest::Test
def test_list_create_from_array
array = [1,2,3]
list = Register.new_list(array)
list = Parfait.new_list(array)
assert_equal array , list.to_a
end
def test_word_create_from_string
string = "something"
word = Register.new_word(string)
assert_equal word , Register.new_word(string)
word = Parfait.new_word(string)
assert_equal word , Parfait.new_word(string)
assert_equal string , word.to_string
end
end

View File

@ -5,12 +5,12 @@ class TestPositioning < MiniTest::Test
Register.machine.boot unless Register.machine.booted
end
def test_list1
list = Register.new_list([1])
list = Parfait.new_list([1])
list.set_layout( Parfait::Layout.new Object)
assert_equal 32 , list.padded_length
end
def test_list5
list = Register.new_list([1,2,3,4,5])
list = Parfait.new_list([1,2,3,4,5])
list.set_layout( Parfait::Layout.new Object)
assert_equal 32 , list.padded_length
end