the further down this goes, the smaller the circles. Soon the point will come. And then back out
This commit is contained in:
parent
f60bbfa9ca
commit
b7c2089046
@ -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
|
||||||
|
@ -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
51
lib/boot/object.rb
Normal 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
|
@ -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
|
|
@ -21,27 +21,6 @@ module Core
|
|||||||
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
|
||||||
def putstring context , string = Vm::Integer , length = Vm::Integer
|
def putstring context , string = Vm::Integer , length = Vm::Integer
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user