diff --git a/lib/boot/boot_space.rb b/lib/boot/boot_space.rb index 6fb1b591..c83f23fd 100644 --- a/lib/boot/boot_space.rb +++ b/lib/boot/boot_space.rb @@ -2,7 +2,7 @@ require "vm/context" require "boot/boot_class" require "vm/call_site" require "arm/arm_machine" -require "core/kernel" +require "kernel/all" require "boot/object" require "boot/string" @@ -69,7 +69,7 @@ module Boot end [:utoa, :putstring,:putint,:fibo,:exit].each do |f| puts "Boot Kernel::#{f}" - obj.add_function Core::Kernel.send(f , @context) + obj.add_function Crystal::Kernel.send(f , @context) end obj = get_or_create_class :String [:get , :set].each do |f| diff --git a/lib/core/integer.rb b/lib/core/integer.rb deleted file mode 100644 index 05bfb94f..00000000 --- a/lib/core/integer.rb +++ /dev/null @@ -1,7 +0,0 @@ -module Core - class Integer - module ClassMethods - end - extend ClassMethods - end -end \ No newline at end of file diff --git a/lib/core/kernel.rb b/lib/core/kernel.rb deleted file mode 100644 index 74157071..00000000 --- a/lib/core/kernel.rb +++ /dev/null @@ -1,107 +0,0 @@ -module Core - class Kernel - - #there are no Kernel instances, only class methods. - # We use this module syntax to avoid the (ugly) self (also eases searching). - module ClassMethods - - def exit context - function = Vm::Function.new(:exit , Vm::Integer , [] ) - ret = Vm::RegisterMachine.instance.exit(function) - function.set_return ret - function - end - - def putstring context - function = Vm::Function.new(:putstring , Vm::Integer , [] ) - ret = Vm::RegisterMachine.instance.write_stdout(function) - function.set_return ret - function - end - - def putint context - putint_function = Vm::Function.new(:putint , Vm::Integer , [] , Vm::Integer ) - buffer = Vm::StringConstant.new(" ") # create a buffer - context.object_space.add_object buffer # and save it (function local variable: a no no) - int = putint_function.receiver - moved_int = putint_function.new_local - utoa = context.object_space.get_or_create_class(:Object).resolve_function(:utoa) - putint_function.instance_eval do - mov( moved_int , int ) # move arg up - add( int , buffer ,nil ) # string to write to (add string address to pc) - add( int , int , buffer.length - 3) # 3 for good measure , ahem. - call( utoa ) - after = new_block("after_call") - insert_at after - # And now we "just" have to print it, using the write_stdout - add( int , buffer , nil ) # string to write to - mov( moved_int , buffer.length ) - end - Vm::RegisterMachine.instance.write_stdout(putint_function) - putint_function - end - - # 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 - # arguments: string address , integer - def utoa context - utoa_function = Vm::Function.new(:utoa , Vm::Integer , [ Vm::Integer ] , Vm::Integer ) - str_addr = utoa_function.receiver - number = utoa_function.args.first - remainder = utoa_function.new_local - Vm::RegisterMachine.instance.div10( utoa_function , number , remainder ) - # make char out of digit (by using ascii encoding) 48 == "0" - utoa_function.instance_eval do - add( remainder , remainder , 48) - strb( remainder, str_addr ) - sub( str_addr, str_addr , 1 ) - cmp( number , 0 ) - callne( utoa_function ) - end - return utoa_function - end - - # testing method, hand coded fibo, expects arg in receiver_register - # result comes in return_register - # a hand coded version of the fibonachi numbers - # not my hand off course, found in the net http://www.peter-cockerell.net/aalp/html/ch-5.html - def fibo context - fibo_function = Vm::Function.new(:fibo , Vm::Integer , [] , Vm::Integer ) - result = fibo_function.return_type - int = fibo_function.receiver - - last = fibo_function.new_block("return") - - f1 = fibo_function.new_local - f2 = fibo_function.new_local - - fibo_function.instance_eval do - cmp int , 1 - mov( result, int , condition_code: :le) - ble( last ) #branch to return, rather than return (as the original) - mov f1 , 1 #set up initial values - mov f2 , 0 - end - - loop = fibo_function.new_block("loop") - fibo_function.insert_at loop - - fibo_function.instance_eval do #loop through - add f1 , f1 , f2 # f1 = f1 + f2 - sub f2 , f1 , f2 # f2 = f1 -f2 - sub int , int , 1 # todo: set.. should do below cmp, but doesn't , set_update_status: 1 - cmp int , 1 - bne( loop ) - mov( result , f1 ) - end - - fibo_function - end - - end - - extend ClassMethods - end -end \ No newline at end of file diff --git a/lib/core/system.rb b/lib/core/system.rb deleted file mode 100644 index 4bd466f5..00000000 --- a/lib/core/system.rb +++ /dev/null @@ -1,10 +0,0 @@ -module Core - module System - module ClassMethods - def puts io , c-string , length - - end - end - extend ClassMethods - end -end diff --git a/lib/crystal.rb b/lib/crystal.rb index d7c19093..56fb20eb 100644 --- a/lib/crystal.rb +++ b/lib/crystal.rb @@ -12,4 +12,4 @@ require "vm/function" require "boot/boot_class" require "boot/boot_space" require "stream_reader" -require "core/kernel" +require "kernel/all" diff --git a/lib/kernel/README.md b/lib/kernel/README.md new file mode 100644 index 00000000..adb4ace8 --- /dev/null +++ b/lib/kernel/README.md @@ -0,0 +1,19 @@ +### Kernel module + +As of writing Kernel is an "old style" module, aka a bunch of functions. + +These functions return their code, ie a Vm::Function object, 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 be written in ruby, +one of those chicken and egg things. C uses Assembler in this situation, we use Kernel function. + +Slightly more here : http://ruby-in-ruby.github.io/2014/06/10/more-clarity.html + +The Kernal module is scattered into several files, but that is just so the file doesn't get too long. + +PS: Old style also means the acual receiver is not used. Kernel function are more like global functions. +PPS: New style is what rails pioneered and has now called Concerns. I call them Aspects, and they not only serve to split +a big file up, but use the receiver and also super, ie the fact that a module gets inserted into the method lookup + sequence in just the same way as an superclass. This solves the old c++ and Java multiple inheritance dilemma. + \ No newline at end of file diff --git a/lib/kernel/all.rb b/lib/kernel/all.rb new file mode 100644 index 00000000..2edd9151 --- /dev/null +++ b/lib/kernel/all.rb @@ -0,0 +1,3 @@ +require_relative "integer" +require_relative "string" +require_relative "system" diff --git a/lib/kernel/integer.rb b/lib/kernel/integer.rb new file mode 100644 index 00000000..6ed03dfb --- /dev/null +++ b/lib/kernel/integer.rb @@ -0,0 +1,86 @@ +#integer related kernel functions +module Crystal + module Kernel + # 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 + # arguments: string address , integer + def self.utoa context + utoa_function = Vm::Function.new(:utoa , Vm::Integer , [ Vm::Integer ] , Vm::Integer ) + str_addr = utoa_function.receiver + number = utoa_function.args.first + remainder = utoa_function.new_local + Vm::RegisterMachine.instance.div10( utoa_function , number , remainder ) + # make char out of digit (by using ascii encoding) 48 == "0" + utoa_function.instance_eval do + add( remainder , remainder , 48) + strb( remainder, str_addr ) + sub( str_addr, str_addr , 1 ) + cmp( number , 0 ) + callne( utoa_function ) + end + return utoa_function + end + + def self.putint context + putint_function = Vm::Function.new(:putint , Vm::Integer , [] , Vm::Integer ) + buffer = Vm::StringConstant.new(" ") # create a buffer + context.object_space.add_object buffer # and save it (function local variable: a no no) + int = putint_function.receiver + moved_int = putint_function.new_local + utoa = context.object_space.get_or_create_class(:Object).resolve_function(:utoa) + putint_function.instance_eval do + mov( moved_int , int ) # move arg up + add( int , buffer ,nil ) # string to write to (add string address to pc) + add( int , int , buffer.length - 3) # 3 for good measure , ahem. + call( utoa ) + after = new_block("after_call") + insert_at after + # And now we "just" have to print it, using the write_stdout + add( int , buffer , nil ) # string to write to + mov( moved_int , buffer.length ) + end + Vm::RegisterMachine.instance.write_stdout(putint_function) + putint_function + end + + # testing method, hand coded fibo, expects arg in receiver_register + # result comes in return_register + # a hand coded version of the fibonachi numbers + # not my hand off course, found in the net http://www.peter-cockerell.net/aalp/html/ch-5.html + def self.fibo context + fibo_function = Vm::Function.new(:fibo , Vm::Integer , [] , Vm::Integer ) + result = fibo_function.return_type + int = fibo_function.receiver + + last = fibo_function.new_block("return") + + f1 = fibo_function.new_local + f2 = fibo_function.new_local + + fibo_function.instance_eval do + cmp int , 1 + mov( result, int , condition_code: :le) + ble( last ) #branch to return, rather than return (as the original) + mov f1 , 1 #set up initial values + mov f2 , 0 + end + + loop = fibo_function.new_block("loop") + fibo_function.insert_at loop + + fibo_function.instance_eval do #loop through + add f1 , f1 , f2 # f1 = f1 + f2 + sub f2 , f1 , f2 # f2 = f1 -f2 + sub int , int , 1 # todo: set.. should do below cmp, but doesn't , set_update_status: 1 + cmp int , 1 + bne( loop ) + mov( result , f1 ) + end + + fibo_function + end + + end +end \ No newline at end of file diff --git a/lib/kernel/string.rb b/lib/kernel/string.rb new file mode 100644 index 00000000..c7584c76 --- /dev/null +++ b/lib/kernel/string.rb @@ -0,0 +1,10 @@ +module Crystal + module Kernel + def self.putstring context + function = Vm::Function.new(:putstring , Vm::Integer , [] ) + ret = Vm::RegisterMachine.instance.write_stdout(function) + function.set_return ret + function + end + end +end diff --git a/lib/kernel/system.rb b/lib/kernel/system.rb new file mode 100644 index 00000000..8f97d66c --- /dev/null +++ b/lib/kernel/system.rb @@ -0,0 +1,10 @@ +module Crystal + module Kernel + def self.exit context + function = Vm::Function.new(:exit , Vm::Integer , [] ) + ret = Vm::RegisterMachine.instance.exit(function) + function.set_return ret + function + end + end +end diff --git a/lib/parfait/README.md b/lib/parfait/README.md new file mode 100644 index 00000000..a12d150a --- /dev/null +++ b/lib/parfait/README.md @@ -0,0 +1,7 @@ +### A thin layer + +Here we have a placeholder for things i am currently developing. + +Basically Parfait is the smallest amount of code needed to make a ruby-like OO system work. + +A work in progress that started from here : http://ruby-in-ruby.github.io/2014/06/10/more-clarity.html diff --git a/lib/core/array.rb b/lib/parfait/array.rb similarity index 100% rename from lib/core/array.rb rename to lib/parfait/array.rb