github.com/qiniu/gopher-lua@v0.2017.11/_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 reg.Set(RA, reg.Pop()) 406 } else if lv.Type() == LTTable { 407 reg.SetNumber(RA, LNumber(lv.(*LTable).Len())) 408 } else { 409 L.RaiseError("__len undefined") 410 } 411 } 412 return 0 413 }, 414 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CONCAT 415 reg := L.reg 416 cf := L.currentFrame 417 lbase := cf.LocalBase 418 A := int(inst>>18) & 0xff //GETA 419 RA := lbase + A 420 B := int(inst & 0x1ff) //GETB 421 C := int(inst>>9) & 0x1ff //GETC 422 RC := lbase + C 423 RB := lbase + B 424 reg.Set(RA, stringConcat(L, RC-RB+1, RC)) 425 return 0 426 }, 427 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_JMP 428 cf := L.currentFrame 429 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 430 cf.Pc += Sbx 431 return 0 432 }, 433 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_EQ 434 cf := L.currentFrame 435 A := int(inst>>18) & 0xff //GETA 436 B := int(inst & 0x1ff) //GETB 437 C := int(inst>>9) & 0x1ff //GETC 438 ret := equals(L, L.rkValue(B), L.rkValue(C), false) 439 v := 1 440 if ret { 441 v = 0 442 } 443 if v == A { 444 cf.Pc++ 445 } 446 return 0 447 }, 448 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LT 449 cf := L.currentFrame 450 A := int(inst>>18) & 0xff //GETA 451 B := int(inst & 0x1ff) //GETB 452 C := int(inst>>9) & 0x1ff //GETC 453 ret := lessThan(L, L.rkValue(B), L.rkValue(C)) 454 v := 1 455 if ret { 456 v = 0 457 } 458 if v == A { 459 cf.Pc++ 460 } 461 return 0 462 }, 463 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LE 464 cf := L.currentFrame 465 A := int(inst>>18) & 0xff //GETA 466 B := int(inst & 0x1ff) //GETB 467 C := int(inst>>9) & 0x1ff //GETC 468 lhs := L.rkValue(B) 469 rhs := L.rkValue(C) 470 ret := false 471 472 if v1, ok1 := lhs.assertFloat64(); ok1 { 473 if v2, ok2 := rhs.assertFloat64(); ok2 { 474 ret = v1 <= v2 475 } else { 476 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 477 } 478 } else { 479 if lhs.Type() != rhs.Type() { 480 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 481 } 482 switch lhs.Type() { 483 case LTString: 484 ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) <= 0 485 default: 486 switch objectRational(L, lhs, rhs, "__le") { 487 case 1: 488 ret = true 489 case 0: 490 ret = false 491 default: 492 ret = !objectRationalWithError(L, rhs, lhs, "__lt") 493 } 494 } 495 } 496 497 v := 1 498 if ret { 499 v = 0 500 } 501 if v == A { 502 cf.Pc++ 503 } 504 return 0 505 }, 506 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TEST 507 reg := L.reg 508 cf := L.currentFrame 509 lbase := cf.LocalBase 510 A := int(inst>>18) & 0xff //GETA 511 RA := lbase + A 512 C := int(inst>>9) & 0x1ff //GETC 513 if LVAsBool(reg.Get(RA)) == (C == 0) { 514 cf.Pc++ 515 } 516 return 0 517 }, 518 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TESTSET 519 reg := L.reg 520 cf := L.currentFrame 521 lbase := cf.LocalBase 522 A := int(inst>>18) & 0xff //GETA 523 RA := lbase + A 524 B := int(inst & 0x1ff) //GETB 525 C := int(inst>>9) & 0x1ff //GETC 526 if value := reg.Get(lbase + B); LVAsBool(value) != (C == 0) { 527 reg.Set(RA, value) 528 } else { 529 cf.Pc++ 530 } 531 return 0 532 }, 533 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CALL 534 reg := L.reg 535 cf := L.currentFrame 536 lbase := cf.LocalBase 537 A := int(inst>>18) & 0xff //GETA 538 RA := lbase + A 539 B := int(inst & 0x1ff) //GETB 540 C := int(inst>>9) & 0x1ff //GETC 541 nargs := B - 1 542 if B == 0 { 543 nargs = reg.Top() - (RA + 1) 544 } 545 lv := reg.Get(RA) 546 nret := C - 1 547 var callable *LFunction 548 var meta bool 549 if fn, ok := lv.assertFunction(); ok { 550 callable = fn 551 meta = false 552 } else { 553 callable, meta = L.metaCall(lv) 554 } 555 // +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 556 if callable.IsG && callGFunction(L, false) { 557 return 1 558 } 559 return 0 560 }, 561 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TAILCALL 562 reg := L.reg 563 cf := L.currentFrame 564 lbase := cf.LocalBase 565 A := int(inst>>18) & 0xff //GETA 566 RA := lbase + A 567 B := int(inst & 0x1ff) //GETB 568 nargs := B - 1 569 if B == 0 { 570 nargs = reg.Top() - (RA + 1) 571 } 572 lv := reg.Get(RA) 573 var callable *LFunction 574 var meta bool 575 if fn, ok := lv.assertFunction(); ok { 576 callable = fn 577 meta = false 578 } else { 579 callable, meta = L.metaCall(lv) 580 } 581 if callable == nil { 582 L.RaiseError("attempt to call a non-function object") 583 } 584 // +inline-call L.closeUpvalues lbase 585 if callable.IsG { 586 luaframe := cf 587 L.pushCallFrame(callFrame{ 588 Fn: callable, 589 Pc: 0, 590 Base: RA, 591 LocalBase: RA + 1, 592 ReturnBase: cf.ReturnBase, 593 NArgs: nargs, 594 NRet: cf.NRet, 595 Parent: cf, 596 TailCall: 0, 597 }, lv, meta) 598 if callGFunction(L, true) { 599 return 1 600 } 601 if L.currentFrame == nil || L.currentFrame.Fn.IsG || luaframe == baseframe { 602 return 1 603 } 604 } else { 605 base := cf.Base 606 cf.Fn = callable 607 cf.Pc = 0 608 cf.Base = RA 609 cf.LocalBase = RA + 1 610 cf.ReturnBase = cf.ReturnBase 611 cf.NArgs = nargs 612 cf.NRet = cf.NRet 613 cf.TailCall++ 614 lbase := cf.LocalBase 615 if meta { 616 cf.NArgs++ 617 L.reg.Insert(lv, cf.LocalBase) 618 } 619 // +inline-call L.initCallFrame cf 620 // +inline-call L.reg.CopyRange base RA -1 reg.Top()-RA-1 621 cf.Base = base 622 cf.LocalBase = base + (cf.LocalBase - lbase + 1) 623 } 624 return 0 625 }, 626 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN 627 reg := L.reg 628 cf := L.currentFrame 629 lbase := cf.LocalBase 630 A := int(inst>>18) & 0xff //GETA 631 RA := lbase + A 632 B := int(inst & 0x1ff) //GETB 633 // +inline-call L.closeUpvalues lbase 634 nret := B - 1 635 if B == 0 { 636 nret = reg.Top() - RA 637 } 638 n := cf.NRet 639 if cf.NRet == MultRet { 640 n = nret 641 } 642 643 if L.Parent != nil && L.stack.Sp() == 1 { 644 // +inline-call copyReturnValues L reg.Top() RA n B 645 switchToParentThread(L, n, false, true) 646 return 1 647 } 648 islast := baseframe == L.stack.Pop() || L.stack.IsEmpty() 649 // +inline-call copyReturnValues L cf.ReturnBase RA n B 650 L.currentFrame = L.stack.Last() 651 if islast || L.currentFrame == nil || L.currentFrame.Fn.IsG { 652 return 1 653 } 654 return 0 655 }, 656 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORLOOP 657 reg := L.reg 658 cf := L.currentFrame 659 lbase := cf.LocalBase 660 A := int(inst>>18) & 0xff //GETA 661 RA := lbase + A 662 if init, ok1 := reg.Get(RA).assertFloat64(); ok1 { 663 if limit, ok2 := reg.Get(RA + 1).assertFloat64(); ok2 { 664 if step, ok3 := reg.Get(RA + 2).assertFloat64(); ok3 { 665 init += step 666 reg.SetNumber(RA, LNumber(init)) 667 if (step > 0 && init <= limit) || (step <= 0 && init >= limit) { 668 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 669 cf.Pc += Sbx 670 reg.SetNumber(RA+3, LNumber(init)) 671 } else { 672 reg.SetTop(RA + 1) 673 } 674 } else { 675 L.RaiseError("for statement step must be a number") 676 } 677 } else { 678 L.RaiseError("for statement limit must be a number") 679 } 680 } else { 681 L.RaiseError("for statement init must be a number") 682 } 683 return 0 684 }, 685 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORPREP 686 reg := L.reg 687 cf := L.currentFrame 688 lbase := cf.LocalBase 689 A := int(inst>>18) & 0xff //GETA 690 RA := lbase + A 691 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 692 if init, ok1 := reg.Get(RA).assertFloat64(); ok1 { 693 if step, ok2 := reg.Get(RA + 2).assertFloat64(); ok2 { 694 reg.SetNumber(RA, LNumber(init-step)) 695 } else { 696 L.RaiseError("for statement step must be a number") 697 } 698 } else { 699 L.RaiseError("for statement init must be a number") 700 } 701 cf.Pc += Sbx 702 return 0 703 }, 704 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TFORLOOP 705 reg := L.reg 706 cf := L.currentFrame 707 lbase := cf.LocalBase 708 A := int(inst>>18) & 0xff //GETA 709 RA := lbase + A 710 C := int(inst>>9) & 0x1ff //GETC 711 nret := C 712 reg.SetTop(RA + 3 + 2) 713 reg.Set(RA+3+2, reg.Get(RA+2)) 714 reg.Set(RA+3+1, reg.Get(RA+1)) 715 reg.Set(RA+3, reg.Get(RA)) 716 L.callR(2, nret, RA+3) 717 if value := reg.Get(RA + 3); value != LNil { 718 reg.Set(RA+2, value) 719 pc := cf.Fn.Proto.Code[cf.Pc] 720 cf.Pc += int(pc&0x3ffff) - opMaxArgSbx 721 } 722 cf.Pc++ 723 return 0 724 }, 725 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETLIST 726 reg := L.reg 727 cf := L.currentFrame 728 lbase := cf.LocalBase 729 A := int(inst>>18) & 0xff //GETA 730 RA := lbase + A 731 B := int(inst & 0x1ff) //GETB 732 C := int(inst>>9) & 0x1ff //GETC 733 if C == 0 { 734 C = int(cf.Fn.Proto.Code[cf.Pc]) 735 cf.Pc++ 736 } 737 offset := (C - 1) * FieldsPerFlush 738 table := reg.Get(RA).(*LTable) 739 nelem := B 740 if B == 0 { 741 nelem = reg.Top() - RA - 1 742 } 743 for i := 1; i <= nelem; i++ { 744 table.RawSetInt(offset+i, reg.Get(RA+i)) 745 } 746 return 0 747 }, 748 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSE 749 cf := L.currentFrame 750 lbase := cf.LocalBase 751 A := int(inst>>18) & 0xff //GETA 752 RA := lbase + A 753 // +inline-call L.closeUpvalues RA 754 return 0 755 }, 756 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSURE 757 reg := L.reg 758 cf := L.currentFrame 759 lbase := cf.LocalBase 760 A := int(inst>>18) & 0xff //GETA 761 RA := lbase + A 762 Bx := int(inst & 0x3ffff) //GETBX 763 proto := cf.Fn.Proto.FunctionPrototypes[Bx] 764 closure := newLFunctionL(proto, cf.Fn.Env, int(proto.NumUpvalues)) 765 reg.Set(RA, closure) 766 for i := 0; i < int(proto.NumUpvalues); i++ { 767 inst = cf.Fn.Proto.Code[cf.Pc] 768 cf.Pc++ 769 B := opGetArgB(inst) 770 switch opGetOpCode(inst) { 771 case OP_MOVE: 772 closure.Upvalues[i] = L.findUpvalue(lbase + B) 773 case OP_GETUPVAL: 774 closure.Upvalues[i] = cf.Fn.Upvalues[B] 775 } 776 } 777 return 0 778 }, 779 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_VARARG 780 reg := L.reg 781 cf := L.currentFrame 782 lbase := cf.LocalBase 783 A := int(inst>>18) & 0xff //GETA 784 RA := lbase + A 785 B := int(inst & 0x1ff) //GETB 786 nparams := int(cf.Fn.Proto.NumParameters) 787 nvarargs := cf.NArgs - nparams 788 if nvarargs < 0 { 789 nvarargs = 0 790 } 791 nwant := B - 1 792 if B == 0 { 793 nwant = nvarargs 794 } 795 // +inline-call reg.CopyRange RA cf.Base+nparams+1 cf.LocalBase nwant 796 return 0 797 }, 798 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOP 799 return 0 800 }, 801 } 802 } 803 804 func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW 805 reg := L.reg 806 cf := L.currentFrame 807 lbase := cf.LocalBase 808 A := int(inst>>18) & 0xff //GETA 809 RA := lbase + A 810 opcode := int(inst >> 26) //GETOPCODE 811 B := int(inst & 0x1ff) //GETB 812 C := int(inst>>9) & 0x1ff //GETC 813 lhs := L.rkValue(B) 814 rhs := L.rkValue(C) 815 v1, ok1 := lhs.assertFloat64() 816 v2, ok2 := rhs.assertFloat64() 817 if ok1 && ok2 { 818 reg.SetNumber(RA, numberArith(L, opcode, LNumber(v1), LNumber(v2))) 819 } else { 820 reg.Set(RA, objectArith(L, opcode, lhs, rhs)) 821 } 822 return 0 823 } 824 825 func luaModulo(lhs, rhs LNumber) LNumber { 826 flhs := float64(lhs) 827 frhs := float64(rhs) 828 v := math.Mod(flhs, frhs) 829 if flhs < 0 || frhs < 0 && !(flhs < 0 && frhs < 0) { 830 v += frhs 831 } 832 return LNumber(v) 833 } 834 835 func numberArith(L *LState, opcode int, lhs, rhs LNumber) LNumber { 836 switch opcode { 837 case OP_ADD: 838 return lhs + rhs 839 case OP_SUB: 840 return lhs - rhs 841 case OP_MUL: 842 return lhs * rhs 843 case OP_DIV: 844 return lhs / rhs 845 case OP_MOD: 846 return luaModulo(lhs, rhs) 847 case OP_POW: 848 flhs := float64(lhs) 849 frhs := float64(rhs) 850 return LNumber(math.Pow(flhs, frhs)) 851 } 852 panic("should not reach here") 853 return LNumber(0) 854 } 855 856 func objectArith(L *LState, opcode int, lhs, rhs LValue) LValue { 857 event := "" 858 switch opcode { 859 case OP_ADD: 860 event = "__add" 861 case OP_SUB: 862 event = "__sub" 863 case OP_MUL: 864 event = "__mul" 865 case OP_DIV: 866 event = "__div" 867 case OP_MOD: 868 event = "__mod" 869 case OP_POW: 870 event = "__pow" 871 } 872 op := L.metaOp2(lhs, rhs, event) 873 if op.Type() == LTFunction { 874 L.reg.Push(op) 875 L.reg.Push(lhs) 876 L.reg.Push(rhs) 877 L.Call(2, 1) 878 return L.reg.Pop() 879 } 880 if str, ok := lhs.(LString); ok { 881 if lnum, err := parseNumber(string(str)); err == nil { 882 lhs = lnum 883 } 884 } 885 if str, ok := rhs.(LString); ok { 886 if rnum, err := parseNumber(string(str)); err == nil { 887 rhs = rnum 888 } 889 } 890 if v1, ok1 := lhs.assertFloat64(); ok1 { 891 if v2, ok2 := rhs.assertFloat64(); ok2 { 892 return numberArith(L, opcode, LNumber(v1), LNumber(v2)) 893 } 894 } 895 L.RaiseError(fmt.Sprintf("cannot perform %v operation between %v and %v", 896 strings.TrimLeft(event, "_"), lhs.Type().String(), rhs.Type().String())) 897 898 return LNil 899 } 900 901 func stringConcat(L *LState, total, last int) LValue { 902 rhs := L.reg.Get(last) 903 total-- 904 for i := last - 1; total > 0; { 905 lhs := L.reg.Get(i) 906 if !(LVCanConvToString(lhs) && LVCanConvToString(rhs)) { 907 op := L.metaOp2(lhs, rhs, "__concat") 908 if op.Type() == LTFunction { 909 L.reg.Push(op) 910 L.reg.Push(lhs) 911 L.reg.Push(rhs) 912 L.Call(2, 1) 913 rhs = L.reg.Pop() 914 total-- 915 i-- 916 } else { 917 L.RaiseError("cannot perform concat operation between %v and %v", lhs.Type().String(), rhs.Type().String()) 918 return LNil 919 } 920 } else { 921 buf := make([]string, total+1) 922 buf[total] = LVAsString(rhs) 923 for total > 0 { 924 lhs = L.reg.Get(i) 925 if !LVCanConvToString(lhs) { 926 break 927 } 928 buf[total-1] = LVAsString(lhs) 929 i-- 930 total-- 931 } 932 rhs = LString(strings.Join(buf, "")) 933 } 934 } 935 return rhs 936 } 937 938 func lessThan(L *LState, lhs, rhs LValue) bool { 939 // optimization for numbers 940 if v1, ok1 := lhs.assertFloat64(); ok1 { 941 if v2, ok2 := rhs.assertFloat64(); ok2 { 942 return v1 < v2 943 } 944 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 945 } 946 if lhs.Type() != rhs.Type() { 947 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 948 return false 949 } 950 ret := false 951 switch lhs.Type() { 952 case LTString: 953 ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) < 0 954 default: 955 ret = objectRationalWithError(L, lhs, rhs, "__lt") 956 } 957 return ret 958 } 959 960 func equals(L *LState, lhs, rhs LValue, raw bool) bool { 961 if lhs.Type() != rhs.Type() { 962 return false 963 } 964 965 ret := false 966 switch lhs.Type() { 967 case LTNil: 968 ret = true 969 case LTNumber: 970 v1, _ := lhs.assertFloat64() 971 v2, _ := rhs.assertFloat64() 972 ret = v1 == v2 973 case LTBool: 974 ret = bool(lhs.(LBool)) == bool(rhs.(LBool)) 975 case LTString: 976 ret = string(lhs.(LString)) == string(rhs.(LString)) 977 case LTUserData, LTTable: 978 if lhs == rhs { 979 ret = true 980 } else if !raw { 981 switch objectRational(L, lhs, rhs, "__eq") { 982 case 1: 983 ret = true 984 default: 985 ret = false 986 } 987 } 988 default: 989 ret = lhs == rhs 990 } 991 return ret 992 } 993 994 func objectRationalWithError(L *LState, lhs, rhs LValue, event string) bool { 995 switch objectRational(L, lhs, rhs, event) { 996 case 1: 997 return true 998 case 0: 999 return false 1000 } 1001 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 1002 return false 1003 } 1004 1005 func objectRational(L *LState, lhs, rhs LValue, event string) int { 1006 m1 := L.metaOp1(lhs, event) 1007 m2 := L.metaOp1(rhs, event) 1008 if m1.Type() == LTFunction && m1 == m2 { 1009 L.reg.Push(m1) 1010 L.reg.Push(lhs) 1011 L.reg.Push(rhs) 1012 L.Call(2, 1) 1013 if LVAsBool(L.reg.Pop()) { 1014 return 1 1015 } 1016 return 0 1017 } 1018 return -1 1019 }