renamed info to MethodSource

This commit is contained in:
Torsten Ruger 2015-07-03 20:13:03 +03:00
parent e959c5b0f5
commit b61c73acdd
24 changed files with 103 additions and 103 deletions

View File

@ -1,7 +1,7 @@
module Arm module Arm
# This implements call logic, which is simply like a c call (not send, that involves lookup and all sorts) # This implements call logic, which is simply like a c call (not send, that involves lookup and all sorts)
# #
# The only target for a call is a CompiledMethod, so we just need to get the address for the code # The only target for a call is a Method, so we just need to get the address for the code
# and call it. # and call it.
# #
# The only slight snag is that we would need to assemble before getting the address, but to assemble # The only slight snag is that we would need to assemble before getting the address, but to assemble

View File

@ -159,7 +159,7 @@ module Parfait
#many basic List functions can not be defined in ruby, such as #many basic List functions can not be defined in ruby, such as
# get/set/length/add/delete # get/set/length/add/delete
# so they must be defined as CompiledMethods in Builtin::Kernel # so they must be defined as Methods in Builtin::Kernel
#ruby 2.1 list (just for reference, keep at bottom) #ruby 2.1 list (just for reference, keep at bottom)
# :at, :fetch, :first, :last, :concat, :<<, :push, :pop, :shift, :unshift, :insert, :each, :each_index, :reverse_each, # :at, :fetch, :first, :last, :concat, :<<, :push, :pop, :shift, :unshift, :insert, :each, :each_index, :reverse_each,

View File

@ -43,7 +43,7 @@ module Parfait
found = get_instance_method( method.name ) found = get_instance_method( method.name )
if found if found
@instance_methods.delete(found) @instance_methods.delete(found)
raise "existed in #{self.name} #{Sof.write found.info.blocks}" raise "existed in #{self.name} #{Sof.write found.source.blocks}"
end end
@instance_methods.push method @instance_methods.push method
#puts "#{self.name} add #{method.name}" #puts "#{self.name} add #{method.name}"

View File

