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