github.com/xmx/lua@v0.0.0-20230324063450-8a298e091302/state.go (about)

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