1
0
mirror of https://github.com/zellyn/go6502.git synced 2025-01-15 06:30:28 +00:00
go6502/asm/context/context.go
2014-08-19 08:22:34 -07:00

188 lines
3.9 KiB
Go

package context
import "fmt"
type Context interface {
Set(name string, value uint16)
Get(name string) (uint16, bool)
SetAddr(uint16)
GetAddr() (uint16, bool)
DivZero() (uint16, error)
RemoveChanged()
Clear()
SettingOn(name string) error
SettingOff(name string) error
Setting(name string) bool
HasSetting(name string) bool
AddMacroName(name string)
HasMacroName(name string) bool
PushMacroCall(name string, number int, locals map[string]bool)
PopMacroCall() bool
GetMacroCall() (string, int, map[string]bool)
LastLabel() string
SetLastLabel(label string)
}
type macroCall struct {
name string
number int
locals map[string]bool
}
type SimpleContext struct {
symbols map[string]symbolValue
addr int32
lastLabel string
highbit byte // OR-mask for ASCII high bit
onOff map[string]bool
onOffDefaults map[string]bool
macroNames map[string]bool
macroCalls []macroCall
}
type symbolValue struct {
v uint16
changed bool // Did the value ever change?
}
func (sc *SimpleContext) fix() {
if sc.symbols == nil {
sc.symbols = make(map[string]symbolValue)
}
}
func (sc *SimpleContext) DivZero() (uint16, error) {
return 0, fmt.Errorf("Not implemented: context.SimpleContext.DivZero()")
}
func (sc *SimpleContext) Get(name string) (uint16, bool) {
if name == "*" {
return sc.GetAddr()
}
sc.fix()
s, found := sc.symbols[name]
return s.v, found
}
func (sc *SimpleContext) SetAddr(addr uint16) {
sc.addr = int32(addr)
}
func (sc *SimpleContext) GetAddr() (uint16, bool) {
if sc.addr == -1 {
return 0, false
}
return uint16(sc.addr), true
}
func (sc *SimpleContext) Set(name string, value uint16) {
sc.fix()
s, found := sc.symbols[name]
if found && s.v != value {
s.changed = true
}
s.v = value
sc.symbols[name] = s
}
func (sc *SimpleContext) RemoveChanged() {
sc.fix()
for n, s := range sc.symbols {
if s.changed {
delete(sc.symbols, n)
}
}
}
func (sc *SimpleContext) Clear() {
sc.symbols = make(map[string]symbolValue)
sc.highbit = 0x00
sc.macroNames = nil
sc.resetOnOff()
}
func (sc *SimpleContext) SettingOn(name string) error {
if !sc.HasSetting(name) {
return fmt.Errorf("no settable variable named '%s'", name)
}
if sc.onOff == nil {
sc.onOff = map[string]bool{name: true}
} else {
sc.onOff[name] = true
}
return nil
}
func (sc *SimpleContext) SettingOff(name string) error {
if !sc.HasSetting(name) {
return fmt.Errorf("no settable variable named '%s'", name)
}
if sc.onOff == nil {
sc.onOff = map[string]bool{name: false}
} else {
sc.onOff[name] = false
}
return nil
}
func (sc *SimpleContext) Setting(name string) bool {
return sc.onOff[name]
}
func (sc *SimpleContext) HasSetting(name string) bool {
_, ok := sc.onOff[name]
return ok
}
func (sc *SimpleContext) AddMacroName(name string) {
if sc.macroNames == nil {
sc.macroNames = make(map[string]bool)
}
sc.macroNames[name] = true
}
func (sc *SimpleContext) HasMacroName(name string) bool {
return sc.macroNames[name]
}
func (sc *SimpleContext) resetOnOff() {
sc.onOff = make(map[string]bool)
for k, v := range sc.onOffDefaults {
sc.onOff[k] = v
}
}
func (sc *SimpleContext) SetOnOffDefaults(defaults map[string]bool) {
sc.onOffDefaults = defaults
sc.resetOnOff()
}
func (sc *SimpleContext) PushMacroCall(name string, number int, locals map[string]bool) {
sc.macroCalls = append(sc.macroCalls, macroCall{name, number, locals})
}
func (sc *SimpleContext) PopMacroCall() bool {
if len(sc.macroCalls) == 0 {
return false
}
sc.macroCalls = sc.macroCalls[0 : len(sc.macroCalls)-1]
return true
}
func (sc *SimpleContext) GetMacroCall() (string, int, map[string]bool) {
if len(sc.macroCalls) == 0 {
return "", 0, nil
}
mc := sc.macroCalls[len(sc.macroCalls)-1]
return mc.name, mc.number, mc.locals
}
func (sc *SimpleContext) LastLabel() string {
return sc.lastLabel
}
func (sc *SimpleContext) SetLastLabel(l string) {
sc.lastLabel = l
}