From 4b05b48197a49f7b33d8642342e6d43f016b1a01 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Tue, 6 Dec 2016 11:38:09 +0200 Subject: [PATCH] some docs --- .travis.yml | 6 ++--- Gemfile.lock | 4 +-- lib/register/boot.rb | 6 ++--- lib/register/builtin/object.rb | 2 +- lib/register/interpreter.rb | 12 +++++++++ lib/register/machine.rb | 5 ++-- lib/register/minimizer.rb | 40 ----------------------------- lib/register/padding.rb | 4 ++- lib/register/parfait.rb | 4 +++ lib/register/parfait/behaviour.rb | 10 +++----- lib/register/parfait/binary_code.rb | 2 +- lib/register/parfait/class.rb | 14 ++++------ lib/register/parfait/indexed.rb | 29 +++++++++++---------- lib/register/parfait/method.rb | 7 ++--- lib/register/parfait/object.rb | 9 +++---- lib/register/positioned.rb | 3 +-- lib/soml/compiler.rb | 15 +++++------ 17 files changed, 71 insertions(+), 101 deletions(-) delete mode 100644 lib/register/minimizer.rb diff --git a/.travis.yml b/.travis.yml index b9666008..9bd9cf42 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,6 @@ cache: bundler script: - CODECLIMATE_REPO_TOKEN=e778c5658e8488a37795ec48f8c6990135f7a2ec35ceadc2e816a4ed1e3f20ab ruby test/test_all.rb rvm: - - 2.0.0 - - 2.1.7 - - 2.2.3 + - 2.1.10 + - 2.2.5 + - 2.3.1 diff --git a/Gemfile.lock b/Gemfile.lock index bed1824f..b9a2ec0e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -87,7 +87,7 @@ GEM method_source (~> 0.8.1) slop (~> 3.4) win32console (~> 1.3) - rake (10.5.0) + rake (11.3.0) rb-fsevent (0.9.6) rb-inotify (0.9.5) ffi (>= 0.5.0) @@ -130,4 +130,4 @@ DEPENDENCIES soml-parser! BUNDLED WITH - 1.11.2 + 1.12.5 diff --git a/lib/register/boot.rb b/lib/register/boot.rb index f6e5ce5a..fcc888bb 100644 --- a/lib/register/boot.rb +++ b/lib/register/boot.rb @@ -20,9 +20,9 @@ module Register # 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: - # - 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 the class objects and assign them to the types + # - create the Class objects and assign them to the types def boot_parfait! boot_types boot_space @@ -138,7 +138,7 @@ module Register # (as that's impossible in ruby) def boot_functions! # 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 @space.get_class_by_name(:Space).add_instance_method Builtin::Space.send(:main, nil) diff --git a/lib/register/builtin/object.rb b/lib/register/builtin/object.rb index 83bcaa11..682ab123 100644 --- a/lib/register/builtin/object.rb +++ b/lib/register/builtin/object.rb @@ -24,7 +24,7 @@ module Register return compiler.method 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 def set_internal_word context compiler = Soml::Compiler.new.create_method(:Object , :set_internal_word , diff --git a/lib/register/interpreter.rb b/lib/register/interpreter.rb index 4111f751..d273e8d4 100644 --- a/lib/register/interpreter.rb +++ b/lib/register/interpreter.rb @@ -2,6 +2,17 @@ require_relative "eventable" 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 # fire events for changed pc and register contents include Eventable @@ -16,6 +27,7 @@ module Register attr_reader :state # running etc 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 @state = :stopped @stdout = "" diff --git a/lib/register/machine.rb b/lib/register/machine.rb index 87777007..c2015a4b 100644 --- a/lib/register/machine.rb +++ b/lib/register/machine.rb @@ -1,8 +1,9 @@ require 'parslet/convenience' require_relative "collector" 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. # diff --git a/lib/register/minimizer.rb b/lib/register/minimizer.rb deleted file mode 100644 index e60ae6c7..00000000 --- a/lib/register/minimizer.rb +++ /dev/null @@ -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 diff --git a/lib/register/padding.rb b/lib/register/padding.rb index 6d8f92c3..f4035c18 100644 --- a/lib/register/padding.rb +++ b/lib/register/padding.rb @@ -1,4 +1,6 @@ - +# Helper functions to pad memory. +# +# Meory is always in lines, chunks of 8 words / 32 bytes module Padding # objects only come in lengths of multiple of 8 words / 32 bytes diff --git a/lib/register/parfait.rb b/lib/register/parfait.rb index 0b7f1ef4..08e0b8d8 100644 --- a/lib/register/parfait.rb +++ b/lib/register/parfait.rb @@ -1,3 +1,7 @@ +# Parfait is the ruby runtime +module Parfait +end + require_relative "parfait/value" require_relative "parfait/integer" require_relative "parfait/object" diff --git a/lib/register/parfait/behaviour.rb b/lib/register/parfait/behaviour.rb index c9fa7e39..cab3e5a0 100644 --- a/lib/register/parfait/behaviour.rb +++ b/lib/register/parfait/behaviour.rb @@ -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 -# 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 -# +# instance_methods is the attribute in the including class that has the methods module Parfait module Behaviour + # when included we set up the instance_methods attribute def self.included(base) base.attribute :instance_methods end @@ -22,6 +19,7 @@ module Parfait return m if m self.instance_methods = List.new end + def method_names names = List.new self.methods.each do |method| diff --git a/lib/register/parfait/binary_code.rb b/lib/register/parfait/binary_code.rb index 7f2b7b47..cea54a7c 100644 --- a/lib/register/parfait/binary_code.rb +++ b/lib/register/parfait/binary_code.rb @@ -6,7 +6,7 @@ module Parfait # 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 def to_s diff --git a/lib/register/parfait/class.rb b/lib/register/parfait/class.rb index 6d09e9d6..9acbe438 100644 --- a/lib/register/parfait/class.rb +++ b/lib/register/parfait/class.rb @@ -1,19 +1,16 @@ -# A class describes the capabilities of a group of objects, ie what data it has -# and functions it responds to. +# Class is mainly a list of methods with a name. The methods are untyped. - -# 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 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. -# 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. # 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 -# The Type lists the names of the instance variables +# An Object carries the data for the instance variables it has. +# The type lists the names of the instance variables # The class keeps a list of instance methods, these have a name and code module Parfait @@ -47,7 +44,6 @@ module Parfait "Class(#{name})" end - def create_instance_method method_name , arguments raise "create_instance_method #{method_name}.#{method_name.class}" unless method_name.is_a?(Symbol) clazz = instance_type().object_class() diff --git a/lib/register/parfait/indexed.rb b/lib/register/parfait/indexed.rb index 1e684d9e..4434f35b 100644 --- a/lib/register/parfait/indexed.rb +++ b/lib/register/parfait/indexed.rb @@ -1,19 +1,18 @@ -# 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 -# the fixed, ie the instance variables -# -# 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. -# -# Using ruby include does not work for similar reasons, so Indexed.at is the main -# function that generates the methods - # ( do have to use a marker module so we can test with is_a?) - 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 + # the fixed, ie the instance variables + # + # 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. + # + # Basic functionality depends on the offset, and those methods are generated by + # the offset method that has to be called seperately when including this Module + module Indexed # marker module def self.included(base) - base.extend(Methods) + base.extend(OffsetMethods) base.attribute :indexed_length end @@ -137,7 +136,9 @@ module Parfait ret 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 ) offset += 1 # for the attribute we add (indexed_length) diff --git a/lib/register/parfait/method.rb b/lib/register/parfait/method.rb index 86904abb..7473990f 100644 --- a/lib/register/parfait/method.rb +++ b/lib/register/parfait/method.rb @@ -18,6 +18,10 @@ module Parfait 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 super() raise "No class #{name}" unless clazz @@ -31,9 +35,6 @@ module Parfait self.arguments = arguments 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 diff --git a/lib/register/parfait/object.rb b/lib/register/parfait/object.rb index dbf0ec71..19deb28a 100644 --- a/lib/register/parfait/object.rb +++ b/lib/register/parfait/object.rb @@ -2,8 +2,8 @@ # and functions to work on that data. # 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 -# word. +# From an implementation perspective it is a chunk of memory with a type as the first +# word (instance of class 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 @@ -17,6 +17,8 @@ module Parfait 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 object = self.allocate #HACK, but used to do the adapter in the init, bu that is too late now @@ -30,9 +32,6 @@ 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 diff --git a/lib/register/positioned.rb b/lib/register/positioned.rb index d0357081..732d1227 100644 --- a/lib/register/positioned.rb +++ b/lib/register/positioned.rb @@ -1,5 +1,4 @@ -#require_relative "type" - +# Helper module that extract position attribute. module Positioned def position if @position.nil? diff --git a/lib/soml/compiler.rb b/lib/soml/compiler.rb index 2938f1d3..e61faea8 100644 --- a/lib/soml/compiler.rb +++ b/lib/soml/compiler.rb @@ -174,21 +174,18 @@ module Soml name end + # load the soml files from parfait directory + # Need to remove this and put it back into ruby code 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 self.new.process( code ) 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