moved the whole parfait into its namespace/module

This commit is contained in:
Torsten Ruger 2015-05-11 18:55:49 +03:00
parent a552e3fbce
commit ab870e3323
13 changed files with 245 additions and 208 deletions

View File

@ -1,17 +1,17 @@
### Parfait: a thin layer ### Parfait: a thin layer
Parfait is the run-time of the vm. Parfait is the run-time of the **vm**.
To be more precise, it is that part of the run-time that can be expressed in ruby. To be more precise, it is that part of the run-time that can be expressed in ruby.
The run-time needs to contain quite a lot of functionality for a dynamic system. The run-time needs to contain quite a lot of functionality for a dynamic system.
And a large part of that functionality must actually be used at compile time too. And a large part of that functionality must actually be used at compile time too.
We reuse the Parfait code at compile-time, by inlining it. We reuse the Parfait code at compile-time, by inlining it.
A work in progress that started from here : http://salama.github.io/2014/06/10/more-clarity.html went on here A work in progress that started from here : http://salama.github.io/2014/06/10/more-clarity.html went on here
http://salama.github.io/2014/07/05/layers-vs-passes.html http://salama.github.io/2014/07/05/layers-vs-passes.html
A step back: the code (program) we compile runs at run - time. A step back: the code (program) we compile runs at run - time.
And so does parfait. So all we have to do is compile it with the program. And so does parfait. So all we have to do is compile it with the program.
And thus parfait can be used at run-time. And thus parfait can be used at run-time.
@ -19,7 +19,7 @@ And thus parfait can be used at run-time.
It's too simple: just slips off the mind like a fish into water. It's too simple: just slips off the mind like a fish into water.
Parfait has a brother, the Builtin module. Builtin contains everything that can not be coded in ruby, Parfait has a brother, the Builtin module. Builtin contains everything that can not be coded in ruby,
but we stil need (things like array access). but we still need (things like array access).
#### Example: Message send #### Example: Message send
@ -27,10 +27,10 @@ It felt a little stupid that it took me so long to notice that sending a message
existing ruby method Object.send existing ruby method Object.send
Off course Object.send takes symbol and the arguments and has the receiver, so all the elements of our Off course Object.send takes symbol and the arguments and has the receiver, so all the elements of our
Messaage are there. And the process that Object.send needs to do is exactly that: Messaage are there. And the process that Object.send needs to do is exactly that:
send that message, ie find the correct method according to the old walk up the inheritance tree rules and dispatch it. send that message, ie find the correct method according to the old walk up the inheritance tree rules and dispatch it.
And as all this happens at runtime, "all" we have to do is code this logic. And since it is at runtime, And as all this happens at runtime, "all" we have to do is code this logic. And since it is at runtime,
we can do it in ruby (as i said, this get's compiled and run, just like the program). we can do it in ruby (as i said, this get's compiled and run, just like the program).
But what about the infinite loop problem: But what about the infinite loop problem:
@ -42,3 +42,16 @@ Part of those are some that we just don't allow to be overridden.
Also what in ruby is object.send is Message.send in salama, as it is the message we are sending and Also what in ruby is object.send is Message.send in salama, as it is the message we are sending and
which defines all the data we need (not the object). The object receives, it does not send. which defines all the data we need (not the object). The object receives, it does not send.
### Vm vs language- core
Parfait is not the language (ie ruby) core library. Core library functionality differs between
languages and so the language core lib must be on top of the vm parfait.
Also Parfait is meant to be as thin as humanly possibly, so extra (nice to have) functionality
will be in future modules.
So the Namespace of the Runtime is actually Parfait (not nothing as in ruby).
Only in the require does one later have to be clever and see which vm one is running in and either
require or not. Maybe one doesn't even have to be so celver, we'll see (as requiring an existing
module should result in noop)

View File

