some docs
This commit is contained in:
parent
229f5896c6
commit
4b05b48197
@ -4,6 +4,6 @@ cache: bundler
|
|||||||
script:
|
script:
|
||||||
- CODECLIMATE_REPO_TOKEN=e778c5658e8488a37795ec48f8c6990135f7a2ec35ceadc2e816a4ed1e3f20ab ruby test/test_all.rb
|
- CODECLIMATE_REPO_TOKEN=e778c5658e8488a37795ec48f8c6990135f7a2ec35ceadc2e816a4ed1e3f20ab ruby test/test_all.rb
|
||||||
rvm:
|
rvm:
|
||||||
- 2.0.0
|
- 2.1.10
|
||||||
- 2.1.7
|
- 2.2.5
|
||||||
- 2.2.3
|
- 2.3.1
|
||||||
|
@ -87,7 +87,7 @@ GEM
|
|||||||
method_source (~> 0.8.1)
|
method_source (~> 0.8.1)
|
||||||
slop (~> 3.4)
|
slop (~> 3.4)
|
||||||
win32console (~> 1.3)
|
win32console (~> 1.3)
|
||||||
rake (10.5.0)
|
rake (11.3.0)
|
||||||
rb-fsevent (0.9.6)
|
rb-fsevent (0.9.6)
|
||||||
rb-inotify (0.9.5)
|
rb-inotify (0.9.5)
|
||||||
ffi (>= 0.5.0)
|
ffi (>= 0.5.0)
|
||||||
@ -130,4 +130,4 @@ DEPENDENCIES
|
|||||||
soml-parser!
|
soml-parser!
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.11.2
|
1.12.5
|
||||||
|
@ -20,9 +20,9 @@ module Register
|
|||||||
# That graph can be programatically built and written (with this to boot that process :-))
|
# That graph can be programatically built and written (with this to boot that process :-))
|
||||||
|
|
||||||
# There are some helpers below, but the roadmap is something like:
|
# There are some helpers below, but the roadmap is something like:
|
||||||
# - create all the types, with thier types, but no classes
|
# - create all the Type instances, with their basic types, but no classes
|
||||||
# - create a space by "hand" , using allocate, not new
|
# - create a space by "hand" , using allocate, not new
|
||||||
# - create the class objects and assign them to the types
|
# - create the Class objects and assign them to the types
|
||||||
def boot_parfait!
|
def boot_parfait!
|
||||||
boot_types
|
boot_types
|
||||||
boot_space
|
boot_space
|
||||||
@ -138,7 +138,7 @@ module Register
|
|||||||
# (as that's impossible in ruby)
|
# (as that's impossible in ruby)
|
||||||
def boot_functions!
|
def boot_functions!
|
||||||
# very fiddly chicken 'n egg problem. Functions need to be in the right order, and in fact we
|
# very fiddly chicken 'n egg problem. Functions need to be in the right order, and in fact we
|
||||||
# have to define some dummies, just for the other to compile
|
# have to define some dummies, just for the others to compile
|
||||||
# TODO go through the virtual parfait layer and adjust function names to what they really are
|
# TODO go through the virtual parfait layer and adjust function names to what they really are
|
||||||
@space.get_class_by_name(:Space).add_instance_method Builtin::Space.send(:main, nil)
|
@space.get_class_by_name(:Space).add_instance_method Builtin::Space.send(:main, nil)
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ module Register
|
|||||||
return compiler.method
|
return compiler.method
|
||||||
end
|
end
|
||||||
|
|
||||||
# self[index] = val basically. Index is the first arg , vlaue the second
|
# self[index] = val basically. Index is the first arg , value the second
|
||||||
# no return
|
# no return
|
||||||
def set_internal_word context
|
def set_internal_word context
|
||||||
compiler = Soml::Compiler.new.create_method(:Object , :set_internal_word ,
|
compiler = Soml::Compiler.new.create_method(:Object , :set_internal_word ,
|
||||||
|
@ -2,6 +2,17 @@
|
|||||||
require_relative "eventable"
|
require_relative "eventable"
|
||||||
|
|
||||||
module Register
|
module Register
|
||||||
|
|
||||||
|
# An interpreter for the register level. As the register machine is a simple model,
|
||||||
|
# interpreting it is not so terribly difficult.
|
||||||
|
#
|
||||||
|
# There is a certain amount of basic machinery to fetch and execute the next instruction
|
||||||
|
# (as a cpu would), and then there is a method for each instruction. Eg an instruction GetSlot
|
||||||
|
# will be executed by method execute_GetSlot
|
||||||
|
#
|
||||||
|
# The Interpreter (a bit like a cpu) has a state flag, a current instruction and registers
|
||||||
|
# We collect the stdout (as a hack not to interpret the OS)
|
||||||
|
#
|
||||||
class Interpreter
|
class Interpreter
|
||||||
# fire events for changed pc and register contents
|
# fire events for changed pc and register contents
|
||||||
include Eventable
|
include Eventable
|
||||||
@ -16,6 +27,7 @@ module Register
|
|||||||
attr_reader :state # running etc
|
attr_reader :state # running etc
|
||||||
attr_reader :flags # somewhat like the lags on a cpu, hash sym => bool (zero .. . )
|
attr_reader :flags # somewhat like the lags on a cpu, hash sym => bool (zero .. . )
|
||||||
|
|
||||||
|
#start in state :stopped and set registers to unknown
|
||||||
def initialize
|
def initialize
|
||||||
@state = :stopped
|
@state = :stopped
|
||||||
@stdout = ""
|
@stdout = ""
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
require 'parslet/convenience'
|
require 'parslet/convenience'
|
||||||
require_relative "collector"
|
require_relative "collector"
|
||||||
module Register
|
module Register
|
||||||
# The Register Machine is a object based virtual machine on which ruby will be implemented.
|
# The Register Machine is an abstraction of the register level. This is seperate from the
|
||||||
#
|
# actual assembler level to allow for several cpu architectures.
|
||||||
|
# The Instructions (see class Instruction) define what the machine can do (ie load/store/maths)
|
||||||
|
|
||||||
# The ast is transformed to virtual-machine objects, some of which represent code, some data.
|
# The ast is transformed to virtual-machine objects, some of which represent code, some data.
|
||||||
#
|
#
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
module Register
|
|
||||||
|
|
||||||
# Remove all functions that are not called
|
|
||||||
# Not called is approximated by the fact that the method name doesn't show up
|
|
||||||
# in any function reachable from main
|
|
||||||
class Minimizer
|
|
||||||
def run
|
|
||||||
@gonners = []
|
|
||||||
Parfait::Space.object_space.classes.values.each do |c|
|
|
||||||
c.instance_methods.each do |f|
|
|
||||||
@gonners << f
|
|
||||||
end
|
|
||||||
end
|
|
||||||
keep Register.machine.space.get_init
|
|
||||||
remove_remaining
|
|
||||||
end
|
|
||||||
|
|
||||||
def keep function
|
|
||||||
index = @gonners.index function
|
|
||||||
unless index
|
|
||||||
puts "function was already removed #{function.name}"
|
|
||||||
return
|
|
||||||
end
|
|
||||||
#puts "stayer #{function.name}"
|
|
||||||
@gonners.delete function
|
|
||||||
function.source.blocks.each do |block|
|
|
||||||
block.codes.each do |code|
|
|
||||||
keep code.method if code.is_a? FunctionCall
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def remove_remaining
|
|
||||||
@gonners.each do |method|
|
|
||||||
next if(method.name == :plus)
|
|
||||||
method.for_class.remove_instance_method method.name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
@ -1,4 +1,6 @@
|
|||||||
|
# Helper functions to pad memory.
|
||||||
|
#
|
||||||
|
# Meory is always in lines, chunks of 8 words / 32 bytes
|
||||||
module Padding
|
module Padding
|
||||||
|
|
||||||
# objects only come in lengths of multiple of 8 words / 32 bytes
|
# objects only come in lengths of multiple of 8 words / 32 bytes
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
# Parfait is the ruby runtime
|
||||||
|
module Parfait
|
||||||
|
end
|
||||||
|
|
||||||
require_relative "parfait/value"
|
require_relative "parfait/value"
|
||||||
require_relative "parfait/integer"
|
require_relative "parfait/integer"
|
||||||
require_relative "parfait/object"
|
require_relative "parfait/object"
|
||||||
|
@ -1,13 +1,10 @@
|
|||||||
|
# Behaviour is something that has methods, basically class and modules superclass
|
||||||
|
|
||||||
# described in the ruby language book as the eigenclass, what you get with
|
# instance_methods is the attribute in the including class that has the methods
|
||||||
# class MyClass
|
|
||||||
# class << self <--- this is called the eigenclass, or metaclass, and really is just
|
|
||||||
# .... the class object but gives us the ability to use the
|
|
||||||
# syntax as if it were a class
|
|
||||||
#
|
|
||||||
|
|
||||||
module Parfait
|
module Parfait
|
||||||
module Behaviour
|
module Behaviour
|
||||||
|
# when included we set up the instance_methods attribute
|
||||||
def self.included(base)
|
def self.included(base)
|
||||||
base.attribute :instance_methods
|
base.attribute :instance_methods
|
||||||
end
|
end
|
||||||
@ -22,6 +19,7 @@ module Parfait
|
|||||||
return m if m
|
return m if m
|
||||||
self.instance_methods = List.new
|
self.instance_methods = List.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def method_names
|
def method_names
|
||||||
names = List.new
|
names = List.new
|
||||||
self.methods.each do |method|
|
self.methods.each do |method|
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
module Parfait
|
module Parfait
|
||||||
# obviously not a "Word" but a ByteArray , but no such class yet
|
# obviously not a "Word" but a ByteArray , but no such class yet
|
||||||
# As on the other hand has no encoding (yet) it is close enough
|
# As String on the other hand has no encoding (yet) it is close enough
|
||||||
class BinaryCode < Word
|
class BinaryCode < Word
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
|
@ -1,19 +1,16 @@
|
|||||||
# A class describes the capabilities of a group of objects, ie what data it has
|
# Class is mainly a list of methods with a name. The methods are untyped.
|
||||||
# and functions it responds to.
|
|
||||||
|
|
||||||
|
|
||||||
# Class is mainly a list of methods with a name. (Note that methods may have many functions)
|
|
||||||
# The memory layout of an object is determined by the Type (see there).
|
# The memory layout of an object is determined by the Type (see there).
|
||||||
# The class carries the "current" type, ie the type an object would be if you created an instance
|
# The class carries the "current" type, ie the type an object would be if you created an instance
|
||||||
# of the class. Note that this changes over time and so many types share the same class.
|
# of the class. Note that this changes over time and so many types share the same class.
|
||||||
|
|
||||||
# It is essential that the class (the object defining the class)
|
# For dynamic OO it is essential that the class (the object defining the class)
|
||||||
# can carry methods. It does so as instance variables.
|
# can carry methods. It does so as instance variables.
|
||||||
# In fact this property is implemented in the Type, as methods
|
# In fact this property is implemented in the Type, as methods
|
||||||
# may be added to any object at run-time
|
# may be added to any object at run-time.
|
||||||
|
|
||||||
# An Object carries the data for the instance variables it has
|
# An Object carries the data for the instance variables it has.
|
||||||
# The Type lists the names of the instance variables
|
# The type 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
|
||||||
|
|
||||||
module Parfait
|
module Parfait
|
||||||
@ -47,7 +44,6 @@ module Parfait
|
|||||||
"Class(#{name})"
|
"Class(#{name})"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def create_instance_method method_name , arguments
|
def create_instance_method method_name , arguments
|
||||||
raise "create_instance_method #{method_name}.#{method_name.class}" unless method_name.is_a?(Symbol)
|
raise "create_instance_method #{method_name}.#{method_name.class}" unless method_name.is_a?(Symbol)
|
||||||
clazz = instance_type().object_class()
|
clazz = instance_type().object_class()
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
# various classes would derive from array in ruby, ie have indexed variables
|
module Parfait
|
||||||
|
# Various classes would derive from array in ruby, ie have indexed variables
|
||||||
#
|
#
|
||||||
# But for our memory type we need the variable part of an object to be after
|
# But for our memory type we need the variable part of an object to be after
|
||||||
# the fixed, ie the instance variables
|
# the fixed, ie the instance variables
|
||||||
@ -6,14 +7,12 @@
|
|||||||
# Just using ruby derivation will not allow us to offset the index, so instead the
|
# Just using ruby derivation will not allow us to offset the index, so instead the
|
||||||
# function will be generated and included to the classes that need them.
|
# function will be generated and included to the classes that need them.
|
||||||
#
|
#
|
||||||
# Using ruby include does not work for similar reasons, so Indexed.at is the main
|
# Basic functionality depends on the offset, and those methods are generated by
|
||||||
# function that generates the methods
|
# the offset method that has to be called seperately when including this Module
|
||||||
# ( do have to use a marker module so we can test with is_a?)
|
|
||||||
|
|
||||||
module Parfait
|
|
||||||
module Indexed # marker module
|
module Indexed # marker module
|
||||||
def self.included(base)
|
def self.included(base)
|
||||||
base.extend(Methods)
|
base.extend(OffsetMethods)
|
||||||
base.attribute :indexed_length
|
base.attribute :indexed_length
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -137,7 +136,9 @@ module Parfait
|
|||||||
ret
|
ret
|
||||||
end
|
end
|
||||||
|
|
||||||
module Methods
|
module OffsetMethods
|
||||||
|
# generate all methods that depend on the (memory) offset
|
||||||
|
# These are get/set shrink_to/grow_to
|
||||||
def offset( offset )
|
def offset( offset )
|
||||||
offset += 1 # for the attribute we add (indexed_length)
|
offset += 1 # for the attribute we add (indexed_length)
|
||||||
|
|
||||||
|
@ -18,6 +18,10 @@ module Parfait
|
|||||||
|
|
||||||
class Method < Object
|
class Method < Object
|
||||||
|
|
||||||
|
attributes [:name , :source , :instructions , :binary ,:arguments , :for_class, :locals ]
|
||||||
|
# not part of the parfait model, hence ruby accessor
|
||||||
|
attr_accessor :source
|
||||||
|
|
||||||
def initialize clazz , name , arguments
|
def initialize clazz , name , arguments
|
||||||
super()
|
super()
|
||||||
raise "No class #{name}" unless clazz
|
raise "No class #{name}" unless clazz
|
||||||
@ -31,9 +35,6 @@ module Parfait
|
|||||||
self.arguments = arguments
|
self.arguments = arguments
|
||||||
self.locals = List.new
|
self.locals = List.new
|
||||||
end
|
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
|
# determine whether this method has an argument by the name
|
||||||
def has_arg name
|
def has_arg name
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
# and functions to work on that data.
|
# and functions to work on that data.
|
||||||
# Only the object may access it's data directly.
|
# Only the object may access it's data directly.
|
||||||
|
|
||||||
# From an implementation perspective it is a chunk of memory with an type as the first
|
# From an implementation perspective it is a chunk of memory with a type as the first
|
||||||
# word.
|
# word (instance of class Type).
|
||||||
|
|
||||||
# Objects are arranged or layed out (in memory) according to their Type
|
# Objects are arranged or layed out (in memory) according to their Type
|
||||||
# every object has a Type. Type objects are immutalbe and may be reused for a group/class
|
# every object has a Type. Type objects are immutalbe and may be reused for a group/class
|
||||||
@ -17,6 +17,8 @@ module Parfait
|
|||||||
|
|
||||||
class Object < Value
|
class Object < Value
|
||||||
|
|
||||||
|
# we define new, so we can do memory layout also at compile time.
|
||||||
|
# At compile time we fake memory by using a global array for pages
|
||||||
def self.new *args
|
def self.new *args
|
||||||
object = self.allocate
|
object = self.allocate
|
||||||
#HACK, but used to do the adapter in the init, bu that is too late now
|
#HACK, but used to do the adapter in the init, bu that is too late now
|
||||||
@ -30,9 +32,6 @@ module Parfait
|
|||||||
object
|
object
|
||||||
end
|
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 Padding
|
||||||
include Positioned
|
include Positioned
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#require_relative "type"
|
# Helper module that extract position attribute.
|
||||||
|
|
||||||
module Positioned
|
module Positioned
|
||||||
def position
|
def position
|
||||||
if @position.nil?
|
if @position.nil?
|
||||||
|
@ -174,21 +174,18 @@ module Soml
|
|||||||
name
|
name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# load the soml files from parfait directory
|
||||||
|
# Need to remove this and put it back into ruby code
|
||||||
def self.load_parfait
|
def self.load_parfait
|
||||||
each_parfait do |parts|
|
["word","class","type","message" ,"integer", "object"].each do |o|
|
||||||
|
str = File.open(File.expand_path("parfait/#{o}.soml", File.dirname(__FILE__))).read
|
||||||
|
syntax = Parser::Salama.new.parse_with_debug(str, reporter: Parslet::ErrorReporter::Deepest.new)
|
||||||
|
parts = Parser::Transform.new.apply(syntax)
|
||||||
code = Soml.ast_to_code parts
|
code = Soml.ast_to_code parts
|
||||||
self.new.process( code )
|
self.new.process( code )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.each_parfait
|
|
||||||
["word","class","type","message" ,"integer", "object"].each do |o|
|
|
||||||
str = File.open(File.expand_path("parfait/#{o}.soml", File.dirname(__FILE__))).read
|
|
||||||
syntax = Parser::Salama.new.parse_with_debug(str, reporter: Parslet::ErrorReporter::Deepest.new)
|
|
||||||
parts = Parser::Transform.new.apply(syntax)
|
|
||||||
yield parts
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user