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