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