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