github.com/coinstack/gopher-lua@v0.0.0-20180626044619-c9c62d4ee45e/vm.go (about) 1 package lua 2 3 //////////////////////////////////////////////////////// 4 // This file was generated by go-inline. DO NOT EDIT. // 5 //////////////////////////////////////////////////////// 6 7 import ( 8 "fmt" 9 "math" 10 "strings" 11 ) 12 13 const ( 14 errMaxInstStr = "exceeded the maximum instruction count" 15 ) 16 17 func mainLoop(L *LState, baseframe *callFrame) { 18 var inst uint32 19 var cf *callFrame 20 21 if L.stack.IsEmpty() { 22 return 23 } 24 25 L.currentFrame = L.stack.Last() 26 if L.currentFrame.Fn.IsG { 27 callGFunction(L, false) 28 return 29 } 30 31 for { 32 cf = L.currentFrame 33 inst = cf.Fn.Proto.Code[cf.Pc] 34 cf.Pc++ 35 opCode := int(inst >> 26) 36 if jumpTable[opCode](L, inst, baseframe) == 1 { 37 return 38 } 39 if L.Options.MaxInstSize > uint64(0) { 40 L.instCount += opProps[opCode].InstCount 41 if L.instCount > L.Options.MaxInstSize { 42 L.RaiseError(errMaxInstStr) 43 return 44 } 45 } 46 } 47 } 48 49 func mainLoopWithContext(L *LState, baseframe *callFrame) { 50 var inst uint32 51 var cf *callFrame 52 53 if L.stack.IsEmpty() { 54 return 55 } 56 57 L.currentFrame = L.stack.Last() 58 if L.currentFrame.Fn.IsG { 59 callGFunction(L, false) 60 return 61 } 62 63 for { 64 cf = L.currentFrame 65 inst = cf.Fn.Proto.Code[cf.Pc] 66 cf.Pc++ 67 select { 68 case <-L.ctx.Done(): 69 L.RaiseError(L.ctx.Err().Error()) 70 return 71 default: 72 opCode := int(inst >> 26) 73 if jumpTable[opCode](L, inst, baseframe) == 1 { 74 return 75 } 76 if L.Options.MaxInstSize > uint64(0) { 77 L.instCount += opProps[opCode].InstCount 78 if L.instCount > L.Options.MaxInstSize { 79 L.RaiseError(errMaxInstStr) 80 return 81 } 82 } 83 } 84 } 85 } 86 87 func copyReturnValues(L *LState, regv, start, n, b int) { // +inline-start 88 if b == 1 { 89 // this section is inlined by go-inline 90 // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' 91 { 92 rg := L.reg 93 regm := regv 94 for i := 0; i < n; i++ { 95 rg.array[regm+i] = LNil 96 } 97 rg.top = regm + n 98 } 99 } else { 100 // this section is inlined by go-inline 101 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 102 { 103 rg := L.reg 104 limit := -1 105 for i := 0; i < n; i++ { 106 if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { 107 rg.array[regv+i] = LNil 108 } else { 109 rg.array[regv+i] = rg.array[tidx] 110 } 111 } 112 rg.top = regv + n 113 } 114 } 115 } // +inline-end 116 117 func switchToParentThread(L *LState, nargs int, haserror bool, kill bool) { 118 parent := L.Parent 119 if parent == nil { 120 L.RaiseError("can not yield from outside of a coroutine") 121 } 122 L.G.CurrentThread = parent 123 L.Parent = nil 124 if !L.wrapped { 125 if haserror { 126 parent.Push(LFalse) 127 } else { 128 parent.Push(LTrue) 129 } 130 } 131 L.XMoveTo(parent, nargs) 132 L.stack.Pop() 133 offset := L.currentFrame.LocalBase - L.currentFrame.ReturnBase 134 L.currentFrame = L.stack.Last() 135 L.reg.SetTop(L.reg.Top() - offset) // remove 'yield' function(including tailcalled functions) 136 if kill { 137 L.kill() 138 } 139 } 140 141 func callGFunction(L *LState, tailcall bool) bool { 142 L.instCount += 40 143 frame := L.currentFrame 144 gfnret := frame.Fn.GFunction(L) 145 if tailcall { 146 L.stack.Remove(L.stack.Sp() - 2) // remove caller lua function frame 147 L.currentFrame = L.stack.Last() 148 } 149 150 if gfnret < 0 { 151 switchToParentThread(L, L.GetTop(), false, false) 152 return true 153 } 154 155 wantret := frame.NRet 156 if wantret == MultRet { 157 wantret = gfnret 158 } 159 160 if tailcall && L.Parent != nil && L.stack.Sp() == 1 { 161 switchToParentThread(L, wantret, false, true) 162 return true 163 } 164 165 // this section is inlined by go-inline 166 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 167 { 168 rg := L.reg 169 regv := frame.ReturnBase 170 start := L.reg.Top() - gfnret 171 limit := -1 172 n := wantret 173 for i := 0; i < n; i++ { 174 if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { 175 rg.array[regv+i] = LNil 176 } else { 177 rg.array[regv+i] = rg.array[tidx] 178 } 179 } 180 rg.top = regv + n 181 } 182 L.stack.Pop() 183 L.currentFrame = L.stack.Last() 184 return false 185 } 186 187 func threadRun(L *LState) { 188 if L.stack.IsEmpty() { 189 return 190 } 191 192 defer func() { 193 if rcv := recover(); rcv != nil { 194 var lv LValue 195 if v, ok := rcv.(*ApiError); ok { 196 lv = v.Object 197 } else { 198 lv = LString(fmt.Sprint(rcv)) 199 } 200 if parent := L.Parent; parent != nil { 201 if L.wrapped { 202 L.Push(lv) 203 parent.Panic(L) 204 } else { 205 L.SetTop(0) 206 L.Push(lv) 207 switchToParentThread(L, 1, true, true) 208 } 209 } else { 210 panic(rcv) 211 } 212 } 213 }() 214 L.mainLoop(L, nil) 215 } 216 217 type instFunc func(*LState, uint32, *callFrame) int 218 219 var jumpTable [opCodeMax + 1]instFunc 220 221 func init() { 222 jumpTable = [opCodeMax + 1]instFunc{ 223 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVE 224 reg := L.reg 225 cf := L.currentFrame 226 lbase := cf.LocalBase 227 A := int(inst>>18) & 0xff //GETA 228 RA := lbase + A 229 B := int(inst & 0x1ff) //GETB 230 reg.Set(RA, reg.Get(lbase+B)) 231 return 0 232 }, 233 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_MOVEN 234 reg := L.reg 235 cf := L.currentFrame 236 lbase := cf.LocalBase 237 A := int(inst>>18) & 0xff //GETA 238 B := int(inst & 0x1ff) //GETB 239 C := int(inst>>9) & 0x1ff //GETC 240 reg.Set(lbase+A, reg.Get(lbase+B)) 241 code := cf.Fn.Proto.Code 242 pc := cf.Pc 243 for i := 0; i < C; i++ { 244 inst = code[pc] 245 pc++ 246 A = int(inst>>18) & 0xff //GETA 247 B = int(inst & 0x1ff) //GETB 248 reg.Set(lbase+A, reg.Get(lbase+B)) 249 } 250 cf.Pc = pc 251 return 0 252 }, 253 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADK 254 reg := L.reg 255 cf := L.currentFrame 256 lbase := cf.LocalBase 257 A := int(inst>>18) & 0xff //GETA 258 RA := lbase + A 259 Bx := int(inst & 0x3ffff) //GETBX 260 reg.Set(RA, cf.Fn.Proto.Constants[Bx]) 261 return 0 262 }, 263 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADBOOL 264 reg := L.reg 265 cf := L.currentFrame 266 lbase := cf.LocalBase 267 A := int(inst>>18) & 0xff //GETA 268 RA := lbase + A 269 B := int(inst & 0x1ff) //GETB 270 C := int(inst>>9) & 0x1ff //GETC 271 if B != 0 { 272 reg.Set(RA, LTrue) 273 } else { 274 reg.Set(RA, LFalse) 275 } 276 if C != 0 { 277 cf.Pc++ 278 } 279 return 0 280 }, 281 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LOADNIL 282 reg := L.reg 283 cf := L.currentFrame 284 lbase := cf.LocalBase 285 A := int(inst>>18) & 0xff //GETA 286 RA := lbase + A 287 B := int(inst & 0x1ff) //GETB 288 for i := RA; i <= lbase+B; i++ { 289 reg.Set(i, LNil) 290 } 291 return 0 292 }, 293 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETUPVAL 294 reg := L.reg 295 cf := L.currentFrame 296 lbase := cf.LocalBase 297 A := int(inst>>18) & 0xff //GETA 298 RA := lbase + A 299 B := int(inst & 0x1ff) //GETB 300 reg.Set(RA, cf.Fn.Upvalues[B].Value()) 301 return 0 302 }, 303 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETGLOBAL 304 reg := L.reg 305 cf := L.currentFrame 306 lbase := cf.LocalBase 307 A := int(inst>>18) & 0xff //GETA 308 RA := lbase + A 309 Bx := int(inst & 0x3ffff) //GETBX 310 //reg.Set(RA, L.getField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx])) 311 reg.Set(RA, L.getFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx])) 312 return 0 313 }, 314 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLE 315 reg := L.reg 316 cf := L.currentFrame 317 lbase := cf.LocalBase 318 A := int(inst>>18) & 0xff //GETA 319 RA := lbase + A 320 B := int(inst & 0x1ff) //GETB 321 C := int(inst>>9) & 0x1ff //GETC 322 reg.Set(RA, L.getField(reg.Get(lbase+B), L.rkValue(C))) 323 return 0 324 }, 325 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_GETTABLEKS 326 reg := L.reg 327 cf := L.currentFrame 328 lbase := cf.LocalBase 329 A := int(inst>>18) & 0xff //GETA 330 RA := lbase + A 331 B := int(inst & 0x1ff) //GETB 332 C := int(inst>>9) & 0x1ff //GETC 333 reg.Set(RA, L.getFieldString(reg.Get(lbase+B), L.rkString(C))) 334 return 0 335 }, 336 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETGLOBAL 337 reg := L.reg 338 cf := L.currentFrame 339 lbase := cf.LocalBase 340 A := int(inst>>18) & 0xff //GETA 341 RA := lbase + A 342 Bx := int(inst & 0x3ffff) //GETBX 343 //L.setField(cf.Fn.Env, cf.Fn.Proto.Constants[Bx], reg.Get(RA)) 344 L.setFieldString(cf.Fn.Env, cf.Fn.Proto.stringConstants[Bx], reg.Get(RA)) 345 return 0 346 }, 347 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETUPVAL 348 reg := L.reg 349 cf := L.currentFrame 350 lbase := cf.LocalBase 351 A := int(inst>>18) & 0xff //GETA 352 RA := lbase + A 353 B := int(inst & 0x1ff) //GETB 354 cf.Fn.Upvalues[B].SetValue(reg.Get(RA)) 355 return 0 356 }, 357 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLE 358 reg := L.reg 359 cf := L.currentFrame 360 lbase := cf.LocalBase 361 A := int(inst>>18) & 0xff //GETA 362 RA := lbase + A 363 B := int(inst & 0x1ff) //GETB 364 C := int(inst>>9) & 0x1ff //GETC 365 L.setField(reg.Get(RA), L.rkValue(B), L.rkValue(C)) 366 return 0 367 }, 368 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETTABLEKS 369 reg := L.reg 370 cf := L.currentFrame 371 lbase := cf.LocalBase 372 A := int(inst>>18) & 0xff //GETA 373 RA := lbase + A 374 B := int(inst & 0x1ff) //GETB 375 C := int(inst>>9) & 0x1ff //GETC 376 L.setFieldString(reg.Get(RA), L.rkString(B), L.rkValue(C)) 377 return 0 378 }, 379 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NEWTABLE 380 reg := L.reg 381 cf := L.currentFrame 382 lbase := cf.LocalBase 383 A := int(inst>>18) & 0xff //GETA 384 RA := lbase + A 385 B := int(inst & 0x1ff) //GETB 386 C := int(inst>>9) & 0x1ff //GETC 387 reg.Set(RA, newLTable(B, C)) 388 return 0 389 }, 390 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SELF 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 C := int(inst>>9) & 0x1ff //GETC 398 selfobj := reg.Get(lbase + B) 399 reg.Set(RA, L.getFieldString(selfobj, L.rkString(C))) 400 reg.Set(RA+1, selfobj) 401 return 0 402 }, 403 opArith, // OP_ADD 404 opArith, // OP_SUB 405 opArith, // OP_MUL 406 opArith, // OP_DIV 407 opArith, // OP_MOD 408 opArith, // OP_POW 409 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_UNM 410 reg := L.reg 411 cf := L.currentFrame 412 lbase := cf.LocalBase 413 A := int(inst>>18) & 0xff //GETA 414 RA := lbase + A 415 B := int(inst & 0x1ff) //GETB 416 unaryv := L.rkValue(B) 417 if nm, ok := unaryv.(LNumber); ok { 418 reg.SetNumber(RA, -nm) 419 } else { 420 op := L.metaOp1(unaryv, "__unm") 421 if op.Type() == LTFunction { 422 reg.Push(op) 423 reg.Push(unaryv) 424 L.Call(1, 1) 425 reg.Set(RA, reg.Pop()) 426 } else if str, ok1 := unaryv.(LString); ok1 { 427 if num, err := parseNumber(string(str)); err == nil { 428 reg.Set(RA, -num) 429 } else { 430 L.RaiseError("__unm undefined") 431 } 432 } else { 433 L.RaiseError("__unm undefined") 434 } 435 } 436 return 0 437 }, 438 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOT 439 reg := L.reg 440 cf := L.currentFrame 441 lbase := cf.LocalBase 442 A := int(inst>>18) & 0xff //GETA 443 RA := lbase + A 444 B := int(inst & 0x1ff) //GETB 445 if LVIsFalse(reg.Get(lbase + B)) { 446 reg.Set(RA, LTrue) 447 } else { 448 reg.Set(RA, LFalse) 449 } 450 return 0 451 }, 452 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LEN 453 reg := L.reg 454 cf := L.currentFrame 455 lbase := cf.LocalBase 456 A := int(inst>>18) & 0xff //GETA 457 RA := lbase + A 458 B := int(inst & 0x1ff) //GETB 459 switch lv := L.rkValue(B).(type) { 460 case LString: 461 reg.SetNumber(RA, LNumber(len(lv))) 462 default: 463 op := L.metaOp1(lv, "__len") 464 if op.Type() == LTFunction { 465 reg.Push(op) 466 reg.Push(lv) 467 L.Call(1, 1) 468 ret := reg.Pop() 469 if ret.Type() == LTNumber { 470 reg.SetNumber(RA, ret.(LNumber)) 471 } else { 472 reg.SetNumber(RA, LNumber(0)) 473 } 474 } else if lv.Type() == LTTable { 475 reg.SetNumber(RA, LNumber(lv.(*LTable).Len())) 476 } else { 477 L.RaiseError("__len undefined") 478 } 479 } 480 return 0 481 }, 482 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CONCAT 483 reg := L.reg 484 cf := L.currentFrame 485 lbase := cf.LocalBase 486 A := int(inst>>18) & 0xff //GETA 487 RA := lbase + A 488 B := int(inst & 0x1ff) //GETB 489 C := int(inst>>9) & 0x1ff //GETC 490 RC := lbase + C 491 RB := lbase + B 492 reg.Set(RA, stringConcat(L, RC-RB+1, RC)) 493 return 0 494 }, 495 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_JMP 496 cf := L.currentFrame 497 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 498 cf.Pc += Sbx 499 return 0 500 }, 501 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_EQ 502 cf := L.currentFrame 503 A := int(inst>>18) & 0xff //GETA 504 B := int(inst & 0x1ff) //GETB 505 C := int(inst>>9) & 0x1ff //GETC 506 ret := equals(L, L.rkValue(B), L.rkValue(C), false) 507 v := 1 508 if ret { 509 v = 0 510 } 511 if v == A { 512 cf.Pc++ 513 } 514 return 0 515 }, 516 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LT 517 cf := L.currentFrame 518 A := int(inst>>18) & 0xff //GETA 519 B := int(inst & 0x1ff) //GETB 520 C := int(inst>>9) & 0x1ff //GETC 521 ret := lessThan(L, L.rkValue(B), L.rkValue(C)) 522 v := 1 523 if ret { 524 v = 0 525 } 526 if v == A { 527 cf.Pc++ 528 } 529 return 0 530 }, 531 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_LE 532 cf := L.currentFrame 533 A := int(inst>>18) & 0xff //GETA 534 B := int(inst & 0x1ff) //GETB 535 C := int(inst>>9) & 0x1ff //GETC 536 lhs := L.rkValue(B) 537 rhs := L.rkValue(C) 538 ret := false 539 540 if v1, ok1 := lhs.assertFloat64(); ok1 { 541 if v2, ok2 := rhs.assertFloat64(); ok2 { 542 ret = v1 <= v2 543 } else { 544 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 545 } 546 } else { 547 if lhs.Type() != rhs.Type() { 548 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 549 } 550 switch lhs.Type() { 551 case LTString: 552 ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) <= 0 553 default: 554 switch objectRational(L, lhs, rhs, "__le") { 555 case 1: 556 ret = true 557 case 0: 558 ret = false 559 default: 560 ret = !objectRationalWithError(L, rhs, lhs, "__lt") 561 } 562 } 563 } 564 565 v := 1 566 if ret { 567 v = 0 568 } 569 if v == A { 570 cf.Pc++ 571 } 572 return 0 573 }, 574 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TEST 575 reg := L.reg 576 cf := L.currentFrame 577 lbase := cf.LocalBase 578 A := int(inst>>18) & 0xff //GETA 579 RA := lbase + A 580 C := int(inst>>9) & 0x1ff //GETC 581 if LVAsBool(reg.Get(RA)) == (C == 0) { 582 cf.Pc++ 583 } 584 return 0 585 }, 586 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TESTSET 587 reg := L.reg 588 cf := L.currentFrame 589 lbase := cf.LocalBase 590 A := int(inst>>18) & 0xff //GETA 591 RA := lbase + A 592 B := int(inst & 0x1ff) //GETB 593 C := int(inst>>9) & 0x1ff //GETC 594 if value := reg.Get(lbase + B); LVAsBool(value) != (C == 0) { 595 reg.Set(RA, value) 596 } else { 597 cf.Pc++ 598 } 599 return 0 600 }, 601 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CALL 602 reg := L.reg 603 cf := L.currentFrame 604 lbase := cf.LocalBase 605 A := int(inst>>18) & 0xff //GETA 606 RA := lbase + A 607 B := int(inst & 0x1ff) //GETB 608 C := int(inst>>9) & 0x1ff //GETC 609 nargs := B - 1 610 if B == 0 { 611 nargs = reg.Top() - (RA + 1) 612 } 613 lv := reg.Get(RA) 614 nret := C - 1 615 var callable *LFunction 616 var meta bool 617 if fn, ok := lv.assertFunction(); ok { 618 callable = fn 619 meta = false 620 } else { 621 callable, meta = L.metaCall(lv) 622 } 623 // this section is inlined by go-inline 624 // source function is 'func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) ' in '_state.go' 625 { 626 ls := L 627 cf := callFrame{Fn: callable, Pc: 0, Base: RA, LocalBase: RA + 1, ReturnBase: RA, NArgs: nargs, NRet: nret, Parent: cf, TailCall: 0} 628 fn := lv 629 if meta { 630 cf.NArgs++ 631 ls.reg.Insert(fn, cf.LocalBase) 632 } 633 if cf.Fn == nil { 634 ls.RaiseError("attempt to call a non-function object") 635 } 636 if ls.stack.sp == ls.Options.CallStackSize { 637 ls.RaiseError("stack overflow") 638 } 639 // this section is inlined by go-inline 640 // source function is 'func (cs *callFrameStack) Push(v callFrame) ' in '_state.go' 641 { 642 cs := ls.stack 643 v := cf 644 cs.array[cs.sp] = v 645 cs.array[cs.sp].Idx = cs.sp 646 cs.sp++ 647 } 648 newcf := ls.stack.Last() 649 // this section is inlined by go-inline 650 // source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' 651 { 652 cf := newcf 653 if cf.Fn.IsG { 654 ls.reg.SetTop(cf.LocalBase + cf.NArgs) 655 } else { 656 proto := cf.Fn.Proto 657 nargs := cf.NArgs 658 np := int(proto.NumParameters) 659 for i := nargs; i < np; i++ { 660 ls.reg.array[cf.LocalBase+i] = LNil 661 nargs = np 662 } 663 664 if (proto.IsVarArg & VarArgIsVarArg) == 0 { 665 if nargs < int(proto.NumUsedRegisters) { 666 nargs = int(proto.NumUsedRegisters) 667 } 668 for i := np; i < nargs; i++ { 669 ls.reg.array[cf.LocalBase+i] = LNil 670 } 671 ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) 672 } else { 673 /* swap vararg positions: 674 closure 675 namedparam1 <- lbase 676 namedparam2 677 vararg1 678 vararg2 679 680 TO 681 682 closure 683 nil 684 nil 685 vararg1 686 vararg2 687 namedparam1 <- lbase 688 namedparam2 689 */ 690 nvarargs := nargs - np 691 if nvarargs < 0 { 692 nvarargs = 0 693 } 694 695 ls.reg.SetTop(cf.LocalBase + nargs + np) 696 for i := 0; i < np; i++ { 697 //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) 698 ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] 699 //ls.reg.Set(cf.LocalBase+i, LNil) 700 ls.reg.array[cf.LocalBase+i] = LNil 701 } 702 703 if CompatVarArg { 704 ls.reg.SetTop(cf.LocalBase + nargs + np + 1) 705 if (proto.IsVarArg & VarArgNeedsArg) != 0 { 706 argtb := newLTable(nvarargs, 0) 707 for i := 0; i < nvarargs; i++ { 708 argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) 709 } 710 argtb.RawSetString("n", LNumber(nvarargs)) 711 //ls.reg.Set(cf.LocalBase+nargs+np, argtb) 712 ls.reg.array[cf.LocalBase+nargs+np] = argtb 713 } else { 714 ls.reg.array[cf.LocalBase+nargs+np] = LNil 715 } 716 } 717 cf.LocalBase += nargs 718 maxreg := cf.LocalBase + int(proto.NumUsedRegisters) 719 ls.reg.SetTop(maxreg) 720 } 721 } 722 } 723 ls.currentFrame = newcf 724 } 725 if callable.IsG && callGFunction(L, false) { 726 return 1 727 } 728 return 0 729 }, 730 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TAILCALL 731 reg := L.reg 732 cf := L.currentFrame 733 lbase := cf.LocalBase 734 A := int(inst>>18) & 0xff //GETA 735 RA := lbase + A 736 B := int(inst & 0x1ff) //GETB 737 nargs := B - 1 738 if B == 0 { 739 nargs = reg.Top() - (RA + 1) 740 } 741 lv := reg.Get(RA) 742 var callable *LFunction 743 var meta bool 744 if fn, ok := lv.assertFunction(); ok { 745 callable = fn 746 meta = false 747 } else { 748 callable, meta = L.metaCall(lv) 749 } 750 if callable == nil { 751 L.RaiseError("attempt to call a non-function object") 752 } 753 // this section is inlined by go-inline 754 // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' 755 { 756 ls := L 757 idx := lbase 758 if ls.uvcache != nil { 759 var prev *Upvalue 760 for uv := ls.uvcache; uv != nil; uv = uv.next { 761 if uv.index >= idx { 762 if prev != nil { 763 prev.next = nil 764 } else { 765 ls.uvcache = nil 766 } 767 uv.Close() 768 } 769 prev = uv 770 } 771 } 772 } 773 if callable.IsG { 774 luaframe := cf 775 L.pushCallFrame(callFrame{ 776 Fn: callable, 777 Pc: 0, 778 Base: RA, 779 LocalBase: RA + 1, 780 ReturnBase: cf.ReturnBase, 781 NArgs: nargs, 782 NRet: cf.NRet, 783 Parent: cf, 784 TailCall: 0, 785 }, lv, meta) 786 if callGFunction(L, true) { 787 return 1 788 } 789 if L.currentFrame == nil || L.currentFrame.Fn.IsG || luaframe == baseframe { 790 return 1 791 } 792 } else { 793 base := cf.Base 794 cf.Fn = callable 795 cf.Pc = 0 796 cf.Base = RA 797 cf.LocalBase = RA + 1 798 cf.ReturnBase = cf.ReturnBase 799 cf.NArgs = nargs 800 cf.NRet = cf.NRet 801 cf.TailCall++ 802 lbase := cf.LocalBase 803 if meta { 804 cf.NArgs++ 805 L.reg.Insert(lv, cf.LocalBase) 806 } 807 // this section is inlined by go-inline 808 // source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go' 809 { 810 ls := L 811 if cf.Fn.IsG { 812 ls.reg.SetTop(cf.LocalBase + cf.NArgs) 813 } else { 814 proto := cf.Fn.Proto 815 nargs := cf.NArgs 816 np := int(proto.NumParameters) 817 for i := nargs; i < np; i++ { 818 ls.reg.array[cf.LocalBase+i] = LNil 819 nargs = np 820 } 821 822 if (proto.IsVarArg & VarArgIsVarArg) == 0 { 823 if nargs < int(proto.NumUsedRegisters) { 824 nargs = int(proto.NumUsedRegisters) 825 } 826 for i := np; i < nargs; i++ { 827 ls.reg.array[cf.LocalBase+i] = LNil 828 } 829 ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) 830 } else { 831 /* swap vararg positions: 832 closure 833 namedparam1 <- lbase 834 namedparam2 835 vararg1 836 vararg2 837 838 TO 839 840 closure 841 nil 842 nil 843 vararg1 844 vararg2 845 namedparam1 <- lbase 846 namedparam2 847 */ 848 nvarargs := nargs - np 849 if nvarargs < 0 { 850 nvarargs = 0 851 } 852 853 ls.reg.SetTop(cf.LocalBase + nargs + np) 854 for i := 0; i < np; i++ { 855 //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) 856 ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] 857 //ls.reg.Set(cf.LocalBase+i, LNil) 858 ls.reg.array[cf.LocalBase+i] = LNil 859 } 860 861 if CompatVarArg { 862 ls.reg.SetTop(cf.LocalBase + nargs + np + 1) 863 if (proto.IsVarArg & VarArgNeedsArg) != 0 { 864 argtb := newLTable(nvarargs, 0) 865 for i := 0; i < nvarargs; i++ { 866 argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) 867 } 868 argtb.RawSetString("n", LNumber(nvarargs)) 869 //ls.reg.Set(cf.LocalBase+nargs+np, argtb) 870 ls.reg.array[cf.LocalBase+nargs+np] = argtb 871 } else { 872 ls.reg.array[cf.LocalBase+nargs+np] = LNil 873 } 874 } 875 cf.LocalBase += nargs 876 maxreg := cf.LocalBase + int(proto.NumUsedRegisters) 877 ls.reg.SetTop(maxreg) 878 } 879 } 880 } 881 // this section is inlined by go-inline 882 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 883 { 884 rg := L.reg 885 regv := base 886 start := RA 887 limit := -1 888 n := reg.Top() - RA - 1 889 for i := 0; i < n; i++ { 890 if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { 891 rg.array[regv+i] = LNil 892 } else { 893 rg.array[regv+i] = rg.array[tidx] 894 } 895 } 896 rg.top = regv + n 897 } 898 cf.Base = base 899 cf.LocalBase = base + (cf.LocalBase - lbase + 1) 900 } 901 return 0 902 }, 903 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_RETURN 904 reg := L.reg 905 cf := L.currentFrame 906 lbase := cf.LocalBase 907 A := int(inst>>18) & 0xff //GETA 908 RA := lbase + A 909 B := int(inst & 0x1ff) //GETB 910 // this section is inlined by go-inline 911 // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' 912 { 913 ls := L 914 idx := lbase 915 if ls.uvcache != nil { 916 var prev *Upvalue 917 for uv := ls.uvcache; uv != nil; uv = uv.next { 918 if uv.index >= idx { 919 if prev != nil { 920 prev.next = nil 921 } else { 922 ls.uvcache = nil 923 } 924 uv.Close() 925 } 926 prev = uv 927 } 928 } 929 } 930 nret := B - 1 931 if B == 0 { 932 nret = reg.Top() - RA 933 } 934 n := cf.NRet 935 if cf.NRet == MultRet { 936 n = nret 937 } 938 939 if L.Parent != nil && L.stack.Sp() == 1 { 940 // this section is inlined by go-inline 941 // source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go' 942 { 943 regv := reg.Top() 944 start := RA 945 b := B 946 if b == 1 { 947 // this section is inlined by go-inline 948 // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' 949 { 950 rg := L.reg 951 regm := regv 952 for i := 0; i < n; i++ { 953 rg.array[regm+i] = LNil 954 } 955 rg.top = regm + n 956 } 957 } else { 958 // this section is inlined by go-inline 959 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 960 { 961 rg := L.reg 962 limit := -1 963 for i := 0; i < n; i++ { 964 if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { 965 rg.array[regv+i] = LNil 966 } else { 967 rg.array[regv+i] = rg.array[tidx] 968 } 969 } 970 rg.top = regv + n 971 } 972 } 973 } 974 switchToParentThread(L, n, false, true) 975 return 1 976 } 977 islast := baseframe == L.stack.Pop() || L.stack.IsEmpty() 978 // this section is inlined by go-inline 979 // source function is 'func copyReturnValues(L *LState, regv, start, n, b int) ' in '_vm.go' 980 { 981 regv := cf.ReturnBase 982 start := RA 983 b := B 984 if b == 1 { 985 // this section is inlined by go-inline 986 // source function is 'func (rg *registry) FillNil(regm, n int) ' in '_state.go' 987 { 988 rg := L.reg 989 regm := regv 990 for i := 0; i < n; i++ { 991 rg.array[regm+i] = LNil 992 } 993 rg.top = regm + n 994 } 995 } else { 996 // this section is inlined by go-inline 997 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 998 { 999 rg := L.reg 1000 limit := -1 1001 for i := 0; i < n; i++ { 1002 if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { 1003 rg.array[regv+i] = LNil 1004 } else { 1005 rg.array[regv+i] = rg.array[tidx] 1006 } 1007 } 1008 rg.top = regv + n 1009 } 1010 } 1011 } 1012 L.currentFrame = L.stack.Last() 1013 if islast || L.currentFrame == nil || L.currentFrame.Fn.IsG { 1014 return 1 1015 } 1016 return 0 1017 }, 1018 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORLOOP 1019 reg := L.reg 1020 cf := L.currentFrame 1021 lbase := cf.LocalBase 1022 A := int(inst>>18) & 0xff //GETA 1023 RA := lbase + A 1024 if init, ok1 := reg.Get(RA).assertFloat64(); ok1 { 1025 if limit, ok2 := reg.Get(RA + 1).assertFloat64(); ok2 { 1026 if step, ok3 := reg.Get(RA + 2).assertFloat64(); ok3 { 1027 init += step 1028 reg.SetNumber(RA, LNumber(init)) 1029 if (step > 0 && init <= limit) || (step <= 0 && init >= limit) { 1030 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 1031 cf.Pc += Sbx 1032 reg.SetNumber(RA+3, LNumber(init)) 1033 } else { 1034 reg.SetTop(RA + 1) 1035 } 1036 } else { 1037 L.RaiseError("for statement step must be a number") 1038 } 1039 } else { 1040 L.RaiseError("for statement limit must be a number") 1041 } 1042 } else { 1043 L.RaiseError("for statement init must be a number") 1044 } 1045 return 0 1046 }, 1047 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_FORPREP 1048 reg := L.reg 1049 cf := L.currentFrame 1050 lbase := cf.LocalBase 1051 A := int(inst>>18) & 0xff //GETA 1052 RA := lbase + A 1053 Sbx := int(inst&0x3ffff) - opMaxArgSbx //GETSBX 1054 if init, ok1 := reg.Get(RA).assertFloat64(); ok1 { 1055 if step, ok2 := reg.Get(RA + 2).assertFloat64(); ok2 { 1056 reg.SetNumber(RA, LNumber(init-step)) 1057 } else { 1058 L.RaiseError("for statement step must be a number") 1059 } 1060 } else { 1061 L.RaiseError("for statement init must be a number") 1062 } 1063 cf.Pc += Sbx 1064 return 0 1065 }, 1066 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_TFORLOOP 1067 reg := L.reg 1068 cf := L.currentFrame 1069 lbase := cf.LocalBase 1070 A := int(inst>>18) & 0xff //GETA 1071 RA := lbase + A 1072 C := int(inst>>9) & 0x1ff //GETC 1073 nret := C 1074 reg.SetTop(RA + 3 + 2) 1075 reg.Set(RA+3+2, reg.Get(RA+2)) 1076 reg.Set(RA+3+1, reg.Get(RA+1)) 1077 reg.Set(RA+3, reg.Get(RA)) 1078 L.callR(2, nret, RA+3) 1079 if value := reg.Get(RA + 3); value != LNil { 1080 reg.Set(RA+2, value) 1081 pc := cf.Fn.Proto.Code[cf.Pc] 1082 cf.Pc += int(pc&0x3ffff) - opMaxArgSbx 1083 } 1084 cf.Pc++ 1085 return 0 1086 }, 1087 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_SETLIST 1088 reg := L.reg 1089 cf := L.currentFrame 1090 lbase := cf.LocalBase 1091 A := int(inst>>18) & 0xff //GETA 1092 RA := lbase + A 1093 B := int(inst & 0x1ff) //GETB 1094 C := int(inst>>9) & 0x1ff //GETC 1095 if C == 0 { 1096 C = int(cf.Fn.Proto.Code[cf.Pc]) 1097 cf.Pc++ 1098 } 1099 offset := (C - 1) * FieldsPerFlush 1100 table := reg.Get(RA).(*LTable) 1101 nelem := B 1102 if B == 0 { 1103 nelem = reg.Top() - RA - 1 1104 } 1105 for i := 1; i <= nelem; i++ { 1106 table.RawSetInt(offset+i, reg.Get(RA+i)) 1107 } 1108 return 0 1109 }, 1110 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSE 1111 cf := L.currentFrame 1112 lbase := cf.LocalBase 1113 A := int(inst>>18) & 0xff //GETA 1114 RA := lbase + A 1115 // this section is inlined by go-inline 1116 // source function is 'func (ls *LState) closeUpvalues(idx int) ' in '_state.go' 1117 { 1118 ls := L 1119 idx := RA 1120 if ls.uvcache != nil { 1121 var prev *Upvalue 1122 for uv := ls.uvcache; uv != nil; uv = uv.next { 1123 if uv.index >= idx { 1124 if prev != nil { 1125 prev.next = nil 1126 } else { 1127 ls.uvcache = nil 1128 } 1129 uv.Close() 1130 } 1131 prev = uv 1132 } 1133 } 1134 } 1135 return 0 1136 }, 1137 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_CLOSURE 1138 reg := L.reg 1139 cf := L.currentFrame 1140 lbase := cf.LocalBase 1141 A := int(inst>>18) & 0xff //GETA 1142 RA := lbase + A 1143 Bx := int(inst & 0x3ffff) //GETBX 1144 proto := cf.Fn.Proto.FunctionPrototypes[Bx] 1145 closure := newLFunctionL(proto, cf.Fn.Env, int(proto.NumUpvalues)) 1146 reg.Set(RA, closure) 1147 for i := 0; i < int(proto.NumUpvalues); i++ { 1148 inst = cf.Fn.Proto.Code[cf.Pc] 1149 cf.Pc++ 1150 B := opGetArgB(inst) 1151 switch opGetOpCode(inst) { 1152 case OP_MOVE: 1153 closure.Upvalues[i] = L.findUpvalue(lbase + B) 1154 case OP_GETUPVAL: 1155 closure.Upvalues[i] = cf.Fn.Upvalues[B] 1156 } 1157 } 1158 return 0 1159 }, 1160 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_VARARG 1161 reg := L.reg 1162 cf := L.currentFrame 1163 lbase := cf.LocalBase 1164 A := int(inst>>18) & 0xff //GETA 1165 RA := lbase + A 1166 B := int(inst & 0x1ff) //GETB 1167 nparams := int(cf.Fn.Proto.NumParameters) 1168 nvarargs := cf.NArgs - nparams 1169 if nvarargs < 0 { 1170 nvarargs = 0 1171 } 1172 nwant := B - 1 1173 if B == 0 { 1174 nwant = nvarargs 1175 } 1176 // this section is inlined by go-inline 1177 // source function is 'func (rg *registry) CopyRange(regv, start, limit, n int) ' in '_state.go' 1178 { 1179 rg := reg 1180 regv := RA 1181 start := cf.Base + nparams + 1 1182 limit := cf.LocalBase 1183 n := nwant 1184 for i := 0; i < n; i++ { 1185 if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 { 1186 rg.array[regv+i] = LNil 1187 } else { 1188 rg.array[regv+i] = rg.array[tidx] 1189 } 1190 } 1191 rg.top = regv + n 1192 } 1193 return 0 1194 }, 1195 func(L *LState, inst uint32, baseframe *callFrame) int { //OP_NOP 1196 return 0 1197 }, 1198 } 1199 } 1200 1201 func opArith(L *LState, inst uint32, baseframe *callFrame) int { //OP_ADD, OP_SUB, OP_MUL, OP_DIV, OP_MOD, OP_POW 1202 reg := L.reg 1203 cf := L.currentFrame 1204 lbase := cf.LocalBase 1205 A := int(inst>>18) & 0xff //GETA 1206 RA := lbase + A 1207 opcode := int(inst >> 26) //GETOPCODE 1208 B := int(inst & 0x1ff) //GETB 1209 C := int(inst>>9) & 0x1ff //GETC 1210 lhs := L.rkValue(B) 1211 rhs := L.rkValue(C) 1212 v1, ok1 := lhs.assertFloat64() 1213 v2, ok2 := rhs.assertFloat64() 1214 if ok1 && ok2 { 1215 reg.SetNumber(RA, numberArith(L, opcode, LNumber(v1), LNumber(v2))) 1216 } else { 1217 reg.Set(RA, objectArith(L, opcode, lhs, rhs)) 1218 } 1219 return 0 1220 } 1221 1222 func luaModulo(lhs, rhs LNumber) LNumber { 1223 flhs := float64(lhs) 1224 frhs := float64(rhs) 1225 v := math.Mod(flhs, frhs) 1226 if flhs < 0 || frhs < 0 && !(flhs < 0 && frhs < 0) { 1227 v += frhs 1228 } 1229 return LNumber(v) 1230 } 1231 1232 func numberArith(L *LState, opcode int, lhs, rhs LNumber) LNumber { 1233 switch opcode { 1234 case OP_ADD: 1235 return lhs + rhs 1236 case OP_SUB: 1237 return lhs - rhs 1238 case OP_MUL: 1239 return lhs * rhs 1240 case OP_DIV: 1241 return lhs / rhs 1242 case OP_MOD: 1243 return luaModulo(lhs, rhs) 1244 case OP_POW: 1245 flhs := float64(lhs) 1246 frhs := float64(rhs) 1247 return LNumber(math.Pow(flhs, frhs)) 1248 } 1249 panic("should not reach here") 1250 return LNumber(0) 1251 } 1252 1253 func objectArith(L *LState, opcode int, lhs, rhs LValue) LValue { 1254 event := "" 1255 switch opcode { 1256 case OP_ADD: 1257 event = "__add" 1258 case OP_SUB: 1259 event = "__sub" 1260 case OP_MUL: 1261 event = "__mul" 1262 case OP_DIV: 1263 event = "__div" 1264 case OP_MOD: 1265 event = "__mod" 1266 case OP_POW: 1267 event = "__pow" 1268 } 1269 op := L.metaOp2(lhs, rhs, event) 1270 if op.Type() == LTFunction { 1271 L.reg.Push(op) 1272 L.reg.Push(lhs) 1273 L.reg.Push(rhs) 1274 L.Call(2, 1) 1275 return L.reg.Pop() 1276 } 1277 if str, ok := lhs.(LString); ok { 1278 if lnum, err := parseNumber(string(str)); err == nil { 1279 lhs = lnum 1280 } 1281 } 1282 if str, ok := rhs.(LString); ok { 1283 if rnum, err := parseNumber(string(str)); err == nil { 1284 rhs = rnum 1285 } 1286 } 1287 if v1, ok1 := lhs.assertFloat64(); ok1 { 1288 if v2, ok2 := rhs.assertFloat64(); ok2 { 1289 return numberArith(L, opcode, LNumber(v1), LNumber(v2)) 1290 } 1291 } 1292 L.RaiseError(fmt.Sprintf("cannot perform %v operation between %v and %v", 1293 strings.TrimLeft(event, "_"), lhs.Type().String(), rhs.Type().String())) 1294 1295 return LNil 1296 } 1297 1298 func stringConcat(L *LState, total, last int) LValue { 1299 rhs := L.reg.Get(last) 1300 total-- 1301 for i := last - 1; total > 0; { 1302 lhs := L.reg.Get(i) 1303 if !(LVCanConvToString(lhs) && LVCanConvToString(rhs)) { 1304 op := L.metaOp2(lhs, rhs, "__concat") 1305 if op.Type() == LTFunction { 1306 L.reg.Push(op) 1307 L.reg.Push(lhs) 1308 L.reg.Push(rhs) 1309 L.Call(2, 1) 1310 rhs = L.reg.Pop() 1311 total-- 1312 i-- 1313 } else { 1314 L.RaiseError("cannot perform concat operation between %v and %v", lhs.Type().String(), rhs.Type().String()) 1315 return LNil 1316 } 1317 } else { 1318 buf := make([]string, total+1) 1319 buf[total] = LVAsString(rhs) 1320 for total > 0 { 1321 lhs = L.reg.Get(i) 1322 if !LVCanConvToString(lhs) { 1323 break 1324 } 1325 buf[total-1] = LVAsString(lhs) 1326 i-- 1327 total-- 1328 } 1329 rhs = LString(strings.Join(buf, "")) 1330 } 1331 } 1332 return rhs 1333 } 1334 1335 func lessThan(L *LState, lhs, rhs LValue) bool { 1336 // optimization for numbers 1337 if v1, ok1 := lhs.assertFloat64(); ok1 { 1338 if v2, ok2 := rhs.assertFloat64(); ok2 { 1339 return v1 < v2 1340 } 1341 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 1342 } 1343 if lhs.Type() != rhs.Type() { 1344 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 1345 return false 1346 } 1347 ret := false 1348 switch lhs.Type() { 1349 case LTString: 1350 ret = strCmp(string(lhs.(LString)), string(rhs.(LString))) < 0 1351 default: 1352 ret = objectRationalWithError(L, lhs, rhs, "__lt") 1353 } 1354 return ret 1355 } 1356 1357 func equals(L *LState, lhs, rhs LValue, raw bool) bool { 1358 if lhs.Type() != rhs.Type() { 1359 return false 1360 } 1361 1362 ret := false 1363 switch lhs.Type() { 1364 case LTNil: 1365 ret = true 1366 case LTNumber: 1367 v1, _ := lhs.assertFloat64() 1368 v2, _ := rhs.assertFloat64() 1369 ret = v1 == v2 1370 case LTBool: 1371 ret = bool(lhs.(LBool)) == bool(rhs.(LBool)) 1372 case LTString: 1373 ret = string(lhs.(LString)) == string(rhs.(LString)) 1374 case LTUserData, LTTable: 1375 if lhs == rhs { 1376 ret = true 1377 } else if !raw { 1378 switch objectRational(L, lhs, rhs, "__eq") { 1379 case 1: 1380 ret = true 1381 default: 1382 ret = false 1383 } 1384 } 1385 default: 1386 ret = lhs == rhs 1387 } 1388 return ret 1389 } 1390 1391 func objectRationalWithError(L *LState, lhs, rhs LValue, event string) bool { 1392 switch objectRational(L, lhs, rhs, event) { 1393 case 1: 1394 return true 1395 case 0: 1396 return false 1397 } 1398 L.RaiseError("attempt to compare %v with %v", lhs.Type().String(), rhs.Type().String()) 1399 return false 1400 } 1401 1402 func objectRational(L *LState, lhs, rhs LValue, event string) int { 1403 m1 := L.metaOp1(lhs, event) 1404 m2 := L.metaOp1(rhs, event) 1405 if m1.Type() == LTFunction && m1 == m2 { 1406 L.reg.Push(m1) 1407 L.reg.Push(lhs) 1408 L.reg.Push(rhs) 1409 L.Call(2, 1) 1410 if LVAsBool(L.reg.Pop()) { 1411 return 1 1412 } 1413 return 0 1414 } 1415 return -1 1416 }