github.com/awirix/lua@v1.6.0/_state.go (about)

     1  package lua
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"math"
     8  	"os"
     9  	"runtime"
    10  	"strings"
    11  	"sync"
    12  	"sync/atomic"
    13  	"time"
    14  
    15  	"github.com/awirix/lua/parse"
    16  )
    17  
    18  const MultRet = -1
    19  const RegistryIndex = -10000
    20  const EnvironIndex = -10001
    21  const GlobalsIndex = -10002
    22  
    23  /* ApiError {{{ */
    24  
    25  type ApiError struct {
    26  	Type       ApiErrorType
    27  	Object     LValue
    28  	StackTrace string
    29  	// Underlying error. This attribute is set only if the Type is ApiErrorFile or ApiErrorSyntax
    30  	Cause error
    31  }
    32  
    33  func newApiError(code ApiErrorType, object LValue) *ApiError {
    34  	return &ApiError{code, object, "", nil}
    35  }
    36  
    37  func newApiErrorS(code ApiErrorType, message string) *ApiError {
    38  	return newApiError(code, LString(message))
    39  }
    40  
    41  func newApiErrorE(code ApiErrorType, err error) *ApiError {
    42  	return &ApiError{code, LString(err.Error()), "", err}
    43  }
    44  
    45  func (e *ApiError) Error() string {
    46  	if len(e.StackTrace) > 0 {
    47  		return fmt.Sprintf("%s\n%s", e.Object.String(), e.StackTrace)
    48  	}
    49  	return e.Object.String()
    50  }
    51  
    52  type ApiErrorType int
    53  
    54  const (
    55  	ApiErrorSyntax ApiErrorType = iota
    56  	ApiErrorFile
    57  	ApiErrorRun
    58  	ApiErrorError
    59  	ApiErrorPanic
    60  )
    61  
    62  /* }}} */
    63  
    64  /* ResumeState {{{ */
    65  
    66  type ResumeState int
    67  
    68  const (
    69  	ResumeOK ResumeState = iota
    70  	ResumeYield
    71  	ResumeError
    72  )
    73  
    74  /* }}} */
    75  
    76  /* P {{{ */
    77  
    78  type P struct {
    79  	Fn      LValue
    80  	NRet    int
    81  	Protect bool
    82  	Handler *LFunction
    83  }
    84  
    85  /* }}} */
    86  
    87  /* Options {{{ */
    88  
    89  // Options is a configuration that is used to create a new LState.
    90  type Options struct {
    91  	// Call stack size. This defaults to `lua.CallStackSize`.
    92  	CallStackSize int
    93  	// Data stack size. This defaults to `lua.RegistrySize`.
    94  	RegistrySize int
    95  	// Allow the registry to grow from the registry size specified up to a value of RegistryMaxSize. A value of 0
    96  	// indicates no growth is permitted. The registry will not shrink again after any growth.
    97  	RegistryMaxSize int
    98  	// If growth is enabled, step up by an additional `RegistryGrowStep` each time to avoid having to resize too often.
    99  	// This defaults to `lua.RegistryGrowStep`
   100  	RegistryGrowStep int
   101  	// Controls whether or not libraries are opened by default
   102  	SkipOpenLibs bool
   103  	// Tells whether a Go stacktrace should be included in a Lua stacktrace when panics occur.
   104  	IncludeGoStackTrace bool
   105  	// If `MinimizeStackMemory` is set, the call stack will be automatically grown or shrank up to a limit of
   106  	// `CallStackSize` in order to minimize memory usage. This does incur a slight performance penalty.
   107  	MinimizeStackMemory bool
   108  	// Stdout used for print function. Defaults to os.Stdout.
   109  	Stdout io.Writer
   110  	// WorkingDir is the working directory for the state. Defaults to current one.
   111  	WorkingDir string
   112  	// IsolateIO is a flag that tells whether the state should isolate its IO operations to the working directory.
   113  	IsolateIO bool
   114  	// TempDir is the temporary directory name. Defaults to os.TempDir().
   115  	TempDir string
   116  }
   117  
   118  /* }}} */
   119  
   120  /* Debug {{{ */
   121  
   122  type Debug struct {
   123  	frame           *callFrame
   124  	Name            string
   125  	What            string
   126  	Source          string
   127  	CurrentLine     int
   128  	NUpvalues       int
   129  	LineDefined     int
   130  	LastLineDefined int
   131  }
   132  
   133  /* }}} */
   134  
   135  /* callFrame {{{ */
   136  
   137  type callFrame struct {
   138  	Idx        int
   139  	Fn         *LFunction
   140  	Parent     *callFrame
   141  	Pc         int
   142  	Base       int
   143  	LocalBase  int
   144  	ReturnBase int
   145  	NArgs      int
   146  	NRet       int
   147  	TailCall   int
   148  }
   149  
   150  type callFrameStack interface {
   151  	Push(v callFrame)
   152  	Pop() *callFrame
   153  	Last() *callFrame
   154  
   155  	SetSp(sp int)
   156  	Sp() int
   157  	At(sp int) *callFrame
   158  
   159  	IsFull() bool
   160  	IsEmpty() bool
   161  
   162  	FreeAll()
   163  }
   164  
   165  type fixedCallFrameStack struct {
   166  	array []callFrame
   167  	sp    int
   168  }
   169  
   170  func newFixedCallFrameStack(size int) callFrameStack {
   171  	return &fixedCallFrameStack{
   172  		array: make([]callFrame, size),
   173  		sp:    0,
   174  	}
   175  }
   176  
   177  func (cs *fixedCallFrameStack) IsEmpty() bool { return cs.sp == 0 }
   178  
   179  func (cs *fixedCallFrameStack) IsFull() bool { return cs.sp == len(cs.array) }
   180  
   181  func (cs *fixedCallFrameStack) Clear() {
   182  	cs.sp = 0
   183  }
   184  
   185  func (cs *fixedCallFrameStack) Push(v callFrame) {
   186  	cs.array[cs.sp] = v
   187  	cs.array[cs.sp].Idx = cs.sp
   188  	cs.sp++
   189  }
   190  
   191  func (cs *fixedCallFrameStack) Sp() int {
   192  	return cs.sp
   193  }
   194  
   195  func (cs *fixedCallFrameStack) SetSp(sp int) {
   196  	cs.sp = sp
   197  }
   198  
   199  func (cs *fixedCallFrameStack) Last() *callFrame {
   200  	if cs.sp == 0 {
   201  		return nil
   202  	}
   203  	return &cs.array[cs.sp-1]
   204  }
   205  
   206  func (cs *fixedCallFrameStack) At(sp int) *callFrame {
   207  	return &cs.array[sp]
   208  }
   209  
   210  func (cs *fixedCallFrameStack) Pop() *callFrame {
   211  	cs.sp--
   212  	return &cs.array[cs.sp]
   213  }
   214  
   215  func (cs *fixedCallFrameStack) FreeAll() {
   216  	// nothing to do for fixed callframestack
   217  }
   218  
   219  // FramesPerSegment should be a power of 2 constant for performance reasons. It will allow the go compiler to change
   220  // the divs and mods into bitshifts. Max is 256 due to current use of uint8 to count how many frames in a segment are
   221  // used.
   222  const FramesPerSegment = 8
   223  
   224  type callFrameStackSegment struct {
   225  	array [FramesPerSegment]callFrame
   226  }
   227  type segIdx uint16
   228  type autoGrowingCallFrameStack struct {
   229  	segments []*callFrameStackSegment
   230  	segIdx   segIdx
   231  	// segSp is the number of frames in the current segment which are used. Full 'sp' value is segIdx * FramesPerSegment + segSp.
   232  	// It points to the next stack slot to use, so 0 means to use the 0th element in the segment, and a value of
   233  	// FramesPerSegment indicates that the segment is full and cannot accommodate another frame.
   234  	segSp uint8
   235  }
   236  
   237  var segmentPool sync.Pool
   238  
   239  func newCallFrameStackSegment() *callFrameStackSegment {
   240  	seg := segmentPool.Get()
   241  	if seg == nil {
   242  		return &callFrameStackSegment{}
   243  	}
   244  	return seg.(*callFrameStackSegment)
   245  }
   246  
   247  func freeCallFrameStackSegment(seg *callFrameStackSegment) {
   248  	segmentPool.Put(seg)
   249  }
   250  
   251  // newCallFrameStack allocates a new stack for a lua state, which will auto grow up to a max size of at least maxSize.
   252  // it will actually grow up to the next segment size multiple after maxSize, where the segment size is dictated by
   253  // FramesPerSegment.
   254  func newAutoGrowingCallFrameStack(maxSize int) callFrameStack {
   255  	cs := &autoGrowingCallFrameStack{
   256  		segments: make([]*callFrameStackSegment, (maxSize+(FramesPerSegment-1))/FramesPerSegment),
   257  		segIdx:   0,
   258  	}
   259  	cs.segments[0] = newCallFrameStackSegment()
   260  	return cs
   261  }
   262  
   263  func (cs *autoGrowingCallFrameStack) IsEmpty() bool {
   264  	return cs.segIdx == 0 && cs.segSp == 0
   265  }
   266  
   267  // IsFull returns true if the stack cannot receive any more stack pushes without overflowing
   268  func (cs *autoGrowingCallFrameStack) IsFull() bool {
   269  	return int(cs.segIdx) == len(cs.segments) && cs.segSp >= FramesPerSegment
   270  }
   271  
   272  func (cs *autoGrowingCallFrameStack) Clear() {
   273  	for i := segIdx(1); i <= cs.segIdx; i++ {
   274  		freeCallFrameStackSegment(cs.segments[i])
   275  		cs.segments[i] = nil
   276  	}
   277  	cs.segIdx = 0
   278  	cs.segSp = 0
   279  }
   280  
   281  func (cs *autoGrowingCallFrameStack) FreeAll() {
   282  	for i := segIdx(0); i <= cs.segIdx; i++ {
   283  		freeCallFrameStackSegment(cs.segments[i])
   284  		cs.segments[i] = nil
   285  	}
   286  }
   287  
   288  // Push pushes the passed callFrame onto the stack. it panics if the stack is full, caller should call IsFull() before
   289  // invoking this to avoid this.
   290  func (cs *autoGrowingCallFrameStack) Push(v callFrame) {
   291  	curSeg := cs.segments[cs.segIdx]
   292  	if cs.segSp >= FramesPerSegment {
   293  		// segment full, push new segment if allowed
   294  		if cs.segIdx < segIdx(len(cs.segments)-1) {
   295  			curSeg = newCallFrameStackSegment()
   296  			cs.segIdx++
   297  			cs.segments[cs.segIdx] = curSeg
   298  			cs.segSp = 0
   299  		} else {
   300  			panic("lua callstack overflow")
   301  		}
   302  	}
   303  	curSeg.array[cs.segSp] = v
   304  	curSeg.array[cs.segSp].Idx = int(cs.segSp) + FramesPerSegment*int(cs.segIdx)
   305  	cs.segSp++
   306  }
   307  
   308  // Sp retrieves the current stack depth, which is the number of frames currently pushed on the stack.
   309  func (cs *autoGrowingCallFrameStack) Sp() int {
   310  	return int(cs.segSp) + int(cs.segIdx)*FramesPerSegment
   311  }
   312  
   313  // SetSp can be used to rapidly unwind the stack, freeing all stack frames on the way. It should not be used to
   314  // allocate new stack space, use Push() for that.
   315  func (cs *autoGrowingCallFrameStack) SetSp(sp int) {
   316  	desiredSegIdx := segIdx(sp / FramesPerSegment)
   317  	desiredFramesInLastSeg := uint8(sp % FramesPerSegment)
   318  	for {
   319  		if cs.segIdx <= desiredSegIdx {
   320  			break
   321  		}
   322  		freeCallFrameStackSegment(cs.segments[cs.segIdx])
   323  		cs.segments[cs.segIdx] = nil
   324  		cs.segIdx--
   325  	}
   326  	cs.segSp = desiredFramesInLastSeg
   327  }
   328  
   329  func (cs *autoGrowingCallFrameStack) Last() *callFrame {
   330  	curSeg := cs.segments[cs.segIdx]
   331  	segSp := cs.segSp
   332  	if segSp == 0 {
   333  		if cs.segIdx == 0 {
   334  			return nil
   335  		}
   336  		curSeg = cs.segments[cs.segIdx-1]
   337  		segSp = FramesPerSegment
   338  	}
   339  	return &curSeg.array[segSp-1]
   340  }
   341  
   342  func (cs *autoGrowingCallFrameStack) At(sp int) *callFrame {
   343  	segIdx := segIdx(sp / FramesPerSegment)
   344  	frameIdx := uint8(sp % FramesPerSegment)
   345  	return &cs.segments[segIdx].array[frameIdx]
   346  }
   347  
   348  // Pop pops off the most recent stack frame and returns it
   349  func (cs *autoGrowingCallFrameStack) Pop() *callFrame {
   350  	curSeg := cs.segments[cs.segIdx]
   351  	if cs.segSp == 0 {
   352  		if cs.segIdx == 0 {
   353  			// stack empty
   354  			return nil
   355  		}
   356  		freeCallFrameStackSegment(curSeg)
   357  		cs.segments[cs.segIdx] = nil
   358  		cs.segIdx--
   359  		cs.segSp = FramesPerSegment
   360  		curSeg = cs.segments[cs.segIdx]
   361  	}
   362  	cs.segSp--
   363  	return &curSeg.array[cs.segSp]
   364  }
   365  
   366  /* }}} */
   367  
   368  /* registry {{{ */
   369  
   370  type registryHandler interface {
   371  	registryOverflow()
   372  }
   373  type registry struct {
   374  	array   []LValue
   375  	top     int
   376  	growBy  int
   377  	maxSize int
   378  	alloc   *allocator
   379  	handler registryHandler
   380  }
   381  
   382  func newRegistry(handler registryHandler, initialSize int, growBy int, maxSize int, alloc *allocator) *registry {
   383  	return &registry{make([]LValue, initialSize), 0, growBy, maxSize, alloc, handler}
   384  }
   385  
   386  func (rg *registry) checkSize(requiredSize int) { // +inline-start
   387  	if requiredSize > cap(rg.array) {
   388  		rg.resize(requiredSize)
   389  	}
   390  } // +inline-end
   391  
   392  func (rg *registry) resize(requiredSize int) { // +inline-start
   393  	newSize := requiredSize + rg.growBy // give some padding
   394  	if newSize > rg.maxSize {
   395  		newSize = rg.maxSize
   396  	}
   397  	if newSize < requiredSize {
   398  		rg.handler.registryOverflow()
   399  		return
   400  	}
   401  	rg.forceResize(newSize)
   402  } // +inline-end
   403  
   404  func (rg *registry) forceResize(newSize int) {
   405  	newSlice := make([]LValue, newSize)
   406  	copy(newSlice, rg.array[:rg.top]) // should we copy the area beyond top? there shouldn't be any valid values there so it shouldn't be necessary.
   407  	rg.array = newSlice
   408  }
   409  func (rg *registry) SetTop(top int) {
   410  	// +inline-call rg.checkSize top
   411  	oldtop := rg.top
   412  	rg.top = top
   413  	for i := oldtop; i < rg.top; i++ {
   414  		rg.array[i] = LNil
   415  	}
   416  	// values beyond top don't need to be valid LValues, so setting them to nil is fine
   417  	// setting them to nil rather than LNil lets us invoke the golang memclr opto
   418  	if rg.top < oldtop {
   419  		nilRange := rg.array[rg.top:oldtop]
   420  		for i := range nilRange {
   421  			nilRange[i] = nil
   422  		}
   423  	}
   424  	//for i := rg.top; i < oldtop; i++ {
   425  	//	rg.array[i] = LNil
   426  	//}
   427  }
   428  
   429  func (rg *registry) Top() int {
   430  	return rg.top
   431  }
   432  
   433  func (rg *registry) Push(v LValue) {
   434  	newSize := rg.top + 1
   435  	// +inline-call rg.checkSize newSize
   436  	rg.array[rg.top] = v
   437  	rg.top++
   438  }
   439  
   440  func (rg *registry) Pop() LValue {
   441  	v := rg.array[rg.top-1]
   442  	rg.array[rg.top-1] = LNil
   443  	rg.top--
   444  	return v
   445  }
   446  
   447  func (rg *registry) Get(reg int) LValue {
   448  	return rg.array[reg]
   449  }
   450  
   451  // CopyRange will move a section of values from index `start` to index `regv`
   452  // It will move `n` values.
   453  // `limit` specifies the maximum end range that can be copied from. If it's set to -1, then it defaults to stopping at
   454  // the top of the registry (values beyond the top are not initialized, so if specifying an alternative `limit` you should
   455  // pass a value <= rg.top.
   456  // If start+n is beyond the limit, then nil values will be copied to the destination slots.
   457  // After the copy, the registry is truncated to be at the end of the copied range, ie the original of the copied values
   458  // are nilled out. (So top will be regv+n)
   459  // CopyRange should ideally be renamed to MoveRange.
   460  func (rg *registry) CopyRange(regv, start, limit, n int) { // +inline-start
   461  	newSize := regv + n
   462  	// +inline-call rg.checkSize newSize
   463  	if limit == -1 || limit > rg.top {
   464  		limit = rg.top
   465  	}
   466  	for i := 0; i < n; i++ {
   467  		srcIdx := start + i
   468  		if srcIdx >= limit || srcIdx < 0 {
   469  			rg.array[regv+i] = LNil
   470  		} else {
   471  			rg.array[regv+i] = rg.array[srcIdx]
   472  		}
   473  	}
   474  
   475  	// values beyond top don't need to be valid LValues, so setting them to nil is fine
   476  	// setting them to nil rather than LNil lets us invoke the golang memclr opto
   477  	oldtop := rg.top
   478  	rg.top = regv + n
   479  	if rg.top < oldtop {
   480  		nilRange := rg.array[rg.top:oldtop]
   481  		for i := range nilRange {
   482  			nilRange[i] = nil
   483  		}
   484  	}
   485  } // +inline-end
   486  
   487  // FillNil fills the registry with nil values from regm to regm+n and then sets the registry top to regm+n
   488  func (rg *registry) FillNil(regm, n int) { // +inline-start
   489  	newSize := regm + n
   490  	// +inline-call rg.checkSize newSize
   491  	for i := 0; i < n; i++ {
   492  		rg.array[regm+i] = LNil
   493  	}
   494  	// values beyond top don't need to be valid LValues, so setting them to nil is fine
   495  	// setting them to nil rather than LNil lets us invoke the golang memclr opto
   496  	oldtop := rg.top
   497  	rg.top = regm + n
   498  	if rg.top < oldtop {
   499  		nilRange := rg.array[rg.top:oldtop]
   500  		for i := range nilRange {
   501  			nilRange[i] = nil
   502  		}
   503  	}
   504  } // +inline-end
   505  
   506  func (rg *registry) Insert(value LValue, reg int) {
   507  	top := rg.Top()
   508  	if reg >= top {
   509  		rg.Set(reg, value)
   510  		return
   511  	}
   512  	top--
   513  	for ; top >= reg; top-- {
   514  		// FIXME consider using copy() here if Insert() is called enough
   515  		rg.Set(top+1, rg.Get(top))
   516  	}
   517  	rg.Set(reg, value)
   518  }
   519  
   520  func (rg *registry) Set(reg int, val LValue) {
   521  	newSize := reg + 1
   522  	// +inline-call rg.checkSize newSize
   523  	rg.array[reg] = val
   524  	if reg >= rg.top {
   525  		rg.top = reg + 1
   526  	}
   527  }
   528  
   529  func (rg *registry) SetNumber(reg int, val LNumber) {
   530  	newSize := reg + 1
   531  	// +inline-call rg.checkSize newSize
   532  	rg.array[reg] = rg.alloc.LNumber2I(val)
   533  	if reg >= rg.top {
   534  		rg.top = reg + 1
   535  	}
   536  }
   537  
   538  func (rg *registry) IsFull() bool {
   539  	return rg.top >= cap(rg.array)
   540  }
   541  
   542  /* }}} */
   543  
   544  /* Global {{{ */
   545  
   546  func newGlobal() *Global {
   547  	return &Global{
   548  		MainThread: nil,
   549  		Registry:   newLTable(0, 32),
   550  		Global:     newLTable(0, 64),
   551  		builtinMts: make(map[int]LValue),
   552  		tempFiles:  make([]*os.File, 0, 10),
   553  	}
   554  }
   555  
   556  /* }}} */
   557  
   558  /* package local methods {{{ */
   559  
   560  func panicWithTraceback(L *LState) {
   561  	err := newApiError(ApiErrorRun, L.Get(-1))
   562  	err.StackTrace = L.stackTrace(0)
   563  	panic(err)
   564  }
   565  
   566  func panicWithoutTraceback(L *LState) {
   567  	err := newApiError(ApiErrorRun, L.Get(-1))
   568  	panic(err)
   569  }
   570  
   571  func newLState(options *Options) *LState {
   572  	al := newAllocator(32)
   573  	ls := &LState{
   574  		G:       newGlobal(),
   575  		Parent:  nil,
   576  		Panic:   panicWithTraceback,
   577  		Dead:    false,
   578  		Options: options,
   579  
   580  		stop:         0,
   581  		alloc:        al,
   582  		currentFrame: nil,
   583  		wrapped:      false,
   584  		uvcache:      nil,
   585  		hasErrorFunc: false,
   586  		mainLoop:     mainLoop,
   587  		ctx:          nil,
   588  	}
   589  	if options.MinimizeStackMemory {
   590  		ls.stack = newAutoGrowingCallFrameStack(options.CallStackSize)
   591  	} else {
   592  		ls.stack = newFixedCallFrameStack(options.CallStackSize)
   593  	}
   594  	ls.reg = newRegistry(ls, options.RegistrySize, options.RegistryGrowStep, options.RegistryMaxSize, al)
   595  	ls.Env = ls.G.Global
   596  	return ls
   597  }
   598  
   599  func (ls *LState) printReg() {
   600  	println("-------------------------")
   601  	println("thread:", ls)
   602  	println("top:", ls.reg.Top())
   603  	if ls.currentFrame != nil {
   604  		println("function base:", ls.currentFrame.Base)
   605  		println("return base:", ls.currentFrame.ReturnBase)
   606  	} else {
   607  		println("(vm not started)")
   608  	}
   609  	println("local base:", ls.currentLocalBase())
   610  	for i := 0; i < ls.reg.Top(); i++ {
   611  		println(i, ls.reg.Get(i).String())
   612  	}
   613  	println("-------------------------")
   614  }
   615  
   616  func (ls *LState) printCallStack() {
   617  	println("-------------------------")
   618  	for i := 0; i < ls.stack.Sp(); i++ {
   619  		print(i)
   620  		print(" ")
   621  		frame := ls.stack.At(i)
   622  		if frame == nil {
   623  			break
   624  		}
   625  		if frame.Fn.IsG {
   626  			println("IsG:", true, "Frame:", frame, "Fn:", frame.Fn)
   627  		} else {
   628  			println("IsG:", false, "Frame:", frame, "Fn:", frame.Fn, "pc:", frame.Pc)
   629  		}
   630  	}
   631  	println("-------------------------")
   632  }
   633  
   634  func (ls *LState) closeAllUpvalues() { // +inline-start
   635  	for cf := ls.currentFrame; cf != nil; cf = cf.Parent {
   636  		if !cf.Fn.IsG {
   637  			ls.closeUpvalues(cf.LocalBase)
   638  		}
   639  	}
   640  } // +inline-end
   641  
   642  func (ls *LState) raiseError(level int, format string, args ...interface{}) {
   643  	if !ls.hasErrorFunc {
   644  		ls.closeAllUpvalues()
   645  	}
   646  	message := format
   647  	if len(args) > 0 {
   648  		message = fmt.Sprintf(format, args...)
   649  	}
   650  	if level > 0 {
   651  		message = fmt.Sprintf("%v %v", ls.where(level-1, true), message)
   652  	}
   653  	if ls.reg.IsFull() {
   654  		// if the registry is full then it won't be possible to push a value, in this case, force a larger size
   655  		ls.reg.forceResize(ls.reg.Top() + 1)
   656  	}
   657  	ls.reg.Push(LString(message))
   658  	ls.Panic(ls)
   659  }
   660  
   661  func (ls *LState) findLocal(frame *callFrame, no int) string {
   662  	fn := frame.Fn
   663  	if !fn.IsG {
   664  		if name, ok := fn.LocalName(no, frame.Pc-1); ok {
   665  			return name
   666  		}
   667  	}
   668  	var top int
   669  	if ls.currentFrame == frame {
   670  		top = ls.reg.Top()
   671  	} else if frame.Idx+1 < ls.stack.Sp() {
   672  		top = ls.stack.At(frame.Idx + 1).Base
   673  	} else {
   674  		return ""
   675  	}
   676  	if top-frame.LocalBase >= no {
   677  		return "(*temporary)"
   678  	}
   679  	return ""
   680  }
   681  
   682  func (ls *LState) where(level int, skipg bool) string {
   683  	dbg, ok := ls.GetStack(level)
   684  	if !ok {
   685  		return ""
   686  	}
   687  	cf := dbg.frame
   688  	proto := cf.Fn.Proto
   689  	sourcename := "[G]"
   690  	if proto != nil {
   691  		sourcename = proto.SourceName
   692  	} else if skipg {
   693  		return ls.where(level+1, skipg)
   694  	}
   695  	line := ""
   696  	if proto != nil {
   697  		line = fmt.Sprintf("%v:", proto.DbgSourcePositions[cf.Pc-1])
   698  	}
   699  	return fmt.Sprintf("%v:%v", sourcename, line)
   700  }
   701  
   702  func (ls *LState) stackTrace(level int) string {
   703  	buf := []string{}
   704  	header := "stack traceback:"
   705  	if ls.currentFrame != nil {
   706  		i := 0
   707  		for dbg, ok := ls.GetStack(i); ok; dbg, ok = ls.GetStack(i) {
   708  			cf := dbg.frame
   709  			buf = append(buf, fmt.Sprintf("\t%v in %v", ls.Where(i), ls.formattedFrameFuncName(cf)))
   710  			if !cf.Fn.IsG && cf.TailCall > 0 {
   711  				for tc := cf.TailCall; tc > 0; tc-- {
   712  					buf = append(buf, "\t(tailcall): ?")
   713  					i++
   714  				}
   715  			}
   716  			i++
   717  		}
   718  	}
   719  	buf = append(buf, fmt.Sprintf("\t%v: %v", "[G]", "?"))
   720  	buf = buf[intMax(0, intMin(level, len(buf))):len(buf)]
   721  	if len(buf) > 20 {
   722  		newbuf := make([]string, 0, 20)
   723  		newbuf = append(newbuf, buf[0:7]...)
   724  		newbuf = append(newbuf, "\t...")
   725  		newbuf = append(newbuf, buf[len(buf)-7:len(buf)]...)
   726  		buf = newbuf
   727  	}
   728  	return fmt.Sprintf("%s\n%s", header, strings.Join(buf, "\n"))
   729  }
   730  
   731  func (ls *LState) formattedFrameFuncName(fr *callFrame) string {
   732  	name, ischunk := ls.frameFuncName(fr)
   733  	if ischunk {
   734  		return name
   735  	}
   736  	if name[0] != '(' && name[0] != '<' {
   737  		return fmt.Sprintf("function '%s'", name)
   738  	}
   739  	return fmt.Sprintf("function %s", name)
   740  }
   741  
   742  func (ls *LState) rawFrameFuncName(fr *callFrame) string {
   743  	name, _ := ls.frameFuncName(fr)
   744  	return name
   745  }
   746  
   747  func (ls *LState) frameFuncName(fr *callFrame) (string, bool) {
   748  	frame := fr.Parent
   749  	if frame == nil {
   750  		if ls.Parent == nil {
   751  			return "main chunk", true
   752  		} else {
   753  			return "corountine", true
   754  		}
   755  	}
   756  	if !frame.Fn.IsG {
   757  		pc := frame.Pc - 1
   758  		for _, call := range frame.Fn.Proto.DbgCalls {
   759  			if call.Pc == pc {
   760  				name := call.Name
   761  				if (name == "?" || fr.TailCall > 0) && !fr.Fn.IsG {
   762  					name = fmt.Sprintf("<%v:%v>", fr.Fn.Proto.SourceName, fr.Fn.Proto.LineDefined)
   763  				}
   764  				return name, false
   765  			}
   766  		}
   767  	}
   768  	if !fr.Fn.IsG {
   769  		return fmt.Sprintf("<%v:%v>", fr.Fn.Proto.SourceName, fr.Fn.Proto.LineDefined), false
   770  	}
   771  	return "(anonymous)", false
   772  }
   773  
   774  func (ls *LState) isStarted() bool {
   775  	return ls.currentFrame != nil
   776  }
   777  
   778  func (ls *LState) kill() {
   779  	ls.Dead = true
   780  }
   781  
   782  func (ls *LState) indexToReg(idx int) int {
   783  	base := ls.currentLocalBase()
   784  	if idx > 0 {
   785  		return base + idx - 1
   786  	} else if idx == 0 {
   787  		return -1
   788  	} else {
   789  		tidx := ls.reg.Top() + idx
   790  		if tidx < base {
   791  			return -1
   792  		}
   793  		return tidx
   794  	}
   795  }
   796  
   797  func (ls *LState) currentLocalBase() int {
   798  	base := 0
   799  	if ls.currentFrame != nil {
   800  		base = ls.currentFrame.LocalBase
   801  	}
   802  	return base
   803  }
   804  
   805  func (ls *LState) currentEnv() *LTable {
   806  	return ls.Env
   807  	/*
   808  		if ls.currentFrame == nil {
   809  			return ls.Env
   810  		}
   811  		return ls.currentFrame.Fn.Env
   812  	*/
   813  }
   814  
   815  func (ls *LState) rkValue(idx int) LValue {
   816  	/*
   817  		if OpIsK(idx) {
   818  			return ls.currentFrame.Fn.Proto.Constants[opIndexK(idx)]
   819  		}
   820  		return ls.reg.Get(ls.currentFrame.LocalBase + idx)
   821  	*/
   822  	if (idx & opBitRk) != 0 {
   823  		return ls.currentFrame.Fn.Proto.Constants[idx & ^opBitRk]
   824  	}
   825  	return ls.reg.array[ls.currentFrame.LocalBase+idx]
   826  }
   827  
   828  func (ls *LState) rkString(idx int) string {
   829  	if (idx & opBitRk) != 0 {
   830  		return ls.currentFrame.Fn.Proto.stringConstants[idx & ^opBitRk]
   831  	}
   832  	return string(ls.reg.array[ls.currentFrame.LocalBase+idx].(LString))
   833  }
   834  
   835  func (ls *LState) closeUpvalues(idx int) { // +inline-start
   836  	if ls.uvcache != nil {
   837  		var prev *Upvalue
   838  		for uv := ls.uvcache; uv != nil; uv = uv.next {
   839  			if uv.index >= idx {
   840  				if prev != nil {
   841  					prev.next = nil
   842  				} else {
   843  					ls.uvcache = nil
   844  				}
   845  				uv.Close()
   846  			}
   847  			prev = uv
   848  		}
   849  	}
   850  } // +inline-end
   851  
   852  func (ls *LState) findUpvalue(idx int) *Upvalue {
   853  	var prev *Upvalue
   854  	var next *Upvalue
   855  	if ls.uvcache != nil {
   856  		for uv := ls.uvcache; uv != nil; uv = uv.next {
   857  			if uv.index == idx {
   858  				return uv
   859  			}
   860  			if uv.index > idx {
   861  				next = uv
   862  				break
   863  			}
   864  			prev = uv
   865  		}
   866  	}
   867  	uv := &Upvalue{reg: ls.reg, index: idx, closed: false}
   868  	if prev != nil {
   869  		prev.next = uv
   870  	} else {
   871  		ls.uvcache = uv
   872  	}
   873  	if next != nil {
   874  		uv.next = next
   875  	}
   876  	return uv
   877  }
   878  
   879  func (ls *LState) metatable(lvalue LValue, rawget bool) LValue {
   880  	var metatable LValue = LNil
   881  	switch obj := lvalue.(type) {
   882  	case *LTable:
   883  		metatable = obj.Metatable
   884  	case *LUserData:
   885  		metatable = obj.Metatable
   886  	default:
   887  		if table, ok := ls.G.builtinMts[int(obj.Type())]; ok {
   888  			metatable = table
   889  		}
   890  	}
   891  
   892  	if !rawget && metatable != LNil {
   893  		oldmt := metatable
   894  		if tb, ok := metatable.(*LTable); ok {
   895  			metatable = tb.RawGetString("__metatable")
   896  			if metatable == LNil {
   897  				metatable = oldmt
   898  			}
   899  		}
   900  	}
   901  
   902  	return metatable
   903  }
   904  
   905  func (ls *LState) metaOp1(lvalue LValue, event string) LValue {
   906  	if mt := ls.metatable(lvalue, true); mt != LNil {
   907  		if tb, ok := mt.(*LTable); ok {
   908  			return tb.RawGetString(event)
   909  		}
   910  	}
   911  	return LNil
   912  }
   913  
   914  func (ls *LState) metaOp2(value1, value2 LValue, event string) LValue {
   915  	if mt := ls.metatable(value1, true); mt != LNil {
   916  		if tb, ok := mt.(*LTable); ok {
   917  			if ret := tb.RawGetString(event); ret != LNil {
   918  				return ret
   919  			}
   920  		}
   921  	}
   922  	if mt := ls.metatable(value2, true); mt != LNil {
   923  		if tb, ok := mt.(*LTable); ok {
   924  			return tb.RawGetString(event)
   925  		}
   926  	}
   927  	return LNil
   928  }
   929  
   930  func (ls *LState) metaCall(lvalue LValue) (*LFunction, bool) {
   931  	if fn, ok := lvalue.(*LFunction); ok {
   932  		return fn, false
   933  	}
   934  	if fn, ok := ls.metaOp1(lvalue, "__call").(*LFunction); ok {
   935  		return fn, true
   936  	}
   937  	return nil, false
   938  }
   939  
   940  func (ls *LState) initCallFrame(cf *callFrame) { // +inline-start
   941  	if cf.Fn.IsG {
   942  		ls.reg.SetTop(cf.LocalBase + cf.NArgs)
   943  	} else {
   944  		proto := cf.Fn.Proto
   945  		nargs := cf.NArgs
   946  		np := int(proto.NumParameters)
   947  		if nargs < np {
   948  			// default any missing arguments to nil
   949  			newSize := cf.LocalBase + np
   950  			// +inline-call ls.reg.checkSize newSize
   951  			for i := nargs; i < np; i++ {
   952  				ls.reg.array[cf.LocalBase+i] = LNil
   953  			}
   954  			nargs = np
   955  			ls.reg.top = newSize
   956  		}
   957  
   958  		if (proto.IsVarArg & VarArgIsVarArg) == 0 {
   959  			if nargs < int(proto.NumUsedRegisters) {
   960  				nargs = int(proto.NumUsedRegisters)
   961  			}
   962  			newSize := cf.LocalBase + nargs
   963  			// +inline-call ls.reg.checkSize newSize
   964  			for i := np; i < nargs; i++ {
   965  				ls.reg.array[cf.LocalBase+i] = LNil
   966  			}
   967  			ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters)
   968  		} else {
   969  			/* swap vararg positions:
   970  					   closure
   971  					   namedparam1 <- lbase
   972  					   namedparam2
   973  					   vararg1
   974  					   vararg2
   975  
   976  			           TO
   977  
   978  					   closure
   979  					   nil
   980  					   nil
   981  					   vararg1
   982  					   vararg2
   983  					   namedparam1 <- lbase
   984  					   namedparam2
   985  			*/
   986  			nvarargs := nargs - np
   987  			if nvarargs < 0 {
   988  				nvarargs = 0
   989  			}
   990  
   991  			ls.reg.SetTop(cf.LocalBase + nargs + np)
   992  			for i := 0; i < np; i++ {
   993  				//ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i))
   994  				ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i]
   995  				//ls.reg.Set(cf.LocalBase+i, LNil)
   996  				ls.reg.array[cf.LocalBase+i] = LNil
   997  			}
   998  
   999  			if CompatVarArg {
  1000  				ls.reg.SetTop(cf.LocalBase + nargs + np + 1)
  1001  				if (proto.IsVarArg & VarArgNeedsArg) != 0 {
  1002  					argtb := newLTable(nvarargs, 0)
  1003  					for i := 0; i < nvarargs; i++ {
  1004  						argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i))
  1005  					}
  1006  					argtb.RawSetString("n", LNumber(nvarargs))
  1007  					//ls.reg.Set(cf.LocalBase+nargs+np, argtb)
  1008  					ls.reg.array[cf.LocalBase+nargs+np] = argtb
  1009  				} else {
  1010  					ls.reg.array[cf.LocalBase+nargs+np] = LNil
  1011  				}
  1012  			}
  1013  			cf.LocalBase += nargs
  1014  			maxreg := cf.LocalBase + int(proto.NumUsedRegisters)
  1015  			ls.reg.SetTop(maxreg)
  1016  		}
  1017  	}
  1018  } // +inline-end
  1019  
  1020  func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) { // +inline-start
  1021  	if meta {
  1022  		cf.NArgs++
  1023  		ls.reg.Insert(fn, cf.LocalBase)
  1024  	}
  1025  	if cf.Fn == nil {
  1026  		ls.RaiseError("attempt to call a non-function object")
  1027  	}
  1028  	if ls.stack.IsFull() {
  1029  		ls.RaiseError("stack overflow")
  1030  	}
  1031  	ls.stack.Push(cf)
  1032  	newcf := ls.stack.Last()
  1033  	// +inline-call ls.initCallFrame newcf
  1034  	ls.currentFrame = newcf
  1035  } // +inline-end
  1036  
  1037  func (ls *LState) callR(nargs, nret, rbase int) {
  1038  	base := ls.reg.Top() - nargs - 1
  1039  	if rbase < 0 {
  1040  		rbase = base
  1041  	}
  1042  	lv := ls.reg.Get(base)
  1043  	fn, meta := ls.metaCall(lv)
  1044  	ls.pushCallFrame(callFrame{
  1045  		Fn:         fn,
  1046  		Pc:         0,
  1047  		Base:       base,
  1048  		LocalBase:  base + 1,
  1049  		ReturnBase: rbase,
  1050  		NArgs:      nargs,
  1051  		NRet:       nret,
  1052  		Parent:     ls.currentFrame,
  1053  		TailCall:   0,
  1054  	}, lv, meta)
  1055  	if ls.G.MainThread == nil {
  1056  		ls.G.MainThread = ls
  1057  		ls.G.CurrentThread = ls
  1058  		ls.mainLoop(ls, nil)
  1059  	} else {
  1060  		ls.mainLoop(ls, ls.currentFrame)
  1061  	}
  1062  	if nret != MultRet {
  1063  		ls.reg.SetTop(rbase + nret)
  1064  	}
  1065  }
  1066  
  1067  func (ls *LState) getField(obj LValue, key LValue) LValue {
  1068  	curobj := obj
  1069  	for i := 0; i < MaxTableGetLoop; i++ {
  1070  		tb, istable := curobj.(*LTable)
  1071  		if istable {
  1072  			ret := tb.RawGet(key)
  1073  			if ret != LNil {
  1074  				return ret
  1075  			}
  1076  		}
  1077  		metaindex := ls.metaOp1(curobj, "__index")
  1078  		if metaindex == LNil {
  1079  			if !istable {
  1080  				ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key.String())
  1081  			}
  1082  			return LNil
  1083  		}
  1084  		if metaindex.Type() == LTFunction {
  1085  			ls.reg.Push(metaindex)
  1086  			ls.reg.Push(curobj)
  1087  			ls.reg.Push(key)
  1088  			ls.Call(2, 1)
  1089  			return ls.reg.Pop()
  1090  		} else {
  1091  			curobj = metaindex
  1092  		}
  1093  	}
  1094  	ls.RaiseError("too many recursions in gettable")
  1095  	return nil
  1096  }
  1097  
  1098  func (ls *LState) getFieldString(obj LValue, key string) LValue {
  1099  	curobj := obj
  1100  	for i := 0; i < MaxTableGetLoop; i++ {
  1101  		tb, istable := curobj.(*LTable)
  1102  		if istable {
  1103  			ret := tb.RawGetString(key)
  1104  			if ret != LNil {
  1105  				return ret
  1106  			}
  1107  		}
  1108  		metaindex := ls.metaOp1(curobj, "__index")
  1109  		if metaindex == LNil {
  1110  			if !istable {
  1111  				ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key)
  1112  			}
  1113  			return LNil
  1114  		}
  1115  		if metaindex.Type() == LTFunction {
  1116  			ls.reg.Push(metaindex)
  1117  			ls.reg.Push(curobj)
  1118  			ls.reg.Push(LString(key))
  1119  			ls.Call(2, 1)
  1120  			return ls.reg.Pop()
  1121  		} else {
  1122  			curobj = metaindex
  1123  		}
  1124  	}
  1125  	ls.RaiseError("too many recursions in gettable")
  1126  	return nil
  1127  }
  1128  
  1129  func (ls *LState) setField(obj LValue, key LValue, value LValue) {
  1130  	curobj := obj
  1131  	for i := 0; i < MaxTableGetLoop; i++ {
  1132  		tb, istable := curobj.(*LTable)
  1133  		if istable {
  1134  			if tb.RawGet(key) != LNil {
  1135  				ls.RawSet(tb, key, value)
  1136  				return
  1137  			}
  1138  		}
  1139  		metaindex := ls.metaOp1(curobj, "__newindex")
  1140  		if metaindex == LNil {
  1141  			if !istable {
  1142  				ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key.String())
  1143  			}
  1144  			ls.RawSet(tb, key, value)
  1145  			return
  1146  		}
  1147  		if metaindex.Type() == LTFunction {
  1148  			ls.reg.Push(metaindex)
  1149  			ls.reg.Push(curobj)
  1150  			ls.reg.Push(key)
  1151  			ls.reg.Push(value)
  1152  			ls.Call(3, 0)
  1153  			return
  1154  		} else {
  1155  			curobj = metaindex
  1156  		}
  1157  	}
  1158  	ls.RaiseError("too many recursions in settable")
  1159  }
  1160  
  1161  func (ls *LState) setFieldString(obj LValue, key string, value LValue) {
  1162  	curobj := obj
  1163  	for i := 0; i < MaxTableGetLoop; i++ {
  1164  		tb, istable := curobj.(*LTable)
  1165  		if istable {
  1166  			if tb.RawGetString(key) != LNil {
  1167  				tb.RawSetString(key, value)
  1168  				return
  1169  			}
  1170  		}
  1171  		metaindex := ls.metaOp1(curobj, "__newindex")
  1172  		if metaindex == LNil {
  1173  			if !istable {
  1174  				ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key)
  1175  			}
  1176  			tb.RawSetString(key, value)
  1177  			return
  1178  		}
  1179  		if metaindex.Type() == LTFunction {
  1180  			ls.reg.Push(metaindex)
  1181  			ls.reg.Push(curobj)
  1182  			ls.reg.Push(LString(key))
  1183  			ls.reg.Push(value)
  1184  			ls.Call(3, 0)
  1185  			return
  1186  		} else {
  1187  			curobj = metaindex
  1188  		}
  1189  	}
  1190  	ls.RaiseError("too many recursions in settable")
  1191  }
  1192  
  1193  /* }}} */
  1194  
  1195  /* api methods {{{ */
  1196  
  1197  func NewState(options *Options) *LState {
  1198  	var ls *LState
  1199  	if options == nil {
  1200  		ls = newLState(&Options{
  1201  			CallStackSize: CallStackSize,
  1202  			RegistrySize:  RegistrySize,
  1203  			Stdout:        os.Stdout,
  1204  		})
  1205  		ls.OpenLibs()
  1206  	} else {
  1207  		if options.Stdout == nil {
  1208  			options.Stdout = os.Stdout
  1209  		}
  1210  
  1211  		if options.CallStackSize < 1 {
  1212  			options.CallStackSize = CallStackSize
  1213  		}
  1214  		if options.RegistrySize < 128 {
  1215  			options.RegistrySize = RegistrySize
  1216  		}
  1217  		if options.RegistryMaxSize < options.RegistrySize {
  1218  			options.RegistryMaxSize = 0 // disable growth if max size is smaller than initial size
  1219  		} else {
  1220  			// if growth enabled, grow step is set
  1221  			if options.RegistryGrowStep < 1 {
  1222  				options.RegistryGrowStep = RegistryGrowStep
  1223  			}
  1224  		}
  1225  		ls = newLState(options)
  1226  		if !options.SkipOpenLibs {
  1227  			ls.OpenLibs()
  1228  		}
  1229  	}
  1230  	return ls
  1231  }
  1232  
  1233  func (ls *LState) IsClosed() bool {
  1234  	return ls.stack == nil
  1235  }
  1236  
  1237  func (ls *LState) Close() {
  1238  	atomic.AddInt32(&ls.stop, 1)
  1239  	for _, file := range ls.G.tempFiles {
  1240  		// ignore errors in these operations
  1241  		file.Close()
  1242  		os.Remove(file.Name())
  1243  	}
  1244  	ls.stack.FreeAll()
  1245  	ls.stack = nil
  1246  }
  1247  
  1248  /* registry operations {{{ */
  1249  
  1250  func (ls *LState) GetTop() int {
  1251  	return ls.reg.Top() - ls.currentLocalBase()
  1252  }
  1253  
  1254  func (ls *LState) SetTop(idx int) {
  1255  	base := ls.currentLocalBase()
  1256  	newtop := ls.indexToReg(idx) + 1
  1257  	if newtop < base {
  1258  		ls.reg.SetTop(base)
  1259  	} else {
  1260  		ls.reg.SetTop(newtop)
  1261  	}
  1262  }
  1263  
  1264  func (ls *LState) Replace(idx int, value LValue) {
  1265  	base := ls.currentLocalBase()
  1266  	if idx > 0 {
  1267  		reg := base + idx - 1
  1268  		if reg < ls.reg.Top() {
  1269  			ls.reg.Set(reg, value)
  1270  		}
  1271  	} else if idx == 0 {
  1272  	} else if idx > RegistryIndex {
  1273  		if tidx := ls.reg.Top() + idx; tidx >= base {
  1274  			ls.reg.Set(tidx, value)
  1275  		}
  1276  	} else {
  1277  		switch idx {
  1278  		case RegistryIndex:
  1279  			if tb, ok := value.(*LTable); ok {
  1280  				ls.G.Registry = tb
  1281  			} else {
  1282  				ls.RaiseError("registry must be a table(%v)", value.Type().String())
  1283  			}
  1284  		case EnvironIndex:
  1285  			if ls.currentFrame == nil {
  1286  				ls.RaiseError("no calling environment")
  1287  			}
  1288  			if tb, ok := value.(*LTable); ok {
  1289  				ls.currentFrame.Fn.Env = tb
  1290  			} else {
  1291  				ls.RaiseError("environment must be a table(%v)", value.Type().String())
  1292  			}
  1293  		case GlobalsIndex:
  1294  			if tb, ok := value.(*LTable); ok {
  1295  				ls.G.Global = tb
  1296  			} else {
  1297  				ls.RaiseError("_G must be a table(%v)", value.Type().String())
  1298  			}
  1299  		default:
  1300  			fn := ls.currentFrame.Fn
  1301  			index := GlobalsIndex - idx - 1
  1302  			if index < len(fn.Upvalues) {
  1303  				fn.Upvalues[index].SetValue(value)
  1304  			}
  1305  		}
  1306  	}
  1307  }
  1308  
  1309  func (ls *LState) Get(idx int) LValue {
  1310  	base := ls.currentLocalBase()
  1311  	if idx > 0 {
  1312  		reg := base + idx - 1
  1313  		if reg < ls.reg.Top() {
  1314  			return ls.reg.Get(reg)
  1315  		}
  1316  		return LNil
  1317  	} else if idx == 0 {
  1318  		return LNil
  1319  	} else if idx > RegistryIndex {
  1320  		tidx := ls.reg.Top() + idx
  1321  		if tidx < base {
  1322  			return LNil
  1323  		}
  1324  		return ls.reg.Get(tidx)
  1325  	} else {
  1326  		switch idx {
  1327  		case RegistryIndex:
  1328  			return ls.G.Registry
  1329  		case EnvironIndex:
  1330  			if ls.currentFrame == nil {
  1331  				return ls.Env
  1332  			}
  1333  			return ls.currentFrame.Fn.Env
  1334  		case GlobalsIndex:
  1335  			return ls.G.Global
  1336  		default:
  1337  			fn := ls.currentFrame.Fn
  1338  			index := GlobalsIndex - idx - 1
  1339  			if index < len(fn.Upvalues) {
  1340  				return fn.Upvalues[index].Value()
  1341  			}
  1342  			return LNil
  1343  		}
  1344  	}
  1345  	return LNil
  1346  }
  1347  
  1348  func (ls *LState) Push(value LValue) {
  1349  	ls.reg.Push(value)
  1350  }
  1351  
  1352  func (ls *LState) Pop(n int) {
  1353  	for i := 0; i < n; i++ {
  1354  		if ls.GetTop() == 0 {
  1355  			ls.RaiseError("register underflow")
  1356  		}
  1357  		ls.reg.Pop()
  1358  	}
  1359  }
  1360  
  1361  func (ls *LState) Insert(value LValue, index int) {
  1362  	reg := ls.indexToReg(index)
  1363  	top := ls.reg.Top()
  1364  	if reg >= top {
  1365  		ls.reg.Set(reg, value)
  1366  		return
  1367  	}
  1368  	if reg <= ls.currentLocalBase() {
  1369  		reg = ls.currentLocalBase()
  1370  	}
  1371  	top--
  1372  	for ; top >= reg; top-- {
  1373  		ls.reg.Set(top+1, ls.reg.Get(top))
  1374  	}
  1375  	ls.reg.Set(reg, value)
  1376  }
  1377  
  1378  func (ls *LState) Remove(index int) {
  1379  	reg := ls.indexToReg(index)
  1380  	top := ls.reg.Top()
  1381  	switch {
  1382  	case reg >= top:
  1383  		return
  1384  	case reg < ls.currentLocalBase():
  1385  		return
  1386  	case reg == top-1:
  1387  		ls.Pop(1)
  1388  		return
  1389  	}
  1390  	for i := reg; i < top-1; i++ {
  1391  		ls.reg.Set(i, ls.reg.Get(i+1))
  1392  	}
  1393  	ls.reg.SetTop(top - 1)
  1394  }
  1395  
  1396  /* }}} */
  1397  
  1398  /* object allocation {{{ */
  1399  
  1400  func (ls *LState) NewTable() *LTable {
  1401  	return newLTable(defaultArrayCap, defaultHashCap)
  1402  }
  1403  
  1404  func (ls *LState) CreateTable(acap, hcap int) *LTable {
  1405  	return newLTable(acap, hcap)
  1406  }
  1407  
  1408  // NewThread returns a new LState that shares with the original state all global objects.
  1409  // 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.
  1410  func (ls *LState) NewThread() (*LState, context.CancelFunc) {
  1411  	thread := newLState(ls.Options)
  1412  	thread.G = ls.G
  1413  	thread.Env = ls.Env
  1414  	var f context.CancelFunc = nil
  1415  	if ls.ctx != nil {
  1416  		thread.mainLoop = mainLoopWithContext
  1417  		thread.ctx, f = context.WithCancel(ls.ctx)
  1418  	}
  1419  	return thread, f
  1420  }
  1421  
  1422  func (ls *LState) NewFunctionFromProto(proto *FunctionProto) *LFunction {
  1423  	return newLFunctionL(proto, ls.Env, int(proto.NumUpvalues))
  1424  }
  1425  
  1426  func (ls *LState) NewUserData() *LUserData {
  1427  	return &LUserData{
  1428  		Env:       ls.currentEnv(),
  1429  		Metatable: LNil,
  1430  	}
  1431  }
  1432  
  1433  func (ls *LState) NewFunction(fn LGFunction) *LFunction {
  1434  	return newLFunctionG(fn, ls.currentEnv(), 0)
  1435  }
  1436  
  1437  func (ls *LState) NewClosure(fn LGFunction, upvalues ...LValue) *LFunction {
  1438  	cl := newLFunctionG(fn, ls.currentEnv(), len(upvalues))
  1439  	for i, lv := range upvalues {
  1440  		cl.Upvalues[i] = &Upvalue{}
  1441  		cl.Upvalues[i].Close()
  1442  		cl.Upvalues[i].SetValue(lv)
  1443  	}
  1444  	return cl
  1445  }
  1446  
  1447  /* }}} */
  1448  
  1449  /* toType {{{ */
  1450  
  1451  func (ls *LState) ToBool(n int) bool {
  1452  	return LVAsBool(ls.Get(n))
  1453  }
  1454  
  1455  func (ls *LState) ToInt(n int) int {
  1456  	if lv, ok := ls.Get(n).(LNumber); ok {
  1457  		return int(lv)
  1458  	}
  1459  	if lv, ok := ls.Get(n).(LString); ok {
  1460  		if num, err := parseNumber(string(lv)); err == nil {
  1461  			return int(num)
  1462  		}
  1463  	}
  1464  	return 0
  1465  }
  1466  
  1467  func (ls *LState) ToInt64(n int) int64 {
  1468  	if lv, ok := ls.Get(n).(LNumber); ok {
  1469  		return int64(lv)
  1470  	}
  1471  	if lv, ok := ls.Get(n).(LString); ok {
  1472  		if num, err := parseNumber(string(lv)); err == nil {
  1473  			return int64(num)
  1474  		}
  1475  	}
  1476  	return 0
  1477  }
  1478  
  1479  func (ls *LState) ToNumber(n int) LNumber {
  1480  	return LVAsNumber(ls.Get(n))
  1481  }
  1482  
  1483  func (ls *LState) ToString(n int) string {
  1484  	return LVAsString(ls.Get(n))
  1485  }
  1486  
  1487  func (ls *LState) ToTable(n int) *LTable {
  1488  	if lv, ok := ls.Get(n).(*LTable); ok {
  1489  		return lv
  1490  	}
  1491  	return nil
  1492  }
  1493  
  1494  func (ls *LState) ToFunction(n int) *LFunction {
  1495  	if lv, ok := ls.Get(n).(*LFunction); ok {
  1496  		return lv
  1497  	}
  1498  	return nil
  1499  }
  1500  
  1501  func (ls *LState) ToUserData(n int) *LUserData {
  1502  	if lv, ok := ls.Get(n).(*LUserData); ok {
  1503  		return lv
  1504  	}
  1505  	return nil
  1506  }
  1507  
  1508  func (ls *LState) ToThread(n int) *LState {
  1509  	if lv, ok := ls.Get(n).(*LState); ok {
  1510  		return lv
  1511  	}
  1512  	return nil
  1513  }
  1514  
  1515  /* }}} */
  1516  
  1517  /* error & debug operations {{{ */
  1518  
  1519  func (ls *LState) registryOverflow() {
  1520  	ls.RaiseError("registry overflow")
  1521  }
  1522  
  1523  // This function is equivalent to luaL_error( http://www.lua.org/manual/5.1/manual.html#luaL_error ).
  1524  func (ls *LState) RaiseError(format string, args ...interface{}) {
  1525  	ls.raiseError(1, format, args...)
  1526  }
  1527  
  1528  // This function is equivalent to lua_error( http://www.lua.org/manual/5.1/manual.html#lua_error ).
  1529  func (ls *LState) Error(lv LValue, level int) {
  1530  	if str, ok := lv.(LString); ok {
  1531  		ls.raiseError(level, string(str))
  1532  	} else {
  1533  		if !ls.hasErrorFunc {
  1534  			ls.closeAllUpvalues()
  1535  		}
  1536  		ls.Push(lv)
  1537  		ls.Panic(ls)
  1538  	}
  1539  }
  1540  
  1541  func (ls *LState) GetInfo(what string, dbg *Debug, fn LValue) (LValue, error) {
  1542  	if !strings.HasPrefix(what, ">") {
  1543  		fn = dbg.frame.Fn
  1544  	} else {
  1545  		what = what[1:]
  1546  	}
  1547  	f, ok := fn.(*LFunction)
  1548  	if !ok {
  1549  		return LNil, newApiErrorS(ApiErrorRun, "can not get debug info(an object in not a function)")
  1550  	}
  1551  
  1552  	retfn := false
  1553  	for _, c := range what {
  1554  		switch c {
  1555  		case 'f':
  1556  			retfn = true
  1557  		case 'S':
  1558  			if dbg.frame != nil && dbg.frame.Parent == nil {
  1559  				dbg.What = "main"
  1560  			} else if f.IsG {
  1561  				dbg.What = "G"
  1562  			} else if dbg.frame != nil && dbg.frame.TailCall > 0 {
  1563  				dbg.What = "tail"
  1564  			} else {
  1565  				dbg.What = "Lua"
  1566  			}
  1567  			if !f.IsG {
  1568  				dbg.Source = f.Proto.SourceName
  1569  				dbg.LineDefined = f.Proto.LineDefined
  1570  				dbg.LastLineDefined = f.Proto.LastLineDefined
  1571  			}
  1572  		case 'l':
  1573  			if !f.IsG && dbg.frame != nil {
  1574  				if dbg.frame.Pc > 0 {
  1575  					dbg.CurrentLine = f.Proto.DbgSourcePositions[dbg.frame.Pc-1]
  1576  				}
  1577  			} else {
  1578  				dbg.CurrentLine = -1
  1579  			}
  1580  		case 'u':
  1581  			dbg.NUpvalues = len(f.Upvalues)
  1582  		case 'n':
  1583  			if dbg.frame != nil {
  1584  				dbg.Name = ls.rawFrameFuncName(dbg.frame)
  1585  			}
  1586  		default:
  1587  			return LNil, newApiErrorS(ApiErrorRun, "invalid what: "+string(c))
  1588  		}
  1589  	}
  1590  
  1591  	if retfn {
  1592  		return f, nil
  1593  	}
  1594  	return LNil, nil
  1595  
  1596  }
  1597  
  1598  func (ls *LState) GetStack(level int) (*Debug, bool) {
  1599  	frame := ls.currentFrame
  1600  	for ; level > 0 && frame != nil; frame = frame.Parent {
  1601  		level--
  1602  		if !frame.Fn.IsG {
  1603  			level -= frame.TailCall
  1604  		}
  1605  	}
  1606  
  1607  	if level == 0 && frame != nil {
  1608  		return &Debug{frame: frame}, true
  1609  	} else if level < 0 && ls.stack.Sp() > 0 {
  1610  		return &Debug{frame: ls.stack.At(0)}, true
  1611  	}
  1612  	return &Debug{}, false
  1613  }
  1614  
  1615  func (ls *LState) GetLocal(dbg *Debug, no int) (string, LValue) {
  1616  	frame := dbg.frame
  1617  	if name := ls.findLocal(frame, no); len(name) > 0 {
  1618  		return name, ls.reg.Get(frame.LocalBase + no - 1)
  1619  	}
  1620  	return "", LNil
  1621  }
  1622  
  1623  func (ls *LState) SetLocal(dbg *Debug, no int, lv LValue) string {
  1624  	frame := dbg.frame
  1625  	if name := ls.findLocal(frame, no); len(name) > 0 {
  1626  		ls.reg.Set(frame.LocalBase+no-1, lv)
  1627  		return name
  1628  	}
  1629  	return ""
  1630  }
  1631  
  1632  func (ls *LState) GetUpvalue(fn *LFunction, no int) (string, LValue) {
  1633  	if fn.IsG {
  1634  		return "", LNil
  1635  	}
  1636  
  1637  	no--
  1638  	if no >= 0 && no < len(fn.Upvalues) {
  1639  		return fn.Proto.DbgUpvalues[no], fn.Upvalues[no].Value()
  1640  	}
  1641  	return "", LNil
  1642  }
  1643  
  1644  func (ls *LState) SetUpvalue(fn *LFunction, no int, lv LValue) string {
  1645  	if fn.IsG {
  1646  		return ""
  1647  	}
  1648  
  1649  	no--
  1650  	if no >= 0 && no < len(fn.Upvalues) {
  1651  		fn.Upvalues[no].SetValue(lv)
  1652  		return fn.Proto.DbgUpvalues[no]
  1653  	}
  1654  	return ""
  1655  }
  1656  
  1657  /* }}} */
  1658  
  1659  /* env operations {{{ */
  1660  
  1661  func (ls *LState) GetFEnv(obj LValue) LValue {
  1662  	switch lv := obj.(type) {
  1663  	case *LFunction:
  1664  		return lv.Env
  1665  	case *LUserData:
  1666  		return lv.Env
  1667  	case *LState:
  1668  		return lv.Env
  1669  	}
  1670  	return LNil
  1671  }
  1672  
  1673  func (ls *LState) SetFEnv(obj LValue, env LValue) {
  1674  	tb, ok := env.(*LTable)
  1675  	if !ok {
  1676  		ls.RaiseError("cannot use %v as an environment", env.Type().String())
  1677  	}
  1678  
  1679  	switch lv := obj.(type) {
  1680  	case *LFunction:
  1681  		lv.Env = tb
  1682  	case *LUserData:
  1683  		lv.Env = tb
  1684  	case *LState:
  1685  		lv.Env = tb
  1686  	}
  1687  	/* do nothing */
  1688  }
  1689  
  1690  /* }}} */
  1691  
  1692  /* table operations {{{ */
  1693  
  1694  func (ls *LState) RawGet(tb *LTable, key LValue) LValue {
  1695  	return tb.RawGet(key)
  1696  }
  1697  
  1698  func (ls *LState) RawGetInt(tb *LTable, key int) LValue {
  1699  	return tb.RawGetInt(key)
  1700  }
  1701  
  1702  func (ls *LState) GetField(obj LValue, skey string) LValue {
  1703  	return ls.getFieldString(obj, skey)
  1704  }
  1705  
  1706  func (ls *LState) GetTable(obj LValue, key LValue) LValue {
  1707  	return ls.getField(obj, key)
  1708  }
  1709  
  1710  func (ls *LState) RawSet(tb *LTable, key LValue, value LValue) {
  1711  	if n, ok := key.(LNumber); ok && math.IsNaN(float64(n)) {
  1712  		ls.RaiseError("table index is NaN")
  1713  	} else if key == LNil {
  1714  		ls.RaiseError("table index is nil")
  1715  	}
  1716  	tb.RawSet(key, value)
  1717  }
  1718  
  1719  func (ls *LState) RawSetInt(tb *LTable, key int, value LValue) {
  1720  	tb.RawSetInt(key, value)
  1721  }
  1722  
  1723  func (ls *LState) SetField(obj LValue, key string, value LValue) {
  1724  	ls.setFieldString(obj, key, value)
  1725  }
  1726  
  1727  func (ls *LState) SetTable(obj LValue, key LValue, value LValue) {
  1728  	ls.setField(obj, key, value)
  1729  }
  1730  
  1731  func (ls *LState) ForEach(tb *LTable, cb func(LValue, LValue)) {
  1732  	tb.ForEach(cb)
  1733  }
  1734  
  1735  func (ls *LState) GetGlobal(name string) LValue {
  1736  	return ls.GetField(ls.Get(GlobalsIndex), name)
  1737  }
  1738  
  1739  func (ls *LState) SetGlobal(name string, value LValue) {
  1740  	ls.SetField(ls.Get(GlobalsIndex), name, value)
  1741  }
  1742  
  1743  func (ls *LState) Next(tb *LTable, key LValue) (LValue, LValue) {
  1744  	return tb.Next(key)
  1745  }
  1746  
  1747  /* }}} */
  1748  
  1749  /* unary operations {{{ */
  1750  
  1751  func (ls *LState) ObjLen(v1 LValue) int {
  1752  	if v1.Type() == LTString {
  1753  		return len(string(v1.(LString)))
  1754  	}
  1755  	op := ls.metaOp1(v1, "__len")
  1756  	if op.Type() == LTFunction {
  1757  		ls.Push(op)
  1758  		ls.Push(v1)
  1759  		ls.Call(1, 1)
  1760  		ret := ls.reg.Pop()
  1761  		if ret.Type() == LTNumber {
  1762  			return int(ret.(LNumber))
  1763  		}
  1764  	} else if v1.Type() == LTTable {
  1765  		return v1.(*LTable).Len()
  1766  	}
  1767  	return 0
  1768  }
  1769  
  1770  /* }}} */
  1771  
  1772  /* binary operations {{{ */
  1773  
  1774  func (ls *LState) Concat(values ...LValue) string {
  1775  	top := ls.reg.Top()
  1776  	for _, value := range values {
  1777  		ls.reg.Push(value)
  1778  	}
  1779  	ret := stringConcat(ls, len(values), ls.reg.Top()-1)
  1780  	ls.reg.SetTop(top)
  1781  	return LVAsString(ret)
  1782  }
  1783  
  1784  func (ls *LState) LessThan(lhs, rhs LValue) bool {
  1785  	return lessThan(ls, lhs, rhs)
  1786  }
  1787  
  1788  func (ls *LState) Equal(lhs, rhs LValue) bool {
  1789  	return equals(ls, lhs, rhs, false)
  1790  }
  1791  
  1792  func (ls *LState) RawEqual(lhs, rhs LValue) bool {
  1793  	return equals(ls, lhs, rhs, true)
  1794  }
  1795  
  1796  /* }}} */
  1797  
  1798  /* register operations {{{ */
  1799  
  1800  func (ls *LState) Register(name string, fn LGFunction) {
  1801  	ls.SetGlobal(name, ls.NewFunction(fn))
  1802  }
  1803  
  1804  /* }}} */
  1805  
  1806  /* load and function call operations {{{ */
  1807  
  1808  func (ls *LState) Load(reader io.Reader, name string) (*LFunction, error) {
  1809  	chunk, err := parse.Parse(reader, name)
  1810  	if err != nil {
  1811  		return nil, newApiErrorE(ApiErrorSyntax, err)
  1812  	}
  1813  	proto, err := Compile(chunk, name)
  1814  	if err != nil {
  1815  		return nil, newApiErrorE(ApiErrorSyntax, err)
  1816  	}
  1817  	return newLFunctionL(proto, ls.currentEnv(), 0), nil
  1818  }
  1819  
  1820  func (ls *LState) Call(nargs, nret int) {
  1821  	ls.callR(nargs, nret, -1)
  1822  }
  1823  
  1824  func (ls *LState) PCall(nargs, nret int, errfunc *LFunction) (err error) {
  1825  	err = nil
  1826  	sp := ls.stack.Sp()
  1827  	base := ls.reg.Top() - nargs - 1
  1828  	oldpanic := ls.Panic
  1829  	ls.Panic = panicWithoutTraceback
  1830  	if errfunc != nil {
  1831  		ls.hasErrorFunc = true
  1832  	}
  1833  	defer func() {
  1834  		ls.Panic = oldpanic
  1835  		ls.hasErrorFunc = false
  1836  		rcv := recover()
  1837  		if rcv != nil {
  1838  			if _, ok := rcv.(*ApiError); !ok {
  1839  				err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv))
  1840  				if ls.Options.IncludeGoStackTrace {
  1841  					buf := make([]byte, 4096)
  1842  					runtime.Stack(buf, false)
  1843  					err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + "\n" + ls.stackTrace(0)
  1844  				}
  1845  			} else {
  1846  				err = rcv.(*ApiError)
  1847  			}
  1848  			if errfunc != nil {
  1849  				ls.Push(errfunc)
  1850  				ls.Push(err.(*ApiError).Object)
  1851  				ls.Panic = panicWithoutTraceback
  1852  				defer func() {
  1853  					ls.Panic = oldpanic
  1854  					rcv := recover()
  1855  					if rcv != nil {
  1856  						if _, ok := rcv.(*ApiError); !ok {
  1857  							err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv))
  1858  							if ls.Options.IncludeGoStackTrace {
  1859  								buf := make([]byte, 4096)
  1860  								runtime.Stack(buf, false)
  1861  								err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + ls.stackTrace(0)
  1862  							}
  1863  						} else {
  1864  							err = rcv.(*ApiError)
  1865  							err.(*ApiError).StackTrace = ls.stackTrace(0)
  1866  						}
  1867  					}
  1868  				}()
  1869  				ls.Call(1, 1)
  1870  				err = newApiError(ApiErrorError, ls.Get(-1))
  1871  			} else if len(err.(*ApiError).StackTrace) == 0 {
  1872  				err.(*ApiError).StackTrace = ls.stackTrace(0)
  1873  			}
  1874  			ls.stack.SetSp(sp)
  1875  			ls.currentFrame = ls.stack.Last()
  1876  			ls.reg.SetTop(base)
  1877  		}
  1878  		ls.stack.SetSp(sp)
  1879  		if sp == 0 {
  1880  			ls.currentFrame = nil
  1881  		}
  1882  	}()
  1883  
  1884  	ls.Call(nargs, nret)
  1885  
  1886  	return
  1887  }
  1888  
  1889  func (ls *LState) GPCall(fn LGFunction, data LValue) error {
  1890  	ls.Push(newLFunctionG(fn, ls.currentEnv(), 0))
  1891  	ls.Push(data)
  1892  	return ls.PCall(1, MultRet, nil)
  1893  }
  1894  
  1895  func (ls *LState) CallByParam(cp P, args ...LValue) error {
  1896  	ls.Push(cp.Fn)
  1897  	for _, arg := range args {
  1898  		ls.Push(arg)
  1899  	}
  1900  
  1901  	if cp.Protect {
  1902  		return ls.PCall(len(args), cp.NRet, cp.Handler)
  1903  	}
  1904  	ls.Call(len(args), cp.NRet)
  1905  	return nil
  1906  }
  1907  
  1908  /* }}} */
  1909  
  1910  /* metatable operations {{{ */
  1911  
  1912  func (ls *LState) GetMetatable(obj LValue) LValue {
  1913  	return ls.metatable(obj, false)
  1914  }
  1915  
  1916  func (ls *LState) SetMetatable(obj LValue, mt LValue) {
  1917  	switch mt.(type) {
  1918  	case *LNilType, *LTable:
  1919  	default:
  1920  		ls.RaiseError("metatable must be a table or nil, but got %v", mt.Type().String())
  1921  	}
  1922  
  1923  	switch v := obj.(type) {
  1924  	case *LTable:
  1925  		v.Metatable = mt
  1926  	case *LUserData:
  1927  		v.Metatable = mt
  1928  	default:
  1929  		ls.G.builtinMts[int(obj.Type())] = mt
  1930  	}
  1931  }
  1932  
  1933  /* }}} */
  1934  
  1935  /* coroutine operations {{{ */
  1936  
  1937  func (ls *LState) Status(th *LState) string {
  1938  	status := "suspended"
  1939  	if th.Dead {
  1940  		status = "dead"
  1941  	} else if ls.G.CurrentThread == th {
  1942  		status = "running"
  1943  	} else if ls.Parent == th {
  1944  		status = "normal"
  1945  	}
  1946  	return status
  1947  }
  1948  
  1949  func (ls *LState) Resume(th *LState, fn *LFunction, args ...LValue) (ResumeState, error, []LValue) {
  1950  	isstarted := th.isStarted()
  1951  	if !isstarted {
  1952  		base := 0
  1953  		th.stack.Push(callFrame{
  1954  			Fn:         fn,
  1955  			Pc:         0,
  1956  			Base:       base,
  1957  			LocalBase:  base + 1,
  1958  			ReturnBase: base,
  1959  			NArgs:      0,
  1960  			NRet:       MultRet,
  1961  			Parent:     nil,
  1962  			TailCall:   0,
  1963  		})
  1964  	}
  1965  
  1966  	if ls.G.CurrentThread == th {
  1967  		return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a running thread"), nil
  1968  	}
  1969  	if th.Dead {
  1970  		return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a dead thread"), nil
  1971  	}
  1972  	th.Parent = ls
  1973  	ls.G.CurrentThread = th
  1974  	if !isstarted {
  1975  		cf := th.stack.Last()
  1976  		th.currentFrame = cf
  1977  		th.SetTop(0)
  1978  		for _, arg := range args {
  1979  			th.Push(arg)
  1980  		}
  1981  		cf.NArgs = len(args)
  1982  		th.initCallFrame(cf)
  1983  		th.Panic = panicWithoutTraceback
  1984  	} else {
  1985  		for _, arg := range args {
  1986  			th.Push(arg)
  1987  		}
  1988  	}
  1989  	top := ls.GetTop()
  1990  	threadRun(th)
  1991  	haserror := LVIsFalse(ls.Get(top + 1))
  1992  	ret := make([]LValue, 0, ls.GetTop())
  1993  	for idx := top + 2; idx <= ls.GetTop(); idx++ {
  1994  		ret = append(ret, ls.Get(idx))
  1995  	}
  1996  	if len(ret) == 0 {
  1997  		ret = append(ret, LNil)
  1998  	}
  1999  	ls.SetTop(top)
  2000  
  2001  	if haserror {
  2002  		return ResumeError, newApiError(ApiErrorRun, ret[0]), nil
  2003  	} else if th.stack.IsEmpty() {
  2004  		return ResumeOK, nil, ret
  2005  	}
  2006  	return ResumeYield, nil, ret
  2007  }
  2008  
  2009  func (ls *LState) Yield(values ...LValue) int {
  2010  	ls.SetTop(0)
  2011  	for _, lv := range values {
  2012  		ls.Push(lv)
  2013  	}
  2014  	return -1
  2015  }
  2016  
  2017  func (ls *LState) XMoveTo(other *LState, n int) {
  2018  	if ls == other {
  2019  		return
  2020  	}
  2021  	top := ls.GetTop()
  2022  	n = intMin(n, top)
  2023  	for i := n; i > 0; i-- {
  2024  		other.Push(ls.Get(top - i + 1))
  2025  	}
  2026  	ls.SetTop(top - n)
  2027  }
  2028  
  2029  /* }}} */
  2030  
  2031  /* GopherLua original APIs {{{ */
  2032  
  2033  // Set maximum memory size. This function can only be called from the main thread.
  2034  func (ls *LState) SetMx(mx int) {
  2035  	if ls.Parent != nil {
  2036  		ls.RaiseError("sub threads are not allowed to set a memory limit")
  2037  	}
  2038  	go func() {
  2039  		limit := uint64(mx * 1024 * 1024) //MB
  2040  		var s runtime.MemStats
  2041  		for atomic.LoadInt32(&ls.stop) == 0 {
  2042  			runtime.ReadMemStats(&s)
  2043  			if s.Alloc >= limit {
  2044  				fmt.Println("out of memory")
  2045  				os.Exit(3)
  2046  			}
  2047  			time.Sleep(100 * time.Millisecond)
  2048  		}
  2049  	}()
  2050  }
  2051  
  2052  // SetContext set a context ctx to this LState. The provided ctx must be non-nil.
  2053  func (ls *LState) SetContext(ctx context.Context) {
  2054  	ls.mainLoop = mainLoopWithContext
  2055  	ls.ctx = ctx
  2056  }
  2057  
  2058  // Context returns the LState's context. To change the context, use WithContext.
  2059  func (ls *LState) Context() context.Context {
  2060  	return ls.ctx
  2061  }
  2062  
  2063  // RemoveContext removes the context associated with this LState and returns this context.
  2064  func (ls *LState) RemoveContext() context.Context {
  2065  	oldctx := ls.ctx
  2066  	ls.mainLoop = mainLoop
  2067  	ls.ctx = nil
  2068  	return oldctx
  2069  }
  2070  
  2071  // Converts the Lua value at the given acceptable index to the chan LValue.
  2072  func (ls *LState) ToChannel(n int) chan LValue {
  2073  	if lv, ok := ls.Get(n).(LChannel); ok {
  2074  		return (chan LValue)(lv)
  2075  	}
  2076  	return nil
  2077  }
  2078  
  2079  // RemoveCallerFrame removes the stack frame above the current stack frame. This is useful in tail calls. It returns
  2080  // the new current frame.
  2081  func (ls *LState) RemoveCallerFrame() *callFrame {
  2082  	cs := ls.stack
  2083  	sp := cs.Sp()
  2084  	parentFrame := cs.At(sp - 2)
  2085  	currentFrame := cs.At(sp - 1)
  2086  	parentsParentFrame := parentFrame.Parent
  2087  	*parentFrame = *currentFrame
  2088  	parentFrame.Parent = parentsParentFrame
  2089  	parentFrame.Idx = sp - 2
  2090  	cs.Pop()
  2091  	return parentFrame
  2092  }
  2093  
  2094  /* }}} */
  2095  
  2096  /* }}} */
  2097  
  2098  //