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