github.com/arnodel/golua@v0.0.0-20230215163904-e0b5347eaaa1/runtime/cont.go (about) 1 package runtime 2 3 import ( 4 "os" 5 "syscall" 6 ) 7 8 // Cont is an interface for things that can be run in a Thread. Implementations 9 // of Cont a typically an invocation of a Lua function or an invocation of a Go 10 // function. 11 type Cont interface { 12 13 // Push "pushes" a Value to the continuation (arguments before a call, or 14 // before resuming a continuation which has been suspended via "yield"). This is to 15 // pass arguments to the continuation before calling RunInThread. 16 Push(*Runtime, Value) 17 18 // PushEtc "pushes" varargs to the continutation, this happens e.g. in Lua 19 // code when running "f(...)". 20 PushEtc(*Runtime, []Value) 21 22 // RunInThread runs the continuation in the given thread, returning either 23 // the next continuation to be run or an error. 24 RunInThread(*Thread) (Cont, error) 25 26 // Next() returns the continuation that follows after this one (could be 27 // e.g. the caller). 28 Next() Cont 29 30 // Parent() returns the continuation that initiated this continuation. It 31 // can be the same as Next() but not necessarily. This is useful for giving 32 // meaningful tracebacks, not used by the runtime engine. 33 Parent() Cont 34 35 // DebugInfo() returns debug info for the continuation. Used for building 36 // error messages and tracebacks. 37 DebugInfo() *DebugInfo 38 } 39 40 // Push is a convenience method that pushes a number of values to the 41 // continuation c. 42 func (r *Runtime) Push(c Cont, vals ...Value) { 43 for _, v := range vals { 44 c.Push(r, v) 45 } 46 } 47 48 // Push1 is a convenience method that pushes v to the continuation c. 49 func (r *Runtime) Push1(c Cont, v Value) { 50 c.Push(r, v) 51 } 52 53 // PushIoError is a convenience method that translates ioErr to a value if 54 // appropriated and pushes that value to c, else returns an error. It is useful 55 // because a number of Go IO errors are considered regular return values by Lua. 56 func (r *Runtime) PushIoError(c Cont, ioErr error) error { 57 // It is not specified in the Lua docs, but the test suite expects an 58 // errno as the third value returned in case of an error. I'm not sure 59 // the conversion to syscall.Errno is future-proof though? 60 61 var err error 62 switch tErr := ioErr.(type) { 63 case *os.PathError: 64 err = tErr.Unwrap() 65 case *os.LinkError: 66 err = tErr.Unwrap() 67 default: 68 return ioErr 69 } 70 r.Push1(c, NilValue) 71 r.Push1(c, StringValue(ioErr.Error())) 72 if errno, ok := err.(syscall.Errno); ok { 73 r.Push1(c, IntValue(int64(errno))) 74 } 75 return nil 76 } 77 78 // ProcessIoError is like PushIoError but its signature makes it convenient to 79 // use in a return statement from a GoFunc implementation. 80 func (r *Runtime) ProcessIoError(c Cont, ioErr error) (Cont, error) { 81 if err := r.PushIoError(c, ioErr); err != nil { 82 return nil, err 83 } 84 return c, nil 85 }