pretty much redid the variable idea (now slot)

This commit is contained in:
Torsten Ruger
2014-08-20 17:14:52 +03:00
parent ba71e568ef
commit 1371d395ec
11 changed files with 111 additions and 129 deletions

View File

@@ -5,7 +5,9 @@ module Ast
class IntegerExpression < Expression
# attr_reader :value
def compile method , message
Virtual::IntegerConstant.new value
to = Virtual::Return.new(Integer)
method.add_code Virtual::Set.new( to , Virtual::IntegerConstant.new(value))
to
end
end
@@ -34,10 +36,11 @@ module Ast
# otherwise it's a method without args and a send is ussued.
# this makes the namespace static, ie when eval and co are implemented method needs recompilation
def compile method , message
return Virtual::Self.new( Virtual::Mystery.new ) if name == :self
return Virtual::Self.new( Virtual::Mystery ) if name == :self
if method.has_var(name)
message.compile_get(method , name )
else
raise "Unimplemented"
message.compile_send( method , name , Virtual::Self.new( Virtual::Mystery.new ) )
end
end

View File

@@ -1,13 +1,18 @@
module Ast
# assignment, like operators are really function calls
# operators are really function calls
class CallSiteExpression < Expression
# attr_reader :name, :args , :receiver
def compile method , message
me = receiver.compile( method, message )
with = args.collect{|a| a.compile( method,message)}
message.compile_send( method , name , me , with )
method.add_code Virtual::Set.new(Virtual::NewSelf.new, me)
args.each_with_index do |arg , i|
val = arg.compile( method, message) #compile in the running method, ie before passing control
method.add_code Virtual::Set.new(Virtual::NewMessageSlot.new(i ,val.type ) , val )
end
method.add_code Virtual::MessageSend.new(name) #and pass control
Virtual::Return.new( method.return_type )
end
def scratch

View File

@@ -4,9 +4,9 @@ module Ast
def compile method , message
args = params.collect do |p|
raise "error, arguemnt must be a identifier, not #{p}" unless p.is_a? NameExpression
Virtual::Argument.new( p.name , Virtual::Mystery.new )
p.name
end
r = receiver ? receiver.compile(method,message) : Virtual::SelfReference.new
r = receiver ? receiver.compile(method,message) : Virtual::Self.new()
method = Virtual::MethodDefinition.new(name , args , r )
#frame = frame.new_frame
return_type = nil

View File

@@ -34,7 +34,9 @@ module Virtual
@string = str
end
attr_reader :string
def type
Virtual::Reference
end
def result= value
class_for(MoveInstruction).new(value , self , :opcode => :mov)
end

View File

@@ -37,13 +37,6 @@ module Virtual
end
end
module Named
def initialize name
@name = name
end
attr_reader :name
end
# the first instruction we need is to stop. Off course in a real machine this would be a syscall, but that is just
# an implementation (in a programm it would be a function). But in a virtual machine, not only do we need this instruction,
# it is indeed the first instruction as just this instruction is the smallest possible programm for the machine.
@@ -73,13 +66,6 @@ module Virtual
class UnconditionalBranch < Branch
end
class MessageGet < Instruction
include Named
end
class FrameGet < Instruction
include Named
end
class MessageSend < Instruction
def initialize name , args = []
@name = name.to_sym
@@ -88,30 +74,14 @@ module Virtual
attr_reader :name , :args
end
class FrameSet < Instruction
def initialize name , val
@name = name.to_sym
@value = val
# class for Set instructions, A set is basically a mem move.
# to and from are indexes into the known objects(frame,message,self and new_message), or from may be a constant
class Set < Instruction
def initialize to , from
@to = to
@from = from
end
attr_reader :name , :value
attr_reader :to , :from
end
class MessageSet < Instruction
def initialize name , val
@name = name.to_sym
@value = val
end
attr_reader :name , :value
end
class LoadSelf < Instruction
def initialize val
@value = val
end
attr_reader :value
end
class ObjectGet < Instruction
include Named
end
end

