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