@ -1,20 +1,23 @@
class Array < Object
#many basic array functions can not be defined in ruby, such as
# get/set/length/add/delete
# so they must be defined as CompiledMethods in Builtin::Kernel
#ruby 2.1 list (just for reference, keep at bottom) module Parfait
# :at, :fetch, :first, :last, :concat, :<<, :push, :pop, :shift, :unshift, :insert, :each, :each_index, :reverse_each, class Array < Object
# :length, :size, :empty?, :find_index, :index, :rindex, :join, :reverse, :reverse!, :rotate, :rotate!, #many basic array functions can not be defined in ruby, such as
# :sort, :sort!, :sort_by!, :collect, :collect!, :map, :map!, :select, :select!, :keep_if, # get/set/length/add/delete
# :values_at, :delete, :delete_at, :delete_if, :reject, :reject!, :zip, :transpose, :replace, :clear, # so they must be defined as CompiledMethods in Builtin::Kernel
# :fill, :include?, :slice, :slice!, :assoc, :rassoc, :+, :*, :-, :&, :|, :uniq, :uniq!, :compact, :compact!,
# :flatten, :flatten!, :count, :shuffle!, :shuffle, :sample, :cycle, :permutation, :combination, #ruby 2.1 list (just for reference, keep at bottom)
# :repeated_permutation, :repeated_combination, :product, :take, :take_while, :drop, :drop_while, # :at, :fetch, :first, :last, :concat, :<<, :push, :pop, :shift, :unshift, :insert, :each, :each_index, :reverse_each,
# :bsearch, :pack, :entries, :sort_by, :grep, :find, :detect, :find_all, :flat_map, :collect_concat, # :length, :size, :empty?, :find_index, :index, :rindex, :join, :reverse, :reverse!, :rotate, :rotate!,
# :inject, :reduce, :partition, :group_by, :all?, :any?, :one?, :none?, # :sort, :sort!, :sort_by!, :collect, :collect!, :map, :map!, :select, :select!, :keep_if,
# :min, :max, :minmax, :min_by, :max_by, :minmax_by, :member?, :each_with_index, :each_entry, # :values_at, :delete, :delete_at, :delete_if, :reject, :reject!, :zip, :transpose, :replace, :clear,
# :each_slice, :each_cons, :each_with_object, :chunk, :slice_before, :lazy # :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
end
end end

View File

@ -8,7 +8,9 @@
# The Layout lists the names of the instance variables # The Layout lists the names of the instance variables
# The class keeps a list of instance methods, these have a name and code # The class keeps a list of instance methods, these have a name and code
class Class < Module module Parfait
# ruby 2.1 list (just for reference, keep at bottom) class Class < Module
#:allocate, :new, :superclass # ruby 2.1 list (just for reference, keep at bottom)
#:allocate, :new, :superclass
end
end end

View File

@ -20,10 +20,12 @@
# Also at runtime Messages and Frames remain completely "normal" objects. Ie have layouts and so on. # Also at runtime Messages and Frames remain completely "normal" objects. Ie have layouts and so on.
# Which resolves the dichotomy of objects on the stack or heap. Sama sama. # Which resolves the dichotomy of objects on the stack or heap. Sama sama.
class Frame < Object module Parfait
def initialize locals , temps class Frame < Object
@locals = locals def initialize locals , temps
@tmps = tmps @locals = locals
@tmps = tmps
end
attr_accessor :locals , :tmps
end end
attr_accessor :locals , :tmps
end end

View File

@ -1,72 +1,73 @@
# almost simplest hash imaginable. make good use of arrays # almost simplest hash imaginable. make good use of arrays
class Hash < Object module Parfait
def initialize class Hash < Object
@keys = Array.new() def initialize
@values = Array.new() @keys = Array.new()
end @values = Array.new()
def values() end
@values def values()
end @values
def keys() end
@keys def keys()
end @keys
def empty? end
@keys.empty? def empty?
end @keys.empty?
def length()
return @keys.length()
end
def get(key)
index = key_index(key)
if( index )
@values[index]
else
nil
end end
end
def [](key)
get(key)
end
def key_index(key) def length()
len = @keys.length() return @keys.length()
index = 0 end
found = nil
while(index < len) def get(key)
if( @keys[index] == key) index = key_index(key)
found = index if( index )
break @values[index]
else
nil
end end
index += 1
end end
found def [](key)
end get(key)
end
def set(key , value) def key_index(key)
index = key_index(key) len = @keys.length()
if( index ) index = 0
@keys[index] = value found = nil
else while(index < len)
@keys.push(key) if( @keys[index] == key)
@values.push(value) found = index
break
end
index += 1
end
found
end end
value
def set(key , value)
index = key_index(key)
if( index )
@keys[index] = value
else
@keys.push(key)
@values.push(value)
end
value
end
def []=(key,val)
set(key,val)
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
end end
def []=(key,val)
set(key,val)
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
end end

