-
Notifications
You must be signed in to change notification settings - Fork 10
/
termination.go
117 lines (103 loc) · 2.6 KB
/
termination.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
package runtime
import "unsafe"
// Termination is a 'dead-end' continuation: it cannot be run.
type Termination struct {
parent Cont
args []Value
pushIndex int
etc *[]Value
}
var _ Cont = (*Termination)(nil)
// NewTermination returns a new pointer to Termination where the first len(args)
// values will be pushed into args and the remaining ones will be added to etc
// if it is non nil, dropped otherwise.
func NewTermination(parent Cont, args []Value, etc *[]Value) *Termination {
return &Termination{parent: parent, args: args, etc: etc}
}
// NewTerminationWith creates a new Termination expecting nArgs args and
// possibly gathering extra args into an etc if hasEtc is true.
func NewTerminationWith(parent Cont, nArgs int, hasEtc bool) *Termination {
var args []Value
var etc *[]Value
if nArgs > 0 {
args = make([]Value, nArgs)
}
if hasEtc {
etc = new([]Value)
}
return NewTermination(parent, args, etc)
}
// Push implements Cont.Push. It just accumulates values into
// a slice.
func (c *Termination) Push(r *Runtime, v Value) {
if c.pushIndex < len(c.args) {
c.args[c.pushIndex] = v
c.pushIndex++
} else if c.etc != nil {
r.RequireSize(unsafe.Sizeof(Value{}))
*c.etc = append(*c.etc, v)
}
}
// PushEtc implements Cont.PushEtc.
func (c *Termination) PushEtc(r *Runtime, etc []Value) {
if c.pushIndex < len(c.args) {
for i, v := range etc {
c.args[c.pushIndex] = v
c.pushIndex++
if c.pushIndex == len(c.args) {
etc = etc[i+1:]
goto FillEtc
}
}
return
}
FillEtc:
if c.etc == nil {
return
}
r.RequireArrSize(unsafe.Sizeof(Value{}), len(etc))
*c.etc = append(*c.etc, etc...)
}
// RunInThread implements Cont.RunInThread. A termination exits
// immediately so it always returns nil.
func (c *Termination) RunInThread(t *Thread) (Cont, error) {
return nil, nil
}
// Next implmements Cont.Next.
func (c *Termination) Next() Cont {
return nil
}
func (c *Termination) Parent() Cont {
if c.parent == nil {
return nil
}
return c.parent.Parent()
}
// DebugInfo implements Cont.DebugInfo.
func (c *Termination) DebugInfo() *DebugInfo {
if c.parent == nil {
return nil
}
return c.parent.DebugInfo()
}
// Get returns the n-th arg pushed to the termination.
func (c *Termination) Get(n int) Value {
if n >= c.pushIndex {
return NilValue
}
return c.args[n]
}
// Etc returns all the extra args pushed to the termination.
func (c *Termination) Etc() []Value {
if c.etc == nil {
return nil
}
return *c.etc
}
// Reset erases all the args pushed to the termination.
func (c *Termination) Reset() {
c.pushIndex = 0
if c.etc != nil {
c.etc = new([]Value)
}
}