github.com/bitxmesh/gopher-lua@v0.0.0-20190327085718-93c344ef97a4/_state.go (about)

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