github.com/coinstack/gopher-lua@v0.0.0-20180626044619-c9c62d4ee45e/_vm.go (about) 1 package lua 2 3 import ( 4 "fmt" 5 "math" 6 "strings" 7 ) 8 9 const ( 10 errMaxInstStr = "exceeded the maximum instruction count" 11 ) 12 13 func mainLoop(L *LState, baseframe *callFrame) { 14 var inst uint32 15 var cf *callFrame 16 17 if L.stack.IsEmpty() { 18 return 19 } 20 21 L.currentFrame = L.stack.Last() 22 if L.currentFrame.Fn.IsG { 23 callGFunction(L, false) 24 return 25 } 26 27 for { 28 cf = L.currentFrame 29 inst = cf.Fn.Proto.Code[cf.Pc] 30 cf.Pc++ 31 opCode := int(inst >> 26) 32 if jumpTable[opCode](L, inst, baseframe) == 1 { 33 return 34 } 35 if L.Options.MaxInstSize > uint64(0) { 36 L.instCount += opProps[opCode].InstCount 37 if L.instCount > L.Options.MaxInstSize { 38 L.RaiseError(errMaxInstStr) 39 return 40 } 41 } 42 } 43 } 44 45 func mainLoopWithContext(L *LState, baseframe *callFrame) { 46 var inst uint32 47 var cf *callFrame 48 49 if L.stack.IsEmpty() { 50 return 51 } 52 53 L.currentFrame = L.stack.Last() 54 if L.currentFrame.Fn.IsG { 55 callGFunction(L, false) 56 return 57 } 58 59 for { 60 cf = L.currentFrame 61 inst = cf.Fn.Proto.Code[cf.Pc] 62 cf.Pc++ 63 select { 64 case <-L.ctx.Done(): 65 L.RaiseError(L.ctx.Err().Error()) 66 return 67 default: 68 opCode := int(inst >> 26) 69 if jumpTable[opCode](L, inst, baseframe) == 1 { 70 return 71 } 72 if L.Options.MaxInstSize > uint64(0) { 73 L.instCount += opProps[opCode].InstCount 74 if L.instCount > L.Options.MaxInstSize { 75 L.RaiseError(errMaxInstStr) 76 return 77 } 78 } 79 } 80 } 81 } 82 83 func copyReturnValues(L *LState, regv, start, n, b int) { // +inline-start 84 if b == 1 { 85 // +inline-call L.reg.FillNil regv n 86 } else { 87 // +inline-call L.reg.CopyRange regv start -1 n 88 } 89 } // +inline-end 90 91 func switchToParentThread(L *LState, nargs int, haserror bool, kill bool) { 92 parent := L.Parent 93 if parent == nil { 94 L.RaiseError("can not yield from outside of a coroutine") 95 } 96 L.G.CurrentThread = parent 97 L.Parent = nil 98 if !L.wrapped { 99 if haserror { 100 parent.Push(LFalse) 101 } else { 102 parent.Push(LTrue) 103 } 104 } 105 L.XMoveTo(parent, nargs) 106 L.stack.Pop() 107 offset := L.currentFrame.LocalBase - L.currentFrame.ReturnBase 108 L.currentFrame = L.stack.Last() 109 L.reg.SetTop(L.reg.Top() - offset) // remove 'yield' function(including tailcalled functions) 110 if kill { 111 L.kill() 112 } 113 } 114 115 func callGFunction(L *LState, tailcall bool) bool { 116 L.instCount += 40 117 frame := L.currentFrame 118 gfnret := frame.Fn.GFunction(L) 119 if tailcall { 120 L.stack.Remove(L.stack.Sp() - 2) // remove caller lua function frame 121 L.currentFrame = L.stack.Last() 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 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.assertFunction(); 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.assertFunction(); 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).assertFloat64(); ok1 { 689 if limit, ok2 := reg.Get(RA + 1).assertFloat64(); ok2 { 690 if step, ok3 := reg.Get(RA + 2).assertFloat64(); ok3 { 691 init += step 692 reg.SetNumber(RA, LNumber(init)) 693 if (step > 0 && init <= limit) || (step <= 0 && init >= limit) { 694 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 695 cf.Pc += Sbx 696 reg.SetNumber(RA+3, LNumber(init)) 697 } else { 698 reg.SetTop(RA + 1) 699 } 700 } else { 701 L.RaiseError("for statement step must be a number") 702 } 703 } else { 704 L.RaiseError("for statement limit must be a number") 705 } 706 } else { 707 L.RaiseError("for statement init must be a number") 708 } 709 return 0 710 }, 711 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORPREP 712 reg := L.reg 713 cf := L.currentFrame 714 lbase := cf.LocalBase 715 A := int(inst>>18) & 0xff //GETA 716 RA := lbase + A 717 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 718 if init, ok1 := reg.Get(RA).assertFloat64(); ok1 { 719 if step, ok2 := reg.Get(RA + 2).assertFloat64(); ok2 { 720 reg.SetNumber(RA, LNumber(init-step)) 721 } else { 722 L.RaiseError("for statement step must be a number") 723 } 724 } else { 725 L.RaiseError("for statement init must be a number") 726 } 727 cf.Pc += Sbx 728 return 0 729 }, 730 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TFORLOOP 731 reg := L.reg 732 cf := L.currentFrame 733 lbase := cf.LocalBase 734 A := int(inst>>18) & 0xff //GETA 735 RA := lbase + A 736 C := int(inst>>9) & 0x1ff //GETC 737 nret := C 738 reg.SetTop(RA + 3 + 2) 739 reg.Set(RA+3+2, reg.Get(RA+2)) 740 reg.Set(RA+3+1, reg.Get(RA+1)) 741 reg.Set(RA+3, reg.Get(RA)) 742 L.callR(2, nret, RA+3) 743 if value := reg.Get(RA + 3); value != LNil { 744 reg.Set(RA+2, value) 745 pc := cf.Fn.Proto.Code[cf.Pc] 746 cf.Pc += int(pc&0x3ffff) - opMaxArgSbx 747 } 748 cf.Pc++ 749 return 0 750 }, 751 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETLIST 752 reg := L.reg 753 cf := L.currentFrame 754 lbase := cf.LocalBase 755 A := int(inst>>18) & 0xff //GETA 756 RA := lbase + A 757 B := int(inst & 0x1ff) //GETB 758 C := int(inst>>9) & 0x1ff //GETC 759 if C == 0 { 760 C = int(cf.Fn.Proto.Code[cf.Pc]) 761 cf.Pc++ 762 } 763 offset := (C - 1) * FieldsPerFlush 764 table := reg.Get(RA).(*LTable) 765 nelem := B 766 if B == 0 { 767 nelem = reg.Top() - RA - 1 768 } 769 for i := 1; i <= nelem; i++ { 770 table.RawSetInt(offset+i, reg.Get(RA+i)) 771 } 772 return 0 773 }, 774 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSE 775 cf := L.currentFrame 776 lbase := cf.LocalBase 777 A := int(inst>>18) & 0xff //GETA 778 RA := lbase + A 779 // +inline-call L.closeUpvalues RA 780 return 0 781 }, 782 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSURE 783 reg := L.reg 784 cf := L.currentFrame 785 lbase := cf.LocalBase 786 A := int(inst>>18) & 0xff //GETA 787 RA := lbase + A 788 Bx := int(inst & 0x3ffff) //GETBX 789 proto := cf.Fn.Proto.FunctionPrototypes[Bx] 790 closure := newLFunctionL(proto, cf.Fn.Env, int(proto.NumUpvalues)) 791 reg.Set(RA, closure) 792 for i := 0; i < int(proto.NumUpvalues); i++ { 793 inst = cf.Fn.Proto.Code[cf.Pc] 794 cf.Pc++ 795 B := opGetArgB(inst) 796 switch opGetOpCode(inst) { 797 case OP_MOVE: 798 closure.Upvalues[i] = L.findUpvalue(lbase + B) 799 case OP_GETUPVAL: 800 closure.Upvalues[i] = cf.Fn.Upvalues[B] 801 } 802 } 803 return 0 804 }, 805 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_VARARG 806 reg := L.reg 807 cf := L.currentFrame 808 lbase := cf.LocalBase 809 A := int(inst>>18) & 0xff //GETA 810 RA := lbase + A 811 B := int(inst & 0x1ff) //GETB 812 nparams := int(cf.Fn.Proto.NumParameters) 813 nvarargs := cf.NArgs - nparams 814 if nvarargs < 0 { 815 nvarargs = 0 816 } 817 nwant := B - 1 818 if B == 0 { 819 nwant = nvarargs 820 } 821 // +inline-call reg.CopyRange RA cf.Base+nparams+1 cf.LocalBase nwant 822 return 0 823 }, 824 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOP 825 return 0 826 }, 827 } 828 } 829 830 func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW 831 reg := L.reg 832 cf := L.currentFrame 833 lbase := cf.LocalBase 834 A := int(inst>>18) & 0xff //GETA 835 RA := lbase + A 836 opcode := int(inst >> 26) //GETOPCODE 837 B := int(inst & 0x1ff) //GETB 838 C := int(inst>>9) & 0x1ff //GETC 839 lhs := L.rkValue(B) 840 rhs := L.rkValue(C) 841 v1, ok1 := lhs.assertFloat64() 842 v2, ok2 := rhs.assertFloat64() 843 if ok1 && ok2 { 844 reg.SetNumber(RA, numberArith(L, opcode, LNumber(v1), LNumber(v2))) 845 } else { 846 reg.Set(RA, objectArith(L, opcode, lhs, rhs)) 847 } 848 return 0 849 } 850 851 func luaModulo(lhs, rhs LNumber) LNumber { 852 flhs := float64(lhs) 853 frhs := float64(rhs) 854 v := math.Mod(flhs, frhs) 855 if flhs < 0 || frhs < 0 && !(flhs < 0 && frhs < 0) { 856 v += frhs 857 } 858 return LNumber(v) 859 } 860 861 func numberArith(L *LState, opcode int, lhs, rhs LNumber) LNumber { 862 switch opcode { 863 case OP_ADD: 864 return lhs + rhs 865 case OP_SUB: 866 return lhs - rhs 867 case OP_MUL: 868 return lhs * rhs 869 case OP_DIV: 870 return lhs / rhs 871 case OP_MOD: 872 return luaModulo(lhs, rhs) 873 case OP_POW: 874 flhs := float64(lhs) 875 frhs := float64(rhs) 876 return LNumber(math.Pow(flhs, frhs)) 877 } 878 panic("should not reach here") 879 return LNumber(0) 880 } 881 882 func objectArith(L *LState, opcode int, lhs, rhs LValue) LValue { 883 event := "" 884 switch opcode { 885 case OP_ADD: 886 event = "__add" 887 case OP_SUB: 888 event = "__sub" 889 case OP_MUL: 890 event = "__mul" 891 case OP_DIV: 892 event = "__div" 893 case OP_MOD: 894 event = "__mod" 895 case OP_POW: 896 event = "__pow" 897 } 898 op := L.metaOp2(lhs, rhs, event) 899 if op.Type() == LTFunction { 900 L.reg.Push(op) 901 L.reg.Push(lhs) 902 L.reg.Push(rhs) 903 L.Call(2, 1) 904 return L.reg.Pop() 905 } 906 if str, ok := lhs.(LString); ok { 907 if lnum, err := parseNumber(string(str)); err == nil { 908 lhs = lnum 909 } 910 } 911 if str, ok := rhs.(LString); ok { 912 if rnum, err := parseNumber(string(str)); err == nil { 913 rhs = rnum 914 } 915 } 916 if v1, ok1 := lhs.assertFloat64(); ok1 { 917 if v2, ok2 := rhs.assertFloat64(); ok2 { 918 return numberArith(L, opcode, LNumber(v1), LNumber(v2)) 919 } 920 } 921 L.RaiseError(fmt.Sprintf("cannot perform %v operation between %v and %v", 922 strings.TrimLeft(event, "_"), lhs.Type().String(), rhs.Type().String())) 923 924 return LNil 925 } 926 927 func stringConcat(L *LState, total, last int) LValue { 928 rhs := L.reg.Get(last) 929 total-- 930 for i := last - 1; total > 0; { 931 lhs := L.reg.Get(i) 932 if !(LVCanConvToString(lhs) && LVCanConvToString(rhs)) { 933 op := L.metaOp2(lhs, rhs, "__concat") 934 if op.Type() == LTFunction { 935 L.reg.Push(op) 936 L.reg.Push(lhs) 937 L.reg.Push(rhs) 938 L.Call(2, 1) 939 rhs = L.reg.Pop() 940 total-- 941 i-- 942 } else { 943 L.RaiseError("cannot perform concat operation between %v and %v", lhs.Type().String(), rhs.Type().String()) 944 return LNil 945 } 946 } else { 947 buf := make([]string, total+1) 948 buf[total] = LVAsString(rhs) 949 for total > 0 { 950 lhs = L.reg.Get(i) 951 if !LVCanConvToString(lhs) { 952 break 953 } 954 buf[total-1] = LVAsString(lhs) 955 i-- 956 total-- 957 } 958 rhs = LString(strings.Join(buf, "")) 959 } 960 } 961 return rhs 962 } 963 964 func lessThan(L *LState, lhs, rhs LValue) bool { 965 // optimization for numbers 966 if v1, ok1 := lhs.assertFloat64(); ok1 { 967 if v2, ok2 := rhs.assertFloat64(); ok2 { 968 return v1 < v2 969 } 970 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 971 } 972 if lhs.Type() != rhs.Type() { 973 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 974 return false 975 } 976 ret := false 977 switch lhs.Type() { 978 case LTString: 979 ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) < 0 980 default: 981 ret = objectRationalWithError(L, lhs, rhs, "__lt") 982 } 983 return ret 984 } 985 986 func equals(L *LState, lhs, rhs LValue, raw bool) bool { 987 if lhs.Type() != rhs.Type() { 988 return false 989 } 990 991 ret := false 992 switch lhs.Type() { 993 case LTNil: 994 ret = true 995 case LTNumber: 996 v1, _ := lhs.assertFloat64() 997 v2, _ := rhs.assertFloat64() 998 ret = v1 == v2 999 case LTBool: 1000 ret = bool(lhs.(LBool)) == bool(rhs.(LBool)) 1001 case LTString: 1002 ret = string(lhs.(LString)) == string(rhs.(LString)) 1003 case LTUserData, LTTable: 1004 if lhs == rhs { 1005 ret = true 1006 } else if !raw { 1007 switch objectRational(L, lhs, rhs, "__eq") { 1008 case 1: 1009 ret = true 1010 default: 1011 ret = false 1012 } 1013 } 1014 default: 1015 ret = lhs == rhs 1016 } 1017 return ret 1018 } 1019 1020 func objectRationalWithError(L *LState, lhs, rhs LValue, event string) bool { 1021 switch objectRational(L, lhs, rhs, event) { 1022 case 1: 1023 return true 1024 case 0: 1025 return false 1026 } 1027 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 1028 return false 1029 } 1030 1031 func objectRational(L *LState, lhs, rhs LValue, event string) int { 1032 m1 := L.metaOp1(lhs, event) 1033 m2 := L.metaOp1(rhs, event) 1034 if m1.Type() == LTFunction && m1 == m2 { 1035 L.reg.Push(m1) 1036 L.reg.Push(lhs) 1037 L.reg.Push(rhs) 1038 L.Call(2, 1) 1039 if LVAsBool(L.reg.Pop()) { 1040 return 1 1041 } 1042 return 0 1043 } 1044 return -1 1045 }