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