polish docs
and a bit of code style
This commit is contained in:
parent
d6a2ea4cfc
commit
f7aac1d1a4
@ -2,25 +2,26 @@ require_relative "attributed"
|
|||||||
|
|
||||||
module Arm
|
module Arm
|
||||||
|
|
||||||
# A Machines main responsibility in the named_listwork is to instantiate Instructions
|
# A Machines main responsibility is to instantiate Instructions.
|
||||||
|
# Arm instructions live in their own directory and are derived from their Risc
|
||||||
|
# couterparts to inherit list functionality
|
||||||
|
|
||||||
# Value functions are mapped to machines by concatenating the values class name + the methd name
|
# Shortcuts are created to easily instantiate Instruction objects.
|
||||||
# Example: IntegerValue.plus( value ) -> Machine.signed_plus (value )
|
# Example: ArmMachine.pop -> StackInstruction.new( {:opcode => :pop}.merge(options) )
|
||||||
|
#
|
||||||
# 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
|
# 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
|
# does is save you typing the clazz.new. It passes the function name as the :opcode
|
||||||
|
|
||||||
class ArmMachine
|
class ArmMachine
|
||||||
|
|
||||||
# conditions specify all the possibilities for branches. Branches are b + condition
|
# conditions specify all the possibilities for branches. Branches are b + condition
|
||||||
# Example: beq means brach if equal.
|
# Example: beq means brach if equal.
|
||||||
# :al means always, so bal is an unconditional branch (but b() also works)
|
# :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
|
# here we create the shortcuts for the "standard" arm instructions that we use.
|
||||||
# Derived machines may use own instructions and define functions for them if so desired
|
# (note that it is possible to add instructions by adding new classes and optionally
|
||||||
|
# new factory functions to this class)
|
||||||
def self.init
|
def self.init
|
||||||
[:push, :pop].each do |inst|
|
[:push, :pop].each do |inst|
|
||||||
define_instruction_one(inst , StackInstruction)
|
define_instruction_one(inst , StackInstruction)
|
||||||
@ -40,7 +41,8 @@ module Arm
|
|||||||
[:b, :call , :swi].each do |inst|
|
[:b, :call , :swi].each do |inst|
|
||||||
define_instruction_one(inst , CallInstruction)
|
define_instruction_one(inst , CallInstruction)
|
||||||
end
|
end
|
||||||
# create all possible brach instructions, but the CallInstruction demangles the
|
|
||||||
|
# create all possible branch instructions, but the CallInstruction demangles the
|
||||||
# code, and has opcode set to :b and :condition_code set to the condition
|
# code, and has opcode set to :b and :condition_code set to the condition
|
||||||
CONDITIONS.each do |suffix|
|
CONDITIONS.each do |suffix|
|
||||||
define_instruction_one("b#{suffix}".to_sym , CallInstruction)
|
define_instruction_one("b#{suffix}".to_sym , CallInstruction)
|
||||||
@ -64,13 +66,10 @@ module Arm
|
|||||||
|
|
||||||
#defining the instruction (opcode, symbol) as an given class.
|
#defining the instruction (opcode, symbol) as an given class.
|
||||||
# the class is a Risc::Instruction derived base class and to create machine specific function
|
# the class is a Risc::Instruction derived base class and to create machine specific function
|
||||||
# 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
|
# These instruction classes must follow a naming pattern and take a hash in the contructor
|
||||||
# Example, a mov() opcode instantiates a Risc::MoveInstruction
|
# Example, a mov() opcode instantiates a Arm::MoveInstruction < Risc::MoveInstruction ,
|
||||||
# for an Arm machine, a class Arm::MoveInstruction < Risc::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 = {} )
|
def self.define_instruction_one(inst , clazz , defaults = {} )
|
||||||
clazz = class_for(clazz)
|
clazz = class_for(clazz)
|
||||||
def_method(inst) do |first , options = nil|
|
def_method(inst) do |first , options = nil|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
module Arm
|
module Arm
|
||||||
class MachineCode
|
class MachineCode
|
||||||
|
|
||||||
def function_call into , call
|
def function_call( into , call )
|
||||||
raise "Not CallSite #{call.inspect}" unless call.is_a? Risc::CallSite
|
raise "Not CallSite #{call.inspect}" unless call.is_a? Risc::CallSite
|
||||||
raise "Not linked #{call.inspect}" unless call.function
|
raise "Not linked #{call.inspect}" unless call.function
|
||||||
into.add_code call( call.function )
|
into.add_code call( call.function )
|
||||||
@ -9,28 +9,28 @@ module Arm
|
|||||||
call.function.return_type
|
call.function.return_type
|
||||||
end
|
end
|
||||||
|
|
||||||
def main_start context
|
def main_start( context )
|
||||||
entry = Risc::Block.new("main_entry",nil,nil)
|
entry = Risc::Block.new("main_entry",nil,nil)
|
||||||
entry.add_code mov( :fp , 0 )
|
entry.add_code mov( :fp , 0 )
|
||||||
entry.add_code call( context.function )
|
entry.add_code call( context.function )
|
||||||
entry
|
entry
|
||||||
end
|
end
|
||||||
def main_exit context
|
def main_exit( context )
|
||||||
exit = Risc::Block.new("main_exit",nil,nil)
|
exit = Risc::Block.new("main_exit",nil,nil)
|
||||||
syscall(exit , 1)
|
syscall(exit , 1)
|
||||||
exit
|
exit
|
||||||
end
|
end
|
||||||
def function_entry block, f_name
|
def function_entry( block, f_name )
|
||||||
block.add_code push( [:lr] )
|
block.add_code push( [:lr] )
|
||||||
block
|
block
|
||||||
end
|
end
|
||||||
def function_exit entry , f_name
|
def function_exit( entry , f_name )
|
||||||
entry.add_code pop( [:pc] )
|
entry.add_code pop( [:pc] )
|
||||||
entry
|
entry
|
||||||
end
|
end
|
||||||
|
|
||||||
# assumes string in standard receiver reg (r2) and moves them down for the syscall
|
# assumes string in standard receiver reg (r2) and moves them down for the syscall
|
||||||
def write_stdout function #, string
|
def write_stdout( function ) #, string
|
||||||
# TODO save and restore r0
|
# TODO save and restore r0
|
||||||
function.mov( :r0 , 1 ) # 1 == stdout
|
function.mov( :r0 , 1 ) # 1 == stdout
|
||||||
function.mov( :r1 , receiver_register )
|
function.mov( :r1 , receiver_register )
|
||||||
@ -39,7 +39,7 @@ module Arm
|
|||||||
end
|
end
|
||||||
|
|
||||||
# stop, do not return
|
# stop, do not return
|
||||||
def exit function #, string
|
def exit( function )#, string
|
||||||
syscall( function.insertion_point , 1 ) # 1 == exit
|
syscall( function.insertion_point , 1 ) # 1 == exit
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ module Arm
|
|||||||
# the number (a Risc::integer) is (itself) divided by 10, ie overwritten by the result
|
# the number (a Risc::integer) is (itself) divided by 10, ie overwritten by the result
|
||||||
# and the remainder is overwritten (ie an out argument)
|
# 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
|
def div10( function, number , remainder )
|
||||||
# Note about division: devision is MUCH more expensive than one would have thought
|
# 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
|
# remainder smaller than an int. i'll post some links sometime. This is from the arm manual
|
||||||
@ -66,7 +66,7 @@ module Arm
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def syscall block , num
|
def syscall( block , num )
|
||||||
# This is very arm specific, syscall number is passed in r7,
|
# This is very arm specific, syscall number is passed in r7,
|
||||||
# other arguments like a c call ie 0 and up
|
# other arguments like a c call ie 0 and up
|
||||||
sys = Risc::Integer.new( Risc::RiscValue.new(SYSCALL_REG) )
|
sys = Risc::Integer.new( Risc::RiscValue.new(SYSCALL_REG) )
|
||||||
|
@ -5,20 +5,20 @@ module Arm
|
|||||||
# for each instruction we call the translator with translate_XXX
|
# for each instruction we call the translator with translate_XXX
|
||||||
# with XXX being the class name.
|
# with XXX being the class name.
|
||||||
# the result is replaced in the stream
|
# the result is replaced in the stream
|
||||||
def translate instruction
|
def translate( instruction )
|
||||||
class_name = instruction.class.name.split("::").last
|
class_name = instruction.class.name.split("::").last
|
||||||
self.send( "translate_#{class_name}".to_sym , instruction)
|
self.send( "translate_#{class_name}".to_sym , instruction)
|
||||||
end
|
end
|
||||||
|
|
||||||
# don't replace labels
|
# don't replace labels
|
||||||
def translate_Label code
|
def translate_Label( code )
|
||||||
nil
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# arm indexes are
|
# arm indexes are
|
||||||
# in bytes, so *4
|
# in bytes, so *4
|
||||||
# if an instruction is passed in we get the index with index function
|
# if an instruction is passed in we get the index with index function
|
||||||
def arm_index index
|
def arm_index( index )
|
||||||
index = index.index if index.is_a?(Risc::Instruction)
|
index = index.index if index.is_a?(Risc::Instruction)
|
||||||
raise "index error 0" if index == 0
|
raise "index error 0" if index == 0
|
||||||
index * 4
|
index * 4
|
||||||
|
@ -4,7 +4,7 @@ module Common
|
|||||||
# set the next instruction (also aliased as <<)
|
# set the next instruction (also aliased as <<)
|
||||||
# throw an error if that is set, use insert for that use case
|
# throw an error if that is set, use insert for that use case
|
||||||
# return the instruction, so chaining works as one wants (not backwards)
|
# return the instruction, so chaining works as one wants (not backwards)
|
||||||
def set_next nekst
|
def set_next( nekst )
|
||||||
raise "Next already set #{@next}" if @next
|
raise "Next already set #{@next}" if @next
|
||||||
@next = nekst
|
@next = nekst
|
||||||
nekst
|
nekst
|
||||||
@ -12,7 +12,7 @@ module Common
|
|||||||
alias :<< :set_next
|
alias :<< :set_next
|
||||||
|
|
||||||
# during translation we replace one by one
|
# during translation we replace one by one
|
||||||
def replace_next nekst
|
def replace_next( nekst )
|
||||||
old = @next
|
old = @next
|
||||||
@next = nekst
|
@next = nekst
|
||||||
@next.append old.next if old
|
@next.append old.next if old
|
||||||
@ -27,7 +27,7 @@ module Common
|
|||||||
# set the give instruction as the next, while moving any existing
|
# set the give instruction as the next, while moving any existing
|
||||||
# instruction along to the given ones's next.
|
# instruction along to the given ones's next.
|
||||||
# ie insert into the linked list that the instructions form
|
# ie insert into the linked list that the instructions form
|
||||||
def insert instruction
|
def insert( instruction )
|
||||||
instruction.set_next @next
|
instruction.set_next @next
|
||||||
@next = instruction
|
@next = instruction
|
||||||
end
|
end
|
||||||
@ -41,11 +41,11 @@ module Common
|
|||||||
|
|
||||||
# set next for the last (see last)
|
# set next for the last (see last)
|
||||||
# so append the given code to the linked list at the end
|
# so append the given code to the linked list at the end
|
||||||
def append code
|
def append( code )
|
||||||
last.set_next code
|
last.set_next code
|
||||||
end
|
end
|
||||||
|
|
||||||
def length labels = []
|
def length( labels = [] )
|
||||||
ret = 1
|
ret = 1
|
||||||
ret += self.next.length( labels ) if self.next
|
ret += self.next.length( labels ) if self.next
|
||||||
ret
|
ret
|
||||||
|
@ -24,6 +24,9 @@ module Common
|
|||||||
def [](i)
|
def [](i)
|
||||||
@statements[i]
|
@statements[i]
|
||||||
end
|
end
|
||||||
|
def <<(o)
|
||||||
|
@statements << o
|
||||||
|
end
|
||||||
def collect(arr)
|
def collect(arr)
|
||||||
@statements.each { |s| s.collect(arr) }
|
@statements.each { |s| s.collect(arr) }
|
||||||
super
|
super
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
Minimal elf support
|
# Minimal elf support
|
||||||
===================
|
|
||||||
|
|
||||||
This is really minimal and works only for our current use case
|
This is really minimal and works only for our current use case
|
||||||
|
|
||||||
- no external functions (all syscalls)
|
- no external functions (all syscalls)
|
||||||
- only position independant code (no relocation)
|
- only position independent code (no relocation)
|
||||||
- embedded data (into text), no data section
|
- embedded data (into text), no data section
|
||||||
|
|
||||||
I was close to going the wilson way, ie assmble, load into memory and jump
|
I was close to going the wilson way, ie assmble, load into memory and jump
|
||||||
|
|
||||||
But it is nice to produce executables. Also easier to test, what with segfaults and such.
|
But it is nice to produce executables. Also easier to test, what with segfaults and such.
|
||||||
|
|
||||||
Executable files are not supported (yet?), but object files work. So the only thing that remains is to
|
Executable files are not supported (yet?), but object files work. So the only thing that
|
||||||
call the linker on the produced object file. The resulting file is an executable that actually works!!
|
remains is to call the linker on the produced object file. The resulting file is an
|
||||||
|
executable that actually works!!
|
||||||
|
|
||||||
Thanks to Mikko for starting this arm/elf project in the first place: https://github.com/cyndis/as
|
Thanks to Mikko for starting this arm/elf project in the first place: https://github.com/cyndis/as
|
||||||
|
|
||||||
|
@ -18,10 +18,6 @@ module Mom
|
|||||||
flat
|
flat
|
||||||
end
|
end
|
||||||
|
|
||||||
def <<(o)
|
|
||||||
@statements << o
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
### Parfait: a thin layer
|
# Parfait: a thin layer
|
||||||
|
|
||||||
Parfait is the run-time of the object system.
|
Parfait is the run-time of the object system.
|
||||||
To be more precise, it is that part of the run-time needed to boot.
|
To be more precise, it is that part of the run-time needed to boot.
|
||||||
@ -6,8 +6,8 @@ To be more precise, it is that part of the run-time needed to boot.
|
|||||||
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, to create the data for the compiled vm.
|
We reuse the Parfait code at compile-time, to create the data for the compiled code.
|
||||||
To do this the vm (re) defines the object memory (in parfait_adapter).
|
To do this the compiler (re) defines the object memory (in parfait_adapter).
|
||||||
|
|
||||||
A work in progress that started from here : http://ruby-x.org/2014/06/10/more-clarity.html
|
A work in progress that started from here : http://ruby-x.org/2014/06/10/more-clarity.html
|
||||||
went on here http://ruby-x.org/2014/07/05/layers-vs-passes.html
|
went on here http://ruby-x.org/2014/07/05/layers-vs-passes.html
|
||||||
@ -22,10 +22,10 @@ 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
|
Parfait has a brother, the Builtin module. Builtin contains everything that can not be coded in
|
||||||
ruby, but we still need (things like List access).
|
ruby, but we still need (things like List access).
|
||||||
|
|
||||||
### Vm vs language- core
|
## Vm vs language- core
|
||||||
|
|
||||||
Parfait is not the language core library. Core library functionality differs between
|
Parfait is not the language core library. Core library functionality differs between
|
||||||
languages and so the language core lib must be on top of the vm parfait.
|
languages and so the language core lib must be on top of parfait.
|
||||||
|
|
||||||
To make this point clear, i have started using different names for the core classes. Hopefully
|
To make this point clear, i have started using different names for the core classes. Hopefully
|
||||||
more sensible ones, ie List instead of Array, Dictionary instead of Hash.
|
more sensible ones, ie List instead of Array, Dictionary instead of Hash.
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
Risc Machine
|
# Risc Machine
|
||||||
================
|
|
||||||
|
|
||||||
The RiscMachine, is an abstract machine with registers. Think of it as an arm machine with
|
The RiscMachine, is an abstract machine with registers. Think of it as an arm machine with
|
||||||
normal instruction names. It is not however an abstraction of existing hardware, but only
|
normal instruction names. It is not however an abstraction of existing hardware, but only
|
||||||
@ -17,31 +16,29 @@ All data is in objects.
|
|||||||
The register machine is aware of Parfait objects, and specifically uses Message and Frame to
|
The register machine is aware of Parfait objects, and specifically uses Message and Frame to
|
||||||
express call semantics.
|
express call semantics.
|
||||||
|
|
||||||
Calls and syscalls
|
## Calls and syscalls
|
||||||
------------------
|
|
||||||
|
|
||||||
The RiscMachine only uses 1 fixed register, the currently worked on Message.
|
The RiscMachine only uses 1 fixed register, the currently worked on Message. (and assumes a
|
||||||
|
program counter and flags, neither of which are directly manipulated)
|
||||||
|
|
||||||
There is no stack, rather messages form a linked list, and preparing to call, the data is pre-filled
|
There is no stack, rather messages form a linked list, and preparing to call, the data is
|
||||||
into the next message. Calling then means moving the new message to the current one and jumping
|
pre-filled into the next message. Calling then means moving the new message to the current
|
||||||
to the address of the method. Returning is the somewhat reverse process.
|
one and jumping to the address of the method. Returning is the somewhat reverse process.
|
||||||
|
|
||||||
Syscalls are implemented by *one* Syscall instruction. The Risc machine does not specify/limit
|
Syscalls are implemented by *one* Syscall instruction. The Risc machine does not specify/limit
|
||||||
the meaning or number of syscalls. This is implemented by the level below, eg the arm/interpreter.
|
the meaning or number of syscalls. This is implemented by the level below, eg the arm/interpreter.
|
||||||
|
|
||||||
Interpreter
|
## Interpreter
|
||||||
===========
|
|
||||||
|
|
||||||
There is an interpreter that can interpret compiled register machine programs.
|
There is an interpreter that can interpret compiled register machine programs.
|
||||||
This is very handy for debugging (an nothing else).
|
This is very handy for debugging (and nothing else).
|
||||||
|
|
||||||
Even more handy is the graphical interface for the interpreter, which is in it's own repository:
|
Even more handy is the graphical interface for the interpreter, which is in it's own repository:
|
||||||
rubyx-debugger.
|
rubyx-debugger.
|
||||||
|
|
||||||
Arm / Elf
|
## Arm / Elf
|
||||||
=========
|
|
||||||
|
|
||||||
There is also a (very strightforward) transformation to arm instructions.
|
There is also a (very straightforward) transformation to arm instructions.
|
||||||
Together with the also quite minimal elf module, arm binaries can be produced.
|
Together with the also quite minimal elf module, arm binaries can be produced.
|
||||||
|
|
||||||
These binaries have no external dependencies and in fact can not even call c at the moment
|
These binaries have no external dependencies and in fact can not even call c at the moment
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
### Builtin module
|
## Builtin module
|
||||||
|
|
||||||
The Builtin module contains functions that can not be coded in ruby.
|
The Builtin module contains functions that can not be coded in ruby.
|
||||||
It is the other side of the parfait coin, part of the runtime.
|
It is the other side of the parfait coin, part of the runtime.
|
||||||
|
|
||||||
The functions are organized by their respective class and get loaded in boot_classes! ,
|
The functions are organised by their respective classes and get loaded in boot_classes! ,
|
||||||
right at the start. (see register/boot.rb)
|
right at the start. (see register/boot.rb)
|
||||||
|
|
||||||
These functions return their code, ie a Parfait::TypedMethod with a MethodSource object,
|
These functions return their code, ie a Parfait::TypedMethod with a MethodSource object,
|
||||||
which can then be called by ruby code as if it were a "normal" function.
|
which can then be called by ruby code as if it were a "normal" function.
|
||||||
|
|
||||||
A normal ruby function is one that is parsed and transformed to code. But not all functionality can
|
A normal ruby function is one that is parsed and transformed to code. But not all
|
||||||
be written in ruby, one of those chicken and egg things.
|
functionality can be written in ruby, one of those chicken and egg things.
|
||||||
C uses Assembler in this situation, we use Builtin functions.
|
C uses Assembler in this situation, we use Builtin functions.
|
||||||
|
|
||||||
Slightly more here : http://ruby-x.org/2014/06/10/more-clarity.html (then still called Kernel)
|
Slightly more here : http://ruby-x.org/2014/06/10/more-clarity.html (then still called Kernel)
|
||||||
|
|
||||||
The Builtin module is scattered into several files, but that is just so the file doesn't get too long.
|
The Builtin module is scattered into several files, but that is just so the file
|
||||||
|
doesn't get too long.
|
||||||
|
@ -5,7 +5,7 @@ module Risc
|
|||||||
# actual assembler level to allow for several cpu architectures.
|
# 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 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.
|
# From code, the next step down is Vool, then Mom (in two steps)
|
||||||
#
|
#
|
||||||
# The next step transforms to the register machine layer, which is quite close to what actually
|
# The next step transforms to the register machine layer, which is quite close to what actually
|
||||||
# executes. The step after transforms to Arm, which creates executables.
|
# executes. The step after transforms to Arm, which creates executables.
|
||||||
|
@ -5,7 +5,7 @@ Virtual Object Oriented Language
|
|||||||
|
|
||||||
in other words, ruby without the fluff.
|
in other words, ruby without the fluff.
|
||||||
|
|
||||||
Possibly later other languages can compile to this level, eg by running in the same jvm.
|
Possibly later other languages can compile to this level and use rx-file as code definition.
|
||||||
|
|
||||||
## Syntax tree
|
## Syntax tree
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ Vool is the layer of concrete syntax tree. The Parser gem is used to parse ruby.
|
|||||||
an abstract syntax tree which is then transformed.
|
an abstract syntax tree which is then transformed.
|
||||||
|
|
||||||
The next layer down is the Mom, Minimal object Machine, which uses an instruction tree.
|
The next layer down is the Mom, Minimal object Machine, which uses an instruction tree.
|
||||||
That is on the way down we create instructions, but stay in tree format. Only the next step
|
That is on the way down we create instructions, but stays in tree format. Only the next step
|
||||||
down to the Risc layer moves to an instruction stream.
|
down to the Risc layer moves to an instruction stream.
|
||||||
|
|
||||||
The nodes of the syntax tree are all the things one would expect from a language, if statements
|
The nodes of the syntax tree are all the things one would expect from a language, if statements
|
||||||
|
@ -12,9 +12,6 @@ module Vool
|
|||||||
@statements.each{ |s| s.create_objects }
|
@statements.each{ |s| s.create_objects }
|
||||||
end
|
end
|
||||||
|
|
||||||
def <<(o)
|
|
||||||
@statements << o
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class ScopeStatement < Statements
|
class ScopeStatement < Statements
|
||||||
|
Loading…
x
Reference in New Issue
Block a user