github.com/erikdubbelboer/gopher-lua@v0.0.0-20160512044044-e68f0dc85040/_state.go (about)

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