From d7cdfcfe618858bb2bea79fec060d0699da8dd10 Mon Sep 17 00:00:00 2001 From: steve Date: Sat, 21 Dec 2019 20:32:09 +0000 Subject: [PATCH] o errors - removed ErrorID, using the error message as the ID - works just as well and simplifies maintenance - the messages should be moved to the relevant packages OR to a locale package. not sure which yet. --- debugger/inputloop.go | 2 +- disassembly/flow.go | 2 +- errors/categories.go | 120 ------------------------------------ errors/errors.go | 28 ++++----- errors/errors_test.go | 22 +++++++ errors/messages.go | 129 ++++++++++++++++++++------------------- hardware/cpu/cpu_test.go | 2 +- patch/doc.go | 0 patch/patch.go | 0 regression/playback.go | 2 +- 10 files changed, 104 insertions(+), 203 deletions(-) delete mode 100644 errors/categories.go create mode 100644 errors/errors_test.go create mode 100644 patch/doc.go create mode 100644 patch/patch.go diff --git a/debugger/inputloop.go b/debugger/inputloop.go index de1a1e40..b1baccc6 100644 --- a/debugger/inputloop.go +++ b/debugger/inputloop.go @@ -164,7 +164,7 @@ func (dbg *Debugger) inputLoop(inputter terminal.Input, videoCycle bool) error { // we now know the we have an Atari Error so we can safely // switch on the internal Errno - switch err.(errors.AtariError).Errno { + switch err.(errors.AtariError).Head { // user interrupts are triggered by the user (in a terminal // environment, usually by pressing ctrl-c) diff --git a/disassembly/flow.go b/disassembly/flow.go index 9c75fb20..e03d5a5f 100644 --- a/disassembly/flow.go +++ b/disassembly/flow.go @@ -18,7 +18,7 @@ func (dsm *Disassembly) flowDisassembly(mc *cpu.CPU) error { return err } - switch err.(errors.AtariError).Errno { + switch err.(errors.AtariError).Head { case errors.ProgramCounterCycled: // originally, a cycled program counter caused the // disassembly to end but thinking about it a bit more, diff --git a/errors/categories.go b/errors/categories.go deleted file mode 100644 index 82a6223e..00000000 --- a/errors/categories.go +++ /dev/null @@ -1,120 +0,0 @@ -package errors - -// list of error numbers -const ( - // PanicErrors should be used only as an alternative to panic(). that is - // errors where there is no good response beyond suggesting that a terrible - // mistake has been made. PanicErrors should be treated like actual - // panic()s and cause the program (or the sub-system) to cease as soon as - // possible. - // - // if is not practical to cause the program to cease then at the very - // least, the PanicError should result in the display of the error message - // in big, friendly letters. - // - // actual panic()s should only be used when the mistake is so heinous that - // it suggests a fundamental misunderstanding has taken place and so, as it - // were, all bets are off. - PanicError Errno = iota - - // sentinal - UserInterrupt - UserSuspend - ScriptEnd - PowerOff - InputDeviceUnplugged - TVOutOfSpec - - // program modes - PlayError - DebuggerError - PerformanceError - DisassemblyError - - // debugger - ParserError - ValidationError - InvalidTarget - CommandError - TerminalError - GUIEventError - ReflectionNotRunning - - // disassembly - DisasmError - - // script - ScriptScribeError - ScriptFileUnavailable - ScriptFileError - ScriptRunError - - // recorder - RecordingError - PlaybackError - PlaybackHashError - - // database - DatabaseError - DatabaseReadError - DatabaseSelectEmpty - DatabaseKeyError - DatabaseFileUnavailable - - // regression - RegressionError - RegressionDigestError - RegressionPlaybackError - - // setup - SetupError - SetupPanelError - - // symbols - SymbolsFileUnavailable - SymbolsFileError - SymbolUnknown - - // cartridgeloader - CartridgeLoader - - // vcs - VCSError - PolycounterError - - // cpu - UnimplementedInstruction - InvalidResult - ProgramCounterCycled - InvalidOperationMidInstruction - - // memory - MemoryError - UnreadableAddress - UnwritableAddress - UnpokeableAddress - UnpeekableAddress - - // cartridges - CartridgeError - CartridgeEjected - - // input - InputDeviceUnavailable - UnknownInputEvent - - // tv - UnknownTVRequest - Television - - // digests - VideoDigest - AudioDigest - - // wavwriter - WavWriter - - // gui - UnsupportedGUIRequest - SDL -) diff --git a/errors/errors.go b/errors/errors.go index bb67e779..a6bee1ed 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -5,23 +5,20 @@ import ( "strings" ) -// Errno is used specified the specific error -type Errno int - // Values is the type used to specify arguments for FormattedErrors type Values []interface{} // AtariError allows code to specify a predefined error and not worry too much about the // message behind that error and how the message will be formatted on output. type AtariError struct { - Errno Errno + Head string Values Values } // New is used to create a new instance of an AtariError. -func New(errno Errno, values ...interface{}) AtariError { +func New(head string, values ...interface{}) AtariError { return AtariError{ - Errno: errno, + Head: head, Values: values, } } @@ -29,7 +26,7 @@ func New(errno Errno, values ...interface{}) AtariError { // Error returns the normalised error message. Most usefully, it compresses // duplicate adjacent AtariError instances. func (er AtariError) Error() string { - s := fmt.Sprintf(messages[er.Errno], er.Values...) + s := fmt.Sprintf(er.Head, er.Values...) // de-duplicate error message parts p := strings.SplitN(s, ": ", 3) @@ -40,16 +37,17 @@ func (er AtariError) Error() string { return strings.Join(p, ": ") } -// Is checks if most recently wrapped error is an AtariError with a specific errno -func Is(err error, errno Errno) bool { +// Is checks if most recently wrapped error is an AtariError with a specific +// head +func Is(err error, head string) bool { switch er := err.(type) { case AtariError: - return er.Errno == errno + return er.Head == head } return false } -// IsAny checks if most recently wrapped error is an AtariError, with any errno +// IsAny checks if most recently wrapped error is an AtariError, with any head func IsAny(err error) bool { switch err.(type) { case AtariError: @@ -58,16 +56,16 @@ func IsAny(err error) bool { return false } -// Has checks to see if the specified AtariError errno appears somewhere in the +// Has checks to see if the specified AtariError head appears somewhere in the // sequence of wrapped errors -func Has(err error, errno Errno) bool { - if Is(err, errno) { +func Has(err error, head string) bool { + if Is(err, head) { return true } for i := range err.(AtariError).Values { if e, ok := err.(AtariError).Values[i].(error); ok { - if Has(e, errno) { + if Has(e, head) { return true } } diff --git a/errors/errors_test.go b/errors/errors_test.go new file mode 100644 index 00000000..18f2a2dd --- /dev/null +++ b/errors/errors_test.go @@ -0,0 +1,22 @@ +package errors_test + +import ( + "fmt" + "gopher2600/errors" + "testing" +) + +func TestError(t *testing.T) { + e := errors.New(errors.SetupError, "foo") + if e.Error() != "setup error: foo" { + t.Errorf("unexpected error message") + } + + // packing errors of the same type next to each other causes + // one of them to be dropped + f := errors.New(errors.SetupError, e) + fmt.Println(f.Error()) + if f.Error() != "setup error: foo" { + t.Errorf("unexpected duplicate error message") + } +} diff --git a/errors/messages.go b/errors/messages.go index b6d607af..4fc7bc9d 100644 --- a/errors/messages.go +++ b/errors/messages.go @@ -1,107 +1,108 @@ package errors -var messages = map[Errno]string{ +// error messages +const ( // panics - PanicError: "panic: %v: %v", + PanicError = "panic: %v: %v" // sentinals - UserInterrupt: "user interrupt", - UserSuspend: "user suspend", - ScriptEnd: "end of script (%v)", - PowerOff: "emulated machine has been powered off", - InputDeviceUnplugged: "controller unplugged from %v", - TVOutOfSpec: "tv out of spec: %v", + UserInterrupt = "user interrupt" + UserSuspend = "user suspend" + ScriptEnd = "end of script (%v)" + PowerOff = "emulated machine has been powered off" + InputDeviceUnplugged = "controller unplugged from %v" + TVOutOfSpec = "tv out of spec: %v" // program modes - PlayError: "error emulating vcs: %v", - DebuggerError: "error debugging vcs: %v", - PerformanceError: "error during performance profiling: %v", - DisassemblyError: "error debugging disassembly: %v", + PlayError = "error emulating vcs: %v" + DebuggerError = "error debugging vcs: %v" + PerformanceError = "error during performance profiling: %v" + DisassemblyError = "error debugging disassembly: %v" // debugger - ParserError: "parser error: %v: %v (char %d)", // first placeholder is the command definition - ValidationError: "%v for %v", - InvalidTarget: "invalid target (%v)", - CommandError: "%v", - TerminalError: "%v", - GUIEventError: "%v", - ReflectionNotRunning: "reflection process is not running", + ParserError = "parser error: %v: %v (char %d)" // first placeholder is the command definition + ValidationError = "%v for %v" + InvalidTarget = "invalid target (%v)" + CommandError = "%v" + TerminalError = "%v" + GUIEventError = "%v" + ReflectionNotRunning = "reflection process is not running" // dissassembly - DisasmError: "disassembly error: %v", + DisasmError = "disassembly error: %v" // script - ScriptFileError: "script error: %v", - ScriptFileUnavailable: "script error: cannot open script file (%v)", - ScriptRunError: "script error: use of '%v' is not allowed in scripts [%v::%d]", - ScriptScribeError: "script scribe error: %v", + ScriptFileError = "script error: %v" + ScriptFileUnavailable = "script error: cannot open script file (%v)" + ScriptRunError = "script error: use of '%v' is not allowed in scripts [%v::%d]" + ScriptScribeError = "script scribe error: %v" // recorder - RecordingError: "controller recording error: %v", - PlaybackError: "controller playback error: %v", - PlaybackHashError: "controller playback error: hash error: %v", + RecordingError = "controller recording error: %v" + PlaybackError = "controller playback error: %v" + PlaybackHashError = "controller playback error: hash error: %v" // database - DatabaseError: "database error: %v", - DatabaseReadError: "datbase error: %v [line %d]", - DatabaseSelectEmpty: "database error: no selected entries", - DatabaseKeyError: "database error: no such key in database [%v]", - DatabaseFileUnavailable: "database error: cannot open database (%v)", + DatabaseError = "database error: %v" + DatabaseReadError = "datbase error: %v [line %d]" + DatabaseSelectEmpty = "database error: no selected entries" + DatabaseKeyError = "database error: no such key in database [%v]" + DatabaseFileUnavailable = "database error: cannot open database (%v)" // regression - RegressionError: "regression test error: %v", - RegressionDigestError: "digest entry: %v", - RegressionPlaybackError: "playback entry: %v", + RegressionError = "regression test error: %v" + RegressionDigestError = "digest entry: %v" + RegressionPlaybackError = "playback entry: %v" // setup - SetupError: "setup error: %v", - SetupPanelError: "setup error: panel entry: %v", + SetupError = "setup error: %v" + SetupPanelError = "setup error: panel entry: %v" // symbols - SymbolsFileError: "symbols error: error processing symbols file: %v", - SymbolsFileUnavailable: "symbols error: no symbols file for %v", - SymbolUnknown: "symbols error: unrecognised symbol (%v)", + SymbolsFileError = "symbols error: error processing symbols file: %v" + SymbolsFileUnavailable = "symbols error: no symbols file for %v" + SymbolUnknown = "symbols error: unrecognised symbol (%v)" // cartridgeloader - CartridgeLoader: "cartridge loading error: %v", + CartridgeLoader = "cartridge loading error: %v" // vcs - VCSError: "vcs error: %v", - PolycounterError: "polycounter error: %v", + VCSError = "vcs error: %v" + PolycounterError = "polycounter error: %v" // cpu - UnimplementedInstruction: "cpu error: unimplemented instruction (%#02x) at (%#04x)", - InvalidResult: "cpu error: %v", - ProgramCounterCycled: "cpu error: program counter cycled back to 0x0000", - InvalidOperationMidInstruction: "cpu error: invalid operation mid-instruction (%v)", + UnimplementedInstruction = "cpu error: unimplemented instruction (%#02x) at (%#04x)" + InvalidResult = "cpu error: %v" + ProgramCounterCycled = "cpu error: program counter cycled back to 0x0000" + InvalidOperationMidInstruction = "cpu error: invalid operation mid-instruction (%v)" // memory - MemoryError: "memory error: %v", - UnreadableAddress: "memory error: memory location is not readable (%#04x)", - UnwritableAddress: "memory error: memory location is not writable (%#04x)", - UnpokeableAddress: "memory error: cannot poke address (%v)", - UnpeekableAddress: "memory error: cannot peek address (%v)", + MemoryError = "memory error: %v" + UnreadableAddress = "memory error: memory location is not readable (%#04x)" + UnwritableAddress = "memory error: memory location is not writable (%#04x)" + UnpokeableAddress = "memory error: cannot poke address (%v)" + UnpeekableAddress = "memory error: cannot peek address (%v)" // cartridges - CartridgeError: "cartridge error: %v", - CartridgeEjected: "cartridge error: no cartridge attached", + CartridgeError = "cartridge error: %v" + CartridgeEjected = "cartridge error: no cartridge attached" // input - InputDeviceUnavailable: "input error: controller hardware unavailable (%v)", - UnknownInputEvent: "input error: %v: unsupported event (%v)", + InputDeviceUnavailable = "input error: controller hardware unavailable (%v)" + UnknownInputEvent = "input error: %v: unsupported event (%v)" // television - UnknownTVRequest: "television error: unsupported request (%v)", - Television: "television error: %v", + UnknownTVRequest = "television error: unsupported request (%v)" + Television = "television error: %v" // digests - VideoDigest: "video digest: %v", - AudioDigest: "audio digest: %v", + VideoDigest = "video digest: %v" + AudioDigest = "audio digest: %v" // audio2wav - WavWriter: "wav writer: %v", + WavWriter = "wav writer: %v" // gui - UnsupportedGUIRequest: "gui error: unsupported request (%v)", - SDL: "SDL: %v", -} + UnsupportedGUIRequest = "gui error: unsupported request (%v)" + SDL = "SDL: %v" +) diff --git a/hardware/cpu/cpu_test.go b/hardware/cpu/cpu_test.go index a244df18..4413cd2d 100644 --- a/hardware/cpu/cpu_test.go +++ b/hardware/cpu/cpu_test.go @@ -576,7 +576,7 @@ func testStrictAddressing(t *testing.T, mc *cpu.CPU, mem *mockMem) { if err == nil { t.Fatalf("not recieved an UnreadableAddress error when we should") } - if err.(errors.AtariError).Errno == errors.UnreadableAddress { + if err.(errors.AtariError).Head == errors.UnreadableAddress { // this is okay } else { t.Fatalf("error during CPU step (%v)\n", err) diff --git a/patch/doc.go b/patch/doc.go new file mode 100644 index 00000000..e69de29b diff --git a/patch/patch.go b/patch/patch.go new file mode 100644 index 00000000..e69de29b diff --git a/regression/playback.go b/regression/playback.go index 6cbbf48e..8df47913 100644 --- a/regression/playback.go +++ b/regression/playback.go @@ -148,7 +148,7 @@ func (reg *PlaybackRegression) regress(newRegression bool, output io.Writer, msg return false, "", errors.New(errors.RegressionPlaybackError, err) } - switch err.(errors.AtariError).Errno { + switch err.(errors.AtariError).Head { // the PowerOff error is expected. if we receive it then that means // the regression test has succeeded case errors.PowerOff: