so close i can smell it, checkpoint
This commit is contained in:
parent
5608c411bf
commit
a61170942f
@ -1,8 +1,35 @@
|
|||||||
require "vm/machine"
|
require "vm/machine"
|
||||||
|
require_relative "instruction"
|
||||||
|
require_relative "stack_instruction"
|
||||||
|
require_relative "logic_instruction"
|
||||||
|
require_relative "memory_instruction"
|
||||||
|
require_relative "call_instruction"
|
||||||
|
|
||||||
module Arm
|
module Arm
|
||||||
class ArmMachine < Vm::Machine
|
class ArmMachine < Vm::Machine
|
||||||
|
|
||||||
|
# defines a method in the current class, with the name inst (first erg)
|
||||||
|
# the method instantiates an instruction of the given class which gets passed a single hash as arg
|
||||||
|
|
||||||
|
# gets called for every "standard" instruction.
|
||||||
|
# may be used for machine specific ones too
|
||||||
|
def define_instruction inst , clazz
|
||||||
|
super
|
||||||
|
return
|
||||||
|
# need to use create_method and move to options hash
|
||||||
|
define_method("#{inst}s") do |*args|
|
||||||
|
instruction clazz , inst , :al , 1 , *args
|
||||||
|
end
|
||||||
|
ArmMachine::COND_CODES.keys.each do |suffix|
|
||||||
|
define_method("#{inst}#{suffix}") do |options|
|
||||||
|
instruction clazz , inst , suffix , 0 , *args
|
||||||
|
end
|
||||||
|
define_method("#{inst}s#{suffix}") do |options|
|
||||||
|
instruction clazz , inst , suffix , 1 , *args
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def word_load value
|
def word_load value
|
||||||
"word"
|
"word"
|
||||||
end
|
end
|
||||||
@ -12,9 +39,17 @@ module Arm
|
|||||||
|
|
||||||
def main_entry
|
def main_entry
|
||||||
e = Vm::Block.new("main_entry")
|
e = Vm::Block.new("main_entry")
|
||||||
|
e.add_code( mov( :left => :fp , :right => 0 ))
|
||||||
end
|
end
|
||||||
def main_exit
|
def main_exit
|
||||||
e = Vm::Block.new("main_exit")
|
e = Vm::Block.new("main_exit")
|
||||||
|
e.join( syscall(0) )
|
||||||
|
end
|
||||||
|
def syscall num
|
||||||
|
e = Vm::Block.new("syscall")
|
||||||
|
e.add_code( MoveInstruction.new( 7 , num ) )
|
||||||
|
e.add_code( CallInstruction.new( :swi ) )
|
||||||
|
e
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -1,6 +1,6 @@
|
|||||||
require_relative "instruction"
|
require_relative "instruction"
|
||||||
|
|
||||||
module Asm
|
module Arm
|
||||||
# There are only three call instructions in arm branch (b), call (bl) and syscall (swi)
|
# There are only three call instructions in arm branch (b), call (bl) and syscall (swi)
|
||||||
|
|
||||||
# A branch could be called a jump as it has no notion of returning
|
# A branch could be called a jump as it has no notion of returning
|
||||||
@ -13,7 +13,7 @@ module Asm
|
|||||||
# in Arm the register layout is different and so we have to place the syscall code into register 7
|
# in Arm the register layout is different and so we have to place the syscall code into register 7
|
||||||
# Registers 0-6 hold the call values as for a normal c call
|
# Registers 0-6 hold the call values as for a normal c call
|
||||||
|
|
||||||
class CallInstruction < Instruction
|
class CallInstruction < Vm::CallInstruction
|
||||||
|
|
||||||
def assemble(io)
|
def assemble(io)
|
||||||
case opcode
|
case opcode
|
||||||
|
82
lib/arm/constants.rb
Normal file
82
lib/arm/constants.rb
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
module Arm
|
||||||
|
|
||||||
|
module Constants
|
||||||
|
OPCODES = {
|
||||||
|
:adc => 0b0101, :add => 0b0100,
|
||||||
|
:and => 0b0000, :bic => 0b1110,
|
||||||
|
:eor => 0b0001, :orr => 0b1100,
|
||||||
|
:rsb => 0b0011, :rsc => 0b0111,
|
||||||
|
:sbc => 0b0110, :sub => 0b0010,
|
||||||
|
|
||||||
|
# for these Rn is sbz (should be zero)
|
||||||
|
:mov => 0b1101,
|
||||||
|
:mvn => 0b1111,
|
||||||
|
# for these Rd is sbz and S=1
|
||||||
|
:cmn => 0b1011,
|
||||||
|
:cmp => 0b1010,
|
||||||
|
:teq => 0b1001,
|
||||||
|
:tst => 0b1000,
|
||||||
|
|
||||||
|
:b => 0b1010,
|
||||||
|
:bl => 0b1011,
|
||||||
|
:bx => 0b00010010
|
||||||
|
}
|
||||||
|
#return the bit patter that the cpu uses for the current instruction @opcode
|
||||||
|
def op_bit_code
|
||||||
|
OPCODES[@opcode] or throw "no code found for #{@opcode.inspect}"
|
||||||
|
end
|
||||||
|
|
||||||
|
#codition codes can be applied to many instructions and thus save branches
|
||||||
|
# :al => always , :eq => equal and so on
|
||||||
|
# eq mov if equal :moveq r1 r2 (also exists as function) will only execute if the last operation was 0
|
||||||
|
COND_CODES = {
|
||||||
|
:al => 0b1110, :eq => 0b0000,
|
||||||
|
:ne => 0b0001, :cs => 0b0010,
|
||||||
|
:mi => 0b0100, :hi => 0b1000,
|
||||||
|
:cc => 0b0011, :pl => 0b0101,
|
||||||
|
:ls => 0b1001, :vc => 0b0111,
|
||||||
|
:lt => 0b1011, :le => 0b1101,
|
||||||
|
:ge => 0b1010, :gt => 0b1100,
|
||||||
|
:vs => 0b0110
|
||||||
|
}
|
||||||
|
#return the bit pattern for the @condition_code variable, which signals the conditional code
|
||||||
|
def cond_bit_code
|
||||||
|
COND_CODES[@condition_code] or throw "no code found for #{@condition_code}"
|
||||||
|
end
|
||||||
|
|
||||||
|
REGISTERS = { 'r0' => 0, 'r1' => 1, 'r2' => 2, 'r3' => 3, 'r4' => 4, 'r5' => 5,
|
||||||
|
'r6' => 6, 'r7' => 7, 'r8' => 8, 'r9' => 9, 'r10' => 10, 'r11' => 11,
|
||||||
|
'r12' => 12, 'r13' => 13, 'r14' => 14, 'r15' => 15, 'a1' => 0, 'a2' => 1,
|
||||||
|
'a3' => 2, 'a4' => 3, 'v1' => 4, 'v2' => 5, 'v3' => 6, 'v4' => 7, 'v5' => 8,
|
||||||
|
'v6' => 9, 'rfp' => 9, 'sl' => 10, 'fp' => 11, 'ip' => 12, 'sp' => 13,
|
||||||
|
'lr' => 14, 'pc' => 15 }
|
||||||
|
def reg name
|
||||||
|
raise "no such register #{reg}" unless REGISTERS[name]
|
||||||
|
Asm::Register.new(name , REGISTERS[name])
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_u8_with_rr(arg)
|
||||||
|
parts = arg.value.to_s(2).rjust(32,'0').scan(/^(0*)(.+?)0*$/).flatten
|
||||||
|
pre_zeros = parts[0].length
|
||||||
|
imm_len = parts[1].length
|
||||||
|
if ((pre_zeros+imm_len) % 2 == 1)
|
||||||
|
u8_imm = (parts[1]+'0').to_i(2)
|
||||||
|
imm_len += 1
|
||||||
|
else
|
||||||
|
u8_imm = parts[1].to_i(2)
|
||||||
|
end
|
||||||
|
if (u8_imm.fits_u8?)
|
||||||
|
# can do!
|
||||||
|
rot_imm = (pre_zeros+imm_len) / 2
|
||||||
|
if (rot_imm > 15)
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return u8_imm | (rot_imm << 8)
|
||||||
|
else
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,24 +1,12 @@
|
|||||||
require_relative "assembly_error"
|
require "vm/instruction"
|
||||||
require_relative "arm_machine"
|
require_relative "constants"
|
||||||
|
|
||||||
module Asm
|
Vm::Instruction.class_eval do
|
||||||
|
include Arm::Constants
|
||||||
|
|
||||||
class Code ; end
|
COND_POSTFIXES = Regexp.union( Arm::Constants::COND_CODES.keys.collect{|k|k.to_s} ).source
|
||||||
|
|
||||||
# Not surprisingly represents an cpu instruction.
|
|
||||||
# This is an abstract base class, with derived classes
|
|
||||||
# Logic / Move / Compare / Stack / Memory (see there)
|
|
||||||
#
|
|
||||||
# Opcode is a (<= three) letter accronym (same as in assembly code). Though in arm, suffixes can
|
|
||||||
# make the opcode longer, we chop those off in the constructor
|
|
||||||
# Argurments are registers or labels or string/num Literals
|
|
||||||
|
|
||||||
class Instruction < Code
|
|
||||||
include ArmMachine
|
|
||||||
|
|
||||||
COND_POSTFIXES = Regexp.union( COND_CODES.keys.collect{|k|k.to_s} ).source
|
def initializ(opcode , condition_code , update_status , args)
|
||||||
|
|
||||||
def initialize(opcode , condition_code , update_status , args)
|
|
||||||
@update_status_flag = update_status
|
@update_status_flag = update_status
|
||||||
@condition_code = condition_code.to_sym
|
@condition_code = condition_code.to_sym
|
||||||
@opcode = opcode
|
@opcode = opcode
|
||||||
@ -43,4 +31,3 @@ module Asm
|
|||||||
4
|
4
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
@ -1,12 +1,12 @@
|
|||||||
require_relative "instruction"
|
require_relative "instruction"
|
||||||
|
|
||||||
module Asm
|
module Arm
|
||||||
# ADDRESSING MODE 1
|
# ADDRESSING MODE 1
|
||||||
# Logic ,Maths, Move and compare instructions (last three below)
|
# Logic ,Maths, Move and compare instructions (last three below)
|
||||||
|
|
||||||
class LogicInstruction < Instruction
|
class LogicInstruction < Vm::LogicInstruction
|
||||||
|
|
||||||
def initialize(opcode , condition_code , update_status , args)
|
def initializ(opcode , condition_code , update_status , args)
|
||||||
super(opcode , condition_code , update_status , args)
|
super(opcode , condition_code , update_status , args)
|
||||||
@rn = nil
|
@rn = nil
|
||||||
@i = 0
|
@i = 0
|
||||||
@ -84,7 +84,7 @@ module Asm
|
|||||||
io.write_uint32 val
|
io.write_uint32 val
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
class CompareInstruction < LogicInstruction
|
class CompareInstruction < Vm::CompareInstruction
|
||||||
def initialize(opcode , condition_code , update_status , args)
|
def initialize(opcode , condition_code , update_status , args)
|
||||||
super(opcode , condition_code , update_status , args)
|
super(opcode , condition_code , update_status , args)
|
||||||
@update_status_flag = 1
|
@update_status_flag = 1
|
||||||
@ -95,11 +95,12 @@ module Asm
|
|||||||
do_build args[1]
|
do_build args[1]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
class MoveInstruction < LogicInstruction
|
class MoveInstruction < Vm::MoveInstruction
|
||||||
def initialize(opcode , condition_code , update_status , args)
|
def initializ(opcode , condition_code , update_status , args)
|
||||||
super(opcode , condition_code , update_status , args)
|
super(opcode , condition_code , update_status , args)
|
||||||
@rn = reg "r0" # register zero = zero bit pattern
|
@rn = reg "r0" # register zero = zero bit pattern
|
||||||
end
|
end
|
||||||
|
|
||||||
def build
|
def build
|
||||||
do_build args[1]
|
do_build args[1]
|
||||||
end
|
end
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
require "asm/nodes"
|
require "asm/nodes"
|
||||||
require_relative "instruction"
|
require_relative "instruction"
|
||||||
|
|
||||||
module Asm
|
module Arm
|
||||||
# ADDRESSING MODE 2
|
# ADDRESSING MODE 2
|
||||||
# Implemented: immediate offset with offset=0
|
# Implemented: immediate offset with offset=0
|
||||||
class MemoryInstruction < Instruction
|
class MemoryInstruction < Vm::MemoryInstruction
|
||||||
|
|
||||||
def initialize(opcode , condition_code , update_status , args)
|
def initialize(opcode , condition_code , update_status , args)
|
||||||
super(opcode , condition_code , update_status , args)
|
super(opcode , condition_code , update_status , args)
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
require_relative "instruction"
|
require_relative "instruction"
|
||||||
|
|
||||||
module Asm
|
module Arm
|
||||||
# ADDRESSING MODE 4
|
# ADDRESSING MODE 4
|
||||||
class StackInstruction < Instruction
|
class StackInstruction < Vm::StackInstruction
|
||||||
|
|
||||||
def initialize(opcode , condition_code , update_status , args)
|
def initializ(opcode , condition_code , update_status , args)
|
||||||
super(opcode , condition_code , update_status , args)
|
super(opcode , condition_code , update_status , args)
|
||||||
@update_status_flag= 0
|
@update_status_flag= 0
|
||||||
@rn = reg "r0" # register zero = zero bit pattern
|
@rn = reg "r0" # register zero = zero bit pattern
|
||||||
|
24
lib/support/hash_attributes.rb
Normal file
24
lib/support/hash_attributes.rb
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Make hash attributes to object attributes
|
||||||
|
|
||||||
|
module Support
|
||||||
|
module HashAttributes
|
||||||
|
# map any function call to an attribute if possible
|
||||||
|
def method_missing name , *args , &block
|
||||||
|
if args.length > 1 or block_given?
|
||||||
|
puts "NO -#{args.length} BLOCK #{block_given?}"
|
||||||
|
super
|
||||||
|
else
|
||||||
|
name = name.to_s
|
||||||
|
if args.length == 1 #must be assignemnt for ir attr= val
|
||||||
|
if name.include? "="
|
||||||
|
return @attributes[name.chop] = args[0]
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return @attributes[name]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -16,7 +16,7 @@ module Vm
|
|||||||
|
|
||||||
# See Value description on how to create code/instructions
|
# See Value description on how to create code/instructions
|
||||||
|
|
||||||
class Block < Value
|
class Block < Code
|
||||||
|
|
||||||
def initialize(name)
|
def initialize(name)
|
||||||
super()
|
super()
|
||||||
@ -31,6 +31,20 @@ module Vm
|
|||||||
def verify
|
def verify
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_code(kode)
|
||||||
|
kode.at(@position)
|
||||||
|
length = kode.length
|
||||||
|
puts "length #{length}"
|
||||||
|
@position += length
|
||||||
|
@codes << kode
|
||||||
|
end
|
||||||
|
|
||||||
|
def assemble(io)
|
||||||
|
@codes.each do |obj|
|
||||||
|
obj.assemble io
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# set the next executed block after self.
|
# set the next executed block after self.
|
||||||
# why is this useful? if it's unconditional, why not merge them:
|
# why is this useful? if it's unconditional, why not merge them:
|
||||||
# So the second block can be used as a jump target. You standard loop needs a block to setup
|
# So the second block can be used as a jump target. You standard loop needs a block to setup
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
require_relative "values"
|
||||||
|
|
||||||
module Vm
|
module Vm
|
||||||
# Base class for anything that we can assemble
|
# Base class for anything that we can assemble
|
||||||
|
|
||||||
@ -9,7 +11,7 @@ module Vm
|
|||||||
# All code is position independant once assembled.
|
# All code is position independant once assembled.
|
||||||
# But for jumps and calls two passes are neccessary.
|
# But for jumps and calls two passes are neccessary.
|
||||||
# The first setting the position, the second assembling
|
# The first setting the position, the second assembling
|
||||||
class Code
|
class Code < Value
|
||||||
|
|
||||||
# just sets position to nil, so we can sell that it has not been set
|
# just sets position to nil, so we can sell that it has not been set
|
||||||
def initialize
|
def initialize
|
||||||
|
@ -5,28 +5,13 @@ module Vm
|
|||||||
|
|
||||||
#currently just holding the program in here so we can have global access
|
#currently just holding the program in here so we can have global access
|
||||||
class Context
|
class Context
|
||||||
|
# Make hash attributes to object attributes
|
||||||
|
include Support::HashAttributes
|
||||||
|
|
||||||
def initialize program
|
def initialize program
|
||||||
@attributes = {}
|
@attributes = {}
|
||||||
@attributes["program"] = program
|
@attributes["program"] = program
|
||||||
end
|
end
|
||||||
|
|
||||||
# map any function call to an attribute if possible
|
|
||||||
def method_missing name , *args , &block
|
|
||||||
if args.length > 1 or block_given?
|
|
||||||
puts "NO -#{args.length} BLOCK #{block_given?}"
|
|
||||||
super
|
|
||||||
else
|
|
||||||
name = name.to_s
|
|
||||||
if args.length == 1 #must be assignemnt for ir attr= val
|
|
||||||
if name.include? "="
|
|
||||||
return @attributes[name.chop] = args[0]
|
|
||||||
else
|
|
||||||
super
|
|
||||||
end
|
|
||||||
else
|
|
||||||
return @attributes[name]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,16 +1,11 @@
|
|||||||
|
require_relative "code"
|
||||||
|
require "support/hash_attributes"
|
||||||
module Vm
|
module Vm
|
||||||
# Instruction represent the actions that affect change on Values
|
|
||||||
# In an OO way of thinking the Value is data, Instruction the functionality
|
|
||||||
|
|
||||||
# But to allow flexibility, the value api bounces back to the machine api, so machines instantiate
|
# Because the idea of what one instruction does, does not always map one to one to real machine
|
||||||
# intructions.
|
|
||||||
|
|
||||||
# When Instructions are instantiated the create a linked list of Values and Instructions.
|
|
||||||
# So Value links to Instruction and Instruction links to Value
|
|
||||||
# Also, because the idea of what one instruction does, does not always map one to one to real machine
|
|
||||||
# instructions, and instruction may link to another instruction thus creating an arbitrary list
|
# instructions, and instruction may link to another instruction thus creating an arbitrary list
|
||||||
# to get the job (the original instruciton) done
|
# to get the job (the original instruciton) done
|
||||||
|
|
||||||
# Admittately it would be simpler just to create the (abstract) instructions and let the machine
|
# Admittately it would be simpler just to create the (abstract) instructions and let the machine
|
||||||
# encode them into what-ever is neccessary, but this approach leaves more possibility to
|
# encode them into what-ever is neccessary, but this approach leaves more possibility to
|
||||||
# optimize the actual instruction stream (not just the crystal instruction stream). Makes sense?
|
# optimize the actual instruction stream (not just the crystal instruction stream). Makes sense?
|
||||||
@ -25,10 +20,14 @@ module Vm
|
|||||||
# - Call
|
# - Call
|
||||||
|
|
||||||
# Instruction derives from Code, for the assembly api
|
# Instruction derives from Code, for the assembly api
|
||||||
class Code ; end
|
|
||||||
|
|
||||||
class Instruction < Code
|
class Instruction < Code
|
||||||
|
# Make hash attributes to object attributes
|
||||||
|
include Support::HashAttributes
|
||||||
|
|
||||||
|
def initialize options
|
||||||
|
@options = options
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class StackInstruction < Instruction
|
class StackInstruction < Instruction
|
||||||
|
@ -11,13 +11,17 @@ module Vm
|
|||||||
# * Note that register content is typed externally. Not as in mri, where int's are tagged. Floats can's
|
# * Note that register content is typed externally. Not as in mri, where int's are tagged. Floats can's
|
||||||
# be tagged and lambda should be it's own type, so tagging does not work
|
# be tagged and lambda should be it's own type, so tagging does not work
|
||||||
|
|
||||||
# Programs are created by invoking methods on subclasses of Value.
|
|
||||||
# But executable code is a sequence of Instructions and subclasses.
|
|
||||||
|
|
||||||
# A Machines main responsibility in the framework is to instantiate Instruction
|
# A Machines main responsibility in the framework is to instantiate Instruction
|
||||||
|
|
||||||
# Value functions are mapped to machines by concatenating the values class name + the methd name
|
# Value functions are mapped to machines by concatenating the values class name + the methd name
|
||||||
# Example: SignedValue.plus( value ) -> Machine.signed_plus (value )
|
# Example: SignedValue.plus( value ) -> Machine.signed_plus (value )
|
||||||
|
|
||||||
|
# Also, shortcuts are created to easily instantiate Instruction objects. The "standard" set of instructions
|
||||||
|
# (arm-influenced) provides for normal operations on a register machine,
|
||||||
|
# Example: pop -> StackInstruction.new( {:opcode => :pop}.merge(options) )
|
||||||
|
# Instructions work with options, so you can pass anything in, and the only thing the functions does
|
||||||
|
# is save you typing the clazz.new. It passes the function name as the :opcode
|
||||||
|
|
||||||
class Machine
|
class Machine
|
||||||
|
|
||||||
# hmm, not pretty but for now
|
# hmm, not pretty but for now
|
||||||
@ -32,6 +36,51 @@ module Vm
|
|||||||
# consistency in this code, but also because that is what is actually done
|
# consistency in this code, but also because that is what is actually done
|
||||||
attr_reader :status
|
attr_reader :status
|
||||||
|
|
||||||
|
|
||||||
|
# here we create the shortcuts for the "standard" instructions, see above
|
||||||
|
# Derived machines may use own instructions and define functions for them if so desired
|
||||||
|
def initialize
|
||||||
|
[:push, :pop].each do |inst|
|
||||||
|
define_instruction(inst , StackInstruction)
|
||||||
|
end
|
||||||
|
|
||||||
|
[:adc, :add, :and, :bic, :eor, :orr, :rsb, :rsc, :sbc, :sub].each do |inst|
|
||||||
|
define_instruction(inst , LogicInstruction)
|
||||||
|
end
|
||||||
|
[:mov, :mvn].each do |inst|
|
||||||
|
define_instruction(inst , MoveInstruction)
|
||||||
|
end
|
||||||
|
[:cmn, :cmp, :teq, :tst].each do |inst|
|
||||||
|
define_instruction(inst , CompareInstruction)
|
||||||
|
end
|
||||||
|
[:strb, :str , :ldrb, :ldr].each do |inst|
|
||||||
|
define_instruction(inst , MemoryInstruction)
|
||||||
|
end
|
||||||
|
[:b, :bl , :swi].each do |inst|
|
||||||
|
define_instruction(inst , CallInstruction)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_method(name, &block)
|
||||||
|
self.class.send(:define_method, name , &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def define_instruction(inst , clazz )
|
||||||
|
c_name = clazz.name
|
||||||
|
my_module = self.class.name.split("::").first
|
||||||
|
clazz_name = clazz.name.split("::").last
|
||||||
|
if(my_module != Vm )
|
||||||
|
module_class = eval("#{my_module}::#{clazz_name}") rescue nil
|
||||||
|
clazz = module_class if module_class
|
||||||
|
end
|
||||||
|
create_method(inst) do |options|
|
||||||
|
options = {} if options == nil
|
||||||
|
options[:opcode] = inst
|
||||||
|
clazz.new(options)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def self.instance
|
def self.instance
|
||||||
@@instance
|
@@instance
|
||||||
end
|
end
|
||||||
|
@ -21,8 +21,6 @@ class TestRunner < MiniTest::Test
|
|||||||
syntax = Parser::Composed.new.parse(string)
|
syntax = Parser::Composed.new.parse(string)
|
||||||
tree = Parser::Transform.new.apply(syntax)
|
tree = Parser::Transform.new.apply(syntax)
|
||||||
|
|
||||||
puts tree.to_yaml
|
|
||||||
|
|
||||||
program = Vm::Program.new "Arm"
|
program = Vm::Program.new "Arm"
|
||||||
expression = tree.to_value
|
expression = tree.to_value
|
||||||
compiled = expression.compile( program.context )
|
compiled = expression.compile( program.context )
|
||||||
@ -30,7 +28,7 @@ class TestRunner < MiniTest::Test
|
|||||||
program.wrap_as_main compiled
|
program.wrap_as_main compiled
|
||||||
puts program.to_yaml
|
puts program.to_yaml
|
||||||
program.verify
|
program.verify
|
||||||
puts program.to_yaml
|
# puts program.to_yaml
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
Loading…
x
Reference in New Issue
Block a user