type now means class name

update reader (with new type definition)
remove type class (now symbol)
update all types to class name symbols
This commit is contained in:
Torsten Ruger 2015-10-14 16:16:03 +03:00
parent d8a5dc147b
commit 1141ed9c99
16 changed files with 72 additions and 121 deletions

View File

@ -12,7 +12,7 @@ GIT
GIT
remote: git://github.com/salama/salama-reader.git
revision: 6bd5e9b5ee26e4e0157283e9af4389b13d660193
revision: ab0a94bd51c996637453331adeb28bf1731f9b65
specs:
salama-reader (0.4.0)
ast (~> 2.1.0)

View File

@ -2,7 +2,7 @@ module Parfait
class Variable < Object
def initialize type , name , value = nil
raise "not type #{type}" unless type == :ref or type == :int
raise "not type #{type}" unless Virtual.machine.space.get_class_by_name(type)
self.type , self.name , self.value = type , name , value
self.value = 0 if self.type == :int and value == nil
raise "must give name for variable" unless name

View File

@ -55,7 +55,6 @@ module Phisol
end
end
require_relative "type"
require_relative "ast_helper"
require_relative "compiler/basic_values"
require_relative "compiler/call_site"

View File

@ -19,26 +19,26 @@ module Phisol
end
def on_true statement
reg = use_reg :ref
reg = use_reg :Boolean
@method.source.add_code Register::LoadConstant.new( statement, true , reg )
return reg
end
def on_false statement
reg = use_reg :ref
reg = use_reg :Boolean
@method.source.add_code Register::LoadConstant.new( statement, false , reg )
return reg
end
def on_nil statement
reg = use_reg :ref
reg = use_reg :NilClass
@method.source.add_code Register::LoadConstant.new( statement, nil , reg )
return reg
end
def on_string statement
value = statement.first.to_sym
reg = use_reg :ref
reg = use_reg :Word
@method.source.constants << value
@method.source.add_code Register::LoadConstant.new( statement, value , reg )
return reg

View File

@ -9,12 +9,7 @@ module Phisol
if receiver
me = process( receiver.to_a.first )
else
if @method.for_class.name == :Integer
type = :int
else
type = :ref
end
me = Register.self_reg type
me = Register.self_reg @method.for_class.name
end
#move the new message (that we need to populate to make a call) to std register
new_message = Register.resolve_to_register(:new_message)
@ -22,7 +17,7 @@ module Phisol
# move our receiver there
@method.source.add_code Register.set_slot( statement , me , :new_message , :receiver)
# load method name and set to new message (for exceptions/debug)
name_tmp = use_reg(:ref)
name_tmp = use_reg(:Word)
@method.source.add_code Register::LoadConstant.new(statement, name , name_tmp)
@method.source.add_code Register.set_slot( statement , name_tmp , :new_message , :name)
# next arguments. reset tmp regs for each and load result into new_message
@ -56,17 +51,12 @@ module Phisol
raise "unimplemented: \n#{code} \nfor #{ref.inspect}"
end
else
if( me.type.is_a? Phisol::Integer)
name = :plus if name == :+
method = Virtual.machine.space.get_class_by_name(:Integer).get_instance_method(name)
puts Virtual.machine.space.get_class_by_name(:Integer).method_names.to_a
raise "Method not implemented Integer.#{name}" unless method
@method.source.add_code Virtual::MethodCall.new( method )
else
method = @clazz.get_instance_method(name)
raise "Method not implemented #{@clazz.name}.#{name}" unless method
@method.source.add_code Virtual::MethodCall.new( method )
end
clazz = Virtual.machine.space.get_class_by_name(me.type)
raise "No such class #{me.type}" unless clazz
method = clazz.get_instance_method(name)
puts Virtual.machine.space.get_class_by_name(:Integer).method_names.to_a
raise "Method not implemented Integer.#{name}" unless method
@method.source.add_code Virtual::MethodCall.new( method )
end
raise "Method not implemented #{me.value}.#{name}" unless method
ret = use_reg( method.source.return_type )

View File

@ -7,7 +7,7 @@ module Phisol
# whichever way this goes the result is stored in the return slot (as all compiles)
def on_name statement
name = statement.to_a.first
return Virtual::Self.new( Phisol::Reference.new(@clazz)) if name == :self
return Virtual::Self.new( @clazz) if name == :self
# either an argument, so it's stored in message
if( index = @method.has_arg(name))
type = @method.arguments[index].type

View File

@ -1,44 +0,0 @@
module Phisol
# Integer and (Object) References are the main derived classes, but float will come.
class Type
def == other
return false unless other.class == self.class
return true
end
# map from a type sym (currently :int/:ref) to a class of subtype of Type
# TODO needs to be made extensible in a defined way.
def self.from_sym type
return type if type.is_a? Type
case type
when :int
self.int
when :ref
self.ref
else
raise "No type maps to:#{type} (#{type.class})"
end
end
def self.int
return Integer.new
end
def self.ref
return Reference.new
end
end
class Integer < Type
end
class Reference < Type
# possibly unknown value, but known class (as in methods)
def initialize clazz = nil
@of_class = clazz
end
attr_reader :of_class
end
end

