1
0
mirror of https://github.com/safiire/n65.git synced 2025-03-03 01:30:07 +00:00

I made it so starting a named scope serves the dual purpose of creating a symbolic reference to the current PC

This commit is contained in:
Safiire 2015-03-05 16:53:55 -08:00
parent 4edbff55a5
commit 8f2500dd60
4 changed files with 52 additions and 11 deletions

View File

@ -25,9 +25,14 @@ module Assembler6502
####
## Execute on the assembler
## Execute on the assembler, also create a symbol referring to
## the current pc which contains a hyphen, and is impossible for
## the user to create. This makes a scope simultaneously act as
## a label to the current PC. If someone tries to use a scope
## name as a label, it can return the address when the scope opened.
def exec(assembler)
assembler.symbol_table.enter_scope(@name)
assembler.symbol_table.define_symbol("-#{@name}", assembler.program_counter)
end

View File

@ -1,3 +1,4 @@
module Assembler6502
class SymbolTable
@ -61,15 +62,22 @@ module Assembler6502
## To go backwards in scope you need to write the full path
## like global.sprite.x or whatever
def resolve_symbol(name)
value = if name.include?('.')
path_ary = name.split('.').map(&:to_sym)
symbol = path_ary.pop
path_ary.shift if path_ary.first == :global
scope = retreive_scope(path_ary)
scope[symbol]
## We also try to look up the address associated with the scope
root = "-#{symbol}".to_sym
v = scope[symbol]
v.kind_of?(Hash) ? v[root] : v
else
root = "-#{name}".to_sym
scope = current_scope
scope[name.to_sym]
## We also try to look up the address associated with the scope
v = scope[name.to_sym] || scope[root]
v.kind_of?(Hash) ? v[root] : v
end
if value.nil?

View File

@ -7,10 +7,9 @@
.segment prog 0
.org $8000
.scope yay
main:
sei
cld
.scope main
sei
cld
loop:
ldx $00
inx
@ -27,5 +26,5 @@ irq:
.org $FFFA
.dw vblank
.dw yay.main
.dw main
.dw irq

View File

@ -3,6 +3,7 @@ require 'minitest/autorun'
require 'minitest/unit'
require_relative '../lib/symbol_table.rb'
require_relative '../lib/assembler.rb'
class TestSymbolTable < MiniTest::Test
@ -10,7 +11,7 @@ class TestSymbolTable < MiniTest::Test
####
## Test that we can make simple global symbols
def _test_define_global_symbols
def test_define_global_symbols
st = SymbolTable.new
st.define_symbol('dog', 'woof')
assert_equal('woof', st.resolve_symbol('dog'))
@ -19,7 +20,7 @@ class TestSymbolTable < MiniTest::Test
####
## Test entering into a sub scope, and setting and retrieving values
def _test_enter_scope
def test_enter_scope
st = SymbolTable.new
st.enter_scope('animals')
st.define_symbol('dog', 'woof')
@ -29,7 +30,7 @@ class TestSymbolTable < MiniTest::Test
####
## Test exiting a sub scope, and seeing that the variable is unavailable by simple name
def _test_exit_scope
def test_exit_scope
st = SymbolTable.new
st.enter_scope('animals')
st.define_symbol('dog', 'woof')
@ -124,5 +125,33 @@ class TestSymbolTable < MiniTest::Test
end
end
####
## I would like the name of the scope to take on the
## value of the program counter at that location.
def test_scope_as_symbol
program = <<-ASM
.ines {"prog": 1, "char": 0, "mapper": 0, "mirror": 0}
.org $8000
.segment prog 0
.scope main
sei
cld
lda \#$00
jmp main
.
jmp main
jmp global.main
ASM
#### There really should be an evaluate string method
assembler = Assembler.new
program.split(/\n/).each do |line|
assembler.assemble_one_line(line)
end
assembler.fulfill_promises
assert_equal(0x8000, assembler.symbol_table.resolve_symbol('global.main'))
end
end