adding the blocks to virtual machine and store instructions in array not list
This commit is contained in:
parent
c2ae184e6e
commit
200228a33d
@ -95,7 +95,7 @@ module Ast
|
|||||||
|
|
||||||
class VariableExpression < NameExpression
|
class VariableExpression < NameExpression
|
||||||
def compile method , message
|
def compile method , message
|
||||||
method.add Virtual::ObjectGet.new(name)
|
method.add_code Virtual::ObjectGet.new(name)
|
||||||
Virtual::Return.new( Virtual::Mystery.new )
|
Virtual::Return.new( Virtual::Mystery.new )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -37,7 +37,7 @@ module Ast
|
|||||||
end
|
end
|
||||||
|
|
||||||
function = Virtual::Function.new(name , me , args )
|
function = Virtual::Function.new(name , me , args )
|
||||||
clazz.add_function function
|
clazz.add_code_function function
|
||||||
|
|
||||||
parent_locals = context.locals
|
parent_locals = context.locals
|
||||||
parent_function = context.function
|
parent_function = context.function
|
||||||
|
@ -6,21 +6,21 @@ module Ast
|
|||||||
# is.is_false(frame,method)
|
# is.is_false(frame,method)
|
||||||
# TODO should/will use different branches for different conditions.
|
# TODO should/will use different branches for different conditions.
|
||||||
branch = Virtual::ImplicitBranch.new "if_merge"
|
branch = Virtual::ImplicitBranch.new "if_merge"
|
||||||
method.add branch
|
method.add_code branch
|
||||||
last = is
|
last = is
|
||||||
if_true.each do |part|
|
if_true.each do |part|
|
||||||
last = part.compile(method,message )
|
last = part.compile(method,message )
|
||||||
raise part.inspect if last.nil?
|
raise part.inspect if last.nil?
|
||||||
end
|
end
|
||||||
merge = Virtual::Label.new(branch.name)
|
merge = Virtual::Label.new(branch.name)
|
||||||
method.add merge
|
method.add_code merge
|
||||||
branch.swap
|
branch.swap
|
||||||
method.current = branch
|
method.current = branch
|
||||||
if_false.each do |part|
|
if_false.each do |part|
|
||||||
last = part.compile(method,message )
|
last = part.compile(method,message )
|
||||||
raise part.inspect if last.nil?
|
raise part.inspect if last.nil?
|
||||||
end
|
end
|
||||||
method.add merge
|
method.add_code merge
|
||||||
branch.swap
|
branch.swap
|
||||||
method.current = merge
|
method.current = merge
|
||||||
#TODO should return the union of the true and false types
|
#TODO should return the union of the true and false types
|
||||||
|
@ -3,12 +3,12 @@ module Ast
|
|||||||
# attr_reader :condition, :body
|
# attr_reader :condition, :body
|
||||||
def compile method , message
|
def compile method , message
|
||||||
start = Virtual::Label.new("while_start")
|
start = Virtual::Label.new("while_start")
|
||||||
method.add start
|
method.add_code start
|
||||||
is = condition.compile(method,message)
|
is = condition.compile(method,message)
|
||||||
branch = Virtual::ImplicitBranch.new "while"
|
branch = Virtual::ImplicitBranch.new "while"
|
||||||
merge = Virtual::Label.new(branch.name)
|
merge = Virtual::Label.new(branch.name)
|
||||||
branch.other = merge #false jumps to end of while
|
branch.other = merge #false jumps to end of while
|
||||||
method.add branch
|
method.add_code branch
|
||||||
last = is
|
last = is
|
||||||
body.each do |part|
|
body.each do |part|
|
||||||
last = part.compile(method,message )
|
last = part.compile(method,message )
|
||||||
|
@ -1,110 +0,0 @@
|
|||||||
require_relative "values"
|
|
||||||
|
|
||||||
module Vm
|
|
||||||
|
|
||||||
# Think flowcharts: blocks are the boxes. The smallest unit of linear code
|
|
||||||
|
|
||||||
# Blocks must end in control instructions (jump/call/return).
|
|
||||||
# And the only valid argument for a jump is a Block
|
|
||||||
|
|
||||||
# Blocks form a linked list
|
|
||||||
|
|
||||||
# There are four ways for a block to get data (to work on)
|
|
||||||
# - hard coded constants (embedded in code)
|
|
||||||
# - memory move
|
|
||||||
# - values passed in (from previous blocks. ie local variables)
|
|
||||||
|
|
||||||
# See Value description on how to create code/instructions
|
|
||||||
|
|
||||||
# Codes then get assembled into bytes (after linking)
|
|
||||||
|
|
||||||
class Block < Code
|
|
||||||
|
|
||||||
def initialize(name , function , next_block )
|
|
||||||
super()
|
|
||||||
@function = function
|
|
||||||
@name = name.to_sym
|
|
||||||
@next = next_block
|
|
||||||
@branch = nil
|
|
||||||
@codes = []
|
|
||||||
# keeping track of register usage, left (assigns) or right (uses)
|
|
||||||
@assigns = []
|
|
||||||
@uses = []
|
|
||||||
end
|
|
||||||
|
|
||||||
attr_reader :name , :next , :codes , :function , :assigns , :uses
|
|
||||||
attr_accessor :branch
|
|
||||||
|
|
||||||
def reachable ret = []
|
|
||||||
add_next ret
|
|
||||||
add_branch ret
|
|
||||||
ret
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_code kode
|
|
||||||
kode.assigns.each { |a| (@assigns << a) unless @assigns.include?(a) }
|
|
||||||
kode.uses.each { |use| (@uses << use) unless (@assigns.include?(use) or @uses.include?(use)) }
|
|
||||||
#puts "IN ADD #{name}#{uses}"
|
|
||||||
@codes << kode
|
|
||||||
end
|
|
||||||
|
|
||||||
def set_next next_b
|
|
||||||
@next = next_b
|
|
||||||
end
|
|
||||||
|
|
||||||
# returns if this is a block that ends in a call (and thus needs local variable handling)
|
|
||||||
def call_block?
|
|
||||||
return false unless codes.last.is_a?(CallInstruction)
|
|
||||||
return false unless codes.last.opcode == :call
|
|
||||||
codes.dup.reverse.find{ |c| c.is_a? StackInstruction }
|
|
||||||
end
|
|
||||||
|
|
||||||
# Code interface follows. Note position is inheitted as is from Code
|
|
||||||
|
|
||||||
# length of the block is the length of it's codes, plus any next block (ie no branch follower)
|
|
||||||
# Note, the next is in effect a linked list and as such may have many blocks behind it.
|
|
||||||
def length
|
|
||||||
cods = @codes.inject(0) {| sum , item | sum + item.length}
|
|
||||||
cods += @next.length if @next
|
|
||||||
cods
|
|
||||||
end
|
|
||||||
|
|
||||||
# to link we link the codes (instructions), plus any next in line block (non- branched)
|
|
||||||
def link_at pos , context
|
|
||||||
super(pos , context)
|
|
||||||
@codes.each do |code|
|
|
||||||
code.link_at(pos , context)
|
|
||||||
pos += code.length
|
|
||||||
end
|
|
||||||
if @next
|
|
||||||
@next.link_at pos , context
|
|
||||||
pos += @next.length
|
|
||||||
end
|
|
||||||
pos
|
|
||||||
end
|
|
||||||
|
|
||||||
# assemble the codes (instructions) and any next in line block
|
|
||||||
def assemble(io)
|
|
||||||
@codes.each do |obj|
|
|
||||||
obj.assemble io
|
|
||||||
end
|
|
||||||
@next.assemble(io) if @next
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
# helper for determining reachable blocks
|
|
||||||
def add_next ret
|
|
||||||
return if @next.nil?
|
|
||||||
return if ret.include? @next
|
|
||||||
ret << @next
|
|
||||||
@next.reachable ret
|
|
||||||
end
|
|
||||||
# helper for determining reachable blocks
|
|
||||||
def add_branch ret
|
|
||||||
return if @branch.nil?
|
|
||||||
return if ret.include? @branch
|
|
||||||
ret << @branch
|
|
||||||
@branch.reachable ret
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
59
lib/virtual/block.rb
Normal file
59
lib/virtual/block.rb
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
require_relative "object"
|
||||||
|
|
||||||
|
module Virtual
|
||||||
|
|
||||||
|
# Think flowcharts: blocks are the boxes. The smallest unit of linear code
|
||||||
|
|
||||||
|
# Blocks must end in control instructions (jump/call/return).
|
||||||
|
# And the only valid argument for a jump is a Block
|
||||||
|
|
||||||
|
# Blocks form a graph, which is managed by the method
|
||||||
|
|
||||||
|
class Block < Virtual::Object
|
||||||
|
|
||||||
|
def initialize(name , method )
|
||||||
|
super()
|
||||||
|
@method = method
|
||||||
|
@name = name.to_sym
|
||||||
|
@branch = nil
|
||||||
|
@codes = []
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader :name , :next , :codes , :method
|
||||||
|
attr_accessor :branch
|
||||||
|
|
||||||
|
def reachable ret = []
|
||||||
|
add_next ret
|
||||||
|
add_branch ret
|
||||||
|
ret
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_code kode
|
||||||
|
@codes << kode
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
# returns if this is a block that ends in a call (and thus needs local variable handling)
|
||||||
|
def call_block?
|
||||||
|
return false unless codes.last.is_a?(CallInstruction)
|
||||||
|
return false unless codes.last.opcode == :call
|
||||||
|
codes.dup.reverse.find{ |c| c.is_a? StackInstruction }
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# helper for determining reachable blocks
|
||||||
|
def add_next ret
|
||||||
|
return if @next.nil?
|
||||||
|
return if ret.include? @next
|
||||||
|
ret << @next
|
||||||
|
@next.reachable ret
|
||||||
|
end
|
||||||
|
# helper for determining reachable blocks
|
||||||
|
def add_branch ret
|
||||||
|
return if @branch.nil?
|
||||||
|
return if ret.include? @branch
|
||||||
|
ret << @branch
|
||||||
|
@branch.reachable ret
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -2,22 +2,16 @@ require_relative "object"
|
|||||||
|
|
||||||
module Virtual
|
module Virtual
|
||||||
|
|
||||||
# Instruction is an abstract for all the code of the object-machine. Derived classe make up the actual functionality
|
# Instruction is an abstract for all the code of the object-machine.
|
||||||
# of the machine.
|
# Derived classes make up the actual functionality of the machine.
|
||||||
# All functions on the machine are captured as instances of instructions
|
# All functions on the machine are captured as instances of instructions
|
||||||
#
|
#
|
||||||
# It is actully the point of the virtual machine layer to express oo functionality in the set of instructions, thus
|
# It is actually the point of the virtual machine layer to express oo functionality in the set of instructions,
|
||||||
# defining a minimal set of instructions needed to implement oo.
|
# thus defining a minimal set of instructions needed to implement oo.
|
||||||
|
|
||||||
# This is partly because jumping over this layer and doing in straight in assember was too big a step
|
# This is partly because jumping over this layer and doing in straight in assember was too big a step
|
||||||
class Instruction < Virtual::Object
|
class Instruction < Virtual::Object
|
||||||
attr_accessor :next
|
|
||||||
def attributes
|
|
||||||
[:next]
|
|
||||||
end
|
|
||||||
def initialize nex = nil
|
|
||||||
@next = nex
|
|
||||||
end
|
|
||||||
# simple thought: don't recurse for labels, just check their names
|
# simple thought: don't recurse for labels, just check their names
|
||||||
def == other
|
def == other
|
||||||
return false unless other.class == self.class
|
return false unless other.class == self.class
|
||||||
@ -25,7 +19,7 @@ module Virtual
|
|||||||
left = send(a)
|
left = send(a)
|
||||||
right = other.send(a)
|
right = other.send(a)
|
||||||
return false unless left.class == right.class
|
return false unless left.class == right.class
|
||||||
if( left.is_a? Label)
|
if( left.is_a? Block)
|
||||||
return false unless left.name == right.name
|
return false unless left.name == right.name
|
||||||
else
|
else
|
||||||
return false unless left == right
|
return false unless left == right
|
||||||
@ -33,23 +27,16 @@ module Virtual
|
|||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
# insert the given instruction as the next after this
|
|
||||||
# insert is not just set, but preserves the previous @next value as the next of the given instruction
|
|
||||||
# so if you think of the instructions as a linked list, it inserts the give instruction _after_ this one
|
|
||||||
def insert instruction
|
|
||||||
instruction.next = @next
|
|
||||||
@next = instruction
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module Named
|
module Named
|
||||||
def initialize name , nex = nil
|
def initialize name
|
||||||
super(nex)
|
|
||||||
@name = name
|
@name = name
|
||||||
end
|
end
|
||||||
attr_reader :name
|
attr_reader :name
|
||||||
def attributes
|
def attributes
|
||||||
[:name ] + super
|
[:name ]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -66,18 +53,12 @@ module Virtual
|
|||||||
class MethodReturn < Instruction
|
class MethodReturn < Instruction
|
||||||
end
|
end
|
||||||
|
|
||||||
#resolves to nothing, but allows forward definition
|
# the next instruction represents the "true" branch and the other is the .... other
|
||||||
class Label < Instruction
|
|
||||||
include Named
|
|
||||||
end
|
|
||||||
|
|
||||||
# the next instruction represents the true branch and the other is the .... other
|
|
||||||
# could have been the false, but false is a keyword and is asymetric to next anyway
|
# could have been the false, but false is a keyword and is asymetric to next anyway
|
||||||
# this is an abstract base class (though no measures are taken to prevent instantiation) and derived
|
# this is an abstract base class (though no measures are taken to prevent instantiation) and derived
|
||||||
# class names indicate the actual test
|
# class names indicate the actual test
|
||||||
class Branch < Instruction
|
class Branch < Instruction
|
||||||
def initialize name , nex = nil , other = nil
|
def initialize name , other = nil
|
||||||
super(nex)
|
|
||||||
unless(name.to_s.split("_").last.to_i > 0)
|
unless(name.to_s.split("_").last.to_i > 0)
|
||||||
name = "#{name}_#{name.to_i(36) % 65536}".to_sym
|
name = "#{name}_#{name.to_i(36) % 65536}".to_sym
|
||||||
end
|
end
|
||||||
@ -87,14 +68,7 @@ module Virtual
|
|||||||
attr_reader :name
|
attr_reader :name
|
||||||
attr_accessor :other
|
attr_accessor :other
|
||||||
def attributes
|
def attributes
|
||||||
[:name , :next , :other]
|
[:name , :other]
|
||||||
end
|
|
||||||
# so code can be "poured in" in the same way as normal, we swap the braches around in after the true condition
|
|
||||||
# and swap them back after
|
|
||||||
def swap
|
|
||||||
tmp = @other
|
|
||||||
@other = @next
|
|
||||||
@next = tmp
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -111,49 +85,45 @@ module Virtual
|
|||||||
end
|
end
|
||||||
|
|
||||||
class MessageSend < Instruction
|
class MessageSend < Instruction
|
||||||
def initialize name , args = [] , nex = nil
|
def initialize name , args = []
|
||||||
super(nex)
|
|
||||||
@name = name.to_sym
|
@name = name.to_sym
|
||||||
@args = args
|
@args = args
|
||||||
end
|
end
|
||||||
attr_reader :name , :args
|
attr_reader :name , :args
|
||||||
def attributes
|
def attributes
|
||||||
[:name , :args ] + super
|
[:name , :args ]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class FrameSet < Instruction
|
class FrameSet < Instruction
|
||||||
def initialize name , val , nex = nil
|
def initialize name , val
|
||||||
super(nex)
|
|
||||||
@name = name.to_sym
|
@name = name.to_sym
|
||||||
@value = val
|
@value = val
|
||||||
end
|
end
|
||||||
attr_reader :name , :value
|
attr_reader :name , :value
|
||||||
def attributes
|
def attributes
|
||||||
[:name , :value] + super
|
[:name , :value]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class MessageSet < Instruction
|
class MessageSet < Instruction
|
||||||
def initialize name , val , nex = nil
|
def initialize name , val
|
||||||
super(nex)
|
|
||||||
@name = name.to_sym
|
@name = name.to_sym
|
||||||
@value = val
|
@value = val
|
||||||
end
|
end
|
||||||
attr_reader :name , :value
|
attr_reader :name , :value
|
||||||
def attributes
|
def attributes
|
||||||
[:name , :value] + super
|
[:name , :value]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class LoadSelf < Instruction
|
class LoadSelf < Instruction
|
||||||
def initialize val , nex = nil
|
def initialize val
|
||||||
super(nex)
|
|
||||||
@value = val
|
@value = val
|
||||||
end
|
end
|
||||||
attr_reader :value
|
attr_reader :value
|
||||||
def attributes
|
def attributes
|
||||||
[:value] + super
|
[:value]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -29,3 +29,5 @@ class Node < List
|
|||||||
@key == key ? @value = value : super(key,value)
|
@key == key ? @value = value : super(key,value)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# https://www.youtube.com/watch?v=HJ-719EGIts
|
@ -37,25 +37,25 @@ module Virtual
|
|||||||
#
|
#
|
||||||
def compile_get method , name
|
def compile_get method , name
|
||||||
if method.has_arg(name)
|
if method.has_arg(name)
|
||||||
method.add MessageGet.new(name)
|
method.add_code MessageGet.new(name)
|
||||||
else
|
else
|
||||||
method.add FrameGet.new(name)
|
method.add_code FrameGet.new(name)
|
||||||
end
|
end
|
||||||
method.get_var(name)
|
method.get_var(name)
|
||||||
end
|
end
|
||||||
|
|
||||||
def compile_send method , name , me , with = []
|
def compile_send method , name , me , with = []
|
||||||
method.add Virtual::LoadSelf.new(me)
|
method.add_code Virtual::LoadSelf.new(me)
|
||||||
method.add MessageSend.new(name , with )
|
method.add_code MessageSend.new(name , with )
|
||||||
Return.new( method.return_type )
|
Return.new( method.return_type )
|
||||||
end
|
end
|
||||||
|
|
||||||
def compile_set method , name , val
|
def compile_set method , name , val
|
||||||
method.set_var(name,val)
|
method.set_var(name,val)
|
||||||
if method.has_arg(name)
|
if method.has_arg(name)
|
||||||
method.add MessageSet.new(name , val )
|
method.add_code MessageSet.new(name , val )
|
||||||
else
|
else
|
||||||
method.add FrameSet.new(name , val )
|
method.add_code FrameSet.new(name , val )
|
||||||
end
|
end
|
||||||
method.get_var(name)
|
method.get_var(name)
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
require_relative "object"
|
require_relative "block"
|
||||||
|
|
||||||
module Virtual
|
module Virtual
|
||||||
# static description of a method
|
# static description of a method
|
||||||
@ -9,6 +9,26 @@ module Virtual
|
|||||||
# known local variable names
|
# known local variable names
|
||||||
# temp variables (numbered)
|
# temp variables (numbered)
|
||||||
#
|
#
|
||||||
|
# Methods are similar to Blocks. Where Blocks can be jumped to, Methods can be called.
|
||||||
|
|
||||||
|
# Methods also have arguments and a return. These are Value subclass instances, ie specify
|
||||||
|
# type (by class type) and register by instance
|
||||||
|
|
||||||
|
# They also have local variables. Args take up the first n regs, then locals the rest. No
|
||||||
|
# direct manipulating of registers (ie specifying the number) should be done.
|
||||||
|
|
||||||
|
# Code-wise Methods are made up from a list of Blocks, in a similar way blocks are made up of codes
|
||||||
|
# The function starts with one block, and that has a start and end (return)
|
||||||
|
|
||||||
|
# Blocks can be linked in two ways:
|
||||||
|
# -linear: flow continues from one to the next as they are sequential both logically and "physically"
|
||||||
|
# use the block set_next for this.
|
||||||
|
# This "the straight line", there must be a continuous sequence from body to return
|
||||||
|
# Linear blocks may be created from an existing block with new_block
|
||||||
|
# - branched: You create new blocks using function.new_block which gets added "after" return
|
||||||
|
# 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.
|
||||||
|
|
||||||
class MethodDefinition < Virtual::Object
|
class MethodDefinition < Virtual::Object
|
||||||
#return the main function (the top level) into which code is compiled
|
#return the main function (the top level) into which code is compiled
|
||||||
def MethodDefinition.main
|
def MethodDefinition.main
|
||||||
@ -17,27 +37,81 @@ module Virtual
|
|||||||
def attributes
|
def attributes
|
||||||
[:name , :args , :receiver , :return_type , :start]
|
[:name , :args , :receiver , :return_type , :start]
|
||||||
end
|
end
|
||||||
def initialize name , args , receiver = Virtual::SelfReference.new , return_type = Virtual::Mystery , start = MethodEnter.new(MethodReturn.new)
|
def initialize name , args , receiver = Virtual::SelfReference.new , return_type = Virtual::Mystery , start = MethodEnter.new()
|
||||||
@name = name.to_sym
|
@name = name.to_sym
|
||||||
@args = args
|
@args = args
|
||||||
@locals = []
|
@locals = []
|
||||||
@tmps = []
|
@tmps = []
|
||||||
@receiver = receiver
|
@receiver = receiver
|
||||||
@return_type = return_type
|
@return_type = return_type
|
||||||
@start = start
|
@blocks = []
|
||||||
@current = @start
|
# first block we have to create with .new , as new_block assumes a current
|
||||||
|
enter = Block.new( name , self ).add_code(start)
|
||||||
|
@blocks << enter
|
||||||
|
@current = enter
|
||||||
|
new_block("return").add_code(MethodReturn.new)
|
||||||
end
|
end
|
||||||
attr_reader :name , :args , :receiver , :start
|
attr_reader :name , :args , :receiver , :blocks
|
||||||
attr_accessor :return_type , :current
|
attr_accessor :return_type , :current
|
||||||
|
|
||||||
# add an instruction after the current (insertion point)
|
# add an instruction after the current (insertion point)
|
||||||
# the added instruction will become the new insertion point
|
# the added instruction will become the new insertion point
|
||||||
def add instruction
|
def add_code instruction
|
||||||
raise instruction.inspect unless instruction.is_a? Instruction
|
raise instruction.inspect unless instruction.is_a? Instruction
|
||||||
@current.insert(instruction) #insert after current
|
@current.add_code(instruction) #insert after current
|
||||||
@current = instruction
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# return a list of registers that are still in use after the given block
|
||||||
|
# a call_site uses pushes and pops these to make them available for code after a call
|
||||||
|
def locals_at l_block
|
||||||
|
used =[]
|
||||||
|
# call assigns the return register, but as it is in l_block, it is not asked.
|
||||||
|
assigned = [ RegisterReference.new(Vm::RegisterMachine.instance.return_register) ]
|
||||||
|
l_block.reachable.each do |b|
|
||||||
|
b.uses.each {|u|
|
||||||
|
(used << u) unless assigned.include?(u)
|
||||||
|
}
|
||||||
|
assigned += b.assigns
|
||||||
|
end
|
||||||
|
used.uniq
|
||||||
|
end
|
||||||
|
|
||||||
|
# control structures need to see blocks as a graph, but they are stored as a list with implict branches
|
||||||
|
# So when creating a new block (with new_block), it is only added to the list, but instructions
|
||||||
|
# still go to the current one
|
||||||
|
# With this function one can change the current block, to actually code it.
|
||||||
|
# This juggling is (unfortunately) neccessary, as all compile functions just keep puring their code into the
|
||||||
|
# method and don't care what other compiles (like if's) do.
|
||||||
|
|
||||||
|
# Example: while, needs 2 extra blocks
|
||||||
|
# 1 condition code, must be its own blockas we jump back to it
|
||||||
|
# - the body, can actually be after the condition as we don't need to jump there
|
||||||
|
# 2 after while block. Condition jumps here
|
||||||
|
# After block 2, the function is linear again and the calling code does not need to know what happened
|
||||||
|
|
||||||
|
# But subsequent statements are still using the original block (self) to add code to
|
||||||
|
# So the while expression creates the extra blocks, adds them and the code and then "moves" the insertion point along
|
||||||
|
def current block
|
||||||
|
@current = block
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
# create a new linear block after the current insertion block.
|
||||||
|
# Linear means there is no brach needed from that one to the new one.
|
||||||
|
# Usually the new one just serves as jump address for a control statement
|
||||||
|
# In code generation , the new_block is written after this one, ie zero runtime cost
|
||||||
|
# This does _not_ change the insertion point, that has do be done with insert_at(block)
|
||||||
|
def new_block new_name
|
||||||
|
block_name = "#{@current.name}_#{new_name}"
|
||||||
|
new_b = Block.new( block_name , self )
|
||||||
|
index = @blocks.index( @current )
|
||||||
|
@blocks.insert( index + 1 , new_b ) # + one because we want the ne after the insert_at
|
||||||
|
return new_b
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# determine whether this method has a variable by the given name
|
# determine whether this method has a variable by the given name
|
||||||
# variables are locals and and arguments
|
# variables are locals and and arguments
|
||||||
# used to determine if a send must be issued
|
# used to determine if a send must be issued
|
||||||
|
@ -5,12 +5,6 @@ module Virtual
|
|||||||
#
|
#
|
||||||
# functions on these classes express their functionality as function objects
|
# functions on these classes express their functionality as function objects
|
||||||
class Object
|
class Object
|
||||||
def initialize
|
|
||||||
@layout = Layout.new( attributes )
|
|
||||||
end
|
|
||||||
def attributes
|
|
||||||
[:layout]
|
|
||||||
end
|
|
||||||
def == other
|
def == other
|
||||||
return false unless other.class == self.class
|
return false unless other.class == self.class
|
||||||
attributes.each do |a|
|
attributes.each do |a|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
module Vm
|
module Virtual
|
||||||
# Plock (Proc-Block) is mostly a Block but also somewhat Proc-ish: A Block that carries data.
|
# Plock (Proc-Block) is mostly a Block but also somewhat Proc-ish: A Block that carries data.
|
||||||
#
|
#
|
||||||
# Data in a Block is usefull in the same way data in objects is. Plocks being otherwise just code.
|
# Data in a Block is usefull in the same way data in objects is. Plocks being otherwise just code.
|
||||||
#
|
#
|
||||||
# But the concept is not quite straigtforwrd: If one think of an Plock enbedded in a normal function,
|
# But the concept is not quite straigtforwrd: If one thinks of a Plock embedded in a normal method,
|
||||||
# the a data in the Plock would be static data. In OO terms this comes quite close to a Proc, if the data is the local
|
# the a data in the Plock would be static data. In OO terms this comes quite close to a Proc, if the data is the local
|
||||||
# variables. Quite possibly they shall be used to implement procs, but that is not the direction now.
|
# variables. Quite possibly they shall be used to implement procs, but that is not the direction now.
|
||||||
#
|
#
|
||||||
@ -16,7 +16,7 @@ module Vm
|
|||||||
# It follows that Plocks should be linear blocks.
|
# It follows that Plocks should be linear blocks.
|
||||||
class Plock < Block
|
class Plock < Block
|
||||||
|
|
||||||
def initialize(name , function , next_block )
|
def initialize(name , method , next_block )
|
||||||
super
|
super
|
||||||
@data = []
|
@data = []
|
||||||
@branch_code = RegisterMachine.instance.b next_block
|
@branch_code = RegisterMachine.instance.b next_block
|
||||||
@ -27,7 +27,7 @@ module Vm
|
|||||||
@branch_code = RegisterMachine.instance.b next_block
|
@branch_code = RegisterMachine.instance.b next_block
|
||||||
end
|
end
|
||||||
|
|
||||||
# Data gets assembled after functions
|
# Data gets assembled after methods
|
||||||
def add_data o
|
def add_data o
|
||||||
return if @objects.include? o
|
return if @objects.include? o
|
||||||
raise "must be derived from Code #{o.inspect}" unless o.is_a? Vm::Code
|
raise "must be derived from Code #{o.inspect}" unless o.is_a? Vm::Code
|
@ -45,7 +45,7 @@ class TestBasic < MiniTest::Test
|
|||||||
|
|
||||||
def test_module_name
|
def test_module_name
|
||||||
@string_input = 'FooBar '
|
@string_input = 'FooBar '
|
||||||
@output = "---RETURN_MARKER- &1 !ruby/object:Boot::BootClassRETURN_MARKER method_definitions: []RETURN_MARKER name: :FooBarRETURN_MARKER super_class_name: :ObjectRETURN_MARKER meta_class: !ruby/object:Boot::MetaClassRETURN_MARKER layout: !ruby/object:Virtual::LayoutRETURN_MARKER members: []RETURN_MARKER functions: []RETURN_MARKER me_self: *1RETURN_MARKER"
|
@output = "---RETURN_MARKER- &1 !ruby/object:Boot::BootClassRETURN_MARKER method_definitions: []RETURN_MARKER name: :FooBarRETURN_MARKER super_class_name: :ObjectRETURN_MARKER meta_class: !ruby/object:Boot::MetaClassRETURN_MARKER functions: []RETURN_MARKER me_self: *1RETURN_MARKER"
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ class Object
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
HERE
|
HERE
|
||||||
@output = "---RETURN_MARKER- &12 !ruby/object:Boot::BootClassRETURN_MARKER method_definitions:RETURN_MARKER - !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :index_ofRETURN_MARKER args: &1 !ruby/class 'Virtual::Reference'RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver:RETURN_MARKER - *1RETURN_MARKER return_type: &7 !ruby/class 'Virtual::Integer'RETURN_MARKER start: &2 !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER current: *2RETURN_MARKER - !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :_get_instance_variableRETURN_MARKER args:RETURN_MARKER - *1RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: *1RETURN_MARKER return_type: &4 !ruby/class 'Virtual::Mystery'RETURN_MARKER start: &3 !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER current: *3RETURN_MARKER - !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :_set_instance_variableRETURN_MARKER args:RETURN_MARKER - *1RETURN_MARKER - *1RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: *1RETURN_MARKER return_type: *4RETURN_MARKER start: &5 !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER current: *5RETURN_MARKER - !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :putstringRETURN_MARKER args: []RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: *4RETURN_MARKER start: &6 !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER current: *6RETURN_MARKER - !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :putintRETURN_MARKER args: []RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: *7RETURN_MARKER return_type: *7RETURN_MARKER start: &8 !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER current: *8RETURN_MARKER - !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :fiboRETURN_MARKER args: []RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: *7RETURN_MARKER return_type: *7RETURN_MARKER start: &9 !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER current: *9RETURN_MARKER - !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :exitRETURN_MARKER args: []RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: *7RETURN_MARKER return_type: *4RETURN_MARKER start: &10 !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER current: *10RETURN_MARKER - !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :get_classRETURN_MARKER args: []RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: *4RETURN_MARKER start: !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::ObjectGetRETURN_MARKER name: :layoutRETURN_MARKER next: !ruby/object:Virtual::LoadSelfRETURN_MARKER value: !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER next: &11 !ruby/object:Virtual::MessageSendRETURN_MARKER name: :get_classRETURN_MARKER args: []RETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER current: *11RETURN_MARKER name: :ObjectRETURN_MARKER super_class_name: :ObjectRETURN_MARKER meta_class: !ruby/object:Boot::MetaClassRETURN_MARKER layout: !ruby/object:Virtual::LayoutRETURN_MARKER members: []RETURN_MARKER functions: []RETURN_MARKER me_self: *12RETURN_MARKER"
|
@output = ""
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ class Message
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
HERE
|
HERE
|
||||||
@output = "---RETURN_MARKER- &6 !ruby/object:Boot::BootClassRETURN_MARKER method_definitions:RETURN_MARKER - !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :get_type_forRETURN_MARKER args:RETURN_MARKER - &2 !ruby/object:Virtual::ArgumentRETURN_MARKER name: :nameRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER locals:RETURN_MARKER - &4 !ruby/object:Virtual::LocalRETURN_MARKER name: :indexRETURN_MARKER type: &3 !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: &1 !ruby/class 'Virtual::Mystery'RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: *1RETURN_MARKER start: !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::ObjectGetRETURN_MARKER name: :layoutRETURN_MARKER next: !ruby/object:Virtual::MessageGetRETURN_MARKER name: :nameRETURN_MARKER next: !ruby/object:Virtual::LoadSelfRETURN_MARKER value: !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER next: !ruby/object:Virtual::MessageSendRETURN_MARKER name: :get_indexRETURN_MARKER args:RETURN_MARKER - *2RETURN_MARKER next: !ruby/object:Virtual::FrameSetRETURN_MARKER name: :indexRETURN_MARKER value: *3RETURN_MARKER next: !ruby/object:Virtual::FrameGetRETURN_MARKER name: :indexRETURN_MARKER next: !ruby/object:Virtual::LoadSelfRETURN_MARKER value: !ruby/object:Virtual::SelfRETURN_MARKER name: :selfRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER next: &5 !ruby/object:Virtual::MessageSendRETURN_MARKER name: :get_atRETURN_MARKER args:RETURN_MARKER - *4RETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER current: *5RETURN_MARKER name: :MessageRETURN_MARKER super_class_name: :ObjectRETURN_MARKER meta_class: !ruby/object:Boot::MetaClassRETURN_MARKER layout: !ruby/object:Virtual::LayoutRETURN_MARKER members: []RETURN_MARKER functions: []RETURN_MARKER me_self: *6RETURN_MARKER"
|
@output = ""
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ def foo(x)
|
|||||||
5
|
5
|
||||||
end
|
end
|
||||||
HERE
|
HERE
|
||||||
@output = "---RETURN_MARKER- !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :fooRETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::ArgumentRETURN_MARKER name: :xRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 5RETURN_MARKER start: &1 !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER current: *1RETURN_MARKER"
|
@output = "---RETURN_MARKER- &1 !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :fooRETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::ArgumentRETURN_MARKER name: :xRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 5RETURN_MARKER blocks:RETURN_MARKER - &2 !ruby/object:Virtual::BlockRETURN_MARKER method: *1RETURN_MARKER name: :fooRETURN_MARKER branch: RETURN_MARKER codes:RETURN_MARKER - !ruby/object:Virtual::MethodEnter {}RETURN_MARKER - !ruby/object:Virtual::BlockRETURN_MARKER method: *1RETURN_MARKER name: :foo_returnRETURN_MARKER branch: RETURN_MARKER codes:RETURN_MARKER - !ruby/object:Virtual::MethodReturn {}RETURN_MARKER current: *2RETURN_MARKER"
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ def String.length(x)
|
|||||||
@length
|
@length
|
||||||
end
|
end
|
||||||
HERE
|
HERE
|
||||||
@output = "---RETURN_MARKER- !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :lengthRETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::ArgumentRETURN_MARKER name: :xRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: &4 !ruby/object:Boot::BootClassRETURN_MARKER method_definitions:RETURN_MARKER - !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :getRETURN_MARKER args:RETURN_MARKER - &1 !ruby/class 'Virtual::Integer'RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: *1RETURN_MARKER return_type: *1RETURN_MARKER start: &2 !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER current: *2RETURN_MARKER - !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :setRETURN_MARKER args:RETURN_MARKER - *1RETURN_MARKER - *1RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: *1RETURN_MARKER return_type: *1RETURN_MARKER start: &3 !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER current: *3RETURN_MARKER name: :StringRETURN_MARKER super_class_name: :ObjectRETURN_MARKER meta_class: !ruby/object:Boot::MetaClassRETURN_MARKER layout: !ruby/object:Virtual::LayoutRETURN_MARKER members: []RETURN_MARKER functions: []RETURN_MARKER me_self: *4RETURN_MARKER return_type: !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER start: !ruby/object:Virtual::MethodEnterRETURN_MARKER next: &5 !ruby/object:Virtual::ObjectGetRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER name: :lengthRETURN_MARKER current: *5RETURN_MARKER"
|
@output = "---RETURN_MARKER- &7 !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :lengthRETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::ArgumentRETURN_MARKER name: :xRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: &6 !ruby/object:Boot::BootClassRETURN_MARKER method_definitions:RETURN_MARKER - &2 !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :getRETURN_MARKER args:RETURN_MARKER - &1 !ruby/class 'Virtual::Integer'RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: *1RETURN_MARKER return_type: *1RETURN_MARKER blocks:RETURN_MARKER - &3 !ruby/object:Virtual::BlockRETURN_MARKER method: *2RETURN_MARKER name: :getRETURN_MARKER branch: RETURN_MARKER codes:RETURN_MARKER - !ruby/object:Virtual::MethodEnter {}RETURN_MARKER - !ruby/object:Virtual::BlockRETURN_MARKER method: *2RETURN_MARKER name: :get_returnRETURN_MARKER branch: RETURN_MARKER codes:RETURN_MARKER - !ruby/object:Virtual::MethodReturn {}RETURN_MARKER current: *3RETURN_MARKER - &4 !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :setRETURN_MARKER args:RETURN_MARKER - *1RETURN_MARKER - *1RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: *1RETURN_MARKER return_type: *1RETURN_MARKER blocks:RETURN_MARKER - &5 !ruby/object:Virtual::BlockRETURN_MARKER method: *4RETURN_MARKER name: :setRETURN_MARKER branch: RETURN_MARKER codes:RETURN_MARKER - !ruby/object:Virtual::MethodEnter {}RETURN_MARKER - !ruby/object:Virtual::BlockRETURN_MARKER method: *4RETURN_MARKER name: :set_returnRETURN_MARKER branch: RETURN_MARKER codes:RETURN_MARKER - !ruby/object:Virtual::MethodReturn {}RETURN_MARKER current: *5RETURN_MARKER name: :StringRETURN_MARKER super_class_name: :ObjectRETURN_MARKER meta_class: !ruby/object:Boot::MetaClassRETURN_MARKER functions: []RETURN_MARKER me_self: *6RETURN_MARKER return_type: !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER blocks:RETURN_MARKER - &8 !ruby/object:Virtual::BlockRETURN_MARKER method: *7RETURN_MARKER name: :lengthRETURN_MARKER branch: RETURN_MARKER codes:RETURN_MARKER - !ruby/object:Virtual::MethodEnter {}RETURN_MARKER - !ruby/object:Virtual::ObjectGetRETURN_MARKER name: :lengthRETURN_MARKER - !ruby/object:Virtual::BlockRETURN_MARKER method: *7RETURN_MARKER name: :length_returnRETURN_MARKER branch: RETURN_MARKER codes:RETURN_MARKER - !ruby/object:Virtual::MethodReturn {}RETURN_MARKER current: *8RETURN_MARKER"
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ def foo(x)
|
|||||||
2 + 5
|
2 + 5
|
||||||
end
|
end
|
||||||
HERE
|
HERE
|
||||||
@output ="---RETURN_MARKER- !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :fooRETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::ArgumentRETURN_MARKER name: :xRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER locals:RETURN_MARKER - !ruby/object:Virtual::LocalRETURN_MARKER name: :abbaRETURN_MARKER type: &1 !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 5RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: !ruby/class 'Virtual::Mystery'RETURN_MARKER start: !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::FrameSetRETURN_MARKER next: !ruby/object:Virtual::LoadSelfRETURN_MARKER next: &2 !ruby/object:Virtual::MessageSendRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER name: :+RETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 5RETURN_MARKER value: !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 2RETURN_MARKER name: :abbaRETURN_MARKER value: *1RETURN_MARKER current: *2RETURN_MARKER"
|
@output ="---RETURN_MARKER- &1 !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :fooRETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::ArgumentRETURN_MARKER name: :xRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER locals:RETURN_MARKER - !ruby/object:Virtual::LocalRETURN_MARKER name: :abbaRETURN_MARKER type: &2 !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 5RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: !ruby/class 'Virtual::Mystery'RETURN_MARKER blocks:RETURN_MARKER - &3 !ruby/object:Virtual::BlockRETURN_MARKER method: *1RETURN_MARKER name: :fooRETURN_MARKER branch: RETURN_MARKER codes:RETURN_MARKER - !ruby/object:Virtual::MethodEnter {}RETURN_MARKER - !ruby/object:Virtual::FrameSetRETURN_MARKER name: :abbaRETURN_MARKER value: *2RETURN_MARKER - !ruby/object:Virtual::LoadSelfRETURN_MARKER value: !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 2RETURN_MARKER - !ruby/object:Virtual::MessageSendRETURN_MARKER name: :+RETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 5RETURN_MARKER - !ruby/object:Virtual::BlockRETURN_MARKER method: *1RETURN_MARKER name: :foo_returnRETURN_MARKER branch: RETURN_MARKER codes:RETURN_MARKER - !ruby/object:Virtual::MethodReturn {}RETURN_MARKER current: *3RETURN_MARKER"
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ def foo()
|
|||||||
2 + 5
|
2 + 5
|
||||||
end
|
end
|
||||||
HERE
|
HERE
|
||||||
@output = "---RETURN_MARKER- !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :fooRETURN_MARKER args: []RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: !ruby/class 'Virtual::Mystery'RETURN_MARKER start: !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::LoadSelfRETURN_MARKER next: &1 !ruby/object:Virtual::MessageSendRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER name: :+RETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 5RETURN_MARKER value: !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 2RETURN_MARKER current: *1RETURN_MARKER"
|
@output = ""
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ def ofthen(n)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
HERE
|
HERE
|
||||||
@output = "---RETURN_MARKER- !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :ofthenRETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::ArgumentRETURN_MARKER name: :nRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER locals:RETURN_MARKER - !ruby/object:Virtual::LocalRETURN_MARKER name: :isitRETURN_MARKER type: &2 !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 42RETURN_MARKER - &1 !ruby/object:Virtual::LocalRETURN_MARKER name: :maybenotRETURN_MARKER type: &4 !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 667RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: *1RETURN_MARKER start: !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::ImplicitBranchRETURN_MARKER next: !ruby/object:Virtual::FrameSetRETURN_MARKER next: &3 !ruby/object:Virtual::LabelRETURN_MARKER next: RETURN_MARKER name: :if_merge_5246RETURN_MARKER name: :isitRETURN_MARKER value: *2RETURN_MARKER name: :if_merge_5246RETURN_MARKER other: !ruby/object:Virtual::FrameSetRETURN_MARKER next: *3RETURN_MARKER name: :maybenotRETURN_MARKER value: *4RETURN_MARKER current: *3RETURN_MARKER"
|
@output = ""
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ def fibonaccit(n)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
HERE
|
HERE
|
||||||
@output = "---RETURN_MARKER- !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :fibonaccitRETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::ArgumentRETURN_MARKER name: :nRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER locals:RETURN_MARKER - !ruby/object:Virtual::LocalRETURN_MARKER name: :aRETURN_MARKER type: &2 !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 0RETURN_MARKER - &4 !ruby/object:Virtual::LocalRETURN_MARKER name: :someRETURN_MARKER type: &3 !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 43RETURN_MARKER - &1 !ruby/object:Virtual::LocalRETURN_MARKER name: :otherRETURN_MARKER type: &5 !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: !ruby/class 'Virtual::Mystery'RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: *1RETURN_MARKER start: !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::FrameSetRETURN_MARKER name: :aRETURN_MARKER value: *2RETURN_MARKER next: &6 !ruby/object:Virtual::LabelRETURN_MARKER name: while_startRETURN_MARKER next: !ruby/object:Virtual::FrameGetRETURN_MARKER name: :nRETURN_MARKER next: !ruby/object:Virtual::ImplicitBranchRETURN_MARKER name: :while_39010RETURN_MARKER other: &7 !ruby/object:Virtual::LabelRETURN_MARKER name: :while_39010RETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER next: !ruby/object:Virtual::FrameSetRETURN_MARKER name: :someRETURN_MARKER value: *3RETURN_MARKER next: !ruby/object:Virtual::FrameGetRETURN_MARKER name: :someRETURN_MARKER next: !ruby/object:Virtual::LoadSelfRETURN_MARKER value: *4RETURN_MARKER next: !ruby/object:Virtual::MessageSendRETURN_MARKER name: :*RETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 4RETURN_MARKER next: !ruby/object:Virtual::FrameSetRETURN_MARKER name: :otherRETURN_MARKER value: *5RETURN_MARKER next: *6RETURN_MARKER current: *7RETURN_MARKER"
|
@output = ""
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -79,7 +79,7 @@ def retvar(n)
|
|||||||
return i
|
return i
|
||||||
end
|
end
|
||||||
HERE
|
HERE
|
||||||
@output = "---RETURN_MARKER- !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :retvarRETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::ArgumentRETURN_MARKER name: :nRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER locals:RETURN_MARKER - !ruby/object:Virtual::LocalRETURN_MARKER name: :iRETURN_MARKER type: &1 !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 5RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: !ruby/object:Virtual::ReferenceRETURN_MARKER clazz: RETURN_MARKER start: !ruby/object:Virtual::MethodEnterRETURN_MARKER next: &2 !ruby/object:Virtual::FrameSetRETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER name: :iRETURN_MARKER value: *1RETURN_MARKER current: *2RETURN_MARKER"
|
@output = ""
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ def retvar(n)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
HERE
|
HERE
|
||||||
@output = "---RETURN_MARKER- !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :retvarRETURN_MARKER args:RETURN_MARKER - &1 !ruby/object:Virtual::ArgumentRETURN_MARKER name: :nRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: !ruby/object:Virtual::ReferenceRETURN_MARKER clazz: RETURN_MARKER start: !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::MessageGetRETURN_MARKER name: :nRETURN_MARKER next: !ruby/object:Virtual::LoadSelfRETURN_MARKER value: *1RETURN_MARKER next: !ruby/object:Virtual::MessageSendRETURN_MARKER name: :>RETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 5RETURN_MARKER next: !ruby/object:Virtual::ImplicitBranchRETURN_MARKER name: :if_merge_5246RETURN_MARKER other: &2 !ruby/object:Virtual::LabelRETURN_MARKER name: :if_merge_5246RETURN_MARKER next: RETURN_MARKER next: *2RETURN_MARKER current: *2RETURN_MARKER"
|
@output = ""
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ def retvar(n)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
HERE
|
HERE
|
||||||
@output = "---RETURN_MARKER- !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :retvarRETURN_MARKER args:RETURN_MARKER - &1 !ruby/object:Virtual::ArgumentRETURN_MARKER name: :nRETURN_MARKER type: &2 !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: !ruby/class 'Virtual::Mystery'RETURN_MARKER locals: []RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: !ruby/object:Virtual::ReferenceRETURN_MARKER clazz: RETURN_MARKER start: !ruby/object:Virtual::MethodEnterRETURN_MARKER next: &3 !ruby/object:Virtual::LabelRETURN_MARKER name: while_startRETURN_MARKER next: !ruby/object:Virtual::MessageGetRETURN_MARKER name: :nRETURN_MARKER next: !ruby/object:Virtual::LoadSelfRETURN_MARKER value: *1RETURN_MARKER next: !ruby/object:Virtual::MessageSendRETURN_MARKER name: :>RETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 5RETURN_MARKER next: !ruby/object:Virtual::ImplicitBranchRETURN_MARKER name: :while_39010RETURN_MARKER other: &4 !ruby/object:Virtual::LabelRETURN_MARKER name: :while_39010RETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER next: !ruby/object:Virtual::MessageGetRETURN_MARKER name: :nRETURN_MARKER next: !ruby/object:Virtual::LoadSelfRETURN_MARKER value: *1RETURN_MARKER next: !ruby/object:Virtual::MessageSendRETURN_MARKER name: :+RETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 1RETURN_MARKER next: !ruby/object:Virtual::MessageSetRETURN_MARKER name: :nRETURN_MARKER value: *2RETURN_MARKER next: *3RETURN_MARKER current: *4RETURN_MARKER"
|
@output = ""
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ def fibonaccit(n)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
HERE
|
HERE
|
||||||
@output = "---RETURN_MARKER- !ruby/object:Virtual::MethodDefinitionRETURN_MARKER name: :fibonaccitRETURN_MARKER args:RETURN_MARKER - &4 !ruby/object:Virtual::ArgumentRETURN_MARKER name: :nRETURN_MARKER type: &7 !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: &1 !ruby/class 'Virtual::Mystery'RETURN_MARKER locals:RETURN_MARKER - &3 !ruby/object:Virtual::LocalRETURN_MARKER name: :aRETURN_MARKER type: &2 !ruby/object:Virtual::LocalRETURN_MARKER name: :bRETURN_MARKER type: &6 !ruby/object:Virtual::ReturnRETURN_MARKER name: :returnRETURN_MARKER type: *1RETURN_MARKER - *2RETURN_MARKER - &5 !ruby/object:Virtual::LocalRETURN_MARKER name: :tmpRETURN_MARKER type: *3RETURN_MARKER tmps: []RETURN_MARKER receiver: !ruby/object:Virtual::SelfReferenceRETURN_MARKER clazz: RETURN_MARKER return_type: *4RETURN_MARKER start: !ruby/object:Virtual::MethodEnterRETURN_MARKER next: !ruby/object:Virtual::FrameSetRETURN_MARKER name: :aRETURN_MARKER value: !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 0RETURN_MARKER next: !ruby/object:Virtual::FrameSetRETURN_MARKER name: :bRETURN_MARKER value: !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 1RETURN_MARKER next: &8 !ruby/object:Virtual::LabelRETURN_MARKER name: while_startRETURN_MARKER next: !ruby/object:Virtual::MessageGetRETURN_MARKER name: :nRETURN_MARKER next: !ruby/object:Virtual::LoadSelfRETURN_MARKER value: *4RETURN_MARKER next: !ruby/object:Virtual::MessageSendRETURN_MARKER name: :>RETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 1RETURN_MARKER next: !ruby/object:Virtual::ImplicitBranchRETURN_MARKER name: :while_39010RETURN_MARKER other: &9 !ruby/object:Virtual::LabelRETURN_MARKER name: :while_39010RETURN_MARKER next: !ruby/object:Virtual::MethodReturnRETURN_MARKER next: RETURN_MARKER next: !ruby/object:Virtual::FrameGetRETURN_MARKER name: :aRETURN_MARKER next: !ruby/object:Virtual::FrameSetRETURN_MARKER name: :tmpRETURN_MARKER value: *3RETURN_MARKER next: !ruby/object:Virtual::FrameGetRETURN_MARKER name: :bRETURN_MARKER next: !ruby/object:Virtual::FrameSetRETURN_MARKER name: :aRETURN_MARKER value: *2RETURN_MARKER next: !ruby/object:Virtual::FrameGetRETURN_MARKER name: :tmpRETURN_MARKER next: !ruby/object:Virtual::FrameGetRETURN_MARKER name: :bRETURN_MARKER next: !ruby/object:Virtual::LoadSelfRETURN_MARKER value: *5RETURN_MARKER next: !ruby/object:Virtual::MessageSendRETURN_MARKER name: :+RETURN_MARKER args:RETURN_MARKER - *2RETURN_MARKER next: !ruby/object:Virtual::FrameSetRETURN_MARKER name: :bRETURN_MARKER value: *6RETURN_MARKER next: !ruby/object:Virtual::FrameGetRETURN_MARKER name: :bRETURN_MARKER next: !ruby/object:Virtual::LoadSelfRETURN_MARKER value: !ruby/object:Virtual::SelfRETURN_MARKER name: :selfRETURN_MARKER type: !ruby/object:Virtual::Mystery {}RETURN_MARKER next: !ruby/object:Virtual::MessageSendRETURN_MARKER name: :putsRETURN_MARKER args:RETURN_MARKER - *2RETURN_MARKER next: !ruby/object:Virtual::MessageGetRETURN_MARKER name: :nRETURN_MARKER next: !ruby/object:Virtual::LoadSelfRETURN_MARKER value: *4RETURN_MARKER next: !ruby/object:Virtual::MessageSendRETURN_MARKER name: :-RETURN_MARKER args:RETURN_MARKER - !ruby/object:Virtual::IntegerConstantRETURN_MARKER integer: 1RETURN_MARKER next: !ruby/object:Virtual::MessageSetRETURN_MARKER name: :nRETURN_MARKER value: *7RETURN_MARKER next: *8RETURN_MARKER current: *9RETURN_MARKER"
|
@output = ""
|
||||||
check
|
check
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -11,7 +11,7 @@ module VirtualHelper
|
|||||||
machine = Virtual::Machine.boot
|
machine = Virtual::Machine.boot
|
||||||
expressions = machine.compile_main @string_input
|
expressions = machine.compile_main @string_input
|
||||||
should = YAML.load(@output.gsub("RETURN_MARKER" , "\n"))
|
should = YAML.load(@output.gsub("RETURN_MARKER" , "\n"))
|
||||||
assert_equal should , expressions , expressions.to_yaml.gsub("\n" , "RETURN_MARKER") + "\n" + expressions.to_yaml
|
assert_equal should , expressions , expressions.to_yaml.gsub("\n" , "RETURN_MARKER") + "\n" + expressions.to_yaml.gsub("!ruby/object:","")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user