-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.go
143 lines (123 loc) · 3.03 KB
/
utils.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
package gmnlisp
import (
"context"
"errors"
"fmt"
"io"
"github.com/hymkor/gmnlisp/pkg/parser"
)
var (
ErrDevisionByZero = errors.New("devision by zeor")
ErrExpectedCharacter = errors.New("expected character")
ErrExpectedCons = errors.New("expected CONS")
ErrExpectedFunction = errors.New("expected function")
ErrExpectedNumber = errors.New("expected number")
ErrExpectedReader = errors.New("expected Reader")
ErrExpectedSequence = errors.New("expected Sequence")
ErrExpectedString = errors.New("expected string")
ErrExpectedSymbol = errors.New("expected symbol")
ErrExpectedSymbolOrList = errors.New("expected symbol or list")
ErrExpectedKeyword = errors.New("expected keyword")
ErrExpectedWriter = errors.New("expected Writer")
ErrIndexOutOfRange = errors.New("index out of range")
ErrInvalidFormat = errors.New("invalid format")
ErrNotSupportType = errors.New("not support type")
ErrQuit = errors.New("bye")
ErrAbort = errors.New("abort")
ErrVariableUnbound = errors.New("unbound variable")
ErrExpectedArray = errors.New("expected array")
ErrExpectedMacro = errors.New("expected macro")
ErrTooFewArguments = parser.ErrTooFewArguments
ErrTooManyArguments = parser.ErrTooManyArguments
ErrCanNotParseNumber = parser.ErrCanNotParseNumber
ErrTooShortTokens = parser.ErrTooShortTokens
)
type EqlMode int
const (
STRICT EqlMode = iota
EQUAL
EQUALP
)
type PrintMode int
const (
PRINT PrintMode = iota
PRINC
)
type Node interface {
Eval(context.Context, *World) (Node, error)
Equals(Node, EqlMode) bool
PrintTo(io.Writer, PrintMode) (int, error)
String() string
GoString() string
}
// IsNone returns whether `node` does not have a value or not
func IsNone(node Node) bool {
if node == nil {
return true
}
_, ok := node.(_NullType)
return ok
}
// Deprecated: use IsNone
func IsNull(node Node) bool {
return IsNone(node)
}
// IsSome returns whether `node` has a value or not
func IsSome(node Node) bool {
if node == nil {
return false
}
_, ok := node.(_NullType)
return !ok
}
// Deprecated: use IsSome
func HasValue(node Node) bool {
return IsSome(node)
}
func List(nodes ...Node) Node {
var cons Node = Null
for i := len(nodes) - 1; i >= 0; i-- {
cons = &Cons{
Car: nodes[i],
Cdr: cons,
}
}
return cons
}
func Shift(list Node) (Node, Node, error) {
cons, ok := list.(*Cons)
if !ok {
return nil, nil, ErrTooFewArguments
}
return cons.getCar(), cons.Cdr, nil
}
func ListToArray(list Node, slice []Node) error {
for i := 0; i < len(slice); i++ {
var err error
slice[i], list, err = Shift(list)
if err != nil {
return err
}
}
if IsSome(list) {
return ErrTooManyArguments
}
return nil
}
func checkContext(ctx context.Context) error {
select {
case <-ctx.Done():
return ctx.Err()
default:
return nil
}
}
func ignoreEOF(err error) error {
if err == io.EOF {
return nil
}
return err
}
func MakeError(e error, s any) error {
return fmt.Errorf("%w: %#v", e, s)
}