-
-
Notifications
You must be signed in to change notification settings - Fork 297
/
types.go
170 lines (146 loc) · 4.44 KB
/
types.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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Package types contains basic types for the Elvish runtime.
package types
import (
"github.com/elves/elvish/util"
)
// Definitions for Value interfaces, some simple Value types and some common
// Value helpers.
// Value is an Elvish value.
type Value interface {
Kinder
Equaler
Hasher
Reprer
}
// Kinder wraps the Kind method.
type Kinder interface {
Kind() string
}
// Reprer wraps the Repr method.
type Reprer interface {
// Repr returns a string that represents a Value. The string either be a
// literal of that Value that is preferably deep-equal to it (like `[a b c]`
// for a list), or a string enclosed in "<>" containing the kind and
// identity of the Value(like `<fn 0xdeadcafe>`).
//
// If indent is at least 0, it should be pretty-printed with the current
// indentation level of indent; the indent of the first line has already
// been written and shall not be written in Repr. The returned string
// should never contain a trailing newline.
Repr(indent int) string
}
// NoPretty can be passed to Repr to suppress pretty-printing.
const NoPretty = util.MinInt
// Equaler wraps the Equal method.
type Equaler interface {
// Equal compares the receiver to another value. Two equal values must have
// the same hash code.
Equal(other interface{}) bool
}
// Hasher wraps the Hash method.
type Hasher interface {
// Hash computes the hash code of the receiver.
Hash() uint32
}
// Booler wraps the Bool method.
type Booler interface {
// Bool computes the truth value of the receiver.
Bool() bool
}
// Stringer wraps the String method.
type Stringer interface {
// Stringer converts the receiver to a string.
String() string
}
// ToString converts a Value to string. When the Value type implements
// String(), it is used. Otherwise Repr(NoPretty) is used.
func ToString(v Value) string {
if s, ok := v.(Stringer); ok {
return s.String()
}
return v.Repr(NoPretty)
}
// Lener wraps the Len method.
type Lener interface {
// Len computes the length of the receiver.
Len() int
}
// Iterator wraps the Iterate method.
type Iterator interface {
// Iterate calls the passed function with each value within the receiver.
// The iteration is aborted if the function returns false.
Iterate(func(v Value) bool)
}
// IteratorValue is an iterable Value.
type IteratorValue interface {
Iterator
Value
}
func CollectFromIterator(it Iterator) []Value {
var vs []Value
if lener, ok := it.(Lener); ok {
vs = make([]Value, 0, lener.Len())
}
it.Iterate(func(v Value) bool {
vs = append(vs, v)
return true
})
return vs
}
// IterateKeyer wraps the IterateKey method.
type IterateKeyer interface {
// IterateKey calls the passed function with each value within the receiver.
// The iteration is aborted if the function returns false.
IterateKey(func(k Value) bool)
}
// IteratePairer wraps the IteratePair method.
type IteratePairer interface {
// IteratePair calls the passed function with each key and value within the
// receiver. The iteration is aborted if the function returns false.
IteratePair(func(k, v Value) bool)
}
// Indexer wraps the Index method.
type Indexer interface {
// Index retrieves the values within the receiver at the specified indicies.
Index(idx []Value) []Value
}
// IndexOneer wraps the IndexOne method.
type IndexOneer interface {
// Index retrieves one value from the receiver at the specified index.
IndexOne(idx Value) Value
}
// GetIndexer adapts a Value to an Indexer if there is an adapter.
func GetIndexer(v Value) (Indexer, bool) {
if indexer, ok := v.(Indexer); ok {
return indexer, true
}
if indexOneer, ok := v.(IndexOneer); ok {
return IndexOneerIndexer{indexOneer}, true
}
return nil, false
}
// IndexOneerIndexer adapts an IndexOneer to an Indexer by calling all the
// indicies on the IndexOner and collect the results.
type IndexOneerIndexer struct {
IndexOneer
}
func (ioi IndexOneerIndexer) Index(vs []Value) []Value {
results := make([]Value, len(vs))
for i, v := range vs {
results[i] = ioi.IndexOneer.IndexOne(v)
}
return results
}
// Assocer wraps the Assoc method.
type Assocer interface {
// Assoc returns a slightly modified version of the receiver with key k
// associated with value v.
Assoc(k, v Value) Value
}
// Dissocer is anything tha can return a slightly modified version of itself with
// the specified key removed, as a new value.
type Dissocer interface {
// Dissoc returns a slightly modified version of the receiver with key k
// dissociated with any value.
Dissoc(k Value) Value
}