View File

@ -4,14 +4,14 @@ module Register
module Integer
module ClassMethods
def plus c
plus_function = Virtual::MethodSource.create_method(:Integer,:int,:plus , [:int] )
plus_function.source.set_return_type Phisol::Type.int
plus_function.source.receiver = Phisol::Integer
plus_function = Virtual::MethodSource.create_method(:Integer,:Integer,:plus , [:Integer] )
plus_function.source.set_return_type :Integer
plus_function.source.receiver = :Integer
tmp = Register.tmp_reg :int
tmp = Register.tmp_reg :Integer
index = Register.arg_index 1
plus_function.source.add_code Register.get_slot( plus_function , :message , index , tmp )
add = Register::OperatorInstruction.new( plus_function, :add , Register.self_reg , tmp )
add = Register::OperatorInstruction.new( plus_function, :add , Register.self_reg(:Integer) , tmp )
plus_function.source.add_code add
return plus_function
end
@ -23,9 +23,9 @@ module Register
# As we write before we recurse (save a push) we write the number backwards
# arguments: string address , integer
# def utoa context
# utoa_function = Virtual::MethodSource.create_method(:Integer ,:utoa , [ Phisol::Integer ] )
# function.source.return_type = Phisol::Type.int
# function.source.receiver = Phisol::Integer
# utoa_function = Virtual::MethodSource.create_method(:Integer ,:utoa , [ :Integer ] )
# function.source.return_type = :Integer
# function.source.receiver = :Integer
# return utoa_function
# # str_addr = utoa_function.receiver
# # number = utoa_function.args.first
@ -43,9 +43,9 @@ module Register
# end
def putint context
putint_function = Virtual::MethodSource.create_method(:Integer,:int,:putint , [] )
putint_function.source.set_return_type Phisol::Type.int
putint_function.source.receiver = Phisol::Integer
putint_function = Virtual::MethodSource.create_method(:Integer,:Integer,:putint , [] )
putint_function.source.set_return_type :Integer
putint_function.source.receiver = :Integer
return putint_function
# buffer = Parfait::Word.new(" ") # create a buffer
# context.object_space.add_object buffer # and save it (function local variable: a no no)
@ -72,9 +72,9 @@ module 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 = Virtual::MethodSource.create_method(:Integer,:int,:fibo , [] )
fibo_function.source.set_return_type Phisol::Type.int
fibo_function.source.receiver = Phisol::Integer
fibo_function = Virtual::MethodSource.create_method(:Integer,:Integer,:fibo , [] )
fibo_function.source.set_return_type :Integer
fibo_function.source.receiver = :Integer
return fibo_function
# result = fibo_function.return_type
# int = fibo_function.receiver

View File

@ -6,14 +6,14 @@ module Register
# 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
def __init__ context
function = Virtual::MethodSource.create_method(:Kernel,:int,:__init__ , [])
function.source.set_return_type Phisol::Type.int
function = Virtual::MethodSource.create_method(:Kernel,:Integer,:__init__ , [])
function.source.set_return_type :Integer
# no method enter or return (automatically added), remove
function.source.blocks.first.codes.pop # no Method enter
function.source.blocks.last.codes.pop # no Method return
#Set up the Space as self upon init
space = Parfait::Space.object_space
function.source.add_code LoadConstant.new(function, space , Register.self_reg)
function.source.add_code LoadConstant.new(function, space , Register.self_reg(:Space))
message_ind = Register.resolve_index( :space , :first_message )
# Load the message to new message register (r3)
function.source.add_code Register.get_slot( function , :self , message_ind , :new_message)
@ -25,16 +25,16 @@ module Register
return function
end
def exit context
function = Virtual::MethodSource.create_method(:Kernel,:int,:exit , [])
function.source.set_return_type Phisol::Type.int
function = Virtual::MethodSource.create_method(:Kernel,:Integer,:exit , [])
function.source.set_return_type :Integer
return function
ret = Virtual::RegisterMachine.instance.exit(function)
function.set_return ret
function
end
def __send context
function = Virtual::MethodSource.create_method(:Kernel,:int ,:__send , [] )
function.source.set_return_type Phisol::Type.int
function = Virtual::MethodSource.create_method(:Kernel,:Integer ,:__send , [] )
function.source.set_return_type :Integer
return function
end

View File

