diff --git a/lib/vm/instruction.rb b/lib/vm/instruction.rb index fd6db839..47f73f80 100644 --- a/lib/vm/instruction.rb +++ b/lib/vm/instruction.rb @@ -43,13 +43,27 @@ module Vm end end class LogicInstruction < Instruction + # result = left op right + # + # Logic instruction are your basic operator implementation. But unlike the (normal) code we write + # these Instructions must have "place" to write their results. Ie when you write 4 + 5 in ruby + # the result is sort of up in the air, but with Instructions the result must be assigned def initialize result , left , right , options = {} @result = result @left = left @right = right super(options) end - attr_accessor :result + # this is used to write code that looks like assignment + # So instructions can be created without the result (register) set, and this assigns where + # the reuslt after the fact, but usually in the same line + # Example (with block b, and variables int,a,b): b.int = a + b + # a + b actually creates an add instruction while the b.int= assigns the result to int + # b.add( int , a , b) is an alternative (assmbler style) way of writing the same. + def assign left + @result = left + self + end end class MathInstruction < Instruction def initialize first , options = {} diff --git a/lib/vm/values.rb b/lib/vm/values.rb index 4bbb4637..8e2d48c2 100644 --- a/lib/vm/values.rb +++ b/lib/vm/values.rb @@ -88,7 +88,10 @@ module Vm end def + other - class_for(LogicInstruction).new(nil , self , other , :opcode => :add) + class_for(LogicInstruction).new(nil , self , other , opcode: :add) + end + def - other + class_for(LogicInstruction).new(nil , self , other , opcode: :sub , update_status: 1 ) end def plus block , first , right CMachine.instance.integer_plus block , self , first , right diff --git a/test/arm/test_small_program.rb b/test/arm/test_small_program.rb index addbe479..f0094acb 100644 --- a/test/arm/test_small_program.rb +++ b/test/arm/test_small_program.rb @@ -13,15 +13,13 @@ class TestSmallProg < MiniTest::Test end def test_loop - start = Vm::Block.new("start") + s = Vm::Block.new("start").scope binding m = @program.main.scope binding r0 = Vm::Integer.new(0) m.r0 = 5 #1 - m << start - start.instance_eval do - sub :r0, :r0, 1 , :update_status => 1 #2 - bne start #3 - end + m << s + s.r0 = r0 - 1 #2 + s.bne s #3 @should = [0,176,160,227,5,0,160,227,1,0,80,226,253,255,255,26,1,112,160,227,0,0,0,239] write "loop" end