-
Notifications
You must be signed in to change notification settings - Fork 0
/
errors.go
144 lines (126 loc) · 4.37 KB
/
errors.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//
// Copyright 2012 Nathan Fiedler. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
package core
import (
"errors"
"fmt"
)
var NumberOutOfRange = errors.New("number value of out range")
var InvalidUtf8String = errors.New("input contains invalid UTF-8 bytes")
var OutOfBounds = errors.New("index out of bounds")
var StringIsImmutable = errors.New("immutable string cannot be set!")
var ParserError = errors.New("unexpected parser error")
var TypeMismatch = errors.New("type mismatch in atom comparison")
var BadMagicNumber = errors.New("magic number does not match")
var BadCodeVersion = errors.New("byte code version not supported")
var UnknownType = errors.New("unknown type, cannot serialize")
// ErrorCode indicates the error status of the Scheme evaluation, with EOK
// representing no error.
type ErrorCode int
// Error constants
const (
EOK ErrorCode = iota // no error
EARGUMENT // e.g. illegal, missing
ECOMMAND // e.g. undefined, unsupported, unknown
ESUPPORT // feature unsupported
ESYNTAX // e.g. invalid number syntax
ESYMBOL // e.g. undefined
ELEXER // lexer error
EIO // I/O error
EINTERNAL // something bad happened
)
// Locatable is any Scheme element whose location within the parsed text is
// known, and is defined by the (1-based) row and column of the input text.
type Locatable interface {
// Location returns the row and column (1-based) of the element.
Location() (int, int)
}
// LispError is used to provide information on the type of error that occurred
// while parsing or evaluating the Lisp script. It implements the error
// interface.
type LispError interface {
error
Locatable
// ErrorCode returns the error code associated with this result.
ErrorCode() ErrorCode
// ErrorMessage returns the error message associated with this result.
ErrorMessage() string
// Ok indicates if the result is a non-error, indicating that
// the result is suitable for consumption.
Ok() bool
// String returns a human readable error message.
String() string
// SetLocation may be used to specify where in the text the error was found.
SetLocation(row, col int)
}
// lispError is an implemention of the LispError interface.
type lispError struct {
ecode ErrorCode
errmsg string
row int
col int
}
// NewLispError creates a new LispError based on the given values.
func NewLispError(err ErrorCode, msg string) LispError {
return &lispError{err, msg, -1, -1}
}
// NewLispErrorf creates a new LispError, formatting the message according
// to the given format and optional arguments.
func NewLispErrorf(err ErrorCode, form string, args ...interface{}) LispError {
detail := fmt.Sprintf(form, args...)
return NewLispError(err, detail)
}
// NewLispErrorl returns a LispError of the given type, for the selected
// element, with the clarifying message. If the element has location
// information, it will be incorporated into the error message.
func NewLispErrorl(err ErrorCode, elem interface{}, msg string) LispError {
str := stringify(elem)
result := NewLispError(err, msg+": "+str)
if le, ok := elem.(Locatable); ok {
result.SetLocation(le.Location())
}
return result
}
// Returns the error portion of this result in string form.
func (e *lispError) Error() string {
return e.String()
}
// Error returns the error code, or EOK if undefined.
func (e *lispError) ErrorCode() ErrorCode {
if e != nil {
return e.ecode
}
return EOK
}
// ErrorMessage returns the error message, if any.
func (e *lispError) ErrorMessage() string {
if e != nil {
return e.errmsg
}
return ""
}
// Location returns the location of the error within the parsed text.
// The values will be -1 if undefined.
func (e *lispError) Location() (int, int) {
return e.row, e.col
}
// SetLocation sets the location information for this error.
func (e *lispError) SetLocation(row, col int) {
e.row = row
e.col = col
}
// Ok returns true if the error code is EOK, false otherwise.
func (e *lispError) Ok() bool {
return e == nil || e.ecode == EOK
}
// String returns a human readable form of the result.
func (e *lispError) String() string {
if e == nil || e.Ok() {
return "(no error)"
}
// Would be nice to print code as text
return fmt.Sprintf("ERR-%04d: %s", int(e.ecode), e.errmsg)
}