@ -6,7 +6,7 @@ module Register
# main entry point, ie __init__ calls this
# defined here as empty, to be redefined
def main context
function = Virtual::MethodSource.create_method(:Object, :int , :main , [])
function = Virtual::MethodSource.create_method(:Object, :Integer , :main , [])
return function
end
@ -17,8 +17,8 @@ module Register
# end
# The at_index is just "below" the api, something we need but don't want to expose,
# so we can't code the above in ruby
def _get_instance_variable context , name = :int
get_function = Virtual::MethodSource.create_method(:Object,:int, :_get_instance_variable , [ ] )
def _get_instance_variable context , name = :Integer
get_function = Virtual::MethodSource.create_method(:Object,:Integer, :_get_instance_variable , [ ] )
return get_function
# me = get_function.receiver
# var_name = get_function.args.first
@ -38,8 +38,8 @@ module Register
# return get_function
end
def _set_instance_variable(context , name = :int , value = :int )
set_function = Virtual::MethodSource.create_method(:Object,:int,:_set_instance_variable ,[] )
def _set_instance_variable(context , name = :Integer , value = :Integer )
set_function = Virtual::MethodSource.create_method(:Object,:Integer,:_set_instance_variable ,[] )
return set_function
# receiver set_function
# me = set_function.receiver

View File

@ -3,7 +3,7 @@ module Register
module Word
module ClassMethods
def putstring context
function = Virtual::MethodSource.create_method(:Word,:int , :putstring , [] )
function = Virtual::MethodSource.create_method(:Word,:Integer , :putstring , [] )
Kernel.emit_syscall( function , :putstring )
function
end

View File

@ -10,7 +10,7 @@ module Register
raise "wrong type for register init #{r}" unless r.is_a? Symbol
raise "double r #{r}" if r.to_s[0,1] == "rr"
raise "not reg #{r}" unless self.class.look_like_reg r
@type = Phisol::Type.from_sym type
@type = type
@symbol = r
@value = value
end
@ -62,24 +62,24 @@ module Register
# The register we use to store the current message object is :r0
def self.message_reg
RegisterValue.new :r0 , :ref
RegisterValue.new :r0 , :Message
end
# A register to hold the receiver of the current message, in oo terms the self. :r1
def self.self_reg type = :ref
def self.self_reg type
RegisterValue.new :r1 , type
end
# The register to hold a possible frame of the currently executing method. :r2
# May be nil if the method has no local variables
def self.frame_reg
RegisterValue.new :r2 , :ref
RegisterValue.new :r2 , :Frame
end
# The register we use to store the new message object is :r3
# The new message is the one being built, to be sent
def self.new_message_reg
RegisterValue.new :r3 , :ref
RegisterValue.new :r3 , :Message
end
# The first scratch register. There is a next_reg_use to get a next and next.
@ -116,7 +116,7 @@ module Register
when :new_message
register = new_message_reg
when :self
register = self_reg
register = self_reg(:Object) #TODO , prpbably have to get rid of this resolve method
when :frame
register = frame_reg
else

View File

@ -37,11 +37,10 @@ module Virtual
raise "create_method #{method_name}.#{method_name.class}" unless method_name.is_a? Symbol
clazz = Virtual.machine.space.get_class_by_name class_name
raise "No such class #{class_name}" unless clazz
return_type = Phisol::Type.from_sym return_type
arguments = []
args.each_with_index do | arg , index |
unless arg.is_a? Parfait::Variable
raise "not type #{arg}:#{arg.class}" unless arg == :int || arg == :ref
raise "not type #{arg}:#{arg.class}" unless Virtual.machine.space.get_class_by_name arg
arg = Parfait::Variable.new arg , "arg#{index}".to_sym
end
arguments << arg
@ -69,7 +68,7 @@ module Virtual
def set_return_type type
return if type.nil?
raise "not type #{type}" unless type.is_a? Phisol::Type
raise "not type #{type}" unless Virtual.machine.space.get_class_by_name type
@return_type = type
end
# add an instruction after the current (insertion point)

View File

@ -26,7 +26,7 @@ module Virtual
end
attr_reader :integer
def type
Phisol::Integer
:Integer
end
def fits_u8?
integer >= 0 and integer <= 255

View File

@ -10,39 +10,46 @@ module Virtual
def test_call_main_plain
@root = :call_site
@string_input = <<HERE
main()
HERE
@string_input = 'main()'
@output = Register::RegisterValue
check
end
def test_call_main_int
@root = :call_site
@string_input = <<HERE
main(1)
HERE
@string_input = 'main(1)'
@output = Register::RegisterValue
check
end
def ttest_call_self_main
@root = :call_site
@string_input = 'self.main()'
@output = Register::RegisterValue
check
end
def test_call_main_string
@root = :call_site
@string_input = <<HERE
main("1")
HERE
@string_input = 'main("1")'
@output = Register::RegisterValue
check
end
def ttest_call_main_op
Virtual.machine.space.get_main.ensure_local(:bar , :int)
Virtual.machine.space.get_main.ensure_local(:bar , :Integer)
@root = :call_site
@string_input = <<HERE
main( bar )
HERE
@string_input = 'main( bar )'
@output = Register::RegisterValue
check
end
def test_call_string_put
@root = :call_site
@string_input = '"Hello Raisa, I am salama".putstring()'
@output = Register::RegisterValue
check
end
end
end

View File

@ -16,7 +16,7 @@ module Virtual
def test_puts
@root = :function_definition
@string_input = <<HERE
int puts(ref str)
int puts(Word str)
main()
end
HERE