the further down this goes, the smaller the circles. Soon the point will come. And then back out

This commit is contained in:
Torsten Ruger 2014-06-03 14:49:02 +03:00
parent f60bbfa9ca
commit b7c2089046
7 changed files with 90 additions and 56 deletions

View File

@ -4,15 +4,21 @@ module Ast
class CallSiteExpression < Expression class CallSiteExpression < Expression
attr_reader :name, :args , :receiver attr_reader :name, :args , :receiver
def initialize name, args , receiver = Ast::NameExpression.new("self") def initialize name, args , receiver = Ast::NameExpression.new(:self)
@name , @args , @receiver = name.to_sym , args , receiver @name , @args , @receiver = name.to_sym , args , receiver
end end
def compile context , into def compile context , into
params = args.collect{ |a| a.compile(context, into) } params = args.collect{ |a| a.compile(context, into) }
#TOOD, this needs dynamic resolution
function = context.current_class.get_or_create_function(name) r = context.current_class.name
raise "Forward declaration not implemented (#{name}) #{inspect}" if function == nil if !receiver.nil? and receiver.name != :self
r = receiver.name
end
clazz = context.object_space.get_or_create_class r
function = context.current_class.get_function(name)
raise "Forward declaration not implemented for #{clazz.name}:#{name} #{inspect}" if function == nil
call = Vm::CallSite.new( name , params , function) call = Vm::CallSite.new( name , params , function)
current_function = context.function current_function = context.function
current_function.save_locals(context , into) if current_function current_function.save_locals(context , into) if current_function

View File

@ -31,10 +31,16 @@ module Ast
locals[arg] = arg_value locals[arg] = arg_value
args << arg_value args << arg_value
end end
class_name = context.current_class.name
function = Vm::Function.new(name , args )
# class depends on receiver # class depends on receiver
context.current_class.add_function function if receiver.nil?
clazz = context.current_class
else
c = context.object_space.get_or_create_class receiver.name.to_sym
clazz = c.meta_class
end
function = Vm::Function.new(name , args )
clazz.add_function function
parent_locals = context.locals parent_locals = context.locals
parent_function = context.function parent_function = context.function

51
lib/boot/object.rb Normal file
View File

@ -0,0 +1,51 @@
module Boot
class Object
module ClassMethods
# 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.
def index_of context , name = Vm::Integer
index_function = Vm::Function.new(:index_of , [Vm::Integer] , Vm::Integer )
return index_function
end
# in ruby, how this goes is
# def _get_instance_variable var
# i = self.index_of(var)
# return at_index(i)
# end
# The at_index is just "below" the api, somehting we need but don't want to expose, so we can't code the above in ruby
def _get_instance_variable context , name = Vm::Integer
get_function = Vm::Function.new(:_get_instance_variable , [Vm::Integer , Vm::Integer ] , Vm::Integer )
me = get_function.args[0]
var_name = get_function.args[1]
return_to = get_function.return_type
index_function = context.object_space.get_or_create_class(:Object).get_or_create_function(:index_of)
b = get_function.body
b.push( me )
index = b.call( index_function )
b.pop(me)
return_to.at_index( get_function.body , me , index )
get_function.set_return return_to
return get_function
end
def _set_instance_variable(name , value)
raise name
end
def _get_singleton_method(name )
raise name
end
def _add_singleton_method(method)
raise "4"
end
def initialize()
raise "4"
end
end
extend ClassMethods
end
end

View File

@ -1,23 +0,0 @@
module Core
class BaseObject
def _set_instance_variable(name , value)
return name
end
def _get_instance_variable( name )
return name
end
def _get_singleton_method(name )
return name
end
def _add_singleton_method(method)
return 4
end
def initialize()
return 4
end
end
end

View File

@ -20,27 +20,6 @@ module Core
def function_exit block , f_name def function_exit block , f_name
Vm::RegisterMachine.instance.function_exit block , f_name Vm::RegisterMachine.instance.function_exit block , f_name
end end
# in ruby, how this goes is
# def _get_instance_variable var
# i = self.index_of(var)
# return at_index(i)
# end
# The at_index is just "below" the api, somehting we need but don't want to expose, so we can't code the above in ruby
def _get_instance_variable context , name = Vm::Integer
get_function = Vm::Function.new(:_get_instance_variable , [Vm::Integer , Vm::Integer ] , Vm::Integer )
me = get_function.args[0]
var_name = get_function.args[1]
return_to = get_function.return_type
index_function = context.object_space.get_or_create_class(:Object).get_or_create_function(:index_of)
b = get_function.body
b.push( me )
index = b.call( index_function )
b.pop(me)
return_to.at_index( get_function.body , me , index )
get_function.set_return return_to
return get_function
end
#TODO this is in the wrong place. It is a function that returns a function object #TODO this is in the wrong place. It is a function that returns a function object
# while all other methods add their code into some block. --> kernel # while all other methods add their code into some block. --> kernel

View File

@ -3,6 +3,7 @@ require_relative "boot_class"
require_relative "call_site" require_relative "call_site"
require "arm/arm_machine" require "arm/arm_machine"
require "core/kernel" require "core/kernel"
require "boot/object"
module Vm module Vm
# The BootSpace is contains all objects for a program. In functional terms it is a program, but on oo # The BootSpace is contains all objects for a program. In functional terms it is a program, but on oo
@ -35,9 +36,18 @@ module Vm
#main gets executed between entry and exit #main gets executed between entry and exit
@main = Block.new("main",nil) @main = Block.new("main",nil)
@exit = Core::Kernel::main_exit Vm::Block.new("main_exit",nil) @exit = Core::Kernel::main_exit Vm::Block.new("main_exit",nil)
boot_classes
end end
attr_reader :context , :main , :classes , :entry , :exit attr_reader :context , :main , :classes , :entry , :exit
def boot_classes
# very fiddly chicken 'n egg problem. Functions need to be in the right order, and in fact we have to define some
# dummies, just for the other to compile
obj = get_or_create_class :Object
[:index_of , :_get_instance_variable].each do |f|
obj.add_function Boot::Object.send(f , @context)
end
end
def add_object o def add_object o
return if @objects.include? o return if @objects.include? o
raise "must be derived from Code #{o.inspect}" unless o.is_a? Code raise "must be derived from Code #{o.inspect}" unless o.is_a? Code
@ -45,7 +55,7 @@ module Vm
end end
def get_or_create_class name def get_or_create_class name
raise "uups #{name}" unless name.is_a? Symbol raise "uups #{name}.#{name.class}" unless name.is_a? Symbol
c = @classes[name] c = @classes[name]
unless c unless c
c = BootClass.new(name,@context) c = BootClass.new(name,@context)

View File

@ -16,20 +16,25 @@ class Object
return @layout.class() return @layout.class()
end end
end end
class Class
def Class.new_object( length )
return 4
end
end
class String class String
def String.new_string( len )
return Class.new_object( len << 2 )
end
def length() def length()
return @length return @length
end end
def self.new_string( len )
4
end
def plus(str) def plus(str)
my_length = @length my_length = @length
str_len = str.length() str_len = str.length()
new_string = String.new_string(my_length + str_len) new_string = String.new_string(my_length + str_len)
i = 0 i = 0
while( i < my_length) do while( i < my_length) do
char = self.get(i) char = get(i)
new_string.set(i , char) new_string.set(i , char)
i = i + 1 i = i + 1
end end