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