bit of documentation
This commit is contained in:
parent
fb54d68020
commit
0bf008b351
39
README.md
39
README.md
@ -14,9 +14,12 @@ of the system, see below. The overhaul is done and rubyx produces working binari
|
|||||||
|
|
||||||
Processing goes through layers: Ruby --> Vool --> Mom --> Risc --> Arm --> binary .
|
Processing goes through layers: Ruby --> Vool --> Mom --> Risc --> Arm --> binary .
|
||||||
|
|
||||||
Currently most functional constructs work to some (usable) degree, ie if, while,
|
Currently most basic constructs work to some (usable) degree, ie if, while,
|
||||||
assignment, ivars, calling and dynamic dispatch all work. Work continues
|
assignment, ivars, calling and dynamic dispatch all work. Simple blocks, those
|
||||||
on blocks currently, see below.
|
that ruby passes implicitly also work (lambdas not).
|
||||||
|
|
||||||
|
Work continues on memory management, which turns out to be pretty basic to do just about
|
||||||
|
anything, even counting to a million.
|
||||||
|
|
||||||
## Layers
|
## Layers
|
||||||
|
|
||||||
@ -149,38 +152,22 @@ Specifically here is a list of what works:
|
|||||||
- assignment (local/args/ivar)
|
- assignment (local/args/ivar)
|
||||||
- static calling (where method is determined at compile time)
|
- static calling (where method is determined at compile time)
|
||||||
- dynamic dispatch with caching
|
- dynamic dispatch with caching
|
||||||
|
- implicit blocks, ie the ones that ruby passes implicitly and are used in enumerating
|
||||||
|
|
||||||
Current work is on implicit blocks, which are surprisingly like static method calls
|
|
||||||
and lambdas like dynamic dispatch.
|
|
||||||
|
|
||||||
## Contributing to rubyx
|
## Contributing to rubyx
|
||||||
|
|
||||||
Probably best to talk to me, if it's not a typo or so.
|
Probably best to talk to me, if it's not a typo or so.
|
||||||
|
|
||||||
There is a todo, for inspiration, though actual tasks that result in pulls, should start
|
I've started to put some github issues out, some basic some not so. Also there is a todo
|
||||||
their live as a github issue. There we can discuss details so that no work is done
|
for the adventurous (bigger things, no BIG things).
|
||||||
in vain. There are some small issues there already, just comment if you're interested.
|
|
||||||
|
Actual tasks that result in pulls, should start their life as a github issue.
|
||||||
|
There we can discuss details so that no work is done
|
||||||
|
in vain. If you're interested in an existing issues, just comment on it.
|
||||||
|
|
||||||
Fork and create a branch before sending pulls.
|
Fork and create a branch before sending pulls.
|
||||||
|
|
||||||
### Stary sky
|
|
||||||
|
|
||||||
Iterate:
|
|
||||||
|
|
||||||
1. more cpus (ie intel)
|
|
||||||
2. more systems (ie mac)
|
|
||||||
3. more syscalls, there are after all some hundreds
|
|
||||||
5. A lot of modern cpu's functionality has to be mapped to ruby and implemented in assembler to be useful
|
|
||||||
6. Different sized machines, with different register types ?
|
|
||||||
7. on 64bit, there would be 8 bits for types and thus allow for rational, complex, and whatnot
|
|
||||||
8. Housekeeping (the superset of gc) is abundant
|
|
||||||
9. Any amount of time could be spent on a decent digital tree (see judy). Or possibly Dr.Cliffs hash.
|
|
||||||
10. Also better string/arrays would be good.
|
|
||||||
11. The minor point of threads and hopefully lock free primitives to deal with that.
|
|
||||||
12. Other languages, python at least, maybe others
|
|
||||||
|
|
||||||
And generally optimise and work towards that perfect world (we never seem to be able to attain).
|
|
||||||
|
|
||||||
## Copyright
|
## Copyright
|
||||||
|
|
||||||
Copyright (c) 2014-8 Torsten Ruger.
|
Copyright (c) 2014-8 Torsten Ruger.
|
||||||
|
35
ToDo.md
35
ToDo.md
@ -10,8 +10,7 @@ Some things that would be nice . .
|
|||||||
- utf8 support (string improvements generally)
|
- utf8 support (string improvements generally)
|
||||||
|
|
||||||
|
|
||||||
Platforms
|
## Platforms
|
||||||
---------
|
|
||||||
|
|
||||||
x86 is up for grabs. I have intentionally started on arm (the most sold cpu) because i do
|
x86 is up for grabs. I have intentionally started on arm (the most sold cpu) because i do
|
||||||
this for fun. And my pi is fun.
|
this for fun. And my pi is fun.
|
||||||
@ -19,24 +18,40 @@ this for fun. And my pi is fun.
|
|||||||
There is a ruby intel assembler called wilson out there. Or then there is Metasm, with
|
There is a ruby intel assembler called wilson out there. Or then there is Metasm, with
|
||||||
good support for many other cpu's (and a lot more code)
|
good support for many other cpu's (and a lot more code)
|
||||||
|
|
||||||
Compliance
|
## Compliance
|
||||||
----------
|
|
||||||
|
|
||||||
Is admittedly a little more fun, but also not really my goal in the near future.
|
Is admittedly a little more fun, but also not really my personal goal in the near future.
|
||||||
|
|
||||||
If i am really honest about this, i think ruby is a little quirky around the edges and i
|
If i am really honest about this, i think ruby is a little quirky around the edges and i
|
||||||
think a lot of that can/should be done as a compatibility layer. Keeping the core clean (and shiny).
|
think a lot of that can/should be done as a compatibility layer. Keeping the core clean (and shiny).
|
||||||
|
|
||||||
Stdlib
|
## Stdlib
|
||||||
------
|
|
||||||
|
|
||||||
Stdlib is not clean. More like a layer that accumulated over the years.
|
Stdlib is not clean. More like a layer that accumulated over the years.
|
||||||
|
|
||||||
Very nice solutions exist for most of the important things. Like celluloid for concurrency. Celluloid-io for
|
Very nice solutions exist for most of the important things.
|
||||||
|
Like celluloid for concurrency. Celluloid-io for
|
||||||
good performance io with or without zero-mq. Fiddle looks nice admittedly.
|
good performance io with or without zero-mq. Fiddle looks nice admittedly.
|
||||||
|
|
||||||
Interesting
|
## Concurrency
|
||||||
-----------
|
|
||||||
|
|
||||||
Solving concurrency is up for grabs. Any solution is a start, channels ala go are nice and
|
Solving concurrency is up for grabs. Any solution is a start, channels ala go are nice and
|
||||||
lock free stuff is the ultimate goal.
|
lock free stuff is the ultimate goal.
|
||||||
|
|
||||||
|
## Stary sky
|
||||||
|
|
||||||
|
Iterate:
|
||||||
|
|
||||||
|
1. more cpus (ie intel)
|
||||||
|
2. more systems (ie mac)
|
||||||
|
3. more syscalls, there are after all some hundreds (most as external gems)
|
||||||
|
5. A lot of modern cpu's functionality has to be mapped to ruby and implemented in assembler to be useful
|
||||||
|
6. Different sized machines, with different register types ?
|
||||||
|
7. on 64bit, there would be 8 bits for types and thus allow for rational, complex, and whatnot
|
||||||
|
8. Housekeeping (the superset of gc) is abundant
|
||||||
|
9. Any amount of time could be spent on a decent digital tree (see judy). Or possibly Dr.Cliffs hash.
|
||||||
|
10. Also better string/arrays would be good.
|
||||||
|
11. The minor point of threads and hopefully lock free primitives to deal with that.
|
||||||
|
12. Other languages, python at least, maybe others
|
||||||
|
|
||||||
|
And generally optimise and work towards that perfect world (we never seem to be able to attain).
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
#integer related kernel functions
|
|
||||||
module Risc
|
module Risc
|
||||||
module Builtin
|
module Builtin
|
||||||
|
# integer related kernel functions
|
||||||
|
# all these functions (return the functione they implement) assume interger input
|
||||||
|
#
|
||||||
|
# This means they will have to be renamed at some point and wrapped
|
||||||
module Integer
|
module Integer
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
include CompileHelper
|
include CompileHelper
|
||||||
|
|
||||||
|
# div by 4, ie shift two left
|
||||||
|
# Mostly created for testing at this point, as it is short
|
||||||
|
# return new int with result
|
||||||
def div4(context)
|
def div4(context)
|
||||||
compiler = compiler_for(:Integer,:div4 ,{})
|
compiler = compiler_for(:Integer,:div4 ,{})
|
||||||
compiler.compiler_builder(compiler.source).build do
|
compiler.compiler_builder(compiler.source).build do
|
||||||
@ -18,18 +24,30 @@ module Risc
|
|||||||
compiler.add_mom( Mom::ReturnSequence.new)
|
compiler.add_mom( Mom::ReturnSequence.new)
|
||||||
return compiler
|
return compiler
|
||||||
end
|
end
|
||||||
|
# implemented by the comparison
|
||||||
def >( context )
|
def >( context )
|
||||||
comparison( :> )
|
comparison( :> )
|
||||||
end
|
end
|
||||||
|
# implemented by the comparison
|
||||||
def <( context )
|
def <( context )
|
||||||
comparison( :< )
|
comparison( :< )
|
||||||
end
|
end
|
||||||
|
# implemented by the comparison
|
||||||
def <=( context )
|
def <=( context )
|
||||||
comparison( :<= )
|
comparison( :<= )
|
||||||
end
|
end
|
||||||
|
# implemented by the comparison
|
||||||
def >=( context )
|
def >=( context )
|
||||||
comparison( :>= )
|
comparison( :>= )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# all (four) comparison operation are quite similar and implemented here
|
||||||
|
# - reduce the ints (assume int as input)
|
||||||
|
# - subtract the fixnums
|
||||||
|
# - check for minus ( < and > )
|
||||||
|
# - also check for zero (<= and >=)
|
||||||
|
# - load true or false object into return, depending on check
|
||||||
|
# - return
|
||||||
def comparison( operator )
|
def comparison( operator )
|
||||||
compiler = compiler_for(:Integer, operator ,{other: :Integer})
|
compiler = compiler_for(:Integer, operator ,{other: :Integer})
|
||||||
builder = compiler.compiler_builder(compiler.source)
|
builder = compiler.compiler_builder(compiler.source)
|
||||||
@ -54,11 +72,19 @@ module Risc
|
|||||||
return compiler
|
return compiler
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# not implemented, would need a itos and that needs "new" (wip)
|
||||||
def putint(context)
|
def putint(context)
|
||||||
compiler = compiler_for(:Integer,:putint ,{})
|
compiler = compiler_for(:Integer,:putint ,{})
|
||||||
compiler.add_mom( Mom::ReturnSequence.new)
|
compiler.add_mom( Mom::ReturnSequence.new)
|
||||||
return compiler
|
return compiler
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# implemented all known binary operators that map straight to machine codes
|
||||||
|
# this function (similar to comparison):
|
||||||
|
# - unpacks the intergers to fixnum
|
||||||
|
# - applies the operator (at a risc level)
|
||||||
|
# - gets a new integer and stores the result
|
||||||
|
# - returns the new int
|
||||||
def operator_method( op_sym )
|
def operator_method( op_sym )
|
||||||
compiler = compiler_for(:Integer, op_sym ,{other: :Integer})
|
compiler = compiler_for(:Integer, op_sym ,{other: :Integer})
|
||||||
builder = compiler.compiler_builder(compiler.source)
|
builder = compiler.compiler_builder(compiler.source)
|
||||||
@ -76,6 +102,7 @@ module Risc
|
|||||||
return compiler
|
return compiler
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# old helper function for div10 (which doesn't use builder yet)
|
||||||
def add_receiver(builder)
|
def add_receiver(builder)
|
||||||
message = Risc.message_reg
|
message = Risc.message_reg
|
||||||
ret_type = builder.compiler.receiver_type
|
ret_type = builder.compiler.receiver_type
|
||||||
|
@ -6,7 +6,6 @@ module Risc
|
|||||||
|
|
||||||
# self[index] basically. Index is the first arg
|
# self[index] basically. Index is the first arg
|
||||||
# return is stored in return_value
|
# return is stored in return_value
|
||||||
# (this method returns a new method off course, like all builtin)
|
|
||||||
def get_internal_word( context )
|
def get_internal_word( context )
|
||||||
compiler = compiler_for(:Object , :get_internal_word ,{at: :Integer})
|
compiler = compiler_for(:Object , :get_internal_word ,{at: :Integer})
|
||||||
compiler.compiler_builder(compiler.source).build do
|
compiler.compiler_builder(compiler.source).build do
|
||||||
@ -22,7 +21,7 @@ module Risc
|
|||||||
end
|
end
|
||||||
|
|
||||||
# self[index] = val basically. Index is the first arg , value the second
|
# self[index] = val basically. Index is the first arg , value the second
|
||||||
# no return
|
# return the value passed in
|
||||||
def set_internal_word( context )
|
def set_internal_word( context )
|
||||||
compiler = compiler_for(:Object , :set_internal_word , {at: :Integer, :value => :Object} )
|
compiler = compiler_for(:Object , :set_internal_word , {at: :Integer, :value => :Object} )
|
||||||
compiler.compiler_builder(compiler.source).build do
|
compiler.compiler_builder(compiler.source).build do
|
||||||
@ -48,8 +47,11 @@ module Risc
|
|||||||
|
|
||||||
# this is the really really first place the machine starts (apart from the jump here)
|
# this is the really really first place the machine starts (apart from the jump here)
|
||||||
# it isn't really a function, ie it is jumped to (not called), exits and may not return
|
# it isn't really a function, ie it is jumped to (not called), exits and may not return
|
||||||
# so it is responsible for initial setup
|
# so it is responsible for initial setup:
|
||||||
def __init__ context
|
# - load fist message, set up Space as receiver
|
||||||
|
# - call main, ie set up message for that etc
|
||||||
|
# - exit (exit_sequence) which passes a machine int out to c
|
||||||
|
def __init__( context )
|
||||||
compiler = MethodCompiler.compiler_for_class(:Object,:__init__ ,
|
compiler = MethodCompiler.compiler_for_class(:Object,:__init__ ,
|
||||||
Parfait::NamedList.type_for({}) , Parfait::NamedList.type_for({}))
|
Parfait::NamedList.type_for({}) , Parfait::NamedList.type_for({}))
|
||||||
builder = compiler.compiler_builder(compiler.source)
|
builder = compiler.compiler_builder(compiler.source)
|
||||||
@ -82,6 +84,7 @@ module Risc
|
|||||||
|
|
||||||
# a sort of inline version of exit method.
|
# a sort of inline version of exit method.
|
||||||
# Used by exit and __init__ (so it doesn't have to call it)
|
# Used by exit and __init__ (so it doesn't have to call it)
|
||||||
|
# Assumes int return value and extracts the fixnum for process exit code
|
||||||
def exit_sequence(builder)
|
def exit_sequence(builder)
|
||||||
save_message( builder )
|
save_message( builder )
|
||||||
message = Risc.message_reg
|
message = Risc.message_reg
|
||||||
@ -90,6 +93,8 @@ module Risc
|
|||||||
builder.add_code Syscall.new("emit_syscall(exit)", :exit )
|
builder.add_code Syscall.new("emit_syscall(exit)", :exit )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# the exit function
|
||||||
|
# mainly calls exit_sequence
|
||||||
def exit( context )
|
def exit( context )
|
||||||
compiler = compiler_for(:Object,:exit ,{})
|
compiler = compiler_for(:Object,:exit ,{})
|
||||||
builder = compiler.compiler_builder(compiler.source)
|
builder = compiler.compiler_builder(compiler.source)
|
||||||
@ -97,6 +102,8 @@ module Risc
|
|||||||
return compiler
|
return compiler
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# emit the syscall with given name
|
||||||
|
# there is a Syscall instruction, but the message has to be saved and restored
|
||||||
def emit_syscall( builder , name )
|
def emit_syscall( builder , name )
|
||||||
save_message( builder )
|
save_message( builder )
|
||||||
builder.add_code Syscall.new("emit_syscall(#{name})", name )
|
builder.add_code Syscall.new("emit_syscall(#{name})", name )
|
||||||
@ -114,6 +121,9 @@ module Risc
|
|||||||
builder.add_transfer("save_message", Risc.message_reg , r8 )
|
builder.add_transfer("save_message", Risc.message_reg , r8 )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# restore the message that we save in r8
|
||||||
|
# get a new int and save the c return into it
|
||||||
|
# tht int gets retured, ie is the return_value of the message
|
||||||
def restore_message(builder)
|
def restore_message(builder)
|
||||||
r8 = RegisterValue.new( :r8 , :Message)
|
r8 = RegisterValue.new( :r8 , :Message)
|
||||||
int = builder.compiler.use_reg(:Integer)
|
int = builder.compiler.use_reg(:Integer)
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
module Risc
|
module Risc
|
||||||
module Builtin
|
module Builtin
|
||||||
class Space
|
class Space
|
||||||
|
@ -4,6 +4,12 @@ module Risc
|
|||||||
module ClassMethods
|
module ClassMethods
|
||||||
include CompileHelper
|
include CompileHelper
|
||||||
|
|
||||||
|
# wrapper for the syscall
|
||||||
|
# io/file currently hardcoded to stdout
|
||||||
|
# set up registers for syscall, ie
|
||||||
|
# - pointer in r1
|
||||||
|
# - length in r2
|
||||||
|
# - emit_syscall (which does the return of an integer, see there)
|
||||||
def putstring( context)
|
def putstring( context)
|
||||||
compiler = compiler_for(:Word , :putstring ,{})
|
compiler = compiler_for(:Word , :putstring ,{})
|
||||||
builder = compiler.compiler_builder(compiler.source)
|
builder = compiler.compiler_builder(compiler.source)
|
||||||
@ -18,7 +24,7 @@ module Risc
|
|||||||
end
|
end
|
||||||
|
|
||||||
# self[index] basically. Index is the first arg > 0
|
# self[index] basically. Index is the first arg > 0
|
||||||
# return (and word sized int) is stored in return_value
|
# return a word sized new int, in return_value
|
||||||
def get_internal_byte( context)
|
def get_internal_byte( context)
|
||||||
compiler = compiler_for(:Word , :get_internal_byte , {at: :Integer})
|
compiler = compiler_for(:Word , :get_internal_byte , {at: :Integer})
|
||||||
compiler.compiler_builder(compiler.source).build do
|
compiler.compiler_builder(compiler.source).build do
|
||||||
@ -30,14 +36,13 @@ module Risc
|
|||||||
add_new_int("get_internal_byte", object , integer)
|
add_new_int("get_internal_byte", object , integer)
|
||||||
message[:return_value] << integer
|
message[:return_value] << integer
|
||||||
end
|
end
|
||||||
|
|
||||||
compiler.add_mom( Mom::ReturnSequence.new)
|
compiler.add_mom( Mom::ReturnSequence.new)
|
||||||
return compiler
|
return compiler
|
||||||
end
|
end
|
||||||
|
|
||||||
# self[index] = val basically. Index is the first arg ( >0),
|
# self[index] = val basically. Index is the first arg ( >0),
|
||||||
# value the second
|
# value the second
|
||||||
# return self
|
# return value
|
||||||
def set_internal_byte( context )
|
def set_internal_byte( context )
|
||||||
compiler = compiler_for(:Word, :set_internal_byte , {at: :Integer , :value => :Integer} )
|
compiler = compiler_for(:Word, :set_internal_byte , {at: :Integer , :value => :Integer} )
|
||||||
compiler.compiler_builder(compiler.source).build do
|
compiler.compiler_builder(compiler.source).build do
|
||||||
|
Loading…
Reference in New Issue
Block a user