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