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