View File

@@ -44,12 +44,6 @@ module Virtual
method.get_var(name)
end
def compile_send method , name , me , with = []
method.add_code Virtual::LoadSelf.new(me)
method.add_code MessageSend.new(name , with )
Return.new( method.return_type )
end
def compile_set method , name , val
method.set_var(name,val)
if method.has_arg(name)

View File

@@ -32,9 +32,9 @@ module Virtual
class MethodDefinition < Virtual::Object
#return the main function (the top level) into which code is compiled
def MethodDefinition.main
MethodDefinition.new(:main , [] , Virtual::SelfReference )
MethodDefinition.new(:main , [] )
end
def initialize name , args , receiver = Virtual::SelfReference.new , return_type = Virtual::Mystery , start = MethodEnter.new()
def initialize name , args , receiver = Virtual::Self.new , return_type = Virtual::Mystery , start = MethodEnter.new()
@name = name.to_sym
@args = args
@locals = []

65
lib/virtual/slot.rb Normal file
View File

@@ -0,0 +1,65 @@
module Virtual
# Slots are named, or rather indexed, storage locations that are typed.
# Four of those locations exist and those correspond to subclasses:
# - the message that has been received: MessageSlot
# - the frame of the method that is executing (local variables): FrameSlot
# - self as an object: SelfSlot
# - a message that will be sent, NewMessageSlot
# additionally frame, self and return are slots in Message and NewMessage
class Slot < Value
RETURN = 0
SELF = 1
attr_accessor :index , :type
private #abstract base class
def initialize index , type
@index = index
@type = type
end
end
class MessageSlot < Slot
def initialize index , type = Mystery
super
end
end
class FrameSlot < Slot
def initialize index , type = Mystery
super
end
end
class SelfSlot < Slot
def initialize index , type = Mystery
super
end
end
class NewMessageSlot < Slot
def initialize index , type = Mystery
super
end
end
class Return < MessageSlot
def initialize type = Mystery
super( RETURN , type )
end
end
class NewReturn < NewMessageSlot
def initialize type = Mystery
super( RETURN , type )
end
end
class Self < MessageSlot
def initialize type = Mystery
super( SELF , type )
end
end
class NewSelf < NewMessageSlot
def initialize type = Mystery
super( SELF , type )
end
end
end

View File

@@ -6,58 +6,17 @@ module Virtual
class Type
def == other
return false unless other.class == self.class
Sof::Util.attributes(self).each do |a|
begin
left = send(a)
rescue NoMethodError
next # not using instance variables that are not defined as attr_readers for equality
end
begin
right = other.send(a)
rescue NoMethodError
return false
end
return false unless left.class == right.class
return false unless left == right
end
return true
end
def inspect
self.class.name + ".new(" + attributes.collect{|a| send(a).inspect }.join(",")+ ")"
end
end
class Integer < Type
def initialize
end
end
class Reference < Type
def initialize clazz = nil
@clazz = clazz
end
attr_accessor :clazz
def at_index block , left , right
block.ldr( self , left , right )
self
end
end
class SelfReference < Reference
end
class Mystery < Type
def initialize
end
def as type
type.new
end
end
end

View File

@@ -27,37 +27,10 @@ module Virtual
end
return true
end
private
private #can't instantiate, must be constant or variable
def initialize
end
end
class Variable < Value
def initialize name , type
@name = name.to_sym
@type = type
end
attr_accessor :name , :type
end
# The subclasses are not strictly speaking neccessary at this def point
# i just don't want to destroy the information for later optimizations
#
# All variables are stored in frames and quite possibly in order arg,local,tmp
class Return < Variable
def initialize type
super(:return , type)
end
end
class Self < Variable
def initialize type
super(:self , type)
end
end
class Argument < Variable
end
class Local < Variable
end
class Temp < Variable
end
end
require_relative "slot"