|
@@ -6,16 +6,15 @@ package lua
|
|
|
|
|
|
import (
|
|
|
"fmt"
|
|
|
+ "github.com/yuin/gopher-lua/parse"
|
|
|
+ "golang.org/x/net/context"
|
|
|
"io"
|
|
|
- "log"
|
|
|
"math"
|
|
|
"os"
|
|
|
"runtime"
|
|
|
"strings"
|
|
|
"sync/atomic"
|
|
|
"time"
|
|
|
-
|
|
|
- "github.com/yuin/gopher-lua/parse"
|
|
|
)
|
|
|
|
|
|
const MultRet = -1
|
|
@@ -337,6 +336,8 @@ func newLState(options Options) *LState {
|
|
|
wrapped: false,
|
|
|
uvcache: nil,
|
|
|
hasErrorFunc: false,
|
|
|
+ mainLoop: mainLoop,
|
|
|
+ ctx: nil,
|
|
|
}
|
|
|
ls.Env = ls.G.Global
|
|
|
return ls
|
|
@@ -442,35 +443,32 @@ func (ls *LState) where(level int, skipg bool) string {
|
|
|
}
|
|
|
|
|
|
func (ls *LState) stackTrace(level int) string {
|
|
|
- return ls.ScriptFileName + "出错!"
|
|
|
- /*
|
|
|
- buf := []string{}
|
|
|
- header := "stack traceback:"
|
|
|
- if ls.currentFrame != nil {
|
|
|
- i := 0
|
|
|
- for dbg, ok := ls.GetStack(i); ok; dbg, ok = ls.GetStack(i) {
|
|
|
- cf := dbg.frame
|
|
|
- buf = append(buf, fmt.Sprintf("\t%v in %v", ls.Where(i), ls.formattedFrameFuncName(cf)))
|
|
|
- if !cf.Fn.IsG && cf.TailCall > 0 {
|
|
|
- for tc := cf.TailCall; tc > 0; tc-- {
|
|
|
- buf = append(buf, "\t(tailcall): ?")
|
|
|
- i++
|
|
|
- }
|
|
|
+ buf := []string{}
|
|
|
+ header := "stack traceback:"
|
|
|
+ if ls.currentFrame != nil {
|
|
|
+ i := 0
|
|
|
+ for dbg, ok := ls.GetStack(i); ok; dbg, ok = ls.GetStack(i) {
|
|
|
+ cf := dbg.frame
|
|
|
+ buf = append(buf, fmt.Sprintf("\t%v in %v", ls.Where(i), ls.formattedFrameFuncName(cf)))
|
|
|
+ if !cf.Fn.IsG && cf.TailCall > 0 {
|
|
|
+ for tc := cf.TailCall; tc > 0; tc-- {
|
|
|
+ buf = append(buf, "\t(tailcall): ?")
|
|
|
+ i++
|
|
|
}
|
|
|
- i++
|
|
|
}
|
|
|
+ i++
|
|
|
}
|
|
|
- buf = append(buf, fmt.Sprintf("\t%v: %v", "[G]", "?"))
|
|
|
- buf = buf[intMax(0, intMin(level, len(buf))):len(buf)]
|
|
|
- if len(buf) > 20 {
|
|
|
- newbuf := make([]string, 0, 20)
|
|
|
- newbuf = append(newbuf, buf[0:7]...)
|
|
|
- newbuf = append(newbuf, "\t...")
|
|
|
- newbuf = append(newbuf, buf[len(buf)-7:len(buf)]...)
|
|
|
- buf = newbuf
|
|
|
- }
|
|
|
- return fmt.Sprintf("%s\n%s", header, strings.Join(buf, "\n"))
|
|
|
- */
|
|
|
+ }
|
|
|
+ buf = append(buf, fmt.Sprintf("\t%v: %v", "[G]", "?"))
|
|
|
+ buf = buf[intMax(0, intMin(level, len(buf))):len(buf)]
|
|
|
+ if len(buf) > 20 {
|
|
|
+ newbuf := make([]string, 0, 20)
|
|
|
+ newbuf = append(newbuf, buf[0:7]...)
|
|
|
+ newbuf = append(newbuf, "\t...")
|
|
|
+ newbuf = append(newbuf, buf[len(buf)-7:len(buf)]...)
|
|
|
+ buf = newbuf
|
|
|
+ }
|
|
|
+ return fmt.Sprintf("%s\n%s", header, strings.Join(buf, "\n"))
|
|
|
}
|
|
|
|
|
|
func (ls *LState) formattedFrameFuncName(fr *callFrame) string {
|
|
@@ -873,9 +871,9 @@ func (ls *LState) callR(nargs, nret, rbase int) {
|
|
|
if ls.G.MainThread == nil {
|
|
|
ls.G.MainThread = ls
|
|
|
ls.G.CurrentThread = ls
|
|
|
- mainLoop(ls, nil)
|
|
|
+ ls.mainLoop(ls, nil)
|
|
|
} else {
|
|
|
- mainLoop(ls, ls.currentFrame)
|
|
|
+ ls.mainLoop(ls, ls.currentFrame)
|
|
|
}
|
|
|
if nret != MultRet {
|
|
|
ls.reg.SetTop(rbase + nret)
|
|
@@ -1152,19 +1150,8 @@ func (ls *LState) Pop(n int) {
|
|
|
for i := 0; i < n; i++ {
|
|
|
if ls.GetTop() == 0 {
|
|
|
ls.RaiseError("register underflow")
|
|
|
- } else {
|
|
|
- ls.reg.Pop()
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-func (ls *LState) PopArgs(n int, info interface{}) {
|
|
|
- for i := 0; i < n; i++ {
|
|
|
- if ls.GetTop() == 0 {
|
|
|
- ls.RaiseError("register underflow", info)
|
|
|
- } else {
|
|
|
- ls.reg.Pop()
|
|
|
}
|
|
|
+ ls.reg.Pop()
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1208,19 +1195,25 @@ func (ls *LState) Remove(index int) {
|
|
|
/* object allocation {{{ */
|
|
|
|
|
|
func (ls *LState) NewTable() *LTable {
|
|
|
- // TODO change size
|
|
|
- return newLTable(32, 32)
|
|
|
+ return newLTable(defaultArrayCap, defaultHashCap)
|
|
|
}
|
|
|
|
|
|
func (ls *LState) CreateTable(acap, hcap int) *LTable {
|
|
|
return newLTable(acap, hcap)
|
|
|
}
|
|
|
|
|
|
-func (ls *LState) NewThread() *LState {
|
|
|
+// NewThread returns a new LState that shares with the original state all global objects.
|
|
|
+// If the original state has context.Context, the new state has a new child context of the original state and this function returns its cancel function.
|
|
|
+func (ls *LState) NewThread() (*LState, context.CancelFunc) {
|
|
|
thread := newLState(ls.Options)
|
|
|
thread.G = ls.G
|
|
|
thread.Env = ls.Env
|
|
|
- return thread
|
|
|
+ var f context.CancelFunc = nil
|
|
|
+ if ls.ctx != nil {
|
|
|
+ thread.mainLoop = mainLoopWithContext
|
|
|
+ thread.ctx, f = context.WithCancel(ls.ctx)
|
|
|
+ }
|
|
|
+ return thread, f
|
|
|
}
|
|
|
|
|
|
func (ls *LState) NewUserData() *LUserData {
|
|
@@ -1318,8 +1311,7 @@ func (ls *LState) ToThread(n int) *LState {
|
|
|
|
|
|
// This function is equivalent to luaL_error( http://www.lua.org/manual/5.1/manual.html#luaL_error ).
|
|
|
func (ls *LState) RaiseError(format string, args ...interface{}) {
|
|
|
- log.Println("Pop 出错,脚本名称", ls.ScriptFileName, args)
|
|
|
- //ls.raiseError(1, format, args...)
|
|
|
+ ls.raiseError(1, format, args...)
|
|
|
}
|
|
|
|
|
|
// This function is equivalent to lua_error( http://www.lua.org/manual/5.1/manual.html#lua_error ).
|
|
@@ -1668,6 +1660,8 @@ func (ls *LState) PCall(nargs, nret int, errfunc *LFunction) (err error) {
|
|
|
} else if len(err.(*ApiError).StackTrace) == 0 {
|
|
|
err.(*ApiError).StackTrace = ls.stackTrace(0)
|
|
|
}
|
|
|
+ ls.stack.SetSp(sp)
|
|
|
+ ls.currentFrame = ls.stack.Last()
|
|
|
ls.reg.SetTop(base)
|
|
|
}
|
|
|
ls.stack.SetSp(sp)
|
|
@@ -1844,6 +1838,25 @@ func (ls *LState) SetMx(mx int) {
|
|
|
}()
|
|
|
}
|
|
|
|
|
|
+// SetContext set a context ctx to this LState. The provided ctx must be non-nil.
|
|
|
+func (ls *LState) SetContext(ctx context.Context) {
|
|
|
+ ls.mainLoop = mainLoopWithContext
|
|
|
+ ls.ctx = ctx
|
|
|
+}
|
|
|
+
|
|
|
+// Context returns the LState's context. To change the context, use WithContext.
|
|
|
+func (ls *LState) Context() context.Context {
|
|
|
+ return ls.ctx
|
|
|
+}
|
|
|
+
|
|
|
+// RemoveContext removes the context associated with this LState and returns this context.
|
|
|
+func (ls *LState) RemoveContext() context.Context {
|
|
|
+ oldctx := ls.ctx
|
|
|
+ ls.mainLoop = mainLoop
|
|
|
+ ls.ctx = nil
|
|
|
+ return oldctx
|
|
|
+}
|
|
|
+
|
|
|
// Converts the Lua value at the given acceptable index to the chan LValue.
|
|
|
func (ls *LState) ToChannel(n int) chan LValue {
|
|
|
if lv, ok := ls.Get(n).(LChannel); ok {
|