@ -1,17 +1,17 @@
Register Machine Register Machine
=============== ===============
This is the logic that uses the compiled virtual object space to produce code and an executable binary. This is the logic that uses the compiled virtual object space to produce code and an executable binary.
There is a mechanism for an actual machine (derived class) to generate harware specific instructions (as the There is a mechanism for an actual machine (derived class) to generate harware specific instructions (as the
plain ones in this directory don't assemble to binary). Currently there is only the Arm module to actually do plain ones in this directory don't assemble to binary). Currently there is only the Arm module to actually do
that. that.
The elf module is used to generate the actual binary from the final Space. Space is a virtual class representing The elf module is used to generate the actual binary from the final Space. Space is a virtual class representing
all objects that will be in the executable. Other than CompiledMethods, objects get transformed to data. all objects that will be in the executable. Other than MethodSource, objects get transformed to data.
But CompiledMethods, which are made up of Blocks, are compiled into a stream of bytes, which are the binary code for the But MethodSource, which are made up of Blocks, are compiled into a stream of bytes,
function. which are the binary code for the function.
Virtual Objects Virtual Objects
---------------- ----------------
@ -32,13 +32,13 @@ and then into the destination. And then we need some fiddling of bits to shift t
Another simple example is a Call. A simple case of a Class function call resolves the class object, Another simple example is a Call. A simple case of a Class function call resolves the class object,
and with the method name the function to be found at compile-time. and with the method name the function to be found at compile-time.
And so this results in a Register::Call, which is an Arm instruction. And so this results in a Register::Call, which is an Arm instruction.
A C call A C call
--------- ---------
Ok, there are no c calls. But syscalls are very similar. Ok, there are no c calls. But syscalls are very similar.
This is not at all as simple as the nice Class call described above. This is not at all as simple as the nice Class call described above.
For syscall in Arm (linux) you have to load registers 0-x (depending on call), load R7 with the For syscall in Arm (linux) you have to load registers 0-x (depending on call), load R7 with the
syscall number and then issue the software interupt instruction. syscall number and then issue the software interupt instruction.

View File

@ -28,7 +28,7 @@ module Register
@machine.objects.each do |objekt| @machine.objects.each do |objekt|
next unless objekt.is_a? Parfait::Method next unless objekt.is_a? Parfait::Method
# should be fill_to_length (with zeros) # should be fill_to_length (with zeros)
objekt.code.set_length(objekt.info.byte_length , 0) objekt.code.set_length(objekt.source.byte_length , 0)
end end
#need the initial jump at 0 and then functions #need the initial jump at 0 and then functions
@machine.init.set_position(at) @machine.init.set_position(at)
@ -47,7 +47,7 @@ module Register
# have to tell the code that will be assembled where it is to # have to tell the code that will be assembled where it is to
# get the jumps/calls right # get the jumps/calls right
if objekt.is_a? Parfait::Method if objekt.is_a? Parfait::Method
objekt.info.set_position( objekt.code.position ) objekt.source.set_position( objekt.code.position )
end end
next if objekt.is_a? Parfait::BinaryCode next if objekt.is_a? Parfait::BinaryCode
objekt.set_position at objekt.set_position at
@ -102,16 +102,16 @@ module Register
return @stream.string return @stream.string
end end
# assemble the CompiledMethodInfo into a stringio # assemble the MethodSource into a stringio
# and then plonk that binary data into the method.code array # and then plonk that binary data into the method.code array
def assemble_binary_method method def assemble_binary_method method
stream = StringIO.new stream = StringIO.new
method.info.blocks.each do |block| method.source.blocks.each do |block|
block.codes.each do |code| block.codes.each do |code|
begin begin
code.assemble( stream ) code.assemble( stream )
rescue => e rescue => e
puts "Method error #{method.name}\n#{Sof.write(method.info.blocks).to_s[0...2000]}" puts "Method error #{method.name}\n#{Sof.write(method.source.blocks).to_s[0...2000]}"
puts Sof.write(code) puts Sof.write(code)
raise e raise e
end end
@ -121,8 +121,8 @@ module Register
index = 1 index = 1
stream.rewind stream.rewind
#puts "Assembled #{method.name} with length #{stream.length}" #puts "Assembled #{method.name} with length #{stream.length}"
raise "length error #{method.code.length} != #{method.info.byte_length}" if method.code.length != method.info.byte_length raise "length error #{method.code.length} != #{method.source.byte_length}" if method.code.length != method.source.byte_length
raise "length error #{stream.length} != #{method.info.byte_length}" if method.info.byte_length != stream.length raise "length error #{stream.length} != #{method.source.byte_length}" if method.source.byte_length != stream.length
stream.each_byte do |b| stream.each_byte do |b|
method.code.set_char(index , b ) method.code.set_char(index , b )
index = index + 1 index = index + 1

View File

@ -6,8 +6,8 @@ It is the other side of the parfait coin, part of the runtime.
The functions are organized by their respective class and get loaded in boot_classes! , The functions are organized by their respective class and get loaded in boot_classes! ,
right at the start. (see virtual/boot.rb) right at the start. (see virtual/boot.rb)
These functions return their code, ie a Virtual::CompiledMethod object, which can then be called by These functions return their code, ie a Parfait::Method with a Virtual::MethodSource object,
ruby code as if it were a "normal" function. 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 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. be written in ruby, one of those chicken and egg things.

View File

@ -10,9 +10,9 @@ module Register
# As we write before we recurse (save a push) we write the number backwards # As we write before we recurse (save a push) we write the number backwards
# arguments: string address , integer # arguments: string address , integer
def utoa context def utoa context
utoa_function = Virtual::CompiledMethodInfo.create_method(:Integer ,:utoa , [ Virtual::Integer ] ) utoa_function = Virtual::MethodSource.create_method(:Integer ,:utoa , [ Virtual::Integer ] )
function.info.return_type = Virtual::Integer function.source.return_type = Virtual::Integer
function.info.receiver = Virtual::Integer function.source.receiver = Virtual::Integer
return utoa_function return utoa_function
str_addr = utoa_function.receiver str_addr = utoa_function.receiver
number = utoa_function.args.first number = utoa_function.args.first
@ -30,9 +30,9 @@ module Register
end end
def putint context def putint context
putint_function = Virtual::CompiledMethodInfo.create_method(:Integer,:putint , [] ) putint_function = Virtual::MethodSource.create_method(:Integer,:putint , [] )
putint_function.info.return_type = Virtual::Integer putint_function.source.return_type = Virtual::Integer
putint_function.info.receiver = Virtual::Integer putint_function.source.receiver = Virtual::Integer
return putint_function return putint_function
buffer = Parfait::Word.new(" ") # create a buffer buffer = Parfait::Word.new(" ") # create a buffer
context.object_space.add_object buffer # and save it (function local variable: a no no) context.object_space.add_object buffer # and save it (function local variable: a no no)
@ -59,9 +59,9 @@ module Register
# a hand coded version of the fibonachi numbers # 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 # not my hand off course, found in the net http://www.peter-cockerell.net/aalp/html/ch-5.html
def fibo context def fibo context
fibo_function = Virtual::CompiledMethodInfo.create_method(:Integer,:fibo , [] ) fibo_function = Virtual::MethodSource.create_method(:Integer,:fibo , [] )
fibo_function.info.return_type = Virtual::Integer fibo_function.source.return_type = Virtual::Integer
fibo_function.info.receiver = Virtual::Integer fibo_function.source.receiver = Virtual::Integer
return fibo_function return fibo_function
result = fibo_function.return_type result = fibo_function.return_type
int = fibo_function.receiver int = fibo_function.receiver

View File

@ -6,41 +6,41 @@ module Register
# it isn't really a function, ie it is jumped to (not called), exits and may not return # 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 # so it is responsible for initial setup
def __init__ context def __init__ context
function = Virtual::CompiledMethodInfo.create_method(:Kernel,:__init__ , []) function = Virtual::MethodSource.create_method(:Kernel,:__init__ , [])
function.info.return_type = Virtual::Integer function.source.return_type = Virtual::Integer
# no method enter or return (automatically added), remove # no method enter or return (automatically added), remove
function.info.blocks.first.codes.pop # no Method enter function.source.blocks.first.codes.pop # no Method enter
function.info.blocks.last.codes.pop # no Method return function.source.blocks.last.codes.pop # no Method return
#Set up the Space as self upon init #Set up the Space as self upon init
space = Parfait::Space.object_space space = Parfait::Space.object_space
function.info.add_code LoadConstant.new( space , Register.self_reg) function.source.add_code LoadConstant.new( space , Register.self_reg)
message_ind = Register.resolve_index( :space , :first_message ) message_ind = Register.resolve_index( :space , :first_message )
# Load the message to new message register (r3) # Load the message to new message register (r3)
function.info.add_code Register.get_slot( :self , message_ind , :new_message) function.source.add_code Register.get_slot( :self , message_ind , :new_message)
# And store the space as the new self (so the call can move it back as self) # And store the space as the new self (so the call can move it back as self)
function.info.add_code Register.set_slot( :self , :new_message , :receiver) function.source.add_code Register.set_slot( :self , :new_message , :receiver)
# now we are set up to issue a call to the main # now we are set up to issue a call to the main
function.info.add_code Virtual::MethodCall.new(Virtual.machine.space.get_main) function.source.add_code Virtual::MethodCall.new(Virtual.machine.space.get_main)
emit_syscall( function , :exit ) emit_syscall( function , :exit )
return function return function
end end
def exit context def exit context
function = Virtual::CompiledMethodInfo.create_method(:Kernel,:exit , []) function = Virtual::MethodSource.create_method(:Kernel,:exit , [])
function.info.return_type = Virtual::Integer function.source.return_type = Virtual::Integer
return function return function
ret = Virtual::RegisterMachine.instance.exit(function) ret = Virtual::RegisterMachine.instance.exit(function)
function.set_return ret function.set_return ret
function function
end end
def __send context def __send context
function = Virtual::CompiledMethodInfo.create_method(:Kernel ,:__send , [] ) function = Virtual::MethodSource.create_method(:Kernel ,:__send , [] )
function.info.return_type = Virtual::Integer function.source.return_type = Virtual::Integer
return function return function
end end
def emit_syscall function , name def emit_syscall function , name
save_message( function ) save_message( function )
function.info.add_code Syscall.new( name ) function.source.add_code Syscall.new( name )
restore_message(function) restore_message(function)
end end
@ -49,20 +49,20 @@ module Register
# This relies on linux to save and restore all registers # This relies on linux to save and restore all registers
# #
def save_message(function) def save_message(function)
function.info.add_code RegisterTransfer.new( Register.message_reg , :r8 ) function.source.add_code RegisterTransfer.new( Register.message_reg , :r8 )
end end
def restore_message(function) def restore_message(function)
return_tmp = Register.tmp_reg return_tmp = Register.tmp_reg
# get the sys return out of the way # get the sys return out of the way
function.info.add_code RegisterTransfer.new( Register.message_reg , return_tmp ) function.source.add_code RegisterTransfer.new( Register.message_reg , return_tmp )
# load the stored message into the base RegisterMachine # load the stored message into the base RegisterMachine
function.info.add_code RegisterTransfer.new( :r8 , Register.message_reg ) function.source.add_code RegisterTransfer.new( :r8 , Register.message_reg )
# save the return value into the message # save the return value into the message
function.info.add_code Register.set_slot( return_tmp , :message , :return_value ) function.source.add_code Register.set_slot( return_tmp , :message , :return_value )
# and "unroll" self and frame # and "unroll" self and frame
function.info.add_code Register.get_slot(:message , :receiver, :self ) function.source.add_code Register.get_slot(:message , :receiver, :self )
function.info.add_code Register.get_slot(:message , :frame , :frame) function.source.add_code Register.get_slot(:message , :frame , :frame)
end end
end end
extend ClassMethods extend ClassMethods

View File

@ -5,15 +5,15 @@ module Register
class List class List
module ClassMethods module ClassMethods
def get context , index = Virtual::Integer def get context , index = Virtual::Integer
get_function = Virtual::CompiledMethodInfo.create_method(:get , [ Virtual::Integer] , Virtual::Integer , Virtual::Integer ) get_function = Virtual::MethodSource.create_method(:get , [ Virtual::Integer] , Virtual::Integer , Virtual::Integer )
return get_function return get_function
end end
def set context , index = Virtual::Integer , object = Virtual::Reference def set context , index = Virtual::Integer , object = Virtual::Reference
set_function = Virtual::CompiledMethodInfo.create_method(:set , [Virtual::Integer, Virtual::Reference] ) set_function = Virtual::MethodSource.create_method(:set , [Virtual::Integer, Virtual::Reference] )
return set_function return set_function
end end
def push context , object = Virtual::Reference def push context , object = Virtual::Reference
push_function = Virtual::CompiledMethodInfo.create_method(:push , [Virtual::Reference] ) push_function = Virtual::MethodSource.create_method(:push , [Virtual::Reference] )
return push_function return push_function
end end
end end

View File

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

View File

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

View File

@ -7,7 +7,7 @@ require "virtual/parfait_adapter"
require "virtual/compiler" require "virtual/compiler"
require "virtual/instruction" require "virtual/instruction"
require "virtual/compiled_method_info" require "virtual/method_source"
require "virtual/slots/slot" require "virtual/slots/slot"
require "virtual/type" require "virtual/type"
# the passes _are_ order dependant # the passes _are_ order dependant
@ -27,7 +27,7 @@ Sof::Volotile.add(Parfait::Frame , [:memory])
Sof::Volotile.add(Parfait::Message , [:memory]) Sof::Volotile.add(Parfait::Message , [:memory])
Sof::Volotile.add(Parfait::BinaryCode , [:memory]) Sof::Volotile.add(Parfait::BinaryCode , [:memory])
Sof::Volotile.add(Virtual::Block , [:method]) Sof::Volotile.add(Virtual::Block , [:method])
Sof::Volotile.add(Virtual::CompiledMethodInfo , [:current]) Sof::Volotile.add(Virtual::MethodSource , [:current])
class Fixnum class Fixnum
def fits_u8? def fits_u8?

View File

@ -21,8 +21,8 @@ also in an similar way that objects have their classes at runtime.
source. Here we add compile functions to ast classes and compile the AST layer into source. Here we add compile functions to ast classes and compile the AST layer into
Virtual::Objects and Parfait::Values Virtual::Objects and Parfait::Values
The main objects are Space (lots of objects), BootClass (represents a class), The main objects are Space (lots of objects), Parfait::Class ,
CompiledMethod (with Blocks and Instruction). Method and MethodSource (with Blocks and Instruction).
**Virtual** Instructions get further transformed into **register** instructions. **Virtual** Instructions get further transformed into **register** instructions.
This is done by an abstractly defined Register Machine with basic Intructions. This is done by an abstractly defined Register Machine with basic Intructions.
@ -59,4 +59,4 @@ and also implement very machine dependent functionality which nevertheless is fu
**Parfait** is that part of the runtime that can be coded in ruby. **Parfait** is that part of the runtime that can be coded in ruby.
It is parsed, like any other code and always included in the resulting binary. It is parsed, like any other code and always included in the resulting binary.
**Builtin** is the part of the runtime that can not be coded in ruby (but is still needed). **Builtin** is the part of the runtime that can not be coded in ruby (but is still needed).
This is coded by construction CompiledMethods in code and neccesarily machine dependant. This is coded by construction MethodSource in code and necessarily machine dependant.

View File

@ -2,7 +2,7 @@ module Virtual
module Compiler module Compiler
# Compiling is the conversion of the AST into 2 things: # Compiling is the conversion of the AST into 2 things:
# - code (ie sequences of Instructions inside Blocks) carried by CompiledMethods # - code (ie sequences of Instructions inside Blocks) carried by MethodSource
# - an object graph containing all the Methods, their classes and Constants # - an object graph containing all the Methods, their classes and Constants
# #
# Some compile methods just add code, some may add structure (ie Blocks) while # Some compile methods just add code, some may add structure (ie Blocks) while

View File

@ -14,24 +14,24 @@ All the headache comes from mixing those two up.*
Similarly, the result of compiling is two-fold: a static and a dynamic part. Similarly, the result of compiling is two-fold: a static and a dynamic part.
- the static part are objects like the constants, but also defined classes and their methods - the static part are objects like the constants, but also defined classes and their methods
- the dynamic part is the code, which is stored as streams of instructions in the CompiledMethod - the dynamic part is the code, which is stored as streams of instructions in the MethodSource
Too make things a little simpler, we create a very high level instruction stream at first and then Too make things a little simpler, we create a very high level instruction stream at first and then
run transformation and optimization passes on the stream to improve it. run transformation and optimization passes on the stream to improve it.
Each ast class gets a compile method that does the compilation. Each ast class gets a compile method that does the compilation.
#### Compiled Method and Instructions #### MethodSource and Instructions
The first argument to the compile method is the CompiledMethod. The first argument to the compile method is the MethodSource.
All code is encoded as a stream of Instructions in the CompiledMethod. All code is encoded as a stream of Instructions in the MethodSource.
Instructions are stored as a list of Blocks, and Blocks are the smallest unit of code, Instructions are stored as a list of Blocks, and Blocks are the smallest unit of code,
which is always linear. which is always linear.
Code is added to the method (using add_code), rather than working with the actual instructions. Code is added to the method (using add_code), rather than working with the actual instructions.
This is so each compiling method can just do it's bit and be unaware of the larger structure This is so each compiling method can just do it's bit and be unaware of the larger structure
that is being created. that is being created.
The genearal structure of the instructions is a graph The general structure of the instructions is a graph
(with if's and whiles and breaks and what), but we build it to have one start and *one* end (return). (with if's and whiles and breaks and what), but we build it to have one start and *one* end (return).

View File

@ -15,25 +15,25 @@ module Virtual
def self.compile_integer expression , method def self.compile_integer expression , method
int = expression.value int = expression.value
to = Return.new(Integer , int) to = Return.new(Integer , int)
method.info.add_code Set.new( int , to ) method.source.add_code Set.new( int , to )
to to
end end
def self.compile_true expression , method def self.compile_true expression , method
to = Return.new(Reference , true ) to = Return.new(Reference , true )
method.info.add_code Set.new( true , to ) method.source.add_code Set.new( true , to )
to to
end end
def self.compile_false expression , method def self.compile_false expression , method
to = Return.new(Reference , false) to = Return.new(Reference , false)
method.info.add_code Set.new( false , to ) method.source.add_code Set.new( false , to )
to to
end end
def self.compile_nil expression , method def self.compile_nil expression , method
to = Return.new(Reference , nil) to = Return.new(Reference , nil)
method.info.add_code Set.new( nil , to ) method.source.add_code Set.new( nil , to )
to to
end end
@ -47,9 +47,9 @@ module Virtual
if method.has_var(name) if method.has_var(name)
# either an argument, so it's stored in message # either an argument, so it's stored in message
if( index = method.has_arg(name)) if( index = method.has_arg(name))
method.info.add_code MessageGet.new(expression.name , index) method.source.add_code MessageGet.new(expression.name , index)
else # or a local so it is in the frame else # or a local so it is in the frame
method.info.add_code FrameGet.new(expression.name , index) method.source.add_code FrameGet.new(expression.name , index)
end end
else else
call = Ast::CallSiteExpression.new(expression.name , [] ) #receiver self is implicit call = Ast::CallSiteExpression.new(expression.name , [] ) #receiver self is implicit
@ -62,7 +62,7 @@ module Virtual
clazz = Space.space.get_class_by_name name clazz = Space.space.get_class_by_name name
raise "uups #{clazz}.#{name}" unless clazz raise "uups #{clazz}.#{name}" unless clazz
to = Return.new(Reference , clazz ) to = Return.new(Reference , clazz )
method.info.add_code Set.new( clazz , to ) method.source.add_code Set.new( clazz , to )
to to
end end
@ -71,8 +71,8 @@ module Virtual
# Clearly a TODO here to implement strings rather than reusing symbols # Clearly a TODO here to implement strings rather than reusing symbols
value = expression.string.to_sym value = expression.string.to_sym
to = Return.new(Reference , value) to = Return.new(Reference , value)
method.info.constants << value method.source.constants << value
method.info.add_code Set.new( value , to ) method.source.add_code Set.new( value , to )
to to
end end
@ -85,16 +85,16 @@ module Virtual
raise "oh noo, nil from where #{expression.right.inspect}" unless r raise "oh noo, nil from where #{expression.right.inspect}" unless r
index = method.has_arg(expression.left.name.to_sym) index = method.has_arg(expression.left.name.to_sym)
if index if index
method.info.add_code Set.new(MessageSlot.new(index , r,type , r ) , Return.new) method.source.add_code Set.new(MessageSlot.new(index , r,type , r ) , Return.new)
else else
index = method.ensure_local(expression.left.name.to_sym) index = method.ensure_local(expression.left.name.to_sym)
method.info.add_code Set.new(FrameSlot.new(index , r.type , r ) , Return.new) method.source.add_code Set.new(FrameSlot.new(index , r.type , r ) , Return.new)
end end
r r
end end
def self.compile_variable expression, method def self.compile_variable expression, method
method.info.add_code InstanceGet.new(expression.name) method.source.add_code InstanceGet.new(expression.name)
Return.new( Unknown ) Return.new( Unknown )
end end
end end

View File

@ -6,9 +6,9 @@ module Virtual
def self.compile_callsite expession , method def self.compile_callsite expession , method
me = Compiler.compile( expession.receiver , method ) me = Compiler.compile( expession.receiver , method )
method.info.add_code NewMessage.new method.source.add_code NewMessage.new
method.info.add_code Set.new( me , NewSelf.new(me.type)) method.source.add_code Set.new( me , NewSelf.new(me.type))
method.info.add_code Set.new( expession.name.to_sym , NewMessageName.new()) method.source.add_code Set.new( expession.name.to_sym , NewMessageName.new())
compiled_args = [] compiled_args = []
expession.args.each_with_index do |arg , i| expession.args.each_with_index do |arg , i|
#compile in the running method, ie before passing control #compile in the running method, ie before passing control
@ -18,13 +18,13 @@ module Virtual
# so the next free is +1 # so the next free is +1
to = NewArgSlot.new(i + 1 ,val.type , val) to = NewArgSlot.new(i + 1 ,val.type , val)
# (doing this immediately, not after the loop, so if it's a return it won't get overwritten) # (doing this immediately, not after the loop, so if it's a return it won't get overwritten)
method.info.add_code Set.new( val , to ) method.source.add_code Set.new( val , to )
compiled_args << to compiled_args << to
end end
method.info.add_code MessageSend.new(expession.name , me , compiled_args) #and pass control method.source.add_code MessageSend.new(expession.name , me , compiled_args) #and pass control
# the effect of the method is that the NewMessage Return slot will be filled, return it # the effect of the method is that the NewMessage Return slot will be filled, return it
# (this is what is moved _inside_ above loop for such expressions that are calls (or constants)) # (this is what is moved _inside_ above loop for such expressions that are calls (or constants))
Return.new( method.info.return_type ) Return.new( method.source.return_type )
end end
end end
end end

View File

@ -18,8 +18,8 @@ module Virtual
r = Self.new() r = Self.new()
class_name = method.for_class.name class_name = method.for_class.name
end end
new_method = CompiledMethodInfo.create_method(class_name, expression.name , args ) new_method = MethodSource.create_method(class_name, expression.name , args )
new_method.info.receiver = r new_method.source.receiver = r
new_method.for_class.add_instance_method new_method new_method.for_class.add_instance_method new_method
#frame = frame.new_frame #frame = frame.new_frame
@ -28,7 +28,7 @@ module Virtual
return_type = Compiler.compile(ex,new_method ) return_type = Compiler.compile(ex,new_method )
raise return_type.inspect if return_type.is_a? Instruction raise return_type.inspect if return_type.is_a? Instruction
end end
new_method.info.return_type = return_type new_method.source.return_type = return_type
new_method new_method
end end
def scratch def scratch

View File

@ -6,18 +6,18 @@ module Virtual
# to execute the logic as the if states it, the blocks are the other way around # to execute the logic as the if states it, the blocks are the other way around
# so we can the jump over the else if true , # so we can the jump over the else if true ,
# and the else joins unconditionally after the true_block # and the else joins unconditionally after the true_block
merge_block = method.info.new_block "if_merge" # last one, created first merge_block = method.source.new_block "if_merge" # last one, created first
true_block = method.info.new_block "if_true" # second, linked in after current, before merge true_block = method.source.new_block "if_true" # second, linked in after current, before merge
false_block = method.info.new_block "if_false" # directly next in order, ie if we don't jump we land here false_block = method.source.new_block "if_false" # directly next in order, ie if we don't jump we land here
is = Compiler.compile(expression.cond, method ) is = Compiler.compile(expression.cond, method )
# TODO should/will use different branches for different conditions. # TODO should/will use different branches for different conditions.
# just a scetch : cond_val = cond_val.is_true?(method) unless cond_val.is_a? BranchCondition # just a scetch : cond_val = cond_val.is_true?(method) unless cond_val.is_a? BranchCondition
method.info.add_code IsTrueBranch.new( true_block ) method.source.add_code IsTrueBranch.new( true_block )
# compile the true block (as we think of it first, even it is second in sequential order) # compile the true block (as we think of it first, even it is second in sequential order)
method.info.current true_block method.source.current true_block
last = is last = is
expression.if_true.each do |part| expression.if_true.each do |part|
last = Compiler.compile(part,method ) last = Compiler.compile(part,method )
@ -25,16 +25,16 @@ module Virtual
end end
# compile the false block # compile the false block
method.info.current false_block method.source.current false_block
expression.if_false.each do |part| expression.if_false.each do |part|
#puts "compiling in if false #{part}" #puts "compiling in if false #{part}"
last = Compiler.compile(part,method ) last = Compiler.compile(part,method )
raise part.inspect if last.nil? raise part.inspect if last.nil?
end end
method.info.add_code UnconditionalBranch.new( merge_block ) method.source.add_code UnconditionalBranch.new( merge_block )
#puts "compiled if: end" #puts "compiled if: end"
method.info.current merge_block method.source.current merge_block
#TODO should return the union of the true and false types #TODO should return the union of the true and false types
last last

View File

@ -53,7 +53,7 @@ module Virtual
@blocks = [@init] @blocks = [@init]
@space.classes.values.each do |c| @space.classes.values.each do |c|
c.instance_methods.each do |f| c.instance_methods.each do |f|
nb = f.info.blocks nb = f.source.blocks
@blocks += nb @blocks += nb
end end
end end

View File

@ -4,7 +4,7 @@ module Virtual
# the static info of a method (with its compiled code, argument names etc ) is part of the # the static info of a method (with its compiled code, argument names etc ) is part of the
# runtime, ie found in Parfait::Method # runtime, ie found in Parfait::Method
# the info we create here is injected int the method and used only at compile-time # the source we create here is injected into the method and used only at compile-time
# receiver # receiver
# return arg (usually mystery, but for coded ones can be more specific) # return arg (usually mystery, but for coded ones can be more specific)
@ -27,11 +27,11 @@ module Virtual
# These (eg if/while) blocks may themselves have linear blocks ,but the last of these # These (eg if/while) blocks may themselves have linear blocks ,but the last of these
# MUST have an uncoditional branch. And remember, all roads lead to return. # MUST have an uncoditional branch. And remember, all roads lead to return.
class CompiledMethodInfo class MethodSource
# create method does two things # create method does two things
# first it creates the parfait method, for the given class, with given argument names # first it creates the parfait method, for the given class, with given argument names
# second, it creates CompiledMethodInfo and attaches it to the method # second, it creates MethodSource and attaches it to the method
# #
# compile code then works with the method, but adds code tot the info # compile code then works with the method, but adds code tot the info
def self.create_method( class_name , method_name , args) def self.create_method( class_name , method_name , args)
@ -40,7 +40,7 @@ module Virtual
clazz = Virtual.machine.space.get_class_by_name class_name clazz = Virtual.machine.space.get_class_by_name class_name
raise "No such class #{class_name}" unless clazz raise "No such class #{class_name}" unless clazz
method = clazz.create_instance_method( method_name , Virtual.new_list(args)) method = clazz.create_instance_method( method_name , Virtual.new_list(args))
method.info = CompiledMethodInfo.new(method) method.source = MethodSource.new(method)
method method
end end
# just passing the method object in for Instructions to make decisions (later) # just passing the method object in for Instructions to make decisions (later)

View File

@ -157,7 +157,7 @@ module Parfait
end end
class Method class Method
attr_accessor :info attr_accessor :source
end end
class Word class Word

View File

@ -15,7 +15,7 @@ module Virtual
object.init_layout object.init_layout
end end
if( object.is_a? Parfait::Method) if( object.is_a? Parfait::Method)
object.info.constants.each{|c| keep(c) } object.source.constants.each{|c| keep(c) }
end end
layout = object.get_layout layout = object.get_layout
keep layout keep layout

View File

@ -24,7 +24,7 @@ module Virtual
end end
#puts "stayer #{function.name}" #puts "stayer #{function.name}"
@gonners.delete function @gonners.delete function
function.info.blocks.each do |block| function.source.blocks.each do |block|
block.codes.each do |code| block.codes.each do |code|
if code.is_a? Virtual::MessageSend if code.is_a? Virtual::MessageSend
@gonners.each do |stay| @gonners.each do |stay|