/
cont.go
85 lines (72 loc) · 2.64 KB
/
cont.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
package runtime
import (
"os"
"syscall"
)
// Cont is an interface for things that can be run in a Thread. Implementations
// of Cont a typically an invocation of a Lua function or an invocation of a Go
// function.
type Cont interface {
// Push "pushes" a Value to the continuation (arguments before a call, or
// before resuming a continuation which has been suspended via "yield"). This is to
// pass arguments to the continuation before calling RunInThread.
Push(*Runtime, Value)
// PushEtc "pushes" varargs to the continutation, this happens e.g. in Lua
// code when running "f(...)".
PushEtc(*Runtime, []Value)
// RunInThread runs the continuation in the given thread, returning either
// the next continuation to be run or an error.
RunInThread(*Thread) (Cont, error)
// Next() returns the continuation that follows after this one (could be
// e.g. the caller).
Next() Cont
// Parent() returns the continuation that initiated this continuation. It
// can be the same as Next() but not necessarily. This is useful for giving
// meaningful tracebacks, not used by the runtime engine.
Parent() Cont
// DebugInfo() returns debug info for the continuation. Used for building
// error messages and tracebacks.
DebugInfo() *DebugInfo
}
// Push is a convenience method that pushes a number of values to the
// continuation c.
func (r *Runtime) Push(c Cont, vals ...Value) {
for _, v := range vals {
c.Push(r, v)
}
}
// Push1 is a convenience method that pushes v to the continuation c.
func (r *Runtime) Push1(c Cont, v Value) {
c.Push(r, v)
}
// PushIoError is a convenience method that translates ioErr to a value if
// appropriated and pushes that value to c, else returns an error. It is useful
// because a number of Go IO errors are considered regular return values by Lua.
func (r *Runtime) PushIoError(c Cont, ioErr error) error {
// It is not specified in the Lua docs, but the test suite expects an
// errno as the third value returned in case of an error. I'm not sure
// the conversion to syscall.Errno is future-proof though?
var err error
switch tErr := ioErr.(type) {
case *os.PathError:
err = tErr.Unwrap()
case *os.LinkError:
err = tErr.Unwrap()
default:
return ioErr
}
r.Push1(c, NilValue)
r.Push1(c, StringValue(ioErr.Error()))
if errno, ok := err.(syscall.Errno); ok {
r.Push1(c, IntValue(int64(errno)))
}
return nil
}
// ProcessIoError is like PushIoError but its signature makes it convenient to
// use in a return statement from a GoFunc implementation.
func (r *Runtime) ProcessIoError(c Cont, ioErr error) (Cont, error) {
if err := r.PushIoError(c, ioErr); err != nil {
return nil, err
}
return c, nil
}