github.com/yuin/gopher-lua@v1.1.2-0.20231212122839-2348fd042596/_state.go (about) 1 package lua 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "math" 8 "os" 9 "runtime" 10 "strings" 11 "sync" 12 "sync/atomic" 13 "time" 14 15 "github.com/yuin/gopher-lua/parse" 16 ) 17 18 const MultRet = -1 19 const RegistryIndex = -10000 20 const EnvironIndex = -10001 21 const GlobalsIndex = -10002 22 23 /* ApiError {{{ */ 24 25 type ApiError struct { 26 Type ApiErrorType 27 Object LValue 28 StackTrace string 29 // Underlying error. This attribute is set only if the Type is ApiErrorFile or ApiErrorSyntax 30 Cause error 31 } 32 33 func newApiError(code ApiErrorType, object LValue) *ApiError { 34 return &ApiError{code, object, "", nil} 35 } 36 37 func newApiErrorS(code ApiErrorType, message string) *ApiError { 38 return newApiError(code, LString(message)) 39 } 40 41 func newApiErrorE(code ApiErrorType, err error) *ApiError { 42 return &ApiError{code, LString(err.Error()), "", err} 43 } 44 45 func (e *ApiError) Error() string { 46 if len(e.StackTrace) > 0 { 47 return fmt.Sprintf("%s\n%s", e.Object.String(), e.StackTrace) 48 } 49 return e.Object.String() 50 } 51 52 type ApiErrorType int 53 54 const ( 55 ApiErrorSyntax ApiErrorType = iota 56 ApiErrorFile 57 ApiErrorRun 58 ApiErrorError 59 ApiErrorPanic 60 ) 61 62 /* }}} */ 63 64 /* ResumeState {{{ */ 65 66 type ResumeState int 67 68 const ( 69 ResumeOK ResumeState = iota 70 ResumeYield 71 ResumeError 72 ) 73 74 /* }}} */ 75 76 /* P {{{ */ 77 78 type P struct { 79 Fn LValue 80 NRet int 81 Protect bool 82 Handler *LFunction 83 } 84 85 /* }}} */ 86 87 /* Options {{{ */ 88 89 // Options is a configuration that is used to create a new LState. 90 type Options struct { 91 // Call stack size. This defaults to `lua.CallStackSize`. 92 CallStackSize int 93 // Data stack size. This defaults to `lua.RegistrySize`. 94 RegistrySize int 95 // Allow the registry to grow from the registry size specified up to a value of RegistryMaxSize. A value of 0 96 // indicates no growth is permitted. The registry will not shrink again after any growth. 97 RegistryMaxSize int 98 // If growth is enabled, step up by an additional `RegistryGrowStep` each time to avoid having to resize too often. 99 // This defaults to `lua.RegistryGrowStep` 100 RegistryGrowStep int 101 // Controls whether or not libraries are opened by default 102 SkipOpenLibs bool 103 // Tells whether a Go stacktrace should be included in a Lua stacktrace when panics occur. 104 IncludeGoStackTrace bool 105 // If `MinimizeStackMemory` is set, the call stack will be automatically grown or shrank up to a limit of 106 // `CallStackSize` in order to minimize memory usage. This does incur a slight performance penalty. 107 MinimizeStackMemory bool 108 } 109 110 /* }}} */ 111 112 /* Debug {{{ */ 113 114 type Debug struct { 115 frame *callFrame 116 Name string 117 What string 118 Source string 119 CurrentLine int 120 NUpvalues int 121 LineDefined int 122 LastLineDefined int 123 } 124 125 /* }}} */ 126 127 /* callFrame {{{ */ 128 129 type callFrame struct { 130 Idx int 131 Fn *LFunction 132 Parent *callFrame 133 Pc int 134 Base int 135 LocalBase int 136 ReturnBase int 137 NArgs int 138 NRet int 139 TailCall int 140 } 141 142 type callFrameStack interface { 143 Push(v callFrame) 144 Pop() *callFrame 145 Last() *callFrame 146 147 SetSp(sp int) 148 Sp() int 149 At(sp int) *callFrame 150 151 IsFull() bool 152 IsEmpty() bool 153 154 FreeAll() 155 } 156 157 type fixedCallFrameStack struct { 158 array []callFrame 159 sp int 160 } 161 162 func newFixedCallFrameStack(size int) callFrameStack { 163 return &fixedCallFrameStack{ 164 array: make([]callFrame, size), 165 sp: 0, 166 } 167 } 168 169 func (cs *fixedCallFrameStack) IsEmpty() bool { return cs.sp == 0 } 170 171 func (cs *fixedCallFrameStack) IsFull() bool { return cs.sp == len(cs.array) } 172 173 func (cs *fixedCallFrameStack) Clear() { 174 cs.sp = 0 175 } 176 177 func (cs *fixedCallFrameStack) Push(v callFrame) { 178 cs.array[cs.sp] = v 179 cs.array[cs.sp].Idx = cs.sp 180 cs.sp++ 181 } 182 183 func (cs *fixedCallFrameStack) Sp() int { 184 return cs.sp 185 } 186 187 func (cs *fixedCallFrameStack) SetSp(sp int) { 188 cs.sp = sp 189 } 190 191 func (cs *fixedCallFrameStack) Last() *callFrame { 192 if cs.sp == 0 { 193 return nil 194 } 195 return &cs.array[cs.sp-1] 196 } 197 198 func (cs *fixedCallFrameStack) At(sp int) *callFrame { 199 return &cs.array[sp] 200 } 201 202 func (cs *fixedCallFrameStack) Pop() *callFrame { 203 cs.sp-- 204 return &cs.array[cs.sp] 205 } 206 207 func (cs *fixedCallFrameStack) FreeAll() { 208 // nothing to do for fixed callframestack 209 } 210 211 // FramesPerSegment should be a power of 2 constant for performance reasons. It will allow the go compiler to change 212 // the divs and mods into bitshifts. Max is 256 due to current use of uint8 to count how many frames in a segment are 213 // used. 214 const FramesPerSegment = 8 215 216 type callFrameStackSegment struct { 217 array [FramesPerSegment]callFrame 218 } 219 type segIdx uint16 220 type autoGrowingCallFrameStack struct { 221 segments []*callFrameStackSegment 222 segIdx segIdx 223 // segSp is the number of frames in the current segment which are used. Full 'sp' value is segIdx * FramesPerSegment + segSp. 224 // It points to the next stack slot to use, so 0 means to use the 0th element in the segment, and a value of 225 // FramesPerSegment indicates that the segment is full and cannot accommodate another frame. 226 segSp uint8 227 } 228 229 var segmentPool sync.Pool 230 231 func newCallFrameStackSegment() *callFrameStackSegment { 232 seg := segmentPool.Get() 233 if seg == nil { 234 return &callFrameStackSegment{} 235 } 236 return seg.(*callFrameStackSegment) 237 } 238 239 func freeCallFrameStackSegment(seg *callFrameStackSegment) { 240 segmentPool.Put(seg) 241 } 242 243 // newCallFrameStack allocates a new stack for a lua state, which will auto grow up to a max size of at least maxSize. 244 // it will actually grow up to the next segment size multiple after maxSize, where the segment size is dictated by 245 // FramesPerSegment. 246 func newAutoGrowingCallFrameStack(maxSize int) callFrameStack { 247 cs := &autoGrowingCallFrameStack{ 248 segments: make([]*callFrameStackSegment, (maxSize+(FramesPerSegment-1))/FramesPerSegment), 249 segIdx: 0, 250 } 251 cs.segments[0] = newCallFrameStackSegment() 252 return cs 253 } 254 255 func (cs *autoGrowingCallFrameStack) IsEmpty() bool { 256 return cs.segIdx == 0 && cs.segSp == 0 257 } 258 259 // IsFull returns true if the stack cannot receive any more stack pushes without overflowing 260 func (cs *autoGrowingCallFrameStack) IsFull() bool { 261 return int(cs.segIdx) == len(cs.segments) && cs.segSp >= FramesPerSegment 262 } 263 264 func (cs *autoGrowingCallFrameStack) Clear() { 265 for i := segIdx(1); i <= cs.segIdx; i++ { 266 freeCallFrameStackSegment(cs.segments[i]) 267 cs.segments[i] = nil 268 } 269 cs.segIdx = 0 270 cs.segSp = 0 271 } 272 273 func (cs *autoGrowingCallFrameStack) FreeAll() { 274 for i := segIdx(0); i <= cs.segIdx; i++ { 275 freeCallFrameStackSegment(cs.segments[i]) 276 cs.segments[i] = nil 277 } 278 } 279 280 // Push pushes the passed callFrame onto the stack. it panics if the stack is full, caller should call IsFull() before 281 // invoking this to avoid this. 282 func (cs *autoGrowingCallFrameStack) Push(v callFrame) { 283 curSeg := cs.segments[cs.segIdx] 284 if cs.segSp >= FramesPerSegment { 285 // segment full, push new segment if allowed 286 if cs.segIdx < segIdx(len(cs.segments)-1) { 287 curSeg = newCallFrameStackSegment() 288 cs.segIdx++ 289 cs.segments[cs.segIdx] = curSeg 290 cs.segSp = 0 291 } else { 292 panic("lua callstack overflow") 293 } 294 } 295 curSeg.array[cs.segSp] = v 296 curSeg.array[cs.segSp].Idx = int(cs.segSp) + FramesPerSegment*int(cs.segIdx) 297 cs.segSp++ 298 } 299 300 // Sp retrieves the current stack depth, which is the number of frames currently pushed on the stack. 301 func (cs *autoGrowingCallFrameStack) Sp() int { 302 return int(cs.segSp) + int(cs.segIdx)*FramesPerSegment 303 } 304 305 // SetSp can be used to rapidly unwind the stack, freeing all stack frames on the way. It should not be used to 306 // allocate new stack space, use Push() for that. 307 func (cs *autoGrowingCallFrameStack) SetSp(sp int) { 308 desiredSegIdx := segIdx(sp / FramesPerSegment) 309 desiredFramesInLastSeg := uint8(sp % FramesPerSegment) 310 for { 311 if cs.segIdx <= desiredSegIdx { 312 break 313 } 314 freeCallFrameStackSegment(cs.segments[cs.segIdx]) 315 cs.segments[cs.segIdx] = nil 316 cs.segIdx-- 317 } 318 cs.segSp = desiredFramesInLastSeg 319 } 320 321 func (cs *autoGrowingCallFrameStack) Last() *callFrame { 322 curSeg := cs.segments[cs.segIdx] 323 segSp := cs.segSp 324 if segSp == 0 { 325 if cs.segIdx == 0 { 326 return nil 327 } 328 curSeg = cs.segments[cs.segIdx-1] 329 segSp = FramesPerSegment 330 } 331 return &curSeg.array[segSp-1] 332 } 333 334 func (cs *autoGrowingCallFrameStack) At(sp int) *callFrame { 335 segIdx := segIdx(sp / FramesPerSegment) 336 frameIdx := uint8(sp % FramesPerSegment) 337 return &cs.segments[segIdx].array[frameIdx] 338 } 339 340 // Pop pops off the most recent stack frame and returns it 341 func (cs *autoGrowingCallFrameStack) Pop() *callFrame { 342 curSeg := cs.segments[cs.segIdx] 343 if cs.segSp == 0 { 344 if cs.segIdx == 0 { 345 // stack empty 346 return nil 347 } 348 freeCallFrameStackSegment(curSeg) 349 cs.segments[cs.segIdx] = nil 350 cs.segIdx-- 351 cs.segSp = FramesPerSegment 352 curSeg = cs.segments[cs.segIdx] 353 } 354 cs.segSp-- 355 return &curSeg.array[cs.segSp] 356 } 357 358 /* }}} */ 359 360 /* registry {{{ */ 361 362 type registryHandler interface { 363 registryOverflow() 364 } 365 type registry struct { 366 array []LValue 367 top int 368 growBy int 369 maxSize int 370 alloc *allocator 371 handler registryHandler 372 } 373 374 func newRegistry(handler registryHandler, initialSize int, growBy int, maxSize int, alloc *allocator) *registry { 375 return ®istry{make([]LValue, initialSize), 0, growBy, maxSize, alloc, handler} 376 } 377 378 func (rg *registry) checkSize(requiredSize int) { // +inline-start 379 if requiredSize > cap(rg.array) { 380 rg.resize(requiredSize) 381 } 382 } // +inline-end 383 384 func (rg *registry) resize(requiredSize int) { // +inline-start 385 newSize := requiredSize + rg.growBy // give some padding 386 if newSize > rg.maxSize { 387 newSize = rg.maxSize 388 } 389 if newSize < requiredSize { 390 rg.handler.registryOverflow() 391 return 392 } 393 rg.forceResize(newSize) 394 } // +inline-end 395 396 func (rg *registry) forceResize(newSize int) { 397 newSlice := make([]LValue, newSize) 398 copy(newSlice, rg.array[:rg.top]) // should we copy the area beyond top? there shouldn't be any valid values there so it shouldn't be necessary. 399 rg.array = newSlice 400 } 401 402 func (rg *registry) SetTop(topi int) { // +inline-start 403 // +inline-call rg.checkSize topi 404 oldtopi := rg.top 405 rg.top = topi 406 for i := oldtopi; i < rg.top; i++ { 407 rg.array[i] = LNil 408 } 409 // values beyond top don't need to be valid LValues, so setting them to nil is fine 410 // setting them to nil rather than LNil lets us invoke the golang memclr opto 411 if rg.top < oldtopi { 412 nilRange := rg.array[rg.top:oldtopi] 413 for i := range nilRange { 414 nilRange[i] = nil 415 } 416 } 417 //for i := rg.top; i < oldtop; i++ { 418 // rg.array[i] = LNil 419 //} 420 } // +inline-end 421 422 func (rg *registry) Top() int { 423 return rg.top 424 } 425 426 func (rg *registry) Push(v LValue) { 427 newSize := rg.top + 1 428 // +inline-call rg.checkSize newSize 429 rg.array[rg.top] = v 430 rg.top++ 431 } 432 433 func (rg *registry) Pop() LValue { 434 v := rg.array[rg.top-1] 435 rg.array[rg.top-1] = LNil 436 rg.top-- 437 return v 438 } 439 440 func (rg *registry) Get(reg int) LValue { 441 return rg.array[reg] 442 } 443 444 // CopyRange will move a section of values from index `start` to index `regv` 445 // It will move `n` values. 446 // `limit` specifies the maximum end range that can be copied from. If it's set to -1, then it defaults to stopping at 447 // the top of the registry (values beyond the top are not initialized, so if specifying an alternative `limit` you should 448 // pass a value <= rg.top. 449 // If start+n is beyond the limit, then nil values will be copied to the destination slots. 450 // After the copy, the registry is truncated to be at the end of the copied range, ie the original of the copied values 451 // are nilled out. (So top will be regv+n) 452 // CopyRange should ideally be renamed to MoveRange. 453 func (rg *registry) CopyRange(regv, start, limit, n int) { // +inline-start 454 newSize := regv + n 455 // +inline-call rg.checkSize newSize 456 if limit == -1 || limit > rg.top { 457 limit = rg.top 458 } 459 for i := 0; i < n; i++ { 460 srcIdx := start + i 461 if srcIdx >= limit || srcIdx < 0 { 462 rg.array[regv+i] = LNil 463 } else { 464 rg.array[regv+i] = rg.array[srcIdx] 465 } 466 } 467 468 // values beyond top don't need to be valid LValues, so setting them to nil is fine 469 // setting them to nil rather than LNil lets us invoke the golang memclr opto 470 oldtop := rg.top 471 rg.top = regv + n 472 if rg.top < oldtop { 473 nilRange := rg.array[rg.top:oldtop] 474 for i := range nilRange { 475 nilRange[i] = nil 476 } 477 } 478 } // +inline-end 479 480 // FillNil fills the registry with nil values from regm to regm+n and then sets the registry top to regm+n 481 func (rg *registry) FillNil(regm, n int) { // +inline-start 482 newSize := regm + n 483 // +inline-call rg.checkSize newSize 484 for i := 0; i < n; i++ { 485 rg.array[regm+i] = LNil 486 } 487 // values beyond top don't need to be valid LValues, so setting them to nil is fine 488 // setting them to nil rather than LNil lets us invoke the golang memclr opto 489 oldtop := rg.top 490 rg.top = regm + n 491 if rg.top < oldtop { 492 nilRange := rg.array[rg.top:oldtop] 493 for i := range nilRange { 494 nilRange[i] = nil 495 } 496 } 497 } // +inline-end 498 499 func (rg *registry) Insert(value LValue, reg int) { 500 top := rg.Top() 501 if reg >= top { 502 // +inline-call rg.Set reg value 503 return 504 } 505 top-- 506 for ; top >= reg; top-- { 507 // FIXME consider using copy() here if Insert() is called enough 508 // +inline-call rg.Set top+1 rg.Get(top) 509 } 510 // +inline-call rg.Set reg value 511 } 512 513 func (rg *registry) Set(regi int, vali LValue) { // +inline-start 514 newSize := regi + 1 515 // +inline-call rg.checkSize newSize 516 rg.array[regi] = vali 517 if regi >= rg.top { 518 rg.top = regi + 1 519 } 520 } // +inline-end 521 522 func (rg *registry) SetNumber(regi int, vali LNumber) { // +inline-start 523 newSize := regi + 1 524 // +inline-call rg.checkSize newSize 525 rg.array[regi] = rg.alloc.LNumber2I(vali) 526 if regi >= rg.top { 527 rg.top = regi + 1 528 } 529 } // +inline-end 530 531 func (rg *registry) IsFull() bool { 532 return rg.top >= cap(rg.array) 533 } 534 535 /* }}} */ 536 537 /* Global {{{ */ 538 539 func newGlobal() *Global { 540 return &Global{ 541 MainThread: nil, 542 Registry: newLTable(0, 32), 543 Global: newLTable(0, 64), 544 builtinMts: make(map[int]LValue), 545 tempFiles: make([]*os.File, 0, 10), 546 } 547 } 548 549 /* }}} */ 550 551 /* package local methods {{{ */ 552 553 func panicWithTraceback(L *LState) { 554 err := newApiError(ApiErrorRun, L.Get(-1)) 555 err.StackTrace = L.stackTrace(0) 556 panic(err) 557 } 558 559 func panicWithoutTraceback(L *LState) { 560 err := newApiError(ApiErrorRun, L.Get(-1)) 561 panic(err) 562 } 563 564 func newLState(options Options) *LState { 565 al := newAllocator(32) 566 ls := &LState{ 567 G: newGlobal(), 568 Parent: nil, 569 Panic: panicWithTraceback, 570 Dead: false, 571 Options: options, 572 573 stop: 0, 574 alloc: al, 575 currentFrame: nil, 576 wrapped: false, 577 uvcache: nil, 578 hasErrorFunc: false, 579 mainLoop: mainLoop, 580 ctx: nil, 581 } 582 if options.MinimizeStackMemory { 583 ls.stack = newAutoGrowingCallFrameStack(options.CallStackSize) 584 } else { 585 ls.stack = newFixedCallFrameStack(options.CallStackSize) 586 } 587 ls.reg = newRegistry(ls, options.RegistrySize, options.RegistryGrowStep, options.RegistryMaxSize, al) 588 ls.Env = ls.G.Global 589 return ls 590 } 591 592 func (ls *LState) printReg() { 593 println("-------------------------") 594 println("thread:", ls) 595 println("top:", ls.reg.Top()) 596 if ls.currentFrame != nil { 597 println("function base:", ls.currentFrame.Base) 598 println("return base:", ls.currentFrame.ReturnBase) 599 } else { 600 println("(vm not started)") 601 } 602 println("local base:", ls.currentLocalBase()) 603 for i := 0; i < ls.reg.Top(); i++ { 604 println(i, ls.reg.Get(i).String()) 605 } 606 println("-------------------------") 607 } 608 609 func (ls *LState) printCallStack() { 610 println("-------------------------") 611 for i := 0; i < ls.stack.Sp(); i++ { 612 print(i) 613 print(" ") 614 frame := ls.stack.At(i) 615 if frame == nil { 616 break 617 } 618 if frame.Fn.IsG { 619 println("IsG:", true, "Frame:", frame, "Fn:", frame.Fn) 620 } else { 621 println("IsG:", false, "Frame:", frame, "Fn:", frame.Fn, "pc:", frame.Pc) 622 } 623 } 624 println("-------------------------") 625 } 626 627 func (ls *LState) closeAllUpvalues() { // +inline-start 628 for cf := ls.currentFrame; cf != nil; cf = cf.Parent { 629 if !cf.Fn.IsG { 630 ls.closeUpvalues(cf.LocalBase) 631 } 632 } 633 } // +inline-end 634 635 func (ls *LState) raiseError(level int, format string, args ...interface{}) { 636 if !ls.hasErrorFunc { 637 ls.closeAllUpvalues() 638 } 639 message := format 640 if len(args) > 0 { 641 message = fmt.Sprintf(format, args...) 642 } 643 if level > 0 { 644 message = fmt.Sprintf("%v %v", ls.where(level-1, true), message) 645 } 646 if ls.reg.IsFull() { 647 // if the registry is full then it won't be possible to push a value, in this case, force a larger size 648 ls.reg.forceResize(ls.reg.Top() + 1) 649 } 650 ls.reg.Push(LString(message)) 651 ls.Panic(ls) 652 } 653 654 func (ls *LState) findLocal(frame *callFrame, no int) string { 655 fn := frame.Fn 656 if !fn.IsG { 657 if name, ok := fn.LocalName(no, frame.Pc-1); ok { 658 return name 659 } 660 } 661 var top int 662 if ls.currentFrame == frame { 663 top = ls.reg.Top() 664 } else if frame.Idx+1 < ls.stack.Sp() { 665 top = ls.stack.At(frame.Idx + 1).Base 666 } else { 667 return "" 668 } 669 if top-frame.LocalBase >= no { 670 return "(*temporary)" 671 } 672 return "" 673 } 674 675 func (ls *LState) where(level int, skipg bool) string { 676 dbg, ok := ls.GetStack(level) 677 if !ok { 678 return "" 679 } 680 cf := dbg.frame 681 proto := cf.Fn.Proto 682 sourcename := "[G]" 683 if proto != nil { 684 sourcename = proto.SourceName 685 } else if skipg { 686 return ls.where(level+1, skipg) 687 } 688 line := "" 689 if proto != nil { 690 line = fmt.Sprintf("%v:", proto.DbgSourcePositions[cf.Pc-1]) 691 } 692 return fmt.Sprintf("%v:%v", sourcename, line) 693 } 694 695 func (ls *LState) stackTrace(level int) string { 696 buf := []string{} 697 header := "stack traceback:" 698 if ls.currentFrame != nil { 699 i := 0 700 for dbg, ok := ls.GetStack(i); ok; dbg, ok = ls.GetStack(i) { 701 cf := dbg.frame 702 buf = append(buf, fmt.Sprintf("\t%v in %v", ls.Where(i), ls.formattedFrameFuncName(cf))) 703 if !cf.Fn.IsG && cf.TailCall > 0 { 704 for tc := cf.TailCall; tc > 0; tc-- { 705 buf = append(buf, "\t(tailcall): ?") 706 i++ 707 } 708 } 709 i++ 710 } 711 } 712 buf = append(buf, fmt.Sprintf("\t%v: %v", "[G]", "?")) 713 buf = buf[intMax(0, intMin(level, len(buf))):len(buf)] 714 if len(buf) > 20 { 715 newbuf := make([]string, 0, 20) 716 newbuf = append(newbuf, buf[0:7]...) 717 newbuf = append(newbuf, "\t...") 718 newbuf = append(newbuf, buf[len(buf)-7:len(buf)]...) 719 buf = newbuf 720 } 721 return fmt.Sprintf("%s\n%s", header, strings.Join(buf, "\n")) 722 } 723 724 func (ls *LState) formattedFrameFuncName(fr *callFrame) string { 725 name, ischunk := ls.frameFuncName(fr) 726 if ischunk { 727 return name 728 } 729 if name[0] != '(' && name[0] != '<' { 730 return fmt.Sprintf("function '%s'", name) 731 } 732 return fmt.Sprintf("function %s", name) 733 } 734 735 func (ls *LState) rawFrameFuncName(fr *callFrame) string { 736 name, _ := ls.frameFuncName(fr) 737 return name 738 } 739 740 func (ls *LState) frameFuncName(fr *callFrame) (string, bool) { 741 frame := fr.Parent 742 if frame == nil { 743 if ls.Parent == nil { 744 return "main chunk", true 745 } else { 746 return "corountine", true 747 } 748 } 749 if !frame.Fn.IsG { 750 pc := frame.Pc - 1 751 for _, call := range frame.Fn.Proto.DbgCalls { 752 if call.Pc == pc { 753 name := call.Name 754 if (name == "?" || fr.TailCall > 0) && !fr.Fn.IsG { 755 name = fmt.Sprintf("<%v:%v>", fr.Fn.Proto.SourceName, fr.Fn.Proto.LineDefined) 756 } 757 return name, false 758 } 759 } 760 } 761 if !fr.Fn.IsG { 762 return fmt.Sprintf("<%v:%v>", fr.Fn.Proto.SourceName, fr.Fn.Proto.LineDefined), false 763 } 764 return "(anonymous)", false 765 } 766 767 func (ls *LState) isStarted() bool { 768 return ls.currentFrame != nil 769 } 770 771 func (ls *LState) kill() { 772 ls.Dead = true 773 if ls.ctxCancelFn != nil { 774 ls.ctxCancelFn() 775 } 776 } 777 778 func (ls *LState) indexToReg(idx int) int { 779 base := ls.currentLocalBase() 780 if idx > 0 { 781 return base + idx - 1 782 } else if idx == 0 { 783 return -1 784 } else { 785 tidx := ls.reg.Top() + idx 786 if tidx < base { 787 return -1 788 } 789 return tidx 790 } 791 } 792 793 func (ls *LState) currentLocalBase() int { 794 base := 0 795 if ls.currentFrame != nil { 796 base = ls.currentFrame.LocalBase 797 } 798 return base 799 } 800 801 func (ls *LState) currentEnv() *LTable { 802 return ls.Env 803 /* 804 if ls.currentFrame == nil { 805 return ls.Env 806 } 807 return ls.currentFrame.Fn.Env 808 */ 809 } 810 811 func (ls *LState) rkValue(idx int) LValue { 812 /* 813 if OpIsK(idx) { 814 return ls.currentFrame.Fn.Proto.Constants[opIndexK(idx)] 815 } 816 return ls.reg.Get(ls.currentFrame.LocalBase + idx) 817 */ 818 if (idx & opBitRk) != 0 { 819 return ls.currentFrame.Fn.Proto.Constants[idx & ^opBitRk] 820 } 821 return ls.reg.array[ls.currentFrame.LocalBase+idx] 822 } 823 824 func (ls *LState) rkString(idx int) string { 825 if (idx & opBitRk) != 0 { 826 return ls.currentFrame.Fn.Proto.stringConstants[idx & ^opBitRk] 827 } 828 return string(ls.reg.array[ls.currentFrame.LocalBase+idx].(LString)) 829 } 830 831 func (ls *LState) closeUpvalues(idx int) { // +inline-start 832 if ls.uvcache != nil { 833 var prev *Upvalue 834 for uv := ls.uvcache; uv != nil; uv = uv.next { 835 if uv.index >= idx { 836 if prev != nil { 837 prev.next = nil 838 } else { 839 ls.uvcache = nil 840 } 841 uv.Close() 842 } 843 prev = uv 844 } 845 } 846 } // +inline-end 847 848 func (ls *LState) findUpvalue(idx int) *Upvalue { 849 var prev *Upvalue 850 var next *Upvalue 851 if ls.uvcache != nil { 852 for uv := ls.uvcache; uv != nil; uv = uv.next { 853 if uv.index == idx { 854 return uv 855 } 856 if uv.index > idx { 857 next = uv 858 break 859 } 860 prev = uv 861 } 862 } 863 uv := &Upvalue{reg: ls.reg, index: idx, closed: false} 864 if prev != nil { 865 prev.next = uv 866 } else { 867 ls.uvcache = uv 868 } 869 if next != nil { 870 uv.next = next 871 } 872 return uv 873 } 874 875 func (ls *LState) metatable(lvalue LValue, rawget bool) LValue { 876 var metatable LValue = LNil 877 switch obj := lvalue.(type) { 878 case *LTable: 879 metatable = obj.Metatable 880 case *LUserData: 881 metatable = obj.Metatable 882 default: 883 if table, ok := ls.G.builtinMts[int(obj.Type())]; ok { 884 metatable = table 885 } 886 } 887 888 if !rawget && metatable != LNil { 889 oldmt := metatable 890 if tb, ok := metatable.(*LTable); ok { 891 metatable = tb.RawGetString("__metatable") 892 if metatable == LNil { 893 metatable = oldmt 894 } 895 } 896 } 897 898 return metatable 899 } 900 901 func (ls *LState) metaOp1(lvalue LValue, event string) LValue { 902 if mt := ls.metatable(lvalue, true); mt != LNil { 903 if tb, ok := mt.(*LTable); ok { 904 return tb.RawGetString(event) 905 } 906 } 907 return LNil 908 } 909 910 func (ls *LState) metaOp2(value1, value2 LValue, event string) LValue { 911 if mt := ls.metatable(value1, true); mt != LNil { 912 if tb, ok := mt.(*LTable); ok { 913 if ret := tb.RawGetString(event); ret != LNil { 914 return ret 915 } 916 } 917 } 918 if mt := ls.metatable(value2, true); mt != LNil { 919 if tb, ok := mt.(*LTable); ok { 920 return tb.RawGetString(event) 921 } 922 } 923 return LNil 924 } 925 926 func (ls *LState) metaCall(lvalue LValue) (*LFunction, bool) { 927 if fn, ok := lvalue.(*LFunction); ok { 928 return fn, false 929 } 930 if fn, ok := ls.metaOp1(lvalue, "__call").(*LFunction); ok { 931 return fn, true 932 } 933 return nil, false 934 } 935 936 func (ls *LState) initCallFrame(cf *callFrame) { // +inline-start 937 if cf.Fn.IsG { 938 ls.reg.SetTop(cf.LocalBase + cf.NArgs) 939 } else { 940 proto := cf.Fn.Proto 941 nargs := cf.NArgs 942 np := int(proto.NumParameters) 943 if nargs < np { 944 // default any missing arguments to nil 945 newSize := cf.LocalBase + np 946 // +inline-call ls.reg.checkSize newSize 947 for i := nargs; i < np; i++ { 948 ls.reg.array[cf.LocalBase+i] = LNil 949 } 950 nargs = np 951 ls.reg.top = newSize 952 } 953 954 if (proto.IsVarArg & VarArgIsVarArg) == 0 { 955 if nargs < int(proto.NumUsedRegisters) { 956 nargs = int(proto.NumUsedRegisters) 957 } 958 newSize := cf.LocalBase + nargs 959 // +inline-call ls.reg.checkSize newSize 960 for i := np; i < nargs; i++ { 961 ls.reg.array[cf.LocalBase+i] = LNil 962 } 963 ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters) 964 } else { 965 /* swap vararg positions: 966 closure 967 namedparam1 <- lbase 968 namedparam2 969 vararg1 970 vararg2 971 972 TO 973 974 closure 975 nil 976 nil 977 vararg1 978 vararg2 979 namedparam1 <- lbase 980 namedparam2 981 */ 982 nvarargs := nargs - np 983 if nvarargs < 0 { 984 nvarargs = 0 985 } 986 987 ls.reg.SetTop(cf.LocalBase + nargs + np) 988 for i := 0; i < np; i++ { 989 //ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i)) 990 ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i] 991 //ls.reg.Set(cf.LocalBase+i, LNil) 992 ls.reg.array[cf.LocalBase+i] = LNil 993 } 994 995 if CompatVarArg { 996 ls.reg.SetTop(cf.LocalBase + nargs + np + 1) 997 if (proto.IsVarArg & VarArgNeedsArg) != 0 { 998 argtb := newLTable(nvarargs, 0) 999 for i := 0; i < nvarargs; i++ { 1000 argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i)) 1001 } 1002 argtb.RawSetString("n", LNumber(nvarargs)) 1003 //ls.reg.Set(cf.LocalBase+nargs+np, argtb) 1004 ls.reg.array[cf.LocalBase+nargs+np] = argtb 1005 } else { 1006 ls.reg.array[cf.LocalBase+nargs+np] = LNil 1007 } 1008 } 1009 cf.LocalBase += nargs 1010 maxreg := cf.LocalBase + int(proto.NumUsedRegisters) 1011 ls.reg.SetTop(maxreg) 1012 } 1013 } 1014 } // +inline-end 1015 1016 func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) { // +inline-start 1017 if meta { 1018 cf.NArgs++ 1019 ls.reg.Insert(fn, cf.LocalBase) 1020 } 1021 if cf.Fn == nil { 1022 ls.RaiseError("attempt to call a non-function object") 1023 } 1024 if ls.stack.IsFull() { 1025 ls.RaiseError("stack overflow") 1026 } 1027 ls.stack.Push(cf) 1028 newcf := ls.stack.Last() 1029 // +inline-call ls.initCallFrame newcf 1030 ls.currentFrame = newcf 1031 } // +inline-end 1032 1033 func (ls *LState) callR(nargs, nret, rbase int) { 1034 base := ls.reg.Top() - nargs - 1 1035 if rbase < 0 { 1036 rbase = base 1037 } 1038 lv := ls.reg.Get(base) 1039 fn, meta := ls.metaCall(lv) 1040 ls.pushCallFrame(callFrame{ 1041 Fn: fn, 1042 Pc: 0, 1043 Base: base, 1044 LocalBase: base + 1, 1045 ReturnBase: rbase, 1046 NArgs: nargs, 1047 NRet: nret, 1048 Parent: ls.currentFrame, 1049 TailCall: 0, 1050 }, lv, meta) 1051 if ls.G.MainThread == nil { 1052 ls.G.MainThread = ls 1053 ls.G.CurrentThread = ls 1054 ls.mainLoop(ls, nil) 1055 } else { 1056 ls.mainLoop(ls, ls.currentFrame) 1057 } 1058 if nret != MultRet { 1059 ls.reg.SetTop(rbase + nret) 1060 } 1061 } 1062 1063 func (ls *LState) getField(obj LValue, key LValue) LValue { 1064 curobj := obj 1065 for i := 0; i < MaxTableGetLoop; i++ { 1066 tb, istable := curobj.(*LTable) 1067 if istable { 1068 ret := tb.RawGet(key) 1069 if ret != LNil { 1070 return ret 1071 } 1072 } 1073 metaindex := ls.metaOp1(curobj, "__index") 1074 if metaindex == LNil { 1075 if !istable { 1076 ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key.String()) 1077 } 1078 return LNil 1079 } 1080 if metaindex.Type() == LTFunction { 1081 ls.reg.Push(metaindex) 1082 ls.reg.Push(curobj) 1083 ls.reg.Push(key) 1084 ls.Call(2, 1) 1085 return ls.reg.Pop() 1086 } else { 1087 curobj = metaindex 1088 } 1089 } 1090 ls.RaiseError("too many recursions in gettable") 1091 return nil 1092 } 1093 1094 func (ls *LState) getFieldString(obj LValue, key string) LValue { 1095 curobj := obj 1096 for i := 0; i < MaxTableGetLoop; i++ { 1097 tb, istable := curobj.(*LTable) 1098 if istable { 1099 ret := tb.RawGetString(key) 1100 if ret != LNil { 1101 return ret 1102 } 1103 } 1104 metaindex := ls.metaOp1(curobj, "__index") 1105 if metaindex == LNil { 1106 if !istable { 1107 ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key) 1108 } 1109 return LNil 1110 } 1111 if metaindex.Type() == LTFunction { 1112 ls.reg.Push(metaindex) 1113 ls.reg.Push(curobj) 1114 ls.reg.Push(LString(key)) 1115 ls.Call(2, 1) 1116 return ls.reg.Pop() 1117 } else { 1118 curobj = metaindex 1119 } 1120 } 1121 ls.RaiseError("too many recursions in gettable") 1122 return nil 1123 } 1124 1125 func (ls *LState) setField(obj LValue, key LValue, value LValue) { 1126 curobj := obj 1127 for i := 0; i < MaxTableGetLoop; i++ { 1128 tb, istable := curobj.(*LTable) 1129 if istable { 1130 if tb.RawGet(key) != LNil { 1131 ls.RawSet(tb, key, value) 1132 return 1133 } 1134 } 1135 metaindex := ls.metaOp1(curobj, "__newindex") 1136 if metaindex == LNil { 1137 if !istable { 1138 ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key.String()) 1139 } 1140 ls.RawSet(tb, key, value) 1141 return 1142 } 1143 if metaindex.Type() == LTFunction { 1144 ls.reg.Push(metaindex) 1145 ls.reg.Push(curobj) 1146 ls.reg.Push(key) 1147 ls.reg.Push(value) 1148 ls.Call(3, 0) 1149 return 1150 } else { 1151 curobj = metaindex 1152 } 1153 } 1154 ls.RaiseError("too many recursions in settable") 1155 } 1156 1157 func (ls *LState) setFieldString(obj LValue, key string, value LValue) { 1158 curobj := obj 1159 for i := 0; i < MaxTableGetLoop; i++ { 1160 tb, istable := curobj.(*LTable) 1161 if istable { 1162 if tb.RawGetString(key) != LNil { 1163 tb.RawSetString(key, value) 1164 return 1165 } 1166 } 1167 metaindex := ls.metaOp1(curobj, "__newindex") 1168 if metaindex == LNil { 1169 if !istable { 1170 ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key) 1171 } 1172 tb.RawSetString(key, value) 1173 return 1174 } 1175 if metaindex.Type() == LTFunction { 1176 ls.reg.Push(metaindex) 1177 ls.reg.Push(curobj) 1178 ls.reg.Push(LString(key)) 1179 ls.reg.Push(value) 1180 ls.Call(3, 0) 1181 return 1182 } else { 1183 curobj = metaindex 1184 } 1185 } 1186 ls.RaiseError("too many recursions in settable") 1187 } 1188 1189 /* }}} */ 1190 1191 /* api methods {{{ */ 1192 1193 func NewState(opts ...Options) *LState { 1194 var ls *LState 1195 if len(opts) == 0 { 1196 ls = newLState(Options{ 1197 CallStackSize: CallStackSize, 1198 RegistrySize: RegistrySize, 1199 }) 1200 ls.OpenLibs() 1201 } else { 1202 if opts[0].CallStackSize < 1 { 1203 opts[0].CallStackSize = CallStackSize 1204 } 1205 if opts[0].RegistrySize < 128 { 1206 opts[0].RegistrySize = RegistrySize 1207 } 1208 if opts[0].RegistryMaxSize < opts[0].RegistrySize { 1209 opts[0].RegistryMaxSize = 0 // disable growth if max size is smaller than initial size 1210 } else { 1211 // if growth enabled, grow step is set 1212 if opts[0].RegistryGrowStep < 1 { 1213 opts[0].RegistryGrowStep = RegistryGrowStep 1214 } 1215 } 1216 ls = newLState(opts[0]) 1217 if !opts[0].SkipOpenLibs { 1218 ls.OpenLibs() 1219 } 1220 } 1221 return ls 1222 } 1223 1224 func (ls *LState) IsClosed() bool { 1225 return ls.stack == nil 1226 } 1227 1228 func (ls *LState) Close() { 1229 atomic.AddInt32(&ls.stop, 1) 1230 for _, file := range ls.G.tempFiles { 1231 // ignore errors in these operations 1232 file.Close() 1233 os.Remove(file.Name()) 1234 } 1235 ls.stack.FreeAll() 1236 ls.stack = nil 1237 } 1238 1239 /* registry operations {{{ */ 1240 1241 func (ls *LState) GetTop() int { 1242 return ls.reg.Top() - ls.currentLocalBase() 1243 } 1244 1245 func (ls *LState) SetTop(idx int) { 1246 base := ls.currentLocalBase() 1247 newtop := ls.indexToReg(idx) + 1 1248 if newtop < base { 1249 ls.reg.SetTop(base) 1250 } else { 1251 ls.reg.SetTop(newtop) 1252 } 1253 } 1254 1255 func (ls *LState) Replace(idx int, value LValue) { 1256 base := ls.currentLocalBase() 1257 if idx > 0 { 1258 reg := base + idx - 1 1259 if reg < ls.reg.Top() { 1260 ls.reg.Set(reg, value) 1261 } 1262 } else if idx == 0 { 1263 } else if idx > RegistryIndex { 1264 if tidx := ls.reg.Top() + idx; tidx >= base { 1265 ls.reg.Set(tidx, value) 1266 } 1267 } else { 1268 switch idx { 1269 case RegistryIndex: 1270 if tb, ok := value.(*LTable); ok { 1271 ls.G.Registry = tb 1272 } else { 1273 ls.RaiseError("registry must be a table(%v)", value.Type().String()) 1274 } 1275 case EnvironIndex: 1276 if ls.currentFrame == nil { 1277 ls.RaiseError("no calling environment") 1278 } 1279 if tb, ok := value.(*LTable); ok { 1280 ls.currentFrame.Fn.Env = tb 1281 } else { 1282 ls.RaiseError("environment must be a table(%v)", value.Type().String()) 1283 } 1284 case GlobalsIndex: 1285 if tb, ok := value.(*LTable); ok { 1286 ls.G.Global = tb 1287 } else { 1288 ls.RaiseError("_G must be a table(%v)", value.Type().String()) 1289 } 1290 default: 1291 fn := ls.currentFrame.Fn 1292 index := GlobalsIndex - idx - 1 1293 if index < len(fn.Upvalues) { 1294 fn.Upvalues[index].SetValue(value) 1295 } 1296 } 1297 } 1298 } 1299 1300 func (ls *LState) Get(idx int) LValue { 1301 base := ls.currentLocalBase() 1302 if idx > 0 { 1303 reg := base + idx - 1 1304 if reg < ls.reg.Top() { 1305 return ls.reg.Get(reg) 1306 } 1307 return LNil 1308 } else if idx == 0 { 1309 return LNil 1310 } else if idx > RegistryIndex { 1311 tidx := ls.reg.Top() + idx 1312 if tidx < base { 1313 return LNil 1314 } 1315 return ls.reg.Get(tidx) 1316 } else { 1317 switch idx { 1318 case RegistryIndex: 1319 return ls.G.Registry 1320 case EnvironIndex: 1321 if ls.currentFrame == nil { 1322 return ls.Env 1323 } 1324 return ls.currentFrame.Fn.Env 1325 case GlobalsIndex: 1326 return ls.G.Global 1327 default: 1328 fn := ls.currentFrame.Fn 1329 index := GlobalsIndex - idx - 1 1330 if index < len(fn.Upvalues) { 1331 return fn.Upvalues[index].Value() 1332 } 1333 return LNil 1334 } 1335 } 1336 return LNil 1337 } 1338 1339 func (ls *LState) Push(value LValue) { 1340 ls.reg.Push(value) 1341 } 1342 1343 func (ls *LState) Pop(n int) { 1344 for i := 0; i < n; i++ { 1345 if ls.GetTop() == 0 { 1346 ls.RaiseError("register underflow") 1347 } 1348 ls.reg.Pop() 1349 } 1350 } 1351 1352 func (ls *LState) Insert(value LValue, index int) { 1353 reg := ls.indexToReg(index) 1354 top := ls.reg.Top() 1355 if reg >= top { 1356 ls.reg.Set(reg, value) 1357 return 1358 } 1359 if reg <= ls.currentLocalBase() { 1360 reg = ls.currentLocalBase() 1361 } 1362 top-- 1363 for ; top >= reg; top-- { 1364 ls.reg.Set(top+1, ls.reg.Get(top)) 1365 } 1366 ls.reg.Set(reg, value) 1367 } 1368 1369 func (ls *LState) Remove(index int) { 1370 reg := ls.indexToReg(index) 1371 top := ls.reg.Top() 1372 switch { 1373 case reg >= top: 1374 return 1375 case reg < ls.currentLocalBase(): 1376 return 1377 case reg == top-1: 1378 ls.Pop(1) 1379 return 1380 } 1381 for i := reg; i < top-1; i++ { 1382 ls.reg.Set(i, ls.reg.Get(i+1)) 1383 } 1384 ls.reg.SetTop(top - 1) 1385 } 1386 1387 /* }}} */ 1388 1389 /* object allocation {{{ */ 1390 1391 func (ls *LState) NewTable() *LTable { 1392 return newLTable(defaultArrayCap, defaultHashCap) 1393 } 1394 1395 func (ls *LState) CreateTable(acap, hcap int) *LTable { 1396 return newLTable(acap, hcap) 1397 } 1398 1399 // NewThread returns a new LState that shares with the original state all global objects. 1400 // If the original state has context.Context, the new state has a new child context of the original state and this function returns its cancel function. 1401 func (ls *LState) NewThread() (*LState, context.CancelFunc) { 1402 thread := newLState(ls.Options) 1403 thread.G = ls.G 1404 thread.Env = ls.Env 1405 var f context.CancelFunc = nil 1406 if ls.ctx != nil { 1407 thread.mainLoop = mainLoopWithContext 1408 thread.ctx, f = context.WithCancel(ls.ctx) 1409 thread.ctxCancelFn = f 1410 } 1411 return thread, f 1412 } 1413 1414 func (ls *LState) NewFunctionFromProto(proto *FunctionProto) *LFunction { 1415 return newLFunctionL(proto, ls.Env, int(proto.NumUpvalues)) 1416 } 1417 1418 func (ls *LState) NewUserData() *LUserData { 1419 return &LUserData{ 1420 Env: ls.currentEnv(), 1421 Metatable: LNil, 1422 } 1423 } 1424 1425 func (ls *LState) NewFunction(fn LGFunction) *LFunction { 1426 return newLFunctionG(fn, ls.currentEnv(), 0) 1427 } 1428 1429 func (ls *LState) NewClosure(fn LGFunction, upvalues ...LValue) *LFunction { 1430 cl := newLFunctionG(fn, ls.currentEnv(), len(upvalues)) 1431 for i, lv := range upvalues { 1432 cl.Upvalues[i] = &Upvalue{} 1433 cl.Upvalues[i].Close() 1434 cl.Upvalues[i].SetValue(lv) 1435 } 1436 return cl 1437 } 1438 1439 /* }}} */ 1440 1441 /* toType {{{ */ 1442 1443 func (ls *LState) ToBool(n int) bool { 1444 return LVAsBool(ls.Get(n)) 1445 } 1446 1447 func (ls *LState) ToInt(n int) int { 1448 if lv, ok := ls.Get(n).(LNumber); ok { 1449 return int(lv) 1450 } 1451 if lv, ok := ls.Get(n).(LString); ok { 1452 if num, err := parseNumber(string(lv)); err == nil { 1453 return int(num) 1454 } 1455 } 1456 return 0 1457 } 1458 1459 func (ls *LState) ToInt64(n int) int64 { 1460 if lv, ok := ls.Get(n).(LNumber); ok { 1461 return int64(lv) 1462 } 1463 if lv, ok := ls.Get(n).(LString); ok { 1464 if num, err := parseNumber(string(lv)); err == nil { 1465 return int64(num) 1466 } 1467 } 1468 return 0 1469 } 1470 1471 func (ls *LState) ToNumber(n int) LNumber { 1472 return LVAsNumber(ls.Get(n)) 1473 } 1474 1475 func (ls *LState) ToString(n int) string { 1476 return LVAsString(ls.Get(n)) 1477 } 1478 1479 func (ls *LState) ToTable(n int) *LTable { 1480 if lv, ok := ls.Get(n).(*LTable); ok { 1481 return lv 1482 } 1483 return nil 1484 } 1485 1486 func (ls *LState) ToFunction(n int) *LFunction { 1487 if lv, ok := ls.Get(n).(*LFunction); ok { 1488 return lv 1489 } 1490 return nil 1491 } 1492 1493 func (ls *LState) ToUserData(n int) *LUserData { 1494 if lv, ok := ls.Get(n).(*LUserData); ok { 1495 return lv 1496 } 1497 return nil 1498 } 1499 1500 func (ls *LState) ToThread(n int) *LState { 1501 if lv, ok := ls.Get(n).(*LState); ok { 1502 return lv 1503 } 1504 return nil 1505 } 1506 1507 /* }}} */ 1508 1509 /* error & debug operations {{{ */ 1510 1511 func (ls *LState) registryOverflow() { 1512 ls.RaiseError("registry overflow") 1513 } 1514 1515 // This function is equivalent to luaL_error( http://www.lua.org/manual/5.1/manual.html#luaL_error ). 1516 func (ls *LState) RaiseError(format string, args ...interface{}) { 1517 ls.raiseError(1, format, args...) 1518 } 1519 1520 // This function is equivalent to lua_error( http://www.lua.org/manual/5.1/manual.html#lua_error ). 1521 func (ls *LState) Error(lv LValue, level int) { 1522 if str, ok := lv.(LString); ok { 1523 ls.raiseError(level, string(str)) 1524 } else { 1525 if !ls.hasErrorFunc { 1526 ls.closeAllUpvalues() 1527 } 1528 ls.Push(lv) 1529 ls.Panic(ls) 1530 } 1531 } 1532 1533 func (ls *LState) GetInfo(what string, dbg *Debug, fn LValue) (LValue, error) { 1534 if !strings.HasPrefix(what, ">") { 1535 fn = dbg.frame.Fn 1536 } else { 1537 what = what[1:] 1538 } 1539 f, ok := fn.(*LFunction) 1540 if !ok { 1541 return LNil, newApiErrorS(ApiErrorRun, "can not get debug info(an object in not a function)") 1542 } 1543 1544 retfn := false 1545 for _, c := range what { 1546 switch c { 1547 case 'f': 1548 retfn = true 1549 case 'S': 1550 if dbg.frame != nil && dbg.frame.Parent == nil { 1551 dbg.What = "main" 1552 } else if f.IsG { 1553 dbg.What = "G" 1554 } else if dbg.frame != nil && dbg.frame.TailCall > 0 { 1555 dbg.What = "tail" 1556 } else { 1557 dbg.What = "Lua" 1558 } 1559 if !f.IsG { 1560 dbg.Source = f.Proto.SourceName 1561 dbg.LineDefined = f.Proto.LineDefined 1562 dbg.LastLineDefined = f.Proto.LastLineDefined 1563 } 1564 case 'l': 1565 if !f.IsG && dbg.frame != nil { 1566 if dbg.frame.Pc > 0 { 1567 dbg.CurrentLine = f.Proto.DbgSourcePositions[dbg.frame.Pc-1] 1568 } 1569 } else { 1570 dbg.CurrentLine = -1 1571 } 1572 case 'u': 1573 dbg.NUpvalues = len(f.Upvalues) 1574 case 'n': 1575 if dbg.frame != nil { 1576 dbg.Name = ls.rawFrameFuncName(dbg.frame) 1577 } 1578 default: 1579 return LNil, newApiErrorS(ApiErrorRun, "invalid what: "+string(c)) 1580 } 1581 } 1582 1583 if retfn { 1584 return f, nil 1585 } 1586 return LNil, nil 1587 1588 } 1589 1590 func (ls *LState) GetStack(level int) (*Debug, bool) { 1591 frame := ls.currentFrame 1592 for ; level > 0 && frame != nil; frame = frame.Parent { 1593 level-- 1594 if !frame.Fn.IsG { 1595 level -= frame.TailCall 1596 } 1597 } 1598 1599 if level == 0 && frame != nil { 1600 return &Debug{frame: frame}, true 1601 } else if level < 0 && ls.stack.Sp() > 0 { 1602 return &Debug{frame: ls.stack.At(0)}, true 1603 } 1604 return &Debug{}, false 1605 } 1606 1607 func (ls *LState) GetLocal(dbg *Debug, no int) (string, LValue) { 1608 frame := dbg.frame 1609 if name := ls.findLocal(frame, no); len(name) > 0 { 1610 return name, ls.reg.Get(frame.LocalBase + no - 1) 1611 } 1612 return "", LNil 1613 } 1614 1615 func (ls *LState) SetLocal(dbg *Debug, no int, lv LValue) string { 1616 frame := dbg.frame 1617 if name := ls.findLocal(frame, no); len(name) > 0 { 1618 ls.reg.Set(frame.LocalBase+no-1, lv) 1619 return name 1620 } 1621 return "" 1622 } 1623 1624 func (ls *LState) GetUpvalue(fn *LFunction, no int) (string, LValue) { 1625 if fn.IsG { 1626 return "", LNil 1627 } 1628 1629 no-- 1630 if no >= 0 && no < len(fn.Upvalues) { 1631 return fn.Proto.DbgUpvalues[no], fn.Upvalues[no].Value() 1632 } 1633 return "", LNil 1634 } 1635 1636 func (ls *LState) SetUpvalue(fn *LFunction, no int, lv LValue) string { 1637 if fn.IsG { 1638 return "" 1639 } 1640 1641 no-- 1642 if no >= 0 && no < len(fn.Upvalues) { 1643 fn.Upvalues[no].SetValue(lv) 1644 return fn.Proto.DbgUpvalues[no] 1645 } 1646 return "" 1647 } 1648 1649 /* }}} */ 1650 1651 /* env operations {{{ */ 1652 1653 func (ls *LState) GetFEnv(obj LValue) LValue { 1654 switch lv := obj.(type) { 1655 case *LFunction: 1656 return lv.Env 1657 case *LUserData: 1658 return lv.Env 1659 case *LState: 1660 return lv.Env 1661 } 1662 return LNil 1663 } 1664 1665 func (ls *LState) SetFEnv(obj LValue, env LValue) { 1666 tb, ok := env.(*LTable) 1667 if !ok { 1668 ls.RaiseError("cannot use %v as an environment", env.Type().String()) 1669 } 1670 1671 switch lv := obj.(type) { 1672 case *LFunction: 1673 lv.Env = tb 1674 case *LUserData: 1675 lv.Env = tb 1676 case *LState: 1677 lv.Env = tb 1678 } 1679 /* do nothing */ 1680 } 1681 1682 /* }}} */ 1683 1684 /* table operations {{{ */ 1685 1686 func (ls *LState) RawGet(tb *LTable, key LValue) LValue { 1687 return tb.RawGet(key) 1688 } 1689 1690 func (ls *LState) RawGetInt(tb *LTable, key int) LValue { 1691 return tb.RawGetInt(key) 1692 } 1693 1694 func (ls *LState) GetField(obj LValue, skey string) LValue { 1695 return ls.getFieldString(obj, skey) 1696 } 1697 1698 func (ls *LState) GetTable(obj LValue, key LValue) LValue { 1699 return ls.getField(obj, key) 1700 } 1701 1702 func (ls *LState) RawSet(tb *LTable, key LValue, value LValue) { 1703 if n, ok := key.(LNumber); ok && math.IsNaN(float64(n)) { 1704 ls.RaiseError("table index is NaN") 1705 } else if key == LNil { 1706 ls.RaiseError("table index is nil") 1707 } 1708 tb.RawSet(key, value) 1709 } 1710 1711 func (ls *LState) RawSetInt(tb *LTable, key int, value LValue) { 1712 tb.RawSetInt(key, value) 1713 } 1714 1715 func (ls *LState) SetField(obj LValue, key string, value LValue) { 1716 ls.setFieldString(obj, key, value) 1717 } 1718 1719 func (ls *LState) SetTable(obj LValue, key LValue, value LValue) { 1720 ls.setField(obj, key, value) 1721 } 1722 1723 func (ls *LState) ForEach(tb *LTable, cb func(LValue, LValue)) { 1724 tb.ForEach(cb) 1725 } 1726 1727 func (ls *LState) GetGlobal(name string) LValue { 1728 return ls.GetField(ls.Get(GlobalsIndex), name) 1729 } 1730 1731 func (ls *LState) SetGlobal(name string, value LValue) { 1732 ls.SetField(ls.Get(GlobalsIndex), name, value) 1733 } 1734 1735 func (ls *LState) Next(tb *LTable, key LValue) (LValue, LValue) { 1736 return tb.Next(key) 1737 } 1738 1739 /* }}} */ 1740 1741 /* unary operations {{{ */ 1742 1743 func (ls *LState) ObjLen(v1 LValue) int { 1744 if v1.Type() == LTString { 1745 return len(string(v1.(LString))) 1746 } 1747 op := ls.metaOp1(v1, "__len") 1748 if op.Type() == LTFunction { 1749 ls.Push(op) 1750 ls.Push(v1) 1751 ls.Call(1, 1) 1752 ret := ls.reg.Pop() 1753 if ret.Type() == LTNumber { 1754 return int(ret.(LNumber)) 1755 } 1756 } else if v1.Type() == LTTable { 1757 return v1.(*LTable).Len() 1758 } 1759 return 0 1760 } 1761 1762 /* }}} */ 1763 1764 /* binary operations {{{ */ 1765 1766 func (ls *LState) Concat(values ...LValue) string { 1767 top := ls.reg.Top() 1768 for _, value := range values { 1769 ls.reg.Push(value) 1770 } 1771 ret := stringConcat(ls, len(values), ls.reg.Top()-1) 1772 ls.reg.SetTop(top) 1773 return LVAsString(ret) 1774 } 1775 1776 func (ls *LState) LessThan(lhs, rhs LValue) bool { 1777 return lessThan(ls, lhs, rhs) 1778 } 1779 1780 func (ls *LState) Equal(lhs, rhs LValue) bool { 1781 return equals(ls, lhs, rhs, false) 1782 } 1783 1784 func (ls *LState) RawEqual(lhs, rhs LValue) bool { 1785 return equals(ls, lhs, rhs, true) 1786 } 1787 1788 /* }}} */ 1789 1790 /* register operations {{{ */ 1791 1792 func (ls *LState) Register(name string, fn LGFunction) { 1793 ls.SetGlobal(name, ls.NewFunction(fn)) 1794 } 1795 1796 /* }}} */ 1797 1798 /* load and function call operations {{{ */ 1799 1800 func (ls *LState) Load(reader io.Reader, name string) (*LFunction, error) { 1801 chunk, err := parse.Parse(reader, name) 1802 if err != nil { 1803 return nil, newApiErrorE(ApiErrorSyntax, err) 1804 } 1805 proto, err := Compile(chunk, name) 1806 if err != nil { 1807 return nil, newApiErrorE(ApiErrorSyntax, err) 1808 } 1809 return newLFunctionL(proto, ls.currentEnv(), 0), nil 1810 } 1811 1812 func (ls *LState) Call(nargs, nret int) { 1813 ls.callR(nargs, nret, -1) 1814 } 1815 1816 func (ls *LState) PCall(nargs, nret int, errfunc *LFunction) (err error) { 1817 err = nil 1818 sp := ls.stack.Sp() 1819 base := ls.reg.Top() - nargs - 1 1820 oldpanic := ls.Panic 1821 ls.Panic = panicWithoutTraceback 1822 if errfunc != nil { 1823 ls.hasErrorFunc = true 1824 } 1825 defer func() { 1826 ls.Panic = oldpanic 1827 ls.hasErrorFunc = false 1828 rcv := recover() 1829 if rcv != nil { 1830 if _, ok := rcv.(*ApiError); !ok { 1831 err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv)) 1832 if ls.Options.IncludeGoStackTrace { 1833 buf := make([]byte, 4096) 1834 runtime.Stack(buf, false) 1835 err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + "\n" + ls.stackTrace(0) 1836 } 1837 } else { 1838 err = rcv.(*ApiError) 1839 } 1840 if errfunc != nil { 1841 ls.Push(errfunc) 1842 ls.Push(err.(*ApiError).Object) 1843 ls.Panic = panicWithoutTraceback 1844 defer func() { 1845 ls.Panic = oldpanic 1846 rcv := recover() 1847 if rcv != nil { 1848 if _, ok := rcv.(*ApiError); !ok { 1849 err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv)) 1850 if ls.Options.IncludeGoStackTrace { 1851 buf := make([]byte, 4096) 1852 runtime.Stack(buf, false) 1853 err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + ls.stackTrace(0) 1854 } 1855 } else { 1856 err = rcv.(*ApiError) 1857 err.(*ApiError).StackTrace = ls.stackTrace(0) 1858 } 1859 ls.stack.SetSp(sp) 1860 ls.currentFrame = ls.stack.Last() 1861 ls.reg.SetTop(base) 1862 } 1863 }() 1864 ls.Call(1, 1) 1865 err = newApiError(ApiErrorError, ls.Get(-1)) 1866 } else if len(err.(*ApiError).StackTrace) == 0 { 1867 err.(*ApiError).StackTrace = ls.stackTrace(0) 1868 } 1869 ls.stack.SetSp(sp) 1870 ls.currentFrame = ls.stack.Last() 1871 ls.reg.SetTop(base) 1872 } 1873 ls.stack.SetSp(sp) 1874 if sp == 0 { 1875 ls.currentFrame = nil 1876 } 1877 }() 1878 1879 ls.Call(nargs, nret) 1880 1881 return 1882 } 1883 1884 func (ls *LState) GPCall(fn LGFunction, data LValue) error { 1885 ls.Push(newLFunctionG(fn, ls.currentEnv(), 0)) 1886 ls.Push(data) 1887 return ls.PCall(1, MultRet, nil) 1888 } 1889 1890 func (ls *LState) CallByParam(cp P, args ...LValue) error { 1891 ls.Push(cp.Fn) 1892 for _, arg := range args { 1893 ls.Push(arg) 1894 } 1895 1896 if cp.Protect { 1897 return ls.PCall(len(args), cp.NRet, cp.Handler) 1898 } 1899 ls.Call(len(args), cp.NRet) 1900 return nil 1901 } 1902 1903 /* }}} */ 1904 1905 /* metatable operations {{{ */ 1906 1907 func (ls *LState) GetMetatable(obj LValue) LValue { 1908 return ls.metatable(obj, false) 1909 } 1910 1911 func (ls *LState) SetMetatable(obj LValue, mt LValue) { 1912 switch mt.(type) { 1913 case *LNilType, *LTable: 1914 default: 1915 ls.RaiseError("metatable must be a table or nil, but got %v", mt.Type().String()) 1916 } 1917 1918 switch v := obj.(type) { 1919 case *LTable: 1920 v.Metatable = mt 1921 case *LUserData: 1922 v.Metatable = mt 1923 default: 1924 ls.G.builtinMts[int(obj.Type())] = mt 1925 } 1926 } 1927 1928 /* }}} */ 1929 1930 /* coroutine operations {{{ */ 1931 1932 func (ls *LState) Status(th *LState) string { 1933 status := "suspended" 1934 if th.Dead { 1935 status = "dead" 1936 } else if ls.G.CurrentThread == th { 1937 status = "running" 1938 } else if ls.Parent == th { 1939 status = "normal" 1940 } 1941 return status 1942 } 1943 1944 func (ls *LState) Resume(th *LState, fn *LFunction, args ...LValue) (ResumeState, error, []LValue) { 1945 isstarted := th.isStarted() 1946 if !isstarted { 1947 base := 0 1948 th.stack.Push(callFrame{ 1949 Fn: fn, 1950 Pc: 0, 1951 Base: base, 1952 LocalBase: base + 1, 1953 ReturnBase: base, 1954 NArgs: 0, 1955 NRet: MultRet, 1956 Parent: nil, 1957 TailCall: 0, 1958 }) 1959 } 1960 1961 if ls.G.CurrentThread == th { 1962 return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a running thread"), nil 1963 } 1964 if th.Dead { 1965 return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a dead thread"), nil 1966 } 1967 th.Parent = ls 1968 ls.G.CurrentThread = th 1969 if !isstarted { 1970 cf := th.stack.Last() 1971 th.currentFrame = cf 1972 th.SetTop(0) 1973 for _, arg := range args { 1974 th.Push(arg) 1975 } 1976 cf.NArgs = len(args) 1977 th.initCallFrame(cf) 1978 th.Panic = panicWithoutTraceback 1979 } else { 1980 for _, arg := range args { 1981 th.Push(arg) 1982 } 1983 } 1984 top := ls.GetTop() 1985 threadRun(th) 1986 haserror := LVIsFalse(ls.Get(top + 1)) 1987 ret := make([]LValue, 0, ls.GetTop()) 1988 for idx := top + 2; idx <= ls.GetTop(); idx++ { 1989 ret = append(ret, ls.Get(idx)) 1990 } 1991 if len(ret) == 0 { 1992 ret = append(ret, LNil) 1993 } 1994 ls.SetTop(top) 1995 1996 if haserror { 1997 return ResumeError, newApiError(ApiErrorRun, ret[0]), nil 1998 } else if th.stack.IsEmpty() { 1999 return ResumeOK, nil, ret 2000 } 2001 return ResumeYield, nil, ret 2002 } 2003 2004 func (ls *LState) Yield(values ...LValue) int { 2005 ls.SetTop(0) 2006 for _, lv := range values { 2007 ls.Push(lv) 2008 } 2009 return -1 2010 } 2011 2012 func (ls *LState) XMoveTo(other *LState, n int) { 2013 if ls == other { 2014 return 2015 } 2016 top := ls.GetTop() 2017 n = intMin(n, top) 2018 for i := n; i > 0; i-- { 2019 other.Push(ls.Get(top - i + 1)) 2020 } 2021 ls.SetTop(top - n) 2022 } 2023 2024 /* }}} */ 2025 2026 /* GopherLua original APIs {{{ */ 2027 2028 // Set maximum memory size. This function can only be called from the main thread. 2029 func (ls *LState) SetMx(mx int) { 2030 if ls.Parent != nil { 2031 ls.RaiseError("sub threads are not allowed to set a memory limit") 2032 } 2033 go func() { 2034 limit := uint64(mx * 1024 * 1024) //MB 2035 var s runtime.MemStats 2036 for atomic.LoadInt32(&ls.stop) == 0 { 2037 runtime.ReadMemStats(&s) 2038 if s.Alloc >= limit { 2039 fmt.Println("out of memory") 2040 os.Exit(3) 2041 } 2042 time.Sleep(100 * time.Millisecond) 2043 } 2044 }() 2045 } 2046 2047 // SetContext set a context ctx to this LState. The provided ctx must be non-nil. 2048 func (ls *LState) SetContext(ctx context.Context) { 2049 ls.mainLoop = mainLoopWithContext 2050 ls.ctx = ctx 2051 } 2052 2053 // Context returns the LState's context. To change the context, use WithContext. 2054 func (ls *LState) Context() context.Context { 2055 return ls.ctx 2056 } 2057 2058 // RemoveContext removes the context associated with this LState and returns this context. 2059 func (ls *LState) RemoveContext() context.Context { 2060 oldctx := ls.ctx 2061 ls.mainLoop = mainLoop 2062 ls.ctx = nil 2063 return oldctx 2064 } 2065 2066 // Converts the Lua value at the given acceptable index to the chan LValue. 2067 func (ls *LState) ToChannel(n int) chan LValue { 2068 if lv, ok := ls.Get(n).(LChannel); ok { 2069 return (chan LValue)(lv) 2070 } 2071 return nil 2072 } 2073 2074 // RemoveCallerFrame removes the stack frame above the current stack frame. This is useful in tail calls. It returns 2075 // the new current frame. 2076 func (ls *LState) RemoveCallerFrame() *callFrame { 2077 cs := ls.stack 2078 sp := cs.Sp() 2079 parentFrame := cs.At(sp - 2) 2080 currentFrame := cs.At(sp - 1) 2081 parentsParentFrame := parentFrame.Parent 2082 *parentFrame = *currentFrame 2083 parentFrame.Parent = parentsParentFrame 2084 parentFrame.Idx = sp - 2 2085 cs.Pop() 2086 return parentFrame 2087 } 2088 2089 /* }}} */ 2090 2091 /* }}} */ 2092 2093 //