View File

@ -1,23 +1,25 @@
# Integer class for representing mathods on Integers # Integer class for representing mathods on Integers
# Integers are Values (not Objects), # Integers are Values (not Objects),
# - they have fixed value # - they have fixed value
# - they are immutable # - they are immutable
# you can *not* assign instance variables or methods # you can *not* assign instance variables or methods
# TODO how this idea works with Numeric ? # TODO how this idea works with Numeric ?
class Integer < Value module Parfait
class Integer < Value
# :integer?, :odd?, :even?, :upto, :downto, :times, :succ, :next, :pred, :chr, :ord, :to_i, :to_int, :floor, # :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, # :ceil, :truncate, :round, :gcd, :lcm, :gcdlcm, :numerator, :denominator, :to_r, :rationalize,
# :singleton_method_added, :coerce, :i, :+@, :-@, :fdiv, :div, :divmod, :%, :modulo, :remainder, :abs, :magnitude, # :singleton_method_added, :coerce, :i, :+@, :-@, :fdiv, :div, :divmod, :%, :modulo, :remainder, :abs, :magnitude,
# :real?, :zero?, :nonzero?, :step, :quo, :to_c, :real, :imaginary, :imag, :abs2, :arg, :angle, :phase, # :real?, :zero?, :nonzero?, :step, :quo, :to_c, :real, :imaginary, :imag, :abs2, :arg, :angle, :phase,
# :rectangular, :rect, :polar, :conjugate, :conj, :>, :>=, :<, :<=, :between? # :rectangular, :rect, :polar, :conjugate, :conj, :>, :>=, :<, :<=, :between?
# #
# Numeric # Numeric
# :singleton_method_added, :coerce, :i, :+@, :-@, :fdiv, :div, :divmod, :%, :modulo, :remainder, :abs, :magnitude, # :singleton_method_added, :coerce, :i, :+@, :-@, :fdiv, :div, :divmod, :%, :modulo, :remainder, :abs, :magnitude,
# :to_int, :real?, :integer?, :zero?, :nonzero?, :floor, :ceil, :round, :truncate, :step, :numerator, :denominator, # :to_int, :real?, :integer?, :zero?, :nonzero?, :floor, :ceil, :round, :truncate, :step, :numerator, :denominator,
# :quo, :to_c, :real, :imaginary, :imag, :abs2, :arg, :angle, :phase, :rectangular, :rect, :polar, :conjugate, :conj, # :quo, :to_c, :real, :imaginary, :imag, :abs2, :arg, :angle, :phase, :rectangular, :rect, :polar, :conjugate, :conj,
# :>, :>=, :<, :<=, :between? # :>, :>=, :<, :<=, :between?
end
end end

View File

@ -6,26 +6,28 @@
# The Layout of an object describes the memory layout of the object # The Layout of an object describes the memory layout of the object
# The Layout is a simple list of the names of instance variables. # The Layout is a simple list of the names of instance variables.
# #
# As every object has a Layout to describe it, the name "layout" is the # As every object has a Layout to describe it, the name "layout" is the
# first name in the list for every Layout. # first name in the list for every Layout.
# But as we want every Object to have a class, this is the second # But as we want every Object to have a class, this is the second
# entry in the list. The name for the entry is "object_class" # entry in the list. The name for the entry is "object_class"
# In other words, the Layout is a list of names that describe # In other words, the Layout is a list of names that describe
# the values stored in an actual object. # the values stored in an actual object.
# The object is an array of values of length n and # The object is an array of values of length n and
# the Layout is an array of names of length n # the Layout is an array of names of length n
# Together they turn the object into a hash like structure # Together they turn the object into a hash like structure
class Layout < Object module Parfait
class Layout < Object
# given a name as symbol, return the integer index of that entry
# we use 0 as "not found" as we don't want negatives, and can't raise
# luckily 0 is always the type-word in an object and so by returning
# one-offsets we can use the return value straight without adding 1
def index_of( name )
#internal implementation....
end
# given a name as symbol, return the integer index of that entry
# we use 0 as "not found" as we don't want negatives, and can't raise
# luckily 0 is always the type-word in an object and so by returning
# one-offsets we can use the return value straight without adding 1
def index_of( name )
#internal implementation....
end end
end end

