diff --git a/lib/braingasm/compiler.rb b/lib/braingasm/compiler.rb index 92791d0..076ecd4 100644 --- a/lib/braingasm/compiler.rb +++ b/lib/braingasm/compiler.rb @@ -36,19 +36,31 @@ def zero end def signed - push_prefix ->(m) { m.last_write >= 0 ? 0 : 1 } + read_cell if @prefixes.empty? + + push_prefix @prefixes.fix_params(->(n, m) { n < 0 ? 1 : 0 }) end def parity - read_cell if @prefixes.empty? - - push_prefix @prefixes.fix_params(->(n, m) { (n % 2) ^ 1 }) + if @prefixes.last.is_a?(Integer) + x = @prefixes.pop + read_cell if @prefixes.empty? + push_prefix @prefixes.fix_params(->(n, m) { n % x == 0 ? 1 : 0 }) + else + read_cell if @prefixes.empty? + push_prefix @prefixes.fix_params(->(n, m) { (n % 2) ^ 1 }) + end end def oddity - read_cell if @prefixes.empty? - - push_prefix @prefixes.fix_params(->(n, m) { n % 2 }) + if @prefixes.last.is_a?(Integer) + x = @prefixes.pop + read_cell if @prefixes.empty? + push_prefix @prefixes.fix_params(->(n, m) { n % x == 0 ? 0 : 1 }) + else + read_cell if @prefixes.empty? + push_prefix @prefixes.fix_params(->(n, m) { n % 2 }) + end end def right diff --git a/lib/braingasm/prefixes.rb b/lib/braingasm/prefixes.rb index 1595976..70a7820 100644 --- a/lib/braingasm/prefixes.rb +++ b/lib/braingasm/prefixes.rb @@ -5,7 +5,7 @@ module Braingasm class PrefixStack extend Forwardable attr_accessor :stack - def_delegators :@stack, :empty?, :<<, :pop, :==, :first + def_delegators :@stack, :empty?, :<<, :pop, :==, :first, :last def initialize @stack = [] diff --git a/lib/braingasm/version.rb b/lib/braingasm/version.rb index 321726c..1aa2018 100644 --- a/lib/braingasm/version.rb +++ b/lib/braingasm/version.rb @@ -1,3 +1,3 @@ module Braingasm - VERSION = "0.4.0" + VERSION = "0.5.0" end diff --git a/spec/compiler_spec.rb b/spec/compiler_spec.rb index a53f6f9..a60a8e5 100644 --- a/spec/compiler_spec.rb +++ b/spec/compiler_spec.rb @@ -228,29 +228,5 @@ module Braingasm end end - describe "#signed" do - before { allow(machine).to receive(:last_write).and_return(0) } - include_examples "generated prefix", :signed - include_examples "simple instruction generation", :signed, :last_write - - it "returns 1 if machine's last write instruction is negative (signed)" do - expect(machine).to receive(:last_write).and_return(-1) - - expect(subject.signed.call(machine)).to be 1 - end - - it "returns 0 if machine's last write instruction is 0 (unsigned)" do - expect(machine).to receive(:last_write).and_return(0) - - expect(subject.signed.call(machine)).to be 0 - end - - it "returns 0 if machine's last write instruction is positive (unsigned)" do - expect(machine).to receive(:last_write).and_return(1) - - expect(subject.signed.call(machine)).to be 0 - end - end - end end diff --git a/spec/features/prefixes_spec.rb b/spec/features/prefixes_spec.rb index 7de9c92..411b4a8 100644 --- a/spec/features/prefixes_spec.rb +++ b/spec/features/prefixes_spec.rb @@ -51,11 +51,27 @@ describe "s" do context "without prefix" do - it "returns 1 if the current cell is negative (signed), 0 otherwise" + it "returns 1 if the current cell is negative (signed), 0 otherwise" do + @machine.tape = [-2, -1, 0, 1, 2] + + run "s, > s, > s, > s, > s," + + expect(@machine.tape).to be == [1, 1, 0, 0, 0] + end end context "with integer prefix" do - it "checks the prefix instead" + it "returns 0 if the given prefix is zero or positive" do + run "#s, > #s," + + expect(@machine.tape[0..1]).to be == [0, 0] + end + + it "returns 1 if the given prefix is negative" do + run "< #s," + + expect(@machine.cell).to be == 1 + end end end @@ -71,12 +87,34 @@ end end - context "with integer prefix" do - it "evaulates the integer instead" do - run "7p, > 8p," + context "with prefix yielding an integer" do + it "evaulates the prefix instead" do + run "4> #p, > #p," - expect(@machine.tape[0]).to be == 0 - expect(@machine.tape[1]).to be == 1 + expect(@machine.tape[4]).to be == 1 + expect(@machine.tape[5]).to be == 0 + end + end + + context "with an integer literal prefix" do + it "returns 1 if the current cell is divisble by the given integer, 0 otherwise" do + @machine.tape = [0, 1, 2, 3] + + run "4[ 3p, > ]" + + expect(@machine.tape[0]).to be == 1 + expect(@machine.tape[1]).to be == 0 + expect(@machine.tape[2]).to be == 0 + expect(@machine.tape[3]).to be == 1 + end + end + + context "with two integer prefixes" do + it "checks the first, modulo the second" do + run "7> #4p, > #4p," + + expect(@machine.tape[7]).to be == 0 + expect(@machine.tape[8]).to be == 1 end end end @@ -93,12 +131,34 @@ end end - context "with integer prefix" do - it "evaulates the integer instead" do - run "7o, > 8o," + context "with prefix yielding an integer" do + it "evaulates the prefix instead" do + run "7> #o, > #o," - expect(@machine.tape[0]).to be == 1 - expect(@machine.tape[1]).to be == 0 + expect(@machine.tape[7]).to be == 1 + expect(@machine.tape[8]).to be == 0 + end + end + + context "with an integer literal prefix" do + it "returns 0 if the current cell is divisble by the given integer, 1 otherwise" do + @machine.tape = [0, 1, 2, 3] + + run "4[ 3o, > ]" + + expect(@machine.tape[0]).to be == 0 + expect(@machine.tape[1]).to be == 1 + expect(@machine.tape[2]).to be == 1 + expect(@machine.tape[3]).to be == 0 + end + end + + context "with two integer prefixes" do + it "checks the first, modulo the second" do + run "3> #4o, > #4o," + + expect(@machine.tape[3]).to be == 1 + expect(@machine.tape[4]).to be == 0 end end end