gitee.com/yfmps/gopher-lua@v0.0.3/_vm.go (about)

     1  package lua
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"strings"
     7  )
     8  
     9  func mainLoop(L *LState, baseframe *callFrame) {
    10  	var inst uint32
    11  	var cf *callFrame
    12  
    13  	if L.stack.IsEmpty() {
    14  		return
    15  	}
    16  
    17  	L.currentFrame = L.stack.Last()
    18  	if L.currentFrame.Fn.IsG {
    19  		callGFunction(L, false)
    20  		return
    21  	}
    22  
    23  	for {
    24  		cf = L.currentFrame
    25  		inst = cf.Fn.Proto.Code[cf.Pc]
    26  		cf.Pc++
    27  		if L.lhook != nil {
    28  			L.lhook.call(L, cf)
    29  		}
    30  		if L.cthook != nil {
    31  			L.cthook.call(L, cf)
    32  		}
    33  		if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 {
    34  			return
    35  		}
    36  	}
    37  }
    38  
    39  func mainLoopWithContext(L *LState, baseframe *callFrame) {
    40  	var inst uint32
    41  	var cf *callFrame
    42  
    43  	if L.stack.IsEmpty() {
    44  		return
    45  	}
    46  
    47  	L.currentFrame = L.stack.Last()
    48  	if L.currentFrame.Fn.IsG {
    49  		callGFunction(L, false)
    50  		return
    51  	}
    52  
    53  	for {
    54  		cf = L.currentFrame
    55  		inst = cf.Fn.Proto.Code[cf.Pc]
    56  		cf.Pc++
    57  		select {
    58  		case <-L.ctx.Done():
    59  			L.RaiseError(L.ctx.Err().Error())
    60  			return
    61  		default:
    62  			if L.lhook != nil {
    63  				L.lhook.call(L, cf)
    64  			}
    65  			if L.cthook != nil {
    66  				L.cthook.call(L, cf)
    67  			}
    68  			if jumpTable[int(inst>>26)](L, inst, baseframe) == 1 {
    69  				return
    70  			}
    71  		}
    72  	}
    73  }
    74  
    75  // regv is the first target register to copy the return values to.
    76  // It can be reg.top, indicating that the copied values are going into new registers, or it can be below reg.top
    77  // Indicating that the values should be within the existing registers.
    78  // b is the available number of return values + 1.
    79  // n is the desired number of return values.
    80  // If n more than the available return values then the extra values are set to nil.
    81  // When this function returns the top of the registry will be set to regv+n.
    82  func copyReturnValues(L *LState, regv, start, n, b int) { // +inline-start
    83  	if b == 1 {
    84  		// +inline-call L.reg.FillNil  regv n
    85  	} else {
    86  		// +inline-call L.reg.CopyRange regv start -1 n
    87  		if b > 1 && n > (b-1) {
    88  			// +inline-call L.reg.FillNil  regv+b-1 n-(b-1)
    89  		}
    90  	}
    91  } // +inline-end
    92  
    93  func switchToParentThread(L *LState, nargs int, haserror bool, kill bool) {
    94  	parent := L.Parent
    95  	if parent == nil {
    96  		L.RaiseError("can not yield from outside of a coroutine")
    97  	}
    98  	L.G.CurrentThread = parent
    99  	L.Parent = nil
   100  	if !L.wrapped {
   101  		if haserror {
   102  			parent.Push(LFalse)
   103  		} else {
   104  			parent.Push(LTrue)
   105  		}
   106  	}
   107  	L.XMoveTo(parent, nargs)
   108  	L.stack.Pop()
   109  	offset := L.currentFrame.LocalBase - L.currentFrame.ReturnBase
   110  	L.currentFrame = L.stack.Last()
   111  	L.reg.SetTop(L.reg.Top() - offset) // remove 'yield' function(including tailcalled functions)
   112  	if kill {
   113  		L.kill()
   114  	}
   115  }
   116  
   117  func callGFunction(L *LState, tailcall bool) bool {
   118  	frame := L.currentFrame
   119  	gfnret := frame.Fn.GFunction(L)
   120  	if tailcall {
   121  		L.currentFrame = L.RemoveCallerFrame()
   122  	}
   123  
   124  	if gfnret < 0 {
   125  		switchToParentThread(L, L.GetTop(), false, false)
   126  		return true
   127  	}
   128  
   129  	wantret := frame.NRet
   130  	if wantret == MultRet {
   131  		wantret = gfnret
   132  	}
   133  
   134  	if tailcall && L.Parent != nil && L.stack.Sp() == 1 {
   135  		switchToParentThread(L, wantret, false, true)
   136  		return true
   137  	}
   138  
   139  	// +inline-call L.reg.CopyRange frame.ReturnBase L.reg.Top()-gfnret -1 wantret
   140  	L.stack.Pop()
   141  	L.currentFrame = L.stack.Last()
   142  	return false
   143  }
   144  
   145  func threadRun(L *LState) {
   146  	if L.stack.IsEmpty() {
   147  		return
   148  	}
   149  
   150  	defer func() {
   151  		if rcv := recover(); rcv != nil {
   152  			var lv LValue
   153  			if v, ok := rcv.(*ApiError); ok {
   154  				lv = v.Object
   155  			} else {
   156  				lv = LString(fmt.Sprint(rcv))
   157  			}
   158  			if parent := L.Parent; parent != nil {
   159  				if L.wrapped {
   160  					L.Push(lv)
   161  					parent.Panic(L)
   162  				} else {
   163  					L.SetTop(0)
   164  					L.Push(lv)
   165  					switchToParentThread(L, 1, true, true)
   166  				}
   167  			} else {
   168  				panic(rcv)
   169  			}
   170  		}
   171  	}()
   172  	L.mainLoop(L, nil)
   173  }
   174  
   175  type instFunc func(*LState, uint32, *callFrame) int
   176  
   177  var jumpTable [opCodeMax + 1]instFunc
   178  
   179  func init() {
   180  	jumpTable = [opCodeMax + 1]instFunc{
   181  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVE
   182  			reg := L.reg
   183  			cf := L.currentFrame
   184  			lbase := cf.LocalBase
   185  			A := int(inst>>18) & 0xff //GETA
   186  			RA := lbase + A
   187  			B := int(inst & 0x1ff) //GETB
   188  			reg.Set(RA, reg.Get(lbase+B))
   189  			return 0
   190  		},
   191  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVEN
   192  			reg := L.reg
   193  			cf := L.currentFrame
   194  			lbase := cf.LocalBase
   195  			A := int(inst>>18) & 0xff //GETA
   196  			B := int(inst & 0x1ff)    //GETB
   197  			C := int(inst>>9) & 0x1ff //GETC
   198  			reg.Set(lbase+A, reg.Get(lbase+B))
   199  			code := cf.Fn.Proto.Code
   200  			pc := cf.Pc
   201  			for i := 0; i < C; i++ {
   202  				inst = code[pc]
   203  				pc++
   204  				A = int(inst>>18) & 0xff //GETA
   205  				B = int(inst & 0x1ff)    //GETB
   206  				reg.Set(lbase+A, reg.Get(lbase+B))
   207  			}
   208  			cf.Pc = pc
   209  			return 0
   210  		},
   211  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADK
   212  			reg := L.reg
   213  			cf := L.currentFrame
   214  			lbase := cf.LocalBase
   215  			A := int(inst>>18) & 0xff //GETA
   216  			RA := lbase + A
   217  			Bx := int(inst & 0x3ffff) //GETBX
   218  			reg.Set(RA, cf.Fn.Proto.Constants[Bx])
   219  			return 0
   220  		},
   221  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADBOOL
   222  			reg := L.reg
   223  			cf := L.currentFrame
   224  			lbase := cf.LocalBase
   225  			A := int(inst>>18) & 0xff //GETA
   226  			RA := lbase + A
   227  			B := int(inst & 0x1ff)    //GETB
   228  			C := int(inst>>9) & 0x1ff //GETC
   229  			if B != 0 {
   230  				reg.Set(RA, LTrue)
   231  			} else {
   232  				reg.Set(RA, LFalse)
   233  			}
   234  			if C != 0 {
   235  				cf.Pc++
   236  			}
   237  			return 0
   238  		},
   239  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADNIL
   240  			reg := L.reg
   241  			cf := L.currentFrame
   242  			lbase := cf.LocalBase
   243  			A := int(inst>>18) & 0xff //GETA
   244  			RA := lbase + A
   245  			B := int(inst & 0x1ff) //GETB
   246  			for i := RA; i <= lbase+B; i++ {
   247  				reg.Set(i, LNil)
   248  			}
   249  			return 0
   250  		},
   251  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETUPVAL
   252  			reg := L.reg
   253  			cf := L.currentFrame
   254  			lbase := cf.LocalBase
   255  			A := int(inst>>18) & 0xff //GETA
   256  			RA := lbase + A
   257  			B := int(inst & 0x1ff) //GETB
   258  			reg.Set(RA, cf.Fn.Upvalues[B].Value())
   259  			return 0
   260  		},
   261  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETGLOBAL
   262  			reg := L.reg
   263  			cf := L.currentFrame
   264  			lbase := cf.LocalBase
   265  			A := int(inst>>18) & 0xff //GETA
   266  			RA := lbase + A
   267  			Bx := int(inst & 0x3ffff) //GETBX
   268  			//reg.Set(RA, L.getField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx]))
   269  			reg.Set(RA, L.getFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx]))
   270  			return 0
   271  		},
   272  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLE
   273  			reg := L.reg
   274  			cf := L.currentFrame
   275  			lbase := cf.LocalBase
   276  			A := int(inst>>18) & 0xff //GETA
   277  			RA := lbase + A
   278  			B := int(inst & 0x1ff)    //GETB
   279  			C := int(inst>>9) & 0x1ff //GETC
   280  			reg.Set(RA, L.getField(reg.Get(lbase+B), L.rkValue(C)))
   281  			return 0
   282  		},
   283  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLEKS
   284  			reg := L.reg
   285  			cf := L.currentFrame
   286  			lbase := cf.LocalBase
   287  			A := int(inst>>18) & 0xff //GETA
   288  			RA := lbase + A
   289  			B := int(inst & 0x1ff)    //GETB
   290  			C := int(inst>>9) & 0x1ff //GETC
   291  			reg.Set(RA, L.getFieldString(reg.Get(lbase+B), L.rkString(C)))
   292  			return 0
   293  		},
   294  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETGLOBAL
   295  			reg := L.reg
   296  			cf := L.currentFrame
   297  			lbase := cf.LocalBase
   298  			A := int(inst>>18) & 0xff //GETA
   299  			RA := lbase + A
   300  			Bx := int(inst & 0x3ffff) //GETBX
   301  			//L.setField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx], reg.Get(RA))
   302  			L.setFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx], reg.Get(RA))
   303  			return 0
   304  		},
   305  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETUPVAL
   306  			reg := L.reg
   307  			cf := L.currentFrame
   308  			lbase := cf.LocalBase
   309  			A := int(inst>>18) & 0xff //GETA
   310  			RA := lbase + A
   311  			B := int(inst & 0x1ff) //GETB
   312  			cf.Fn.Upvalues[B].SetValue(reg.Get(RA))
   313  			return 0
   314  		},
   315  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLE
   316  			reg := L.reg
   317  			cf := L.currentFrame
   318  			lbase := cf.LocalBase
   319  			A := int(inst>>18) & 0xff //GETA
   320  			RA := lbase + A
   321  			B := int(inst & 0x1ff)    //GETB
   322  			C := int(inst>>9) & 0x1ff //GETC
   323  			L.setField(reg.Get(RA), L.rkValue(B), L.rkValue(C))
   324  			return 0
   325  		},
   326  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLEKS
   327  			reg := L.reg
   328  			cf := L.currentFrame
   329  			lbase := cf.LocalBase
   330  			A := int(inst>>18) & 0xff //GETA
   331  			RA := lbase + A
   332  			B := int(inst & 0x1ff)    //GETB
   333  			C := int(inst>>9) & 0x1ff //GETC
   334  			L.setFieldString(reg.Get(RA), L.rkString(B), L.rkValue(C))
   335  			return 0
   336  		},
   337  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NEWTABLE
   338  			reg := L.reg
   339  			cf := L.currentFrame
   340  			lbase := cf.LocalBase
   341  			A := int(inst>>18) & 0xff //GETA
   342  			RA := lbase + A
   343  			B := int(inst & 0x1ff)    //GETB
   344  			C := int(inst>>9) & 0x1ff //GETC
   345  			reg.Set(RA, newLTable(B, C))
   346  			return 0
   347  		},
   348  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SELF
   349  			reg := L.reg
   350  			cf := L.currentFrame
   351  			lbase := cf.LocalBase
   352  			A := int(inst>>18) & 0xff //GETA
   353  			RA := lbase + A
   354  			B := int(inst & 0x1ff)    //GETB
   355  			C := int(inst>>9) & 0x1ff //GETC
   356  			selfobj := reg.Get(lbase + B)
   357  			reg.Set(RA, L.getFieldString(selfobj, L.rkString(C)))
   358  			reg.Set(RA+1, selfobj)
   359  			return 0
   360  		},
   361  		opArith, // OP_ADD
   362  		opArith, // OP_SUB
   363  		opArith, // OP_MUL
   364  		opArith, // OP_DIV
   365  		opArith, // OP_MOD
   366  		opArith, // OP_POW
   367  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_UNM
   368  			reg := L.reg
   369  			cf := L.currentFrame
   370  			lbase := cf.LocalBase
   371  			A := int(inst>>18) & 0xff //GETA
   372  			RA := lbase + A
   373  			B := int(inst & 0x1ff) //GETB
   374  			unaryv := L.rkValue(B)
   375  			if nm, ok := unaryv.(LNumber); ok {
   376  				reg.SetNumber(RA, -nm)
   377  			} else {
   378  				op := L.metaOp1(unaryv, "__unm")
   379  				if op.Type() == LTFunction {
   380  					reg.Push(op)
   381  					reg.Push(unaryv)
   382  					L.Call(1, 1)
   383  					reg.Set(RA, reg.Pop())
   384  				} else if str, ok1 := unaryv.(LString); ok1 {
   385  					if num, err := parseNumber(string(str)); err == nil {
   386  						reg.Set(RA, -num)
   387  					} else {
   388  						L.RaiseError("__unm undefined")
   389  					}
   390  				} else {
   391  					L.RaiseError("__unm undefined")
   392  				}
   393  			}
   394  			return 0
   395  		},
   396  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOT
   397  			reg := L.reg
   398  			cf := L.currentFrame
   399  			lbase := cf.LocalBase
   400  			A := int(inst>>18) & 0xff //GETA
   401  			RA := lbase + A
   402  			B := int(inst & 0x1ff) //GETB
   403  			if LVIsFalse(reg.Get(lbase + B)) {
   404  				reg.Set(RA, LTrue)
   405  			} else {
   406  				reg.Set(RA, LFalse)
   407  			}
   408  			return 0
   409  		},
   410  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LEN
   411  			reg := L.reg
   412  			cf := L.currentFrame
   413  			lbase := cf.LocalBase
   414  			A := int(inst>>18) & 0xff //GETA
   415  			RA := lbase + A
   416  			B := int(inst & 0x1ff) //GETB
   417  			switch lv := L.rkValue(B).(type) {
   418  			case LString:
   419  				reg.SetNumber(RA, LNumber(len(lv)))
   420  			default:
   421  				op := L.metaOp1(lv, "__len")
   422  				if op.Type() == LTFunction {
   423  					reg.Push(op)
   424  					reg.Push(lv)
   425  					L.Call(1, 1)
   426  					ret := reg.Pop()
   427  					if ret.Type() == LTNumber {
   428  						reg.SetNumber(RA, ret.(LNumber))
   429  					} else {
   430  						reg.SetNumber(RA, LNumber(0))
   431  					}
   432  				} else if lv.Type() == LTTable {
   433  					reg.SetNumber(RA, LNumber(lv.(*LTable).Len()))
   434  				} else {
   435  					L.RaiseError("__len undefined")
   436  				}
   437  			}
   438  			return 0
   439  		},
   440  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CONCAT
   441  			reg := L.reg
   442  			cf := L.currentFrame
   443  			lbase := cf.LocalBase
   444  			A := int(inst>>18) & 0xff //GETA
   445  			RA := lbase + A
   446  			B := int(inst & 0x1ff)    //GETB
   447  			C := int(inst>>9) & 0x1ff //GETC
   448  			RC := lbase + C
   449  			RB := lbase + B
   450  			reg.Set(RA, stringConcat(L, RC-RB+1, RC))
   451  			return 0
   452  		},
   453  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_JMP
   454  			cf := L.currentFrame
   455  			Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX
   456  			cf.Pc += Sbx
   457  			return 0
   458  		},
   459  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_EQ
   460  			cf := L.currentFrame
   461  			A := int(inst>>18) & 0xff //GETA
   462  			B := int(inst & 0x1ff)    //GETB
   463  			C := int(inst>>9) & 0x1ff //GETC
   464  			ret := equals(L, L.rkValue(B), L.rkValue(C), false)
   465  			v := 1
   466  			if ret {
   467  				v = 0
   468  			}
   469  			if v == A {
   470  				cf.Pc++
   471  			}
   472  			return 0
   473  		},
   474  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LT
   475  			cf := L.currentFrame
   476  			A := int(inst>>18) & 0xff //GETA
   477  			B := int(inst & 0x1ff)    //GETB
   478  			C := int(inst>>9) & 0x1ff //GETC
   479  			ret := lessThan(L, L.rkValue(B), L.rkValue(C))
   480  			v := 1
   481  			if ret {
   482  				v = 0
   483  			}
   484  			if v == A {
   485  				cf.Pc++
   486  			}
   487  			return 0
   488  		},
   489  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LE
   490  			cf := L.currentFrame
   491  			A := int(inst>>18) & 0xff //GETA
   492  			B := int(inst & 0x1ff)    //GETB
   493  			C := int(inst>>9) & 0x1ff //GETC
   494  			lhs := L.rkValue(B)
   495  			rhs := L.rkValue(C)
   496  			ret := false
   497  
   498  			if v1, ok1 := lhs.assertFloat64(); ok1 {
   499  				if v2, ok2 := rhs.assertFloat64(); ok2 {
   500  					ret = v1 <= v2
   501  				} else {
   502  					L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
   503  				}
   504  			} else {
   505  				if lhs.Type() != rhs.Type() {
   506  					L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
   507  				}
   508  				switch lhs.Type() {
   509  				case LTString:
   510  					ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) <= 0
   511  				default:
   512  					switch objectRational(L, lhs, rhs, "__le") {
   513  					case 1:
   514  						ret = true
   515  					case 0:
   516  						ret = false
   517  					default:
   518  						ret = !objectRationalWithError(L, rhs, lhs, "__lt")
   519  					}
   520  				}
   521  			}
   522  
   523  			v := 1
   524  			if ret {
   525  				v = 0
   526  			}
   527  			if v == A {
   528  				cf.Pc++
   529  			}
   530  			return 0
   531  		},
   532  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TEST
   533  			reg := L.reg
   534  			cf := L.currentFrame
   535  			lbase := cf.LocalBase
   536  			A := int(inst>>18) & 0xff //GETA
   537  			RA := lbase + A
   538  			C := int(inst>>9) & 0x1ff //GETC
   539  			if LVAsBool(reg.Get(RA)) == (C == 0) {
   540  				cf.Pc++
   541  			}
   542  			return 0
   543  		},
   544  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TESTSET
   545  			reg := L.reg
   546  			cf := L.currentFrame
   547  			lbase := cf.LocalBase
   548  			A := int(inst>>18) & 0xff //GETA
   549  			RA := lbase + A
   550  			B := int(inst & 0x1ff)    //GETB
   551  			C := int(inst>>9) & 0x1ff //GETC
   552  			if value := reg.Get(lbase + B); LVAsBool(value) != (C == 0) {
   553  				reg.Set(RA, value)
   554  			} else {
   555  				cf.Pc++
   556  			}
   557  			return 0
   558  		},
   559  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CALL
   560  			if L.chook != nil {
   561  				L.chook.call(L, baseframe)
   562  			}
   563  			reg := L.reg
   564  			cf := L.currentFrame
   565  			lbase := cf.LocalBase
   566  			A := int(inst>>18) & 0xff //GETA
   567  			RA := lbase + A
   568  			B := int(inst & 0x1ff)    //GETB
   569  			C := int(inst>>9) & 0x1ff //GETC
   570  			nargs := B - 1
   571  			if B == 0 {
   572  				nargs = reg.Top() - (RA + 1)
   573  			}
   574  			lv := reg.Get(RA)
   575  			nret := C - 1
   576  			var callable *LFunction
   577  			var meta bool
   578  			if fn, ok := lv.assertFunction(); ok {
   579  				callable = fn
   580  				meta = false
   581  			} else {
   582  				callable, meta = L.metaCall(lv)
   583  			}
   584  			// +inline-call L.pushCallFrame callFrame{Fn:callable,Pc:0,Base:RA,LocalBase:RA+1,ReturnBase:RA,NArgs:nargs,NRet:nret,Parent:cf,TailCall:0} lv meta
   585  			if callable.IsG && callGFunction(L, false) {
   586  				return 1
   587  			}
   588  			return 0
   589  		},
   590  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TAILCALL
   591  			reg := L.reg
   592  			cf := L.currentFrame
   593  			lbase := cf.LocalBase
   594  			A := int(inst>>18) & 0xff //GETA
   595  			RA := lbase + A
   596  			B := int(inst & 0x1ff) //GETB
   597  			nargs := B - 1
   598  			if B == 0 {
   599  				nargs = reg.Top() - (RA + 1)
   600  			}
   601  			lv := reg.Get(RA)
   602  			var callable *LFunction
   603  			var meta bool
   604  			if fn, ok := lv.assertFunction(); ok {
   605  				callable = fn
   606  				meta = false
   607  			} else {
   608  				callable, meta = L.metaCall(lv)
   609  			}
   610  			if callable == nil {
   611  				L.RaiseError("attempt to call a non-function object")
   612  			}
   613  			// +inline-call L.closeUpvalues lbase
   614  			if callable.IsG {
   615  				luaframe := cf
   616  				L.pushCallFrame(callFrame{
   617  					Fn:         callable,
   618  					Pc:         0,
   619  					Base:       RA,
   620  					LocalBase:  RA + 1,
   621  					ReturnBase: cf.ReturnBase,
   622  					NArgs:      nargs,
   623  					NRet:       cf.NRet,
   624  					Parent:     cf,
   625  					TailCall:   0,
   626  				}, lv, meta)
   627  				if callGFunction(L, true) {
   628  					return 1
   629  				}
   630  				if L.currentFrame == nil || L.currentFrame.Fn.IsG || luaframe == baseframe {
   631  					return 1
   632  				}
   633  			} else {
   634  				base := cf.Base
   635  				cf.Fn = callable
   636  				cf.Pc = 0
   637  				cf.Base = RA
   638  				cf.LocalBase = RA + 1
   639  				cf.ReturnBase = cf.ReturnBase
   640  				cf.NArgs = nargs
   641  				cf.NRet = cf.NRet
   642  				cf.TailCall++
   643  				lbase := cf.LocalBase
   644  				if meta {
   645  					cf.NArgs++
   646  					L.reg.Insert(lv, cf.LocalBase)
   647  				}
   648  				// +inline-call L.initCallFrame cf
   649  				// +inline-call L.reg.CopyRange base RA -1 reg.Top()-RA-1
   650  				cf.Base = base
   651  				cf.LocalBase = base + (cf.LocalBase - lbase + 1)
   652  			}
   653  			return 0
   654  		},
   655  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN
   656  			if L.rhook != nil {
   657  				L.rhook.call(L, baseframe)
   658  			}
   659  			reg := L.reg
   660  			cf := L.currentFrame
   661  			lbase := cf.LocalBase
   662  			A := int(inst>>18) & 0xff //GETA
   663  			RA := lbase + A
   664  			B := int(inst & 0x1ff) //GETB
   665  			// +inline-call L.closeUpvalues lbase
   666  			nret := B - 1
   667  			if B == 0 {
   668  				nret = reg.Top() - RA
   669  			}
   670  			n := cf.NRet
   671  			if cf.NRet == MultRet {
   672  				n = nret
   673  			}
   674  
   675  			if L.Parent != nil && L.stack.Sp() == 1 {
   676  				// +inline-call copyReturnValues L reg.Top() RA n B
   677  				switchToParentThread(L, n, false, true)
   678  				return 1
   679  			}
   680  			islast := baseframe == L.stack.Pop() || L.stack.IsEmpty()
   681  			// +inline-call copyReturnValues L cf.ReturnBase RA n B
   682  			L.currentFrame = L.stack.Last()
   683  			if islast || L.currentFrame == nil || L.currentFrame.Fn.IsG {
   684  				return 1
   685  			}
   686  			return 0
   687  		},
   688  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORLOOP
   689  			reg := L.reg
   690  			cf := L.currentFrame
   691  			lbase := cf.LocalBase
   692  			A := int(inst>>18) & 0xff //GETA
   693  			RA := lbase + A
   694  			if init, ok1 := reg.Get(RA).assertFloat64(); ok1 {
   695  				if limit, ok2 := reg.Get(RA + 1).assertFloat64(); ok2 {
   696  					if step, ok3 := reg.Get(RA + 2).assertFloat64(); ok3 {
   697  						init += step
   698  						reg.SetNumber(RA, LNumber(init))
   699  						if (step > 0 && init <= limit) || (step <= 0 && init >= limit) {
   700  							Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX
   701  							cf.Pc += Sbx
   702  							reg.SetNumber(RA+3, LNumber(init))
   703  						} else {
   704  							reg.SetTop(RA + 1)
   705  						}
   706  					} else {
   707  						L.RaiseError("for statement step must be a number")
   708  					}
   709  				} else {
   710  					L.RaiseError("for statement limit must be a number")
   711  				}
   712  			} else {
   713  				L.RaiseError("for statement init must be a number")
   714  			}
   715  			return 0
   716  		},
   717  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORPREP
   718  			reg := L.reg
   719  			cf := L.currentFrame
   720  			lbase := cf.LocalBase
   721  			A := int(inst>>18) & 0xff //GETA
   722  			RA := lbase + A
   723  			Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX
   724  			if init, ok1 := reg.Get(RA).assertFloat64(); ok1 {
   725  				if step, ok2 := reg.Get(RA + 2).assertFloat64(); ok2 {
   726  					reg.SetNumber(RA, LNumber(init-step))
   727  				} else {
   728  					L.RaiseError("for statement step must be a number")
   729  				}
   730  			} else {
   731  				L.RaiseError("for statement init must be a number")
   732  			}
   733  			cf.Pc += Sbx
   734  			return 0
   735  		},
   736  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TFORLOOP
   737  			reg := L.reg
   738  			cf := L.currentFrame
   739  			lbase := cf.LocalBase
   740  			A := int(inst>>18) & 0xff //GETA
   741  			RA := lbase + A
   742  			C := int(inst>>9) & 0x1ff //GETC
   743  			nret := C
   744  			reg.SetTop(RA + 3 + 2)
   745  			reg.Set(RA+3+2, reg.Get(RA+2))
   746  			reg.Set(RA+3+1, reg.Get(RA+1))
   747  			reg.Set(RA+3, reg.Get(RA))
   748  			L.callR(2, nret, RA+3)
   749  			if value := reg.Get(RA + 3); value != LNil {
   750  				reg.Set(RA+2, value)
   751  				pc := cf.Fn.Proto.Code[cf.Pc]
   752  				cf.Pc += int(pc&0x3ffff) - opMaxArgSbx
   753  			}
   754  			cf.Pc++
   755  			return 0
   756  		},
   757  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETLIST
   758  			reg := L.reg
   759  			cf := L.currentFrame
   760  			lbase := cf.LocalBase
   761  			A := int(inst>>18) & 0xff //GETA
   762  			RA := lbase + A
   763  			B := int(inst & 0x1ff)    //GETB
   764  			C := int(inst>>9) & 0x1ff //GETC
   765  			if C == 0 {
   766  				C = int(cf.Fn.Proto.Code[cf.Pc])
   767  				cf.Pc++
   768  			}
   769  			offset := (C - 1) * FieldsPerFlush
   770  			table := reg.Get(RA).(*LTable)
   771  			nelem := B
   772  			if B == 0 {
   773  				nelem = reg.Top() - RA - 1
   774  			}
   775  			for i := 1; i <= nelem; i++ {
   776  				table.RawSetInt(offset+i, reg.Get(RA+i))
   777  			}
   778  			return 0
   779  		},
   780  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSE
   781  			cf := L.currentFrame
   782  			lbase := cf.LocalBase
   783  			A := int(inst>>18) & 0xff //GETA
   784  			RA := lbase + A
   785  			// +inline-call L.closeUpvalues RA
   786  			return 0
   787  		},
   788  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSURE
   789  			reg := L.reg
   790  			cf := L.currentFrame
   791  			lbase := cf.LocalBase
   792  			A := int(inst>>18) & 0xff //GETA
   793  			RA := lbase + A
   794  			Bx := int(inst & 0x3ffff) //GETBX
   795  			proto := cf.Fn.Proto.FunctionPrototypes[Bx]
   796  			closure := newLFunctionL(proto, cf.Fn.Env, int(proto.NumUpvalues))
   797  			reg.Set(RA, closure)
   798  			for i := 0; i < int(proto.NumUpvalues); i++ {
   799  				inst = cf.Fn.Proto.Code[cf.Pc]
   800  				cf.Pc++
   801  				B := opGetArgB(inst)
   802  				switch opGetOpCode(inst) {
   803  				case OP_MOVE:
   804  					closure.Upvalues[i] = L.findUpvalue(lbase + B)
   805  				case OP_GETUPVAL:
   806  					closure.Upvalues[i] = cf.Fn.Upvalues[B]
   807  				}
   808  			}
   809  			return 0
   810  		},
   811  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_VARARG
   812  			reg := L.reg
   813  			cf := L.currentFrame
   814  			lbase := cf.LocalBase
   815  			A := int(inst>>18) & 0xff //GETA
   816  			RA := lbase + A
   817  			B := int(inst & 0x1ff) //GETB
   818  			nparams := int(cf.Fn.Proto.NumParameters)
   819  			nvarargs := cf.NArgs - nparams
   820  			if nvarargs < 0 {
   821  				nvarargs = 0
   822  			}
   823  			nwant := B - 1
   824  			if B == 0 {
   825  				nwant = nvarargs
   826  			}
   827  			// +inline-call reg.CopyRange RA cf.Base+nparams+1 cf.LocalBase nwant
   828  			return 0
   829  		},
   830  		func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOP
   831  			return 0
   832  		},
   833  	}
   834  }
   835  
   836  func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW
   837  	reg := L.reg
   838  	cf := L.currentFrame
   839  	lbase := cf.LocalBase
   840  	A := int(inst>>18) & 0xff //GETA
   841  	RA := lbase + A
   842  	opcode := int(inst >> 26) //GETOPCODE
   843  	B := int(inst & 0x1ff)    //GETB
   844  	C := int(inst>>9) & 0x1ff //GETC
   845  	lhs := L.rkValue(B)
   846  	rhs := L.rkValue(C)
   847  	v1, ok1 := lhs.assertFloat64()
   848  	v2, ok2 := rhs.assertFloat64()
   849  	if ok1 && ok2 {
   850  		reg.SetNumber(RA, numberArith(L, opcode, LNumber(v1), LNumber(v2)))
   851  	} else {
   852  		reg.Set(RA, objectArith(L, opcode, lhs, rhs))
   853  	}
   854  	return 0
   855  }
   856  
   857  func luaModulo(lhs, rhs LNumber) LNumber {
   858  	flhs := float64(lhs)
   859  	frhs := float64(rhs)
   860  	v := math.Mod(flhs, frhs)
   861  	if flhs < 0 || frhs < 0 && !(flhs < 0 && frhs < 0) {
   862  		v += frhs
   863  	}
   864  	return LNumber(v)
   865  }
   866  
   867  func numberArith(L *LState, opcode int, lhs, rhs LNumber) LNumber {
   868  	switch opcode {
   869  	case OP_ADD:
   870  		return lhs + rhs
   871  	case OP_SUB:
   872  		return lhs - rhs
   873  	case OP_MUL:
   874  		return lhs * rhs
   875  	case OP_DIV:
   876  		return lhs / rhs
   877  	case OP_MOD:
   878  		return luaModulo(lhs, rhs)
   879  	case OP_POW:
   880  		flhs := float64(lhs)
   881  		frhs := float64(rhs)
   882  		return LNumber(math.Pow(flhs, frhs))
   883  	}
   884  	panic("should not reach here")
   885  	return LNumber(0)
   886  }
   887  
   888  func objectArith(L *LState, opcode int, lhs, rhs LValue) LValue {
   889  	event := ""
   890  	switch opcode {
   891  	case OP_ADD:
   892  		event = "__add"
   893  	case OP_SUB:
   894  		event = "__sub"
   895  	case OP_MUL:
   896  		event = "__mul"
   897  	case OP_DIV:
   898  		event = "__div"
   899  	case OP_MOD:
   900  		event = "__mod"
   901  	case OP_POW:
   902  		event = "__pow"
   903  	}
   904  	op := L.metaOp2(lhs, rhs, event)
   905  	if op.Type() == LTFunction {
   906  		L.reg.Push(op)
   907  		L.reg.Push(lhs)
   908  		L.reg.Push(rhs)
   909  		L.Call(2, 1)
   910  		return L.reg.Pop()
   911  	}
   912  	if str, ok := lhs.(LString); ok {
   913  		if lnum, err := parseNumber(string(str)); err == nil {
   914  			lhs = lnum
   915  		}
   916  	}
   917  	if str, ok := rhs.(LString); ok {
   918  		if rnum, err := parseNumber(string(str)); err == nil {
   919  			rhs = rnum
   920  		}
   921  	}
   922  	if v1, ok1 := lhs.assertFloat64(); ok1 {
   923  		if v2, ok2 := rhs.assertFloat64(); ok2 {
   924  			return numberArith(L, opcode, LNumber(v1), LNumber(v2))
   925  		}
   926  	}
   927  	L.RaiseError(fmt.Sprintf("cannot perform %v operation between %v and %v",
   928  		strings.TrimLeft(event, "_"), lhs.Type().String(), rhs.Type().String()))
   929  
   930  	return LNil
   931  }
   932  
   933  func stringConcat(L *LState, total, last int) LValue {
   934  	rhs := L.reg.Get(last)
   935  	total--
   936  	for i := last - 1; total > 0; {
   937  		lhs := L.reg.Get(i)
   938  		if !(LVCanConvToString(lhs) && LVCanConvToString(rhs)) {
   939  			op := L.metaOp2(lhs, rhs, "__concat")
   940  			if op.Type() == LTFunction {
   941  				L.reg.Push(op)
   942  				L.reg.Push(lhs)
   943  				L.reg.Push(rhs)
   944  				L.Call(2, 1)
   945  				rhs = L.reg.Pop()
   946  				total--
   947  				i--
   948  			} else {
   949  				L.RaiseError("cannot perform concat operation between %v and %v", lhs.Type().String(), rhs.Type().String())
   950  				return LNil
   951  			}
   952  		} else {
   953  			buf := make([]string, total+1)
   954  			buf[total] = LVAsString(rhs)
   955  			for total > 0 {
   956  				lhs = L.reg.Get(i)
   957  				if !LVCanConvToString(lhs) {
   958  					break
   959  				}
   960  				buf[total-1] = LVAsString(lhs)
   961  				i--
   962  				total--
   963  			}
   964  			rhs = LString(strings.Join(buf, ""))
   965  		}
   966  	}
   967  	return rhs
   968  }
   969  
   970  func lessThan(L *LState, lhs, rhs LValue) bool {
   971  	// optimization for numbers
   972  	if v1, ok1 := lhs.assertFloat64(); ok1 {
   973  		if v2, ok2 := rhs.assertFloat64(); ok2 {
   974  			return v1 < v2
   975  		}
   976  		L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
   977  	}
   978  	if lhs.Type() != rhs.Type() {
   979  		L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
   980  		return false
   981  	}
   982  	ret := false
   983  	switch lhs.Type() {
   984  	case LTString:
   985  		ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) < 0
   986  	default:
   987  		ret = objectRationalWithError(L, lhs, rhs, "__lt")
   988  	}
   989  	return ret
   990  }
   991  
   992  func equals(L *LState, lhs, rhs LValue, raw bool) bool {
   993  	if lhs.Type() != rhs.Type() {
   994  		return false
   995  	}
   996  
   997  	ret := false
   998  	switch lhs.Type() {
   999  	case LTNil:
  1000  		ret = true
  1001  	case LTNumber:
  1002  		v1, _ := lhs.assertFloat64()
  1003  		v2, _ := rhs.assertFloat64()
  1004  		ret = v1 == v2
  1005  	case LTBool:
  1006  		ret = bool(lhs.(LBool)) == bool(rhs.(LBool))
  1007  	case LTString:
  1008  		ret = string(lhs.(LString)) == string(rhs.(LString))
  1009  	case LTUserData, LTTable:
  1010  		if lhs == rhs {
  1011  			ret = true
  1012  		} else if !raw {
  1013  			switch objectRational(L, lhs, rhs, "__eq") {
  1014  			case 1:
  1015  				ret = true
  1016  			default:
  1017  				ret = false
  1018  			}
  1019  		}
  1020  	default:
  1021  		ret = lhs == rhs
  1022  	}
  1023  	return ret
  1024  }
  1025  
  1026  func objectRationalWithError(L *LState, lhs, rhs LValue, event string) bool {
  1027  	switch objectRational(L, lhs, rhs, event) {
  1028  	case 1:
  1029  		return true
  1030  	case 0:
  1031  		return false
  1032  	}
  1033  	L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String())
  1034  	return false
  1035  }
  1036  
  1037  func objectRational(L *LState, lhs, rhs LValue, event string) int {
  1038  	m1 := L.metaOp1(lhs, event)
  1039  	m2 := L.metaOp1(rhs, event)
  1040  	if m1.Type() == LTFunction && m1 == m2 {
  1041  		L.reg.Push(m1)
  1042  		L.reg.Push(lhs)
  1043  		L.reg.Push(rhs)
  1044  		L.Call(2, 1)
  1045  		if LVAsBool(L.reg.Pop()) {
  1046  			return 1
  1047  		}
  1048  		return 0
  1049  	}
  1050  	return -1
  1051  }