-
Notifications
You must be signed in to change notification settings - Fork 8
/
seq.go
78 lines (66 loc) · 1.42 KB
/
seq.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
// Copyright Suneido Software Corp. All rights reserved.
// Governed by the MIT license found in the LICENSE file.
package builtin
import (
"math"
. "github.com/apmckinlay/gsuneido/core"
"github.com/apmckinlay/gsuneido/util/assert"
)
var _ = builtin(SeqQ, "(value)")
func SeqQ(val Value) Value {
_, ok := val.(*SuSequence)
return SuBool(ok)
}
var _ = builtin(Seq, "(from=false, to=false, by=1)")
func Seq(from, to, by Value) Value {
if from == False {
from = Zero
to = MaxInt
} else if to == False {
to = from
from = Zero
}
f := ToInt(from)
return NewSuSequence(
&seqIter{from: f, to: ToInt(to), by: ToInt(by), i: f})
}
type seqIter struct {
MayLock
from int
to int
by int
i int
}
func (seq *seqIter) Next() Value {
if seq.Lock() {
defer seq.Unlock()
}
assert.That(seq.by != 0)
if seq.i >= seq.to {
return nil
}
i := seq.i
seq.i += seq.by
return IntVal(i)
}
func (seq *seqIter) Dup() Iter {
if seq.Lock() {
defer seq.Unlock()
}
return &seqIter{from: seq.from, to: seq.to, by: seq.by, i: seq.from}
}
func (seq *seqIter) Infinite() bool {
// to is read-only so no locking required
return seq.to == math.MaxInt32 // has to match MaxInt opcode
}
func (seq *seqIter) Instantiate() *SuObject {
n := (seq.to - seq.from + (seq.by - 1)) / seq.by
InstantiateMax(n)
list := make([]Value, n)
i := seq.from
for j := 0; i < seq.to; j++ {
list[j] = IntVal(i)
i += seq.by
}
return NewSuObject(list)
}