summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2018-09-23 07:21:57 +0200
committerDimitri Sokolyuk <demon@dim13.org>2018-09-23 07:21:57 +0200
commit77efe0fa4e9c6c485421cc7950c9853e30faab49 (patch)
treea433dc8efdeb4f2ae72824fa37246a2a52ab92d8
parent3083cf2e33daa94af7fc8ee89fe82501cc878782 (diff)
collect errors
-rw-r--r--go/forth/forth.go38
1 files changed, 22 insertions, 16 deletions
diff --git a/go/forth/forth.go b/go/forth/forth.go
index e9a32da..9bfba42 100644
--- a/go/forth/forth.go
+++ b/go/forth/forth.go
@@ -2,11 +2,18 @@ package forth
import (
"errors"
- "io"
"strconv"
"strings"
)
+var (
+ ErrEOL = errors.New("end of line")
+ ErrStack = errors.New("stack underflow")
+ ErrZero = errors.New("division by zero")
+ ErrWord = errors.New("name cannot be a number")
+ ErrUnknown = errors.New("unknown word")
+)
+
type stack []int
func (s *stack) push(n ...int) error {
@@ -17,7 +24,7 @@ func (s *stack) push(n ...int) error {
func (s *stack) pop() (int, error) {
depth := len(*s)
if depth < 1 {
- return 0, errors.New("stack underflow")
+ return 0, ErrStack
}
tos := (*s)[depth-1]
*s = (*s)[:depth-1]
@@ -83,7 +90,7 @@ func div(s *stack) error {
return err
}
if tos == 0 {
- return errors.New("division by zero")
+ return ErrZero
}
return s.push(nos / tos)
}
@@ -134,7 +141,7 @@ func colon(dict dictionary, l *lexer) error {
return err
}
if _, ok := number(name); ok {
- return errors.New("name cannot be a number")
+ return ErrWord
}
w, err := compile(dict, l)
if err != nil {
@@ -148,7 +155,7 @@ func compile(dict dictionary, l *lexer) ([]word, error) {
var words []word
for {
v, err := l.Next()
- if err == io.EOF {
+ if err == ErrEOL {
return words, nil
}
// colon operator
@@ -171,7 +178,7 @@ func compile(dict dictionary, l *lexer) ([]word, error) {
words = append(words, literal(n))
continue
}
- return nil, errors.New("unknown word")
+ return nil, ErrUnknown
}
}
@@ -186,7 +193,7 @@ func NewLexer(line string) *lexer {
func (l *lexer) Next() (string, error) {
if l.pos >= len(l.fields) {
- return "", io.EOF
+ return "", ErrEOL
}
s := l.fields[l.pos]
l.pos++
@@ -203,19 +210,18 @@ func Forth(v []string) ([]int, error) {
dict.add("drop", drop)
dict.add("swap", swap)
dict.add("over", over)
- var words []word
+ s := new(stack)
for _, line := range v {
- l := NewLexer(line)
- w, err := compile(dict, l)
+ // compile
+ words, err := compile(dict, NewLexer(line))
if err != nil {
return nil, err
}
- words = append(words, w...)
- }
- s := new(stack)
- for _, w := range words {
- if err := w(s); err != nil {
- return nil, err
+ // execute
+ for _, w := range words {
+ if err := w(s); err != nil {
+ return nil, err
+ }
}
}
return s.values(), nil