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