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