github.com/arnodel/golua@v0.0.0-20230215163904-e0b5347eaaa1/runtime/termination.go (about) 1 package runtime 2 3 import "unsafe" 4 5 // Termination is a 'dead-end' continuation: it cannot be run. 6 type Termination struct { 7 parent Cont 8 args []Value 9 pushIndex int 10 etc *[]Value 11 } 12 13 var _ Cont = (*Termination)(nil) 14 15 // NewTermination returns a new pointer to Termination where the first len(args) 16 // values will be pushed into args and the remaining ones will be added to etc 17 // if it is non nil, dropped otherwise. 18 func NewTermination(parent Cont, args []Value, etc *[]Value) *Termination { 19 return &Termination{parent: parent, args: args, etc: etc} 20 } 21 22 // NewTerminationWith creates a new Termination expecting nArgs args and 23 // possibly gathering extra args into an etc if hasEtc is true. 24 func NewTerminationWith(parent Cont, nArgs int, hasEtc bool) *Termination { 25 var args []Value 26 var etc *[]Value 27 if nArgs > 0 { 28 args = make([]Value, nArgs) 29 } 30 if hasEtc { 31 etc = new([]Value) 32 } 33 return NewTermination(parent, args, etc) 34 } 35 36 // Push implements Cont.Push. It just accumulates values into 37 // a slice. 38 func (c *Termination) Push(r *Runtime, v Value) { 39 if c.pushIndex < len(c.args) { 40 c.args[c.pushIndex] = v 41 c.pushIndex++ 42 } else if c.etc != nil { 43 r.RequireSize(unsafe.Sizeof(Value{})) 44 *c.etc = append(*c.etc, v) 45 } 46 } 47 48 // PushEtc implements Cont.PushEtc. 49 func (c *Termination) PushEtc(r *Runtime, etc []Value) { 50 if c.pushIndex < len(c.args) { 51 for i, v := range etc { 52 c.args[c.pushIndex] = v 53 c.pushIndex++ 54 if c.pushIndex == len(c.args) { 55 etc = etc[i+1:] 56 goto FillEtc 57 } 58 } 59 return 60 } 61 FillEtc: 62 if c.etc == nil { 63 return 64 } 65 r.RequireArrSize(unsafe.Sizeof(Value{}), len(etc)) 66 *c.etc = append(*c.etc, etc...) 67 } 68 69 // RunInThread implements Cont.RunInThread. A termination exits 70 // immediately so it always returns nil. 71 func (c *Termination) RunInThread(t *Thread) (Cont, error) { 72 return nil, nil 73 } 74 75 // Next implmements Cont.Next. 76 func (c *Termination) Next() Cont { 77 return nil 78 } 79 80 func (c *Termination) Parent() Cont { 81 if c.parent == nil { 82 return nil 83 } 84 return c.parent.Parent() 85 } 86 87 // DebugInfo implements Cont.DebugInfo. 88 func (c *Termination) DebugInfo() *DebugInfo { 89 if c.parent == nil { 90 return nil 91 } 92 return c.parent.DebugInfo() 93 } 94 95 // Get returns the n-th arg pushed to the termination. 96 func (c *Termination) Get(n int) Value { 97 if n >= c.pushIndex { 98 return NilValue 99 } 100 return c.args[n] 101 } 102 103 // Etc returns all the extra args pushed to the termination. 104 func (c *Termination) Etc() []Value { 105 if c.etc == nil { 106 return nil 107 } 108 return *c.etc 109 } 110 111 // Reset erases all the args pushed to the termination. 112 func (c *Termination) Reset() { 113 c.pushIndex = 0 114 if c.etc != nil { 115 c.etc = new([]Value) 116 } 117 }