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

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