View File

@ -2,41 +2,43 @@
# A message is what is sent when you invoke a method. Args and stuff are packed up in to a Message # A message is what is sent when you invoke a method. Args and stuff are packed up in to a Message
# and the Message is sent to the receiver. # and the Message is sent to the receiver.
class Message < Object module Parfait
class Message < Object
def get_type_for(name) def get_type_for(name)
index = @layout.get_index(name) index = @layout.get_index(name)
get_at(index) get_at(index)
end end
def __send def __send
typ = get_type_for( :receiver ) typ = get_type_for( :receiver )
# TODO: this will obviously be recoded as case, once that is done :-) # TODO: this will obviously be recoded as case, once that is done :-)
# depending on value type get method # depending on value type get method
if( typ == Integer ) if( typ == Integer )
method = Integer.get_method @method_name method = Integer.get_method @method_name
else
if( typ != ObjectReference )
raise "unimplemented case"
else else
method = @receiver.get_singeton_method @method_name if( typ != ObjectReference )
# Find the method for the given object (receiver) according to ruby dispatch rules: raise "unimplemented case"
# - see if the receiver object has a (singleton) method by the name else
# - get receivers class and look for instance methods of the name method = @receiver.get_singeton_method @method_name
# - go up inheritance tree # Find the method for the given object (receiver) according to ruby dispatch rules:
# - start over with method_missing instead # - see if the receiver object has a (singleton) method by the name
# -> guaranteed to end at object.method_missing # - get receivers class and look for instance methods of the name
unless method # - go up inheritance tree
cl = @receiver.layout.object_class # - start over with method_missing instead
method = cl.get_instance_or_super_method @method_name # -> guaranteed to end at object.method_missing
unless method
cl = @receiver.layout.object_class
method = cl.get_instance_or_super_method @method_name
end
end end
end end
end unless method
unless method message = Message.new( @receiver , :method_missing , [@method_name] + @args)
message = Message.new( @receiver , :method_missing , [@method_name] + @args) message.send
message.send else
else method.call
method.call end
end end
end end
end end

View File

@ -1,6 +1,6 @@
# A module describes the capabilities of a group of objects, ie what data it has # A module describes the capabilities of a group of objects, ie what data it has
# and functions it responds to. # and functions it responds to.
# The group may be a Class, but a module may be included into classes and objects too. # The group may be a Class, but a module may be included into classes and objects too.
# #
# The class also keeps a list of class methods (with names+code) # The class also keeps a list of class methods (with names+code)
@ -11,12 +11,14 @@
# In fact this property is implemented in the Object, as methods # In fact this property is implemented in the Object, as methods
# may be added to any object at run-time # may be added to any object at run-time
class Module module Parfait
# :<, :<=, :>, :>=, :included_modules, :include?, :name, :ancestors, :instance_methods, :public_instance_methods, class Module
# :protected_instance_methods, :private_instance_methods, :constants, :const_get, :const_set, :const_defined?, # :<, :<=, :>, :>=, :included_modules, :include?, :name, :ancestors, :instance_methods, :public_instance_methods,
# :const_missing, :class_variables, :remove_class_variable, :class_variable_get, :class_variable_set, # :protected_instance_methods, :private_instance_methods, :constants, :const_get, :const_set, :const_defined?,
# :class_variable_defined?, :public_constant, :private_constant, :singleton_class?, :include, :prepend, # :const_missing, :class_variables, :remove_class_variable, :class_variable_get, :class_variable_set,
# :module_exec, :class_exec, :module_eval, :class_eval, :method_defined?, :public_method_defined?, # :class_variable_defined?, :public_constant, :private_constant, :singleton_class?, :include, :prepend,
# :private_method_defined?, :protected_method_defined?, :public_class_method, :private_class_method, :autoload, # :module_exec, :class_exec, :module_eval, :class_eval, :method_defined?, :public_method_defined?,
# :autoload?, :instance_method, :public_instance_method # :private_method_defined?, :protected_method_defined?, :public_class_method, :private_class_method, :autoload,
# :autoload?, :instance_method, :public_instance_method
end
end end

