-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils.go
136 lines (115 loc) · 2.51 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
package gmnlisp
import (
"context"
"errors"
"fmt"
"io"
"github.com/hymkor/gmnlisp/pkg/parser"
)
var (
ErrAbort = errors.New("abort")
ErrDevisionByZero = errors.New("devision by zeor")
ErrExpectedClass = errors.New("expected class")
ErrExpectedMacro = errors.New("expected macro")
ErrExpectedStream = errors.New("expected stream")
ErrExpectedWriter = errors.New("expected writer")
ErrIndexOutOfRange = errors.New("index out of range")
ErrInvalidFormat = errors.New("invalid format")
ErrNoMatchMethods = errors.New("no match methods")
ErrNotSupportType = errors.New("not support type")
ErrQuit = errors.New("bye")
ErrCanNotParseNumber = parser.ErrCanNotParseNumber
ErrTooFewArguments = parser.ErrTooFewArguments
ErrTooManyArguments = parser.ErrTooManyArguments
ErrTooShortTokens = parser.ErrTooShortTokens
)
type EqlMode int
const (
STRICT EqlMode = iota
EQUAL
EQUALP
)
type PrintMode int
const (
PRINT PrintMode = iota // AS S-Expression
PRINC // AS IS
)
type Node interface {
Equals(Node, EqlMode) bool
String() string
ClassOf() Class
}
// 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)
}
func funEval(ctx context.Context, w *World, arg Node) (Node, error) {
return w.Eval(ctx, arg)
}