github.com/guardangely/gopher-lua@v0.0.0-20200324075529-f92e6f279f59/_state.go (about)

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