View File

@ -1,35 +1,37 @@
# to be precise, this should be an ObjectReference, as the Reference is a Value # to be precise, this should be an ObjectReference, as the Reference is a Value
# but we don't want to make that distinction all the time , so we don't. # but we don't want to make that distinction all the time , so we don't.
# that does lead to the fact that we have Reference functions on the Object though # that does lead to the fact that we have Reference functions on the Object though
class Object < Value module Parfait
class Object < Value
def get_type() def get_type()
OBJECT_TYPE OBJECT_TYPE
end
# This is the crux of the object system. The class of an object is stored in the objects
# memory (as opposed to an integer that has no memory and so always has the same class)
#
# In Salama we store the class in the Layout, and so the Layout is the only fixed
# data that every object carries.
def get_class()
@layout.get_class()
end
def get_layout()
@layout
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, :instance_variables, :instance_variable_get, :instance_variable_set, :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__
end end
# This is the crux of the object system. The class of an object is stored in the objects
# memory (as opposed to an integer that has no memory and so always has the same class)
#
# In Salama we store the class in the Layout, and so the Layout is the only fixed
# data that every object carries.
def get_class()
@layout.get_class()
end
def get_layout()
@layout
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, :instance_variables, :instance_variable_get, :instance_variable_set, :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__
end end

View File

@ -8,6 +8,8 @@
# object. The smallest object is usually a cache line, 16 bytes or # object. The smallest object is usually a cache line, 16 bytes or
# an exponent of two larger. # an exponent of two larger.
class Page < Object module Parfait
class Page < Object
end
end end

View File

@ -8,8 +8,10 @@
# "New" is slightly misleading in that normal operation only ever # "New" is slightly misleading in that normal operation only ever
# recycles objects. # recycles objects.
class Space < Object module Parfait
class Space < Object
# ObjectSpace # ObjectSpace
# :each_object, :garbage_collect, :define_finalizer, :undefine_finalizer, :_id2ref, :count_objects # :each_object, :garbage_collect, :define_finalizer, :undefine_finalizer, :_id2ref, :count_objects
end
end end

View File

@ -12,26 +12,28 @@
# Value is an abstract class that unifies the "has a type" concept # Value is an abstract class that unifies the "has a type" concept
# Types are not "objectified", but are represented as integer constants # Types are not "objectified", but are represented as integer constants
class Value module Parfait
class Value
# to make the machine work, the constants need # to make the machine work, the constants need
# - to start at 0 # - to start at 0
# - be unique # - be unique
# - be smaller enough to fit into the 2-4 bits available # - be smaller enough to fit into the 2-4 bits available
INTEGER_VALUE = 0 INTEGER_VALUE = 0
OBJECT_VALUE = 1 OBJECT_VALUE = 1
# the type is what identifies the value
def get_type()
raise "abstract clalled on #{self}"
end
# Get class works on the type. The value's type is stored by the machine. # the type is what identifies the value
# So this function is not overriden in derived classes, because it is used def get_type()
# to espablish what class a value has! (it's that "fake" oo i mentioned) raise "abstract clalled on #{self}"
def get_class() end
type = self.get_type()
return Integer if( type == INTEGER_VALUE ) # Get class works on the type. The value's type is stored by the machine.
raise "invalid type" # So this function is not overriden in derived classes, because it is used
# to espablish what class a value has! (it's that "fake" oo i mentioned)
def get_class()
type = self.get_type()
return Integer if( type == INTEGER_VALUE )
raise "invalid type"
end
end end
end end