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