mirror of
https://github.com/safiire/n65.git
synced 2024-12-22 18:29:36 +00:00
Added the ability to do arithmetic on symbolic names :)
This commit is contained in:
parent
21af1f0bf6
commit
6b387e20df
@ -46,7 +46,7 @@ module N65
|
||||
|
||||
|
||||
####
|
||||
## Initialize with filename
|
||||
## Initialize with a byte array
|
||||
def initialize(bytes_array)
|
||||
@bytes_array = bytes_array
|
||||
end
|
||||
@ -62,7 +62,7 @@ module N65
|
||||
when Fixnum
|
||||
byte
|
||||
when String
|
||||
value = saved_assembler.symbol_table.resolve_symbol(byte)
|
||||
saved_assembler.symbol_table.resolve_symbol(byte)
|
||||
else
|
||||
fail(InvalidByteValue, byte)
|
||||
end
|
||||
|
@ -6,28 +6,28 @@ module N65
|
||||
## All the regexes used to parse in one module
|
||||
module Regexes
|
||||
## Mnemonics
|
||||
Mnemonic = '([A-Za-z]{3})'
|
||||
Branches = '(BPL|BMI|BVC|BVS|BCC|BCS|BNE|BEQ|bpl|bmi|bvc|bvs|bcc|bcs|bne|beq)'
|
||||
Mnemonic = '([A-Za-z]{3})'
|
||||
Branches = '(BPL|BMI|BVC|BVS|BCC|BCS|BNE|BEQ|bpl|bmi|bvc|bvs|bcc|bcs|bne|beq)'
|
||||
|
||||
## Numeric Literals
|
||||
Hex8 = '\$([A-Fa-f0-9]{1,2})'
|
||||
Hex16 = '\$([A-Fa-f0-9]{3,4})'
|
||||
Hex8 = '\$([A-Fa-f0-9]{1,2})'
|
||||
Hex16 = '\$([A-Fa-f0-9]{3,4})'
|
||||
|
||||
Bin8 = '%([01]{1,8})'
|
||||
Bin16 = '%([01]{9,16})'
|
||||
Bin8 = '%([01]{1,8})'
|
||||
Bin16 = '%([01]{9,16})'
|
||||
|
||||
Num8 = Regexp.union(Regexp.new(Hex8), Regexp.new(Bin8)).to_s
|
||||
Num16 = Regexp.union(Regexp.new(Hex16),Regexp.new(Bin16)).to_s
|
||||
Num8 = Regexp.union(Regexp.new(Hex8), Regexp.new(Bin8)).to_s
|
||||
Num16 = Regexp.union(Regexp.new(Hex16),Regexp.new(Bin16)).to_s
|
||||
|
||||
Immediate = "\##{Num8}"
|
||||
Immediate = "\##{Num8}"
|
||||
|
||||
## Symbols, must begin with a letter, and supports dot syntax
|
||||
Sym = '([a-zA-Z][a-zA-Z\d_\.]*)'
|
||||
Sym = '([a-zA-Z][a-zA-Z\d_\.]*(?:[\+\-\*\/]\d+)*)'
|
||||
|
||||
|
||||
## The X or Y register
|
||||
XReg = '[Xx]'
|
||||
YReg = '[Yy]'
|
||||
XReg = '[Xx]'
|
||||
YReg = '[Yy]'
|
||||
end
|
||||
|
||||
end
|
||||
|
@ -56,10 +56,30 @@ module N65
|
||||
|
||||
|
||||
####
|
||||
##
|
||||
## Separate arithmetic from scope name
|
||||
def find_arithmetic(name)
|
||||
last_name = name.split('.').last
|
||||
md = last_name.match(/([\+\-\*\/])(\d+)$/)
|
||||
f = lambda{|v| v}
|
||||
|
||||
unless md.nil?
|
||||
full_match, operator, argument = md.to_a
|
||||
name.gsub!(full_match, '')
|
||||
f = lambda {|value| value.send(operator.to_sym, argument.to_i) }
|
||||
end
|
||||
|
||||
[name, f]
|
||||
end
|
||||
|
||||
|
||||
####
|
||||
## Resolve a symbol to its value
|
||||
def resolve_symbol(name)
|
||||
name, arithmetic = find_arithmetic(name)
|
||||
|
||||
method = name.include?('.') ? :resolve_symbol_dot_syntax : :resolve_symbol_scoped
|
||||
value = self.send(method, name)
|
||||
value = arithmetic.call(value)
|
||||
|
||||
fail(UndefinedSymbol, name) if value.nil?
|
||||
value
|
||||
|
@ -1,3 +1,3 @@
|
||||
module N65
|
||||
VERSION ||= "1.1.0"
|
||||
VERSION ||= "1.5.0"
|
||||
end
|
||||
|
78
test/test_arithmetic_symbols.rb
Normal file
78
test/test_arithmetic_symbols.rb
Normal file
@ -0,0 +1,78 @@
|
||||
gem 'minitest'
|
||||
require 'minitest/autorun'
|
||||
require 'minitest/unit'
|
||||
|
||||
require_relative '../lib/n65.rb'
|
||||
|
||||
|
||||
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
|
||||
|
@ -74,7 +74,7 @@ class TestSymbolTable < MiniTest::Test
|
||||
|
||||
####
|
||||
## Test exiting a sub scope, and being able to access a symbol through a full path
|
||||
def test_exit_scope
|
||||
def test_exit_scope_full_path
|
||||
st = SymbolTable.new
|
||||
st.enter_scope('animals')
|
||||
st.define_symbol('dog', 'woof')
|
||||
|
Loading…
Reference in New Issue
Block a user