From e651b57d08f0dd5e0387e53c294644f3b6d0db03 Mon Sep 17 00:00:00 2001 From: Torsten Ruger Date: Sat, 30 May 2015 12:20:39 +0300 Subject: [PATCH] homing in on line length 100 --- README.md | 2 +- lib/arm/arm_machine.rb | 10 +++---- lib/arm/constants.rb | 9 ++++-- lib/arm/instructions/call_instruction.rb | 6 ++-- lib/arm/instructions/move_instruction.rb | 20 +++++++------ lib/arm/machine_code.rb | 12 ++++---- lib/arm/passes/save_implementation.rb | 5 ++-- lib/parfait/meta_class.rb | 5 ++-- lib/parfait/space.rb | 3 +- lib/register/assembler.rb | 18 ++++++------ lib/register/builtin/integer.rb | 3 +- lib/register/builtin/object.rb | 6 ++-- lib/register/register_reference.rb | 3 +- lib/virtual/compiled_method_info.rb | 21 ++++++++------ lib/virtual/compiler/basic_expressions.rb | 4 ++- lib/virtual/compiler/if_expression.rb | 3 +- lib/virtual/compiler/module_expression.rb | 3 +- lib/virtual/compiler/return_expression.rb | 4 ++- lib/virtual/instructions/halt.rb | 7 +++-- lib/virtual/instructions/instance_get.rb | 6 ++-- lib/virtual/instructions/set.rb | 4 +-- lib/virtual/machine.rb | 33 ++++++++++++---------- lib/virtual/message.rb | 20 +++++++------ lib/virtual/parfait_adapter.rb | 4 ++- lib/virtual/passes/frame_implementation.rb | 18 +++++++----- lib/virtual/passes/get_implementation.rb | 6 ++-- lib/virtual/passes/send_implementation.rb | 8 ++++-- lib/virtual/plock.rb | 20 +++++++------ lib/virtual/positioned.rb | 4 ++- 29 files changed, 159 insertions(+), 108 deletions(-) diff --git a/README.md b/README.md index d3f31195..df0acba8 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ inlining, but i have at least an idea. ### Sof -**S**alama **O**bject **F**ile format is a yaml ike format to look at code dumps and help testing. +**S**alama **O**bject **F**ile format is a yaml like format to look at code dumps and help testing. The dumper is ok and does produce (as intended) considerably denser dumps than yaml When a reader is done (not started) the idea is to use sof as pre-compiled, language independent diff --git a/lib/arm/arm_machine.rb b/lib/arm/arm_machine.rb index 91559834..5e381f5c 100644 --- a/lib/arm/arm_machine.rb +++ b/lib/arm/arm_machine.rb @@ -9,15 +9,15 @@ module Arm # Also, shortcuts are created to easily instantiate Instruction objects. # Example: pop -> StackInstruction.new( {:opcode => :pop}.merge(options) ) - # Instructions work with options, so you can pass anything in, and the only thing the functions does - # is save you typing the clazz.new. It passes the function name as the :opcode + # Instructions work with options, so you can pass anything in, and the only thing the functions + # does is save you typing the clazz.new. It passes the function name as the :opcode class ArmMachine # conditions specify all the possibilities for branches. Branches are b + condition # Example: beq means brach if equal. # :al means always, so bal is an unconditional branch (but b() also works) - CONDITIONS = [ :al , :eq , :ne , :lt , :le, :ge, :gt , :cs , :mi , :hi , :cc , :pl, :ls , :vc , :vs ] + CONDITIONS = [:al ,:eq ,:ne ,:lt ,:le ,:ge,:gt ,:cs ,:mi ,:hi ,:cc ,:pl,:ls ,:vc ,:vs] # here we create the shortcuts for the "standard" instructions, see above # Derived machines may use own instructions and define functions for them if so desired @@ -67,8 +67,8 @@ module Arm # an actual machine must create derived classes (from this base class) # These instruction classes must follow a naming pattern and take a hash in the contructor # Example, a mov() opcode instantiates a Register::MoveInstruction - # for an Arm machine, a class Arm::MoveInstruction < Register::MoveInstruction exists, and it will - # be used to define the mov on an arm machine. + # for an Arm machine, a class Arm::MoveInstruction < Register::MoveInstruction exists, and it + # will be used to define the mov on an arm machine. # This methods picks up that derived class and calls a define_instruction methods that can # be overriden in subclasses def self.define_instruction_one(inst , clazz , defaults = {} ) diff --git a/lib/arm/constants.rb b/lib/arm/constants.rb index e56d7bfd..db72d571 100644 --- a/lib/arm/constants.rb +++ b/lib/arm/constants.rb @@ -28,7 +28,8 @@ module Arm #codition codes can be applied to many instructions and thus save branches # :al => always , :eq => equal and so on - # eq mov if equal :moveq r1 r2 (also exists as function) will only execute if the last operation was 0 + # eq mov if equal :moveq r1 r2 (also exists as function) will only execute + # if the last operation was 0 COND_CODES = { :al => 0b1110, :eq => 0b0000, :ne => 0b0001, :cs => 0b0010, @@ -39,7 +40,8 @@ module Arm :ge => 0b1010, :gt => 0b1100, :vs => 0b0110 } - #return the bit pattern for the @attributes[:condition_code] variable, which signals the conditional code + # return the bit pattern for the @attributes[:condition_code] variable, + # which signals the conditional code def cond_bit_code COND_CODES[@attributes[:condition_code]] or throw "no code found for #{@attributes[:condition_code]}" end @@ -96,7 +98,8 @@ module Arm op = 0 #codes that one can shift, first two probably most common. # l (in lsr) means logical, ie unsigned, a (in asr) is arithmetic, ie signed - {'lsl' => 0b000, 'lsr' => 0b010, 'asr' => 0b100, 'ror' => 0b110, 'rrx' => 0b110}.each do |short, bin| + shift_codes = {'lsl' => 0b000, 'lsr' => 0b010, 'asr' => 0b100, 'ror' => 0b110, 'rrx' => 0b110} + shift_codes.each do |short, bin| long = "shift_#{short}".to_sym if shif = @attributes[long] # TODO delete this code, AFTER you understand it diff --git a/lib/arm/instructions/call_instruction.rb b/lib/arm/instructions/call_instruction.rb index 05693a6b..eba67757 100644 --- a/lib/arm/instructions/call_instruction.rb +++ b/lib/arm/instructions/call_instruction.rb @@ -36,8 +36,10 @@ module Arm if arg.is_a?(Virtual::Block) or arg.is_a?(Parfait::Method) #relative addressing for jumps/calls diff = arg.position - self.position - # but because of the arm "theoretical" 3- stage pipeline, we have to subtract 2 words (fetch/decode) - # But, for methods, this happens to be the size of the object header, so there it balances out, but not blocks + # but because of the arm "theoretical" 3- stage pipeline, + # we have to subtract 2 words (fetch/decode) + # But, for methods, this happens to be the size of the object header, + # so there it balances out, but not blocks diff -= 8 if arg.is_a?(Virtual::Block) arg = diff end diff --git a/lib/arm/instructions/move_instruction.rb b/lib/arm/instructions/move_instruction.rb index 29ec74b3..8f1d83c5 100644 --- a/lib/arm/instructions/move_instruction.rb +++ b/lib/arm/instructions/move_instruction.rb @@ -19,12 +19,12 @@ module Arm attr_accessor :to , :from # arm intructions are pretty sensible, and always 4 bytes (thumb not supported) - # but not all constants fit into the part of the instruction that is left after the instruction code, - # so large moves have to be split into two instructions. + # but not all constants fit into the part of the instruction that is left after the instruction + # code, so large moves have to be split into two instructions. # we handle this "transparently", just this instruction looks longer - # alas, full transparency is not achieved as we only know when to use 2 instruction once we know where the - # other object is, and that position is only set after code positions have been determined (in link) and so - # see below in assemble + # alas, full transparency is not achieved as we only know when to use 2 instruction once we + # know where the other object is, and that position is only set after code positions have been + # determined (in link) and so see below in assemble def mem_length @extra ? 8 : 4 end @@ -52,13 +52,14 @@ module Arm operand = op_with_rot immediate = 1 else - # unfortunately i was wrong in thinking the pi is armv7. The good news is the code below implements - # the movw instruction (armv7 for moving a word) and works + # unfortunately i was wrong in thinking the pi is armv7. The good news is the code + # below implements the movw instruction (armv7 for moving a word) and works #armv7 raise "Too big #{right} " if (right >> 16) > 0 #armv7 operand = (right & 0xFFF) #armv7 immediate = 1 #armv7 rn = (right >> 12) - # a little STRANGE, that the armv7 movw (move a 2 byte word) is an old test opcode, but there it is + # a little STRANGE, that the armv7 movw (move a 2 byte word) is an old test opcode, + # but there it is #armv7 @attributes[:opcode] = :tst raise "No negatives implemented #{right} " if right < 0 # and so it continues: when we notice that the const doesn't fit, first time we raise an @@ -74,7 +75,8 @@ module Arm raise "no fit for #{right}" unless operand immediate = 1 @extra = ArmMachine.add( to , to , (right & 0xFF) ) - #TODO: this is still a hack, as it does not encode all possible values. The way it _should_ be done + #TODO: this is still a hack, as it does not encode all possible values. + # The way it _should_ be done # is to check that the first part is doabe with u8_with_rr AND leaves a u8 remainder end elsif (right.is_a?(Symbol) or right.is_a?(::Register::RegisterReference)) diff --git a/lib/arm/machine_code.rb b/lib/arm/machine_code.rb index f685492a..2cbe9bfb 100644 --- a/lib/arm/machine_code.rb +++ b/lib/arm/machine_code.rb @@ -43,16 +43,16 @@ module Arm syscall( function.insertion_point , 1 ) # 1 == exit end - + # the number (a Virtual::integer) is (itself) divided by 10, ie overwritten by the result # and the remainder is overwritten (ie an out argument) - # not really a function, more a macro, + # not really a function, more a macro, def div10 function, number , remainder # Note about division: devision is MUCH more expensive than one would have thought - # And coding it is a bit of a mind leap: it's all about finding a a result that gets the + # And coding it is a bit of a mind leap: it's all about finding a a result that gets the # remainder smaller than an int. i'll post some links sometime. This is from the arm manual tmp = function.new_local - function.instance_eval do + function.instance_eval do sub( remainder , number , 10 ) sub( number , number , number , shift_lsr: 2) add( number , number , number , shift_lsr: 4) @@ -67,7 +67,8 @@ module Arm end def syscall block , num - # This is very arm specific, syscall number is passed in r7, other arguments like a c call ie 0 and up + # This is very arm specific, syscall number is passed in r7, + # other arguments like a c call ie 0 and up sys = Virtual::Integer.new( Virtual::RegisterReference.new(SYSCALL_REG) ) ret = Virtual::Integer.new( Virtual::RegisterReference.new(RETURN_REG) ) block.add_code mov( sys , num ) @@ -78,4 +79,3 @@ module Arm end end - diff --git a/lib/arm/passes/save_implementation.rb b/lib/arm/passes/save_implementation.rb index 73aea7d0..bce8babb 100644 --- a/lib/arm/passes/save_implementation.rb +++ b/lib/arm/passes/save_implementation.rb @@ -1,9 +1,10 @@ module Arm # Arm stores the return address in a register (not on the stack) - # The register is called link , or lr for short . Maybe because it provides the "link" back to the caller (?) + # The register is called link , or lr for short . + # Maybe because it provides the "link" back to the caller (?) - # the vm defines a register for the location, so we store it there. + # the vm defines a register for the location, so we store it there. class SaveImplementation def run block diff --git a/lib/parfait/meta_class.rb b/lib/parfait/meta_class.rb index 497399c7..e311dbc6 100644 --- a/lib/parfait/meta_class.rb +++ b/lib/parfait/meta_class.rb @@ -12,7 +12,7 @@ module Virtual # PS: can't say i fancy the << self syntax and am considerernig adding a # keyword for it, like meta # In effect it is a very similar construct to def self.function(...) - # So one could write def meta.function(...) and thus define on the meta-class + # So one could write def meta.function(...) and thus define on the meta-class class MetaClass < Object # no name, nor nothing. as this is just the object really @@ -44,7 +44,8 @@ module Virtual # get the function and if not found, try superclasses. raise error if not found def resolve_method name fun = get_function name - # TODO THE BOOK says is class A derives from B , then the metaclass of A derives from the metaclass of B + # TODO THE BOOK says is class A derives from B , then the metaclass of + # A derives from the metaclass of B # just get to it ! (and stop whimpering) raise "Method not found #{name} , for #{inspect}" unless fun fun diff --git a/lib/parfait/space.rb b/lib/parfait/space.rb index 57a82a5c..1363faf6 100644 --- a/lib/parfait/space.rb +++ b/lib/parfait/space.rb @@ -14,7 +14,8 @@ module Parfait # The Space contains all objects for a program. In functional terms it is a program, but in oo # it is a collection of objects, some of which are data, some classes, some functions - # The main entry is a function called (of all things) "main", This _must be supplied by the compling + # The main entry is a function called (of all things) "main". + # This _must be supplied by the compled code (similar to c) # There is a start and exit block that call main, which receives an List of strings # While data ususally would live in a .data section, we may also "inline" it into the code diff --git a/lib/register/assembler.rb b/lib/register/assembler.rb index 31a44317..4cd2a9db 100644 --- a/lib/register/assembler.rb +++ b/lib/register/assembler.rb @@ -1,12 +1,13 @@ module Register class LinkException < Exception end - # Assmble the object space into a binary. + # Assemble the object space into a binary. # Link first to get positions, then assemble - # link and assemble functions for each class are close to each other, so to get them the same. - # meaning: as the link function determines the length of an object and the assemble actually writes the bytes - # they are pretty much dependant. In an earlier version they were functions on the objects, but now it - # has gone to a visitor pattern. + + # The link function determines the length of an object and the assemble actually + # writes the bytes they are pretty much dependant. In an earlier version they were + # functions on the objects, but now it has gone to a visitor pattern. + class Assembler TYPE_REF = 0 TYPE_INT = 1 @@ -119,7 +120,9 @@ module Register # write type and layout of the instance, and the variables that are passed # variables ar values, ie int or refs. For refs the object needs to save the object first def assemble_self( object , variables ) - raise "Object(#{object.object_id}) not linked #{object.inspect}" unless @objects[object.object_id] + unless @objects[object.object_id] + raise "Object(#{object.object_id}) not linked #{object.inspect}" + end type = type_word(variables) @stream.write_uint32( type ) write_ref_for(object.layout[:names] ) @@ -207,9 +210,8 @@ module Register private - # write means we write the resulting address straight into the assembler stream (ie don't return it) + # write means we write the resulting address straight into the assembler stream # object means the object of which we write the address - # and we write the address into the self, given as second parameter def write_ref_for object @stream.write_sint32 object.position end diff --git a/lib/register/builtin/integer.rb b/lib/register/builtin/integer.rb index 7263593a..23585c7e 100644 --- a/lib/register/builtin/integer.rb +++ b/lib/register/builtin/integer.rb @@ -2,7 +2,8 @@ module Builtin module Integer module ClassMethods - # The conversion to base10 is quite a bit more complicated than i thought. The bulk of it is in div10 + # The conversion to base10 is quite a bit more complicated than i thought. + # The bulk of it is in div10 # We set up variables, do the devision and write the result to the string # then check if were done and recurse if neccessary # As we write before we recurse (save a push) we write the number backwards diff --git a/lib/register/builtin/object.rb b/lib/register/builtin/object.rb index 2d60bfd5..62a6c648 100644 --- a/lib/register/builtin/object.rb +++ b/lib/register/builtin/object.rb @@ -4,7 +4,8 @@ module Builtin # return the index of the variable. Now "normal" code can't really do anything with that, but # set/get instance variable use it. - # This is just a placeholder, as we code this in ruby, but the instance methods need the definition before. + # This is just a placeholder, as we code this in ruby, + # but the instance methods need the definition before. def index_of context , name = Virtual::Integer index_function = Virtual::CompiledMethodInfo.create_method("Object" , "index_of" , [Virtual::Reference] ) index_function.info.return_type = Virtual::Integer @@ -22,7 +23,8 @@ module Builtin # i = self.index_of(var) # return at_index(i) # end - # The at_index is just "below" the api, something we need but don't want to expose, so we can't code the above in ruby + # The at_index is just "below" the api, something we need but don't want to expose, + # so we can't code the above in ruby def _get_instance_variable context , name = Virtual::Integer get_function = Virtual::CompiledMethodInfo.create_method("Object","_get_instance_variable" , [ Virtual::Reference ] ) return get_function diff --git a/lib/register/register_reference.rb b/lib/register/register_reference.rb index 85848006..5e73c7df 100644 --- a/lib/register/register_reference.rb +++ b/lib/register/register_reference.rb @@ -2,7 +2,8 @@ module Register # RegisterReference is not the name for a register, "only" for a certain use of it. # In a way it is like a variable name, a storage location. The location is a register off course, - # but which register can be changed, and _all_ instructions sharing the RegisterReference then use that register + # but which register can be changed, and _all_ instructions sharing the RegisterReference then + # use that register # In other words a simple level of indirection, or change from value to reference sematics. class RegisterReference diff --git a/lib/virtual/compiled_method_info.rb b/lib/virtual/compiled_method_info.rb index 63c1ce54..cfc1361b 100644 --- a/lib/virtual/compiled_method_info.rb +++ b/lib/virtual/compiled_method_info.rb @@ -15,8 +15,8 @@ module Virtual # They also have local variables. - # Code-wise Methods are made up from a list of Blocks, in a similar way blocks are made up of Instructions - # The function starts with one block, and that has a start and end (return) + # Code-wise Methods are made up from a list of Blocks, in a similar way blocks are made up of + # Instructions. The function starts with one block, and that has a start and end (return) # Blocks can be linked in two ways: # -linear: flow continues from one to the next as they are sequential both logically and @@ -59,7 +59,9 @@ module Virtual # add an instruction after the current (insertion point) # the added instruction will become the new insertion point def add_code instruction - raise instruction.inspect unless (instruction.is_a?(Instruction) or instruction.is_a?(Register::Instruction)) + unless (instruction.is_a?(Instruction) or instruction.is_a?(Register::Instruction)) + raise instruction.inspect + end @current.add_code(instruction) #insert after current self end @@ -79,21 +81,24 @@ module Virtual used.uniq end - # control structures need to see blocks as a graph, but they are stored as a list with implict branches + # control structures need to see blocks as a graph, but they are stored as a list with implict + # branches # So when creating a new block (with new_block), it is only added to the list, but instructions # still go to the current one # With this function one can change the current block, to actually code it. - # This juggling is (unfortunately) neccessary, as all compile functions just keep puring their code into the - # method and don't care what other compiles (like if's) do. + # This juggling is (unfortunately) neccessary, as all compile functions just keep puring their + # code into the method and don't care what other compiles (like if's) do. # Example: while, needs 2 extra blocks # 1 condition code, must be its own blockas we jump back to it # - the body, can actually be after the condition as we don't need to jump there # 2 after while block. Condition jumps here - # After block 2, the function is linear again and the calling code does not need to know what happened + # After block 2, the function is linear again and the calling code does not need to know what + # happened # But subsequent statements are still using the original block (self) to add code to - # So the while expression creates the extra blocks, adds them and the code and then "moves" the insertion point along + # So the while expression creates the extra blocks, adds them and the code and then "moves" + # the insertion point along def current block @current = block self diff --git a/lib/virtual/compiler/basic_expressions.rb b/lib/virtual/compiler/basic_expressions.rb index 6a6d734b..06421983 100644 --- a/lib/virtual/compiler/basic_expressions.rb +++ b/lib/virtual/compiler/basic_expressions.rb @@ -79,7 +79,9 @@ module Virtual #attr_reader :left, :right def self.compile_assignment expression , method - raise "must assign to NameExpression , not #{expression.left}" unless expression.left.instance_of? Ast::NameExpression + unless expression.left.instance_of? Ast::NameExpression + raise "must assign to NameExpression , not #{expression.left}" + end r = Compiler.compile(expression.right , method ) raise "oh noo, nil from where #{expression.right.inspect}" unless r index = method.has_arg(Virtual.new_word name) diff --git a/lib/virtual/compiler/if_expression.rb b/lib/virtual/compiler/if_expression.rb index d21eaa44..583d10d0 100644 --- a/lib/virtual/compiler/if_expression.rb +++ b/lib/virtual/compiler/if_expression.rb @@ -4,7 +4,8 @@ module Virtual def self.compile_if expression , method # to execute the logic as the if states it, the blocks are the other way around - # so we can the jump over the else if true ,and the else joins unconditionally after the true_block + # so we can the jump over the else if true , + # and the else joins unconditionally after the true_block merge_block = method.info.new_block "if_merge" # last one, created first true_block = method.info.new_block "if_true" # second, linked in after current, before merge false_block = method.info.new_block "if_false" # directly next in order, ie if we don't jump we land here diff --git a/lib/virtual/compiler/module_expression.rb b/lib/virtual/compiler/module_expression.rb index be83edb3..a18d185b 100644 --- a/lib/virtual/compiler/module_expression.rb +++ b/lib/virtual/compiler/module_expression.rb @@ -10,7 +10,8 @@ module Virtual puts "Created class #{clazz.name.inspect}" expression.expressions.each do |expr| # check if it's a function definition and add - # if not, execute it, but that does means we should be in salama (executable), not ruby. ie throw an error for now + # if not, execute it, but that does means we should be in salama (executable), not ruby. + # ie throw an error for now raise "only functions for now #{expr.inspect}" unless expr.is_a? Ast::FunctionExpression #puts "compiling expression #{expression}" expression_value = Compiler.compile(expr,method ) diff --git a/lib/virtual/compiler/return_expression.rb b/lib/virtual/compiler/return_expression.rb index 546a9548..9e12946f 100644 --- a/lib/virtual/compiler/return_expression.rb +++ b/lib/virtual/compiler/return_expression.rb @@ -15,7 +15,9 @@ module Virtual if expression_value.is_a?(IntegerConstant) or expression_value.is_a?(ObjectConstant) return_reg.load into , expression_value else - return_reg.move( into, expression_value ) if expression_value.register_symbol != return_reg.register_symbol + if expression_value.register_symbol != return_reg.register_symbol + return_reg.move( into, expression_value ) + end end #function.set_return return_reg return return_reg diff --git a/lib/virtual/instructions/halt.rb b/lib/virtual/instructions/halt.rb index c75c4a24..2005af46 100644 --- a/lib/virtual/instructions/halt.rb +++ b/lib/virtual/instructions/halt.rb @@ -1,10 +1,11 @@ module Virtual - # the first instruction we need is to stop. Off course in a real machine this would be a syscall, but that is just - # an implementation (in a programm it would be a function). + # the first instruction we need is to stop. Off course in a real machine this would be a syscall, + # but that is just an implementation (in a programm it would be a function). # But in a virtual machine, not only do we need this instruction, - # it is indeed the first instruction as just this instruction is the smallest possible programm for the machine. + # it is indeed the first instruction as just this instruction is the smallest possible programm + # for the machine. # As such it is the next instruction for any first instruction that we generate. class Halt < Instruction end diff --git a/lib/virtual/instructions/instance_get.rb b/lib/virtual/instructions/instance_get.rb index 0f5f7709..cf843c14 100644 --- a/lib/virtual/instructions/instance_get.rb +++ b/lib/virtual/instructions/instance_get.rb @@ -1,7 +1,9 @@ module Virtual - # Get a instance variable by _name_ . So we have to resolve the name to an index to trnsform into a Slot - # The slot may the be used in a set on left or right hand. The transformation is done by GetImplementation + # Get a instance variable by _name_ . So we have to resolve the name to an index to + # transform into a Slot + # The slot may the be used in a set on left or right hand. + # The transformation is done by GetImplementation class InstanceGet < Instruction def initialize name @name = name.to_sym diff --git a/lib/virtual/instructions/set.rb b/lib/virtual/instructions/set.rb index 0fc1ec55..65d2f24b 100644 --- a/lib/virtual/instructions/set.rb +++ b/lib/virtual/instructions/set.rb @@ -1,8 +1,8 @@ module Virtual # class for Set instructions, A set is basically a mem move. - # to and from are indexes into the known objects(frame,message,self and new_message), these are represented as slots - # (see there) + # to and from are indexes into the known objects(frame,message,self and new_message), + # these are represented as slots (see there) # from may be a Constant (Object,Integer,String,Class) class Set < Instruction def initialize to , from diff --git a/lib/virtual/machine.rb b/lib/virtual/machine.rb index d8029412..6e51b65f 100644 --- a/lib/virtual/machine.rb +++ b/lib/virtual/machine.rb @@ -1,34 +1,37 @@ module Virtual - # The Virtual Machine is a value based virtual machine in which ruby is implemented. While it is value based, - # it resembles oo in basic ways of object encapsulation and method invokation, it is a "closed" / static sytem - # in that all types are know and there is no dynamic dispatch (so we don't bite our tail here). + # The Virtual Machine is a value based virtual machine in which ruby is implemented. + # While it is value based, it resembles oo in basic ways of object encapsulation and method + # invocation, it is a "closed" / static sytem in that all types are know and there is no + # dynamic dispatch (so we don't bite our tail here). # # It is minimal and realistic and low level - # - minimal means that if one thing can be implemented by another, it is left out. This is quite the opposite from - # ruby, which has several loops, many redundant if forms and the like. - # - realistic means it is easy to implement on a 32 bit machine (arm) and possibly 64 bit. Memory access, a stack, - # some registers of same size are the underlying hardware. (not ie byte machine) - # - low level means it's basic instructions are realively easily implemented in a register machine. ie send is not - # a an instruction but a function. + # - minimal means that if one thing can be implemented by another, it is left out. This is quite + # the opposite from ruby, which has several loops, many redundant if forms and the like. + # - realistic means it is easy to implement on a 32 bit machine (arm) and possibly 64 bit. + # Memory access,some registers of same size are the underlying hardware. (not ie byte machine) + # - low level means it's basic instructions are realively easily implemented in a register machine. + # ie send is not a an instruction but a function. # - # So the memory model of the machine allows for indexed access into an "object" . A fixed number of objects exist - # (ie garbage collection is reclaming, not destroying and recreating) although there may be a way to increase that number. + # So the memory model of the machine allows for indexed access into an "object" . + # A fixed number of objects exist (ie garbage collection is reclaming, not destroying and + # recreating) although there may be a way to increase that number. # # The ast is transformed to virtaul-machine objects, some of which represent code, some data. # # The next step transforms to the register machine layer, which is what actually executes. # - # More concretely, a virtual machine is a sort of oo turing machine, it has a current instruction, executes the - # instructions, fetches the next one and so on. + # More concretely, a virtual machine is a sort of oo turing machine, it has a current instruction, + # executes the instructions, fetches the next one and so on. # Off course the instructions are not soo simple, but in oo terms quite so. # # The machine is virtual in the sense that it is completely modeled in software, # it's complete state explicitly available (not implicitly by walking stacks or something) # The machine has a no register, but local variables, a scope at each point in time. - # Scope changes with calls and blocks, but is saved at each level. In terms of lower level implementation this means - # that the the model is such that what is a variable in ruby, never ends up being just on the pysical stack. + # Scope changes with calls and blocks, but is saved at each level. In terms of lower level + # implementation this means that the the model is such that what is a variable in ruby, + # never ends up being just on the pysical stack. # class Machine diff --git a/lib/virtual/message.rb b/lib/virtual/message.rb index 248b1043..72f6a97c 100644 --- a/lib/virtual/message.rb +++ b/lib/virtual/message.rb @@ -1,21 +1,23 @@ module Virtual # So when an object calls a method, or sends a message, this is what it sends: a Message - # A message contains the sender, return and exceptional return addresses,the arguments, and a slot for the frame. + # A message contains the sender, return and exceptional return addresses,the arguments, + # and a slot for the frame. - # As such it is a very run-time object, deep in the machinery as it were, and does not have meaningful - # methods you could call at compile time. + # As such it is a very run-time object, deep in the machinery as it were, and does not have + # meaningful methods you could call at compile time. - # The methods that are there, are nevertheless meant to be called at compile time and generate code, rather than - # executing it. + # The methods that are there, are nevertheless meant to be called at compile time and generate + # code, rather than executing it. # The caller creates the Message and passes control to the receiver's method - # The receiver create a new Frame to hold local and temporary variables and (later) creates default values for - # arguments that were not passed + # The receiver create a new Frame to hold local and temporary variables and (later) creates + # default values for arguments that were not passed - # How the actual finding of the method takes place (acording to the ruby rules) is not simple, but as there is a - # guaranteed result (be it method_missing) it does not matter to the passing mechanism described + # How the actual finding of the method takes place (acording to the ruby rules) is not simple, + # but as there is a guaranteed result (be it method_missing) it does not matter to the passing + # mechanism described # During compilation Message and frame objects are created to do type analysis diff --git a/lib/virtual/parfait_adapter.rb b/lib/virtual/parfait_adapter.rb index a364b223..6096dec8 100644 --- a/lib/virtual/parfait_adapter.rb +++ b/lib/virtual/parfait_adapter.rb @@ -25,7 +25,9 @@ module FakeMem end #TODO, this is copied from module Positioned, maybe avoid duplication ? def position - raise "position accessed but not set at #{mem_length} for #{self.inspect[0...1000]}" if @position == nil + if @position == nil + raise "position accessed but not set at #{mem_length} for #{self.inspect[0...1000]}" + end @position end def set_position pos diff --git a/lib/virtual/passes/frame_implementation.rb b/lib/virtual/passes/frame_implementation.rb index 8c9306ba..be189898 100644 --- a/lib/virtual/passes/frame_implementation.rb +++ b/lib/virtual/passes/frame_implementation.rb @@ -3,14 +3,18 @@ module Virtual # Frames and Message are very similar apart from the class name # - All existing instances are stored in the space for both - # - Size is currently 2, ie 16 words (TODO a little flexibility here would not hurt, but the mountain is big) - # - Unused instances for a linked list with their first instance variable. This is HARD coded to avoid any lookup + # - Size is currently 2, ie 16 words + # (TODO a little flexibility here would not hurt, but the mountain is big) + # - Unused instances for a linked list with their first instance variable. + # This is HARD coded to avoid any lookup - # Just as a reminder: a message object is created before a send and holds return address/message and arguemnts + self - # frames are created upon entering a method and hold local and temporary variables - # as a result one of each is created for every single method call. A LOT, so make it fast luke - # Note: this is off course the reason for stack based implementations that just increment a known pointer/register or - # something. But i think most programs are memory bound and a few extra instructions don't hurt. + # Just as a reminder: a message object is created before a send and holds return address/message + # and arguemnts + self frames are created upon entering a method and hold local and temporary + # variables as a result one of each is created for every single method call. + # A LOT, so make it fast luke + # Note: this is off course the reason for stack based implementations that just increment + # a known pointer/register or something. But i think most programs are memory bound + # and a few extra instructions don't hurt. # After all, we are buying a big prize:oo, otherwise known as sanity. class FrameImplementation diff --git a/lib/virtual/passes/get_implementation.rb b/lib/virtual/passes/get_implementation.rb index 4f7b8e15..64f69e1c 100644 --- a/lib/virtual/passes/get_implementation.rb +++ b/lib/virtual/passes/get_implementation.rb @@ -1,7 +1,9 @@ module Virtual - # This implements instance variable get (not the opposite of Set, such a thing does not exists, their slots) + # This implements instance variable get (not the opposite of Set, + # such a thing does not exists, their slots) - # Ivar get needs to acces the layout, find the index of the name, and shuffle the data to return register + # Ivar get needs to acces the layout, find the index of the name, + # and shuffle the data to return register # In short it's so complicated we implement it in ruby and stick the implementation here class GetImplementation def run block diff --git a/lib/virtual/passes/send_implementation.rb b/lib/virtual/passes/send_implementation.rb index db9e2f84..9a8bedc8 100644 --- a/lib/virtual/passes/send_implementation.rb +++ b/lib/virtual/passes/send_implementation.rb @@ -4,9 +4,11 @@ module Virtual # That off course opens up an endless loop possibility that we stop by # implementing Class and Module methods - # Note: I find it slightly unsemetrical that the NewMessage object needs to be created before this instruction - # This is because all expressions create a (return) value and that return value is overwritten by the next - # expression unless saved. And since the message is the place to save it it needs to exist. qed + # Note: I find it slightly unsymmetrical that the NewMessage object needs to be created + # before this instruction. + # This is because all expressions create a (return) value and that return value is + # overwritten by the next expression unless saved. + # And since the message is the place to save it it needs to exist. qed class SendImplementation def run block block.codes.dup.each do |code| diff --git a/lib/virtual/plock.rb b/lib/virtual/plock.rb index 59cc6395..cdf04ca8 100644 --- a/lib/virtual/plock.rb +++ b/lib/virtual/plock.rb @@ -4,18 +4,22 @@ module Virtual # Data in a Block is usefull in the same way data in objects is. Plocks being otherwise just code. # # But the concept is not quite straigtforwrd: If one thinks of a Plock embedded in a normal method, - # the a data in the Plock would be static data. In OO terms this comes quite close to a Proc, if the data is the local - # variables. Quite possibly they shall be used to implement procs, but that is not the direction now. + # the a data in the Plock would be static data. In OO terms this comes quite close to a Proc, + # if the data is the local variables. + # Quite possibly they shall be used to implement procs, but that is not the direction now. # - # For now we use Plocks behaind the scenes as it were. In the code that you never see, method invocation mainly. - # - # In terms of implementation the Plock is a Block with data (Not too much data, mainly a couple of references). - # The block writes it's instructions as normal, but a jump is inserted as the last instruction. The jump is to the - # next block, over the data that is inserted after the block code (and so before the next) + # For now we use Plocks behaind the scenes as it were. In the code that you never see, + # method invocation mainly. + # + # In terms of implementation the Plock is a Block with data + # (Not too much data, mainly a couple of references). + # The block writes it's instructions as normal, but a jump is inserted as the last instruction. + # The jump is to the next block, over the data that is inserted after the block code + # (and so before the next) # # It follows that Plocks should be linear blocks. class Plock < Block - + def initialize(name , method , next_block ) super @data = [] diff --git a/lib/virtual/positioned.rb b/lib/virtual/positioned.rb index aa72bedd..3660bb7a 100644 --- a/lib/virtual/positioned.rb +++ b/lib/virtual/positioned.rb @@ -2,7 +2,9 @@ require_relative "type" module Positioned def position - raise "position accessed but not set at #{mem_length} for #{self.inspect[0...500]}" if @position == nil + if @position == nil + raise "position accessed but not set at #{mem_length} for #{self.inspect[0...500]}" + end @position end def set_position pos