diff --git a/lib/n65/symbol_table.rb b/lib/n65/symbol_table.rb index 6cc2234..af7434f 100644 --- a/lib/n65/symbol_table.rb +++ b/lib/n65/symbol_table.rb @@ -54,7 +54,7 @@ module N65 scope[symbol.to_sym] = value end - # Separate arithmetic from scope name + # Separate arithmetic from symbol def find_arithmetic(name) last_name = name.split('.').last md = last_name.match(%r{([+\-*/])(\d+)$}) @@ -62,7 +62,7 @@ module N65 unless md.nil? full_match, operator, argument = md.to_a - name.gsub!(full_match, '') + name = name.gsub(full_match, '') f = ->(value) { value.send(operator.to_sym, argument.to_i) } end diff --git a/n65.gemspec b/n65.gemspec index c8ca351..f5c504d 100644 --- a/n65.gemspec +++ b/n65.gemspec @@ -22,7 +22,6 @@ Gem::Specification.new do |spec| spec.required_ruby_version = '>= 2.4.0' spec.add_development_dependency 'bundler' - spec.add_development_dependency 'minitest' spec.add_development_dependency 'rake' spec.add_development_dependency 'rubocop' spec.add_development_dependency 'rspec' diff --git a/spec/lib/n65/symbol_table_spec.rb b/spec/lib/n65/symbol_table_spec.rb index cf39650..bd9c831 100644 --- a/spec/lib/n65/symbol_table_spec.rb +++ b/spec/lib/n65/symbol_table_spec.rb @@ -203,7 +203,7 @@ RSpec.describe(N65::SymbolTable) do 0xea, # NOP 0xea, # NOP 0xea, # NOP - 0x60 # RTS forward_symbol + 0x60 # RTS ] end let(:emitted_rom) { assembler.emit_binary_rom.bytes[16...26] } @@ -214,4 +214,78 @@ RSpec.describe(N65::SymbolTable) do expect(emitted_rom).to eq(correct_binary) end end + + context 'when setting a symbols value' do + before do + subject.define_symbol('variable', 0xff) + end + + it 'can resolve to that value' do + expect(subject.resolve_symbol('variable')).to eq(0xff) + end + end + + context 'when performing artithmetic on a symbol' do + before do + subject.define_symbol('variable', 0x20) + end + + it 'can perform addition on the symbol' do + expect(subject.resolve_symbol('variable+1')).to eq(0x21) + end + + it 'can perform subtraction on the symbol' do + expect(subject.resolve_symbol('variable-16')).to eq(0x10) + end + + it 'can perform multiplication on the symbol' do + expect(subject.resolve_symbol('variable*2')).to eq(0x40) + end + + it 'can perform division on the symbol' do + expect(subject.resolve_symbol('variable/2')).to eq(0x10) + end + end + + context 'when performing arithmetic on a scope struct' do + let(:assembler) { N65::Assembler.new } + let(:program) do + <<~'ASM' + .ines {"prog": 1, "char": 0, "mapper": 0, "mirror": 0} + + .org $0020 + .scope struct + .space a 1 + .space b 1 + . + + .org $8000 + .scope main + sei + cld + lda struct+1 zp + lda struct*2 zp + rts + . + ASM + end + let(:emitted_rom) { assembler.emit_binary_rom.bytes[16...23] } + let(:correct_binary) do + [ + 0x78, # sei + 0xd8, # cld + 0xa5, # lda + 0x21, # $20 + 1 + 0xa5, # lda + 0x40, # $20 * 2 + 0x60 # rts + ] + end + + before { assembler.assemble_string(program) } + + it 'assembles the symbol arithmetic correctly' do + expect(emitted_rom).to eq(correct_binary) + end + end end diff --git a/test/test_arithmetic_symbols.rb b/test/test_arithmetic_symbols.rb deleted file mode 100644 index d30eaea..0000000 --- a/test/test_arithmetic_symbols.rb +++ /dev/null @@ -1,69 +0,0 @@ -gem 'minitest' -require 'minitest/autorun' -require 'minitest/unit' -require_relative '../lib/n65' - -class TestArithmeticSymbols < MiniTest::Test - include N65 - - def test_identify_plain_symbol - re = Regexp.new(Regexes::Sym) - assert_match(re, 'dog') - assert_match(re, 'animal.dog') - assert_match(re, 'global.animal.dog') - end - - def test_symbol_values - st = SymbolTable.new - st.define_symbol('variable', 0xff) - assert_equal(0xff, st.resolve_symbol('variable')) - end - - def test_perform_symbolic_arithmetic - st = SymbolTable.new - st.define_symbol('variable', 0x20) - assert_equal(0x21, st.resolve_symbol('variable+1')) - assert_equal(0x40, st.resolve_symbol('variable*2')) - end - - def test_symbol_addition - program = <<-ASM - .ines {"prog": 1, "char": 0, "mapper": 0, "mirror": 0} - - .org $0020 - .scope struct - .space a 1 - .space b 1 - . - - .org $8000 - .scope main - sei - cld - lda struct+1 zp - lda struct*2 zp - rts - . - ASM - - assembler = Assembler.new - program.split(/\n/).each do |line| - assembler.assemble_one_line(line) - end - assembler.fulfill_promises - - binary = assembler.emit_binary_rom[16...23].split(//).map(&:ord) - - ## So yay, arithmetic on symbols works now :) - correct = [ - 0x78, # sei - 0xd8, # cld - 0xa5, # lda - 0x21, # $20 + 1 - 0xa5, # lda - 0x40, # $20 * 2 - 0x60 # rts - ] - assert_equal(binary, correct) - end -end