-
Notifications
You must be signed in to change notification settings - Fork 0
/
type_value.go
154 lines (135 loc) · 2.29 KB
/
type_value.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
145
146
147
148
149
150
151
152
153
154
package mtcl
import (
"strconv"
"strings"
)
type Value interface {
value()
Len() int
String() string
Type() string
Expand() Values
}
type Values []Value
func Empty() Values {
return nil
}
func (Values) value() {}
func (vs Values) String() string {
switch len(vs) {
case 0:
return ""
case 1:
return vs[0].String()
default:
var out strings.Builder
for i, v := range vs {
str := v.String()
if str == "" {
continue
}
out.Grow(len(str) + 1)
if i > 0 && out.Len() > 0 {
out.WriteByte(' ')
}
out.WriteString(str)
}
return out.String()
}
}
func (vs Values) Expand() Values {
return vs
}
func (vs Values) Len() int {
return len(vs)
}
func (vs Values) Type() string {
return "vec"
}
func (vs Values) Iterator() Iterator {
return func(vals Values) (bool, error) {
if len(vals) == 0 {
return len(vs) > 0, nil
}
if len(vs) < len(vals) {
return false, nil
}
copy(vals, vs)
vs = vs[len(vals):]
return true, nil
}
}
type Iterable interface {
Value
Iterator() Iterator
}
type Iterator func(vals Values) (bool, error)
func EmptyIterator() Iterator {
return func(Values) (bool, error) {
return false, nil
}
}
type OnceIterable struct {
Value
}
func (o OnceIterable) Iterator() Iterator {
if IsEmpty(o.Value) {
return EmptyIterator()
}
return OnceIterator(o.Value)
}
func OnceIterator(val Value) Iterator {
var iter Iterator
iter = func(vals Values) (bool, error) {
if len(vals) == 0 {
return true, nil
}
iter = func(vals Values) (bool, error) { return false, nil }
if len(vals) != 1 {
return false, nil
}
vals[0] = val
return true, nil
}
return func(vals Values) (bool, error) {
return iter(vals)
}
}
func Truthy(val Value) bool {
if IsEmpty(val) {
return false
}
switch val := val.(type) {
case *Int:
return val.Sign() != 0
case Bool:
return bool(val)
case String:
b, err := strconv.ParseBool(string(val))
return b || err != nil
case Values:
for _, sub := range val {
if Truthy(sub) {
return true
}
}
}
return false
}
func IsEmpty(val Value) bool {
switch val := val.(type) {
case *Int:
return false
case String:
return len(val) == 0
case Values:
return len(val) == 0
case Map:
return len(val) == 0
case Bool:
return !bool(val)
case nil:
return true
}
return false
}