gitee.com/yfmps/gopher-lua@v0.0.3/_state.go (about) 1 package lua 2 3 import ( 4 "context" 5 "fmt" 6 "io" 7 "math" 8 "os" 9 "runtime" 10 "strings" 11 "sync" 12 "sync/atomic" 13 "time" 14 15 "github.com/yuin/gopher-lua/parse" 16 ) 17 18 const MultRet = -1 19 const RegistryIndex = -10000 20 const EnvironIndex = -10001 21 const GlobalsIndex = -10002 22 23 /* ApiError {{{ */ 24 25 type ApiError struct { 26 Type ApiErrorType 27 Object LValue 28 StackTrace string 29 // Underlying error. This attribute is set only if the Type is ApiErrorFile or ApiErrorSyntax 30 Cause error 31 } 32 33 func newApiError(code ApiErrorType, object LValue) *ApiError { 34 return &ApiError{code, object, "", nil} 35 } 36 37 func newApiErrorS(code ApiErrorType, message string) *ApiError { 38 return newApiError(code, LString(message)) 39 } 40 41 func newApiErrorE(code ApiErrorType, err error) *ApiError { 42 return &ApiError{code, LString(err.Error()), "", err} 43 } 44 45 func (e *ApiError) Error() string { 46 if len(e.StackTrace) > 0 { 47 return fmt.Sprintf("%s\n%s", e.Object.String(), e.StackTrace) 48 } 49 return e.Object.String() 50 } 51 52 type ApiErrorType int 53 54 const ( 55 ApiErrorSyntax ApiErrorType = iota 56 ApiErrorFile 57 ApiErrorRun 58 ApiErrorError 59 ApiErrorPanic 60 ) 61 62 /* }}} */ 63 64 /* ResumeState {{{ */ 65 66 type ResumeState int 67 68 const ( 69 ResumeOK ResumeState = iota 70 ResumeYield 71 ResumeError 72 ) 73 74 /* }}} */ 75 76 /* P {{{ */ 77 78 type P struct { 79 Fn LValue 80 NRet int 81 Protect bool 82 Handler *LFunction 83 } 84 85 /* }}} */ 86 87 /* Options {{{ */ 88 89 // Options is a configuration that is used to create a new LState. 90 type Options struct { 91 // Call stack size. This defaults to `lua.CallStackSize`. 92 CallStackSize int 93 // Data stack size. This defaults to `lua.RegistrySize`. 94 RegistrySize int 95 // Allow the registry to grow from the registry size specified up to a value of RegistryMaxSize. A value of 0 96 // indicates no growth is permitted. The registry will not shrink again after any growth. 97 RegistryMaxSize int 98 // If growth is enabled, step up by an additional `RegistryGrowStep` each time to avoid having to resize too often. 99 // This defaults to `lua.RegistryGrowStep` 100 RegistryGrowStep int 101 // Controls whether or not libraries are opened by default 102 SkipOpenLibs bool 103 // Tells whether a Go stacktrace should be included in a Lua stacktrace when panics occur. 104 IncludeGoStackTrace bool 105 // If `MinimizeStackMemory` is set, the call stack will be automatically grown or shrank up to a limit of 106 // `CallStackSize` in order to minimize memory usage. This does incur a slight performance penalty. 107 MinimizeStackMemory bool 108 } 109 110 /* }}} */ 111 112 /* Debug {{{ */ 113 114 type Debug struct { 115 frame *callFrame 116 Name string 117 What string 118 Source string 119 CurrentLine int 120 NUpvalues int 121 LineDefined int 122 LastLineDefined int 123 } 124 125 /* }}} */ 126 127 /* callFrame {{{ */ 128 129 type callFrame struct { 130 Idx int 131 Fn *LFunction 132 Parent *callFrame 133 Pc int 134 Base int 135 LocalBase int 136 ReturnBase int 137 NArgs int 138 NRet int 139 TailCall int 140 } 141 142 type callFrameStack interface { 143 Push(v callFrame) 144 Pop() *callFrame 145 Last() *callFrame 146 147 SetSp(sp int) 148 Sp() int 149 At(sp int) *callFrame 150 151 IsFull() bool 152 IsEmpty() bool 153 154 FreeAll() 155 } 156 157 type fixedCallFrameStack struct { 158 array []callFrame 159 sp int 160 } 161 162 func newFixedCallFrameStack(size int) callFrameStack { 163 return &fixedCallFrameStack{ 164 array: make([]callFrame, size), 165 sp: 0, 166 } 167 } 168 169 func (cs *fixedCallFrameStack) IsEmpty() bool { return cs.sp == 0 } 170 171 func (cs *fixedCallFrameStack) IsFull() bool { return cs.sp == len(cs.array) } 172 173 func (cs *fixedCallFrameStack) Clear() { 174 cs.sp = 0 175 } 176 177 func (cs *fixedCallFrameStack) Push(v callFrame) { 178 cs.array[cs.sp] = v 179 cs.array[cs.sp].Idx = cs.sp 180 cs.sp++ 181 } 182 183 func (cs *fixedCallFrameStack) Sp() int { 184 return cs.sp 185 } 186 187 func (cs *fixedCallFrameStack) SetSp(sp int) { 188 cs.sp = sp 189 } 190 191 func (cs *fixedCallFrameStack) Last() *callFrame { 192 if cs.sp == 0 { 193 return nil 194 } 195 return &cs.array[cs.sp-1] 196 } 197 198 func (cs *fixedCallFrameStack) At(sp int) *callFrame { 199 return &cs.array[sp] 200 } 201 202 func (cs *fixedCallFrameStack) Pop() *callFrame { 203 cs.sp-- 204 return &cs.array[cs.sp] 205 } 206 207 func (cs *fixedCallFrameStack) FreeAll() { 208 // nothing to do for fixed callframestack 209 } 210 211 // FramesPerSegment should be a power of 2 constant for performance reasons. It will allow the go compiler to change 212 // the divs and mods into bitshifts. Max is 256 due to current use of uint8 to count how many frames in a segment are 213 // used. 214 const FramesPerSegment = 8 215 216 type callFrameStackSegment struct { 217 array [FramesPerSegment]callFrame 218 } 219 type segIdx uint16 220 type autoGrowingCallFrameStack struct { 221 segments []*callFrameStackSegment 222 segIdx segIdx 223 // segSp is the number of frames in the current segment which are used. Full 'sp' value is segIdx * FramesPerSegment + segSp. 224 // It points to the next stack slot to use, so 0 means to use the 0th element in the segment, and a value of 225 // FramesPerSegment indicates that the segment is full and cannot accommodate another frame. 226 segSp uint8 227 } 228 229 var segmentPool sync.Pool 230 231 func newCallFrameStackSegment() *callFrameStackSegment { 232 seg := segmentPool.Get() 233 if seg == nil { 234 return &callFrameStackSegment{} 235 } 236 return seg.(*callFrameStackSegment) 237 } 238 239 func freeCallFrameStackSegment(seg *callFrameStackSegment) { 240 segmentPool.Put(seg) 241 } 242 243 // newCallFrameStack allocates a new stack for a lua state, which will auto grow up to a max size of at least maxSize. 244 // it will actually grow up to the next segment size multiple after maxSize, where the segment size is dictated by 245 // FramesPerSegment. 246 func newAutoGrowingCallFrameStack(maxSize int) callFrameStack { 247 cs := &autoGrowingCallFrameStack{ 248 segments: make([]*callFrameStackSegment, (maxSize+(FramesPerSegment-1))/FramesPerSegment), 249 segIdx: 0, 250 } 251 cs.segments[0] = newCallFrameStackSegment() 252 return cs 253 } 254 255 func (cs *autoGrowingCallFrameStack) IsEmpty() bool { 256 return cs.segIdx == 0 && cs.segSp == 0 257 } 258 259 // IsFull returns true if the stack cannot receive any more stack pushes without overflowing 260 func (cs *autoGrowingCallFrameStack) IsFull() bool { 261 return int(cs.segIdx) == len(cs.segments) && cs.segSp >= FramesPerSegment 262 } 263 264 func (cs *autoGrowingCallFrameStack) Clear() { 265 for i := segIdx(1); i <= cs.segIdx; i++ { 266 freeCallFrameStackSegment(cs.segments[i]) 267 cs.segments[i] = nil 268 } 269 cs.segIdx = 0 270 cs.segSp = 0 271 } 272 273 func (cs *autoGrowingCallFrameStack) FreeAll() { 274 for i := segIdx(0); i <= cs.segIdx; i++ { 275 freeCallFrameStackSegment(cs.segments[i]) 276 cs.segments[i] = nil 277 } 278 } 279 280 // Push pushes the passed callFrame onto the stack. it panics if the stack is full, caller should call IsFull() before 281 // invoking this to avoid this. 282 func (cs *autoGrowingCallFrameStack) Push(v callFrame) { 283 curSeg := cs.segments[cs.segIdx] 284 if cs.segSp >= FramesPerSegment { 285 // segment full, push new segment if allowed 286 if cs.segIdx < segIdx(len(cs.segments)-1) { 287 curSeg = newCallFrameStackSegment() 288 cs.segIdx++ 289 cs.segments[cs.segIdx] = curSeg 290 cs.segSp = 0 291 } else { 292 panic("lua callstack overflow") 293 } 294 } 295 curSeg.array[cs.segSp] = v 296 curSeg.array[cs.segSp].Idx = int(cs.segSp) + FramesPerSegment*int(cs.segIdx) 297 cs.segSp++ 298 } 299 300 // Sp retrieves the current stack depth, which is the number of frames currently pushed on the stack. 301 func (cs *autoGrowingCallFrameStack) Sp() int { 302 return int(cs.segSp) + int(cs.segIdx)*FramesPerSegment 303 } 304 305 // SetSp can be used to rapidly unwind the stack, freeing all stack frames on the way. It should not be used to 306 // allocate new stack space, use Push() for that. 307 func (cs *autoGrowingCallFrameStack) SetSp(sp int) { 308 desiredSegIdx := segIdx(sp / FramesPerSegment) 309 desiredFramesInLastSeg := uint8(sp % FramesPerSegment) 310 for { 311 if cs.segIdx <= desiredSegIdx { 312 break 313 } 314 freeCallFrameStackSegment(cs.segments[cs.segIdx]) 315 cs.segments[cs.segIdx] = nil 316 cs.segIdx-- 317 } 318 cs.segSp = desiredFramesInLastSeg 319 } 320 321 func (cs *autoGrowingCallFrameStack) Last() *callFrame { 322 curSeg := cs.segments[cs.segIdx] 323 segSp := cs.segSp 324 if segSp == 0 { 325 if cs.segIdx == 0 { 326 return nil 327 } 328 curSeg = cs.segments[cs.segIdx-1] 329 segSp = FramesPerSegment 330 } 331 return &curSeg.array[segSp-1] 332 } 333 334 func (cs *autoGrowingCallFrameStack) At(sp int) *callFrame { 335 segIdx := segIdx(sp / FramesPerSegment) 336 frameIdx := uint8(sp % FramesPerSegment) 337 return &cs.segments[segIdx].array[frameIdx] 338 } 339 340 // Pop pops off the most recent stack frame and returns it 341 func (cs *autoGrowingCallFrameStack) Pop() *callFrame { 342 curSeg := cs.segments[cs.segIdx] 343 if cs.segSp == 0 { 344 if cs.segIdx == 0 { 345 // stack empty 346 return nil 347 } 348 freeCallFrameStackSegment(curSeg) 349 cs.segments[cs.segIdx] = nil 350 cs.segIdx-- 351 cs.segSp = FramesPerSegment 352 curSeg = cs.segments[cs.segIdx] 353 } 354 cs.segSp-- 355 return &curSeg.array[cs.segSp] 356 } 357 358 /* }}} */ 359 360 /* registry {{{ */ 361 362 type registryHandler interface { 363 registryOverflow() 364 } 365 type registry struct { 366 array []LValue 367 top int 368 growBy int 369 maxSize int 370 alloc *allocator 371 handler registryHandler 372 } 373 374 func newRegistry(handler registryHandler, initialSize int, growBy int, maxSize int, alloc *allocator) *registry { 375 return ®istry{make([]LValue, initialSize), 0, growBy, maxSize, alloc, handler} 376 } 377 378 func (rg *registry) checkSize(requiredSize int) { // +inline-start 379 if requiredSize > cap(rg.array) { 380 rg.resize(requiredSize) 381 } 382 } // +inline-end 383 384 func (rg *registry) resize(requiredSize int) { // +inline-start 385 newSize := requiredSize + rg.growBy // give some padding 386 if newSize > rg.maxSize { 387 newSize = rg.maxSize 388 } 389 if newSize < requiredSize { 390 rg.handler.registryOverflow() 391 return 392 } 393 rg.forceResize(newSize) 394 } // +inline-end 395 396 func (rg *registry) forceResize(newSize int) { 397 newSlice := make([]LValue, newSize) 398 copy(newSlice, rg.array[:rg.top]) // should we copy the area beyond top? there shouldn't be any valid values there so it shouldn't be necessary. 399 rg.array = newSlice 400 } 401 func (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 421 func (rg *registry) Top() int { 422 return rg.top 423 } 424 425 func (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 432 func (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 439 func (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. 452 func (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 480 func (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 498 func (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 512 func (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 521 func (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 530 func (rg *registry) IsFull() bool { 531 return rg.top >= cap(rg.array) 532 } 533 534 /* }}} */ 535 536 /* Global {{{ */ 537 538 func 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 552 func panicWithTraceback(L *LState) { 553 err := newApiError(ApiErrorRun, L.Get(-1)) 554 err.StackTrace = L.stackTrace(0) 555 panic(err) 556 } 557 558 func panicWithoutTraceback(L *LState) { 559 err := newApiError(ApiErrorRun, L.Get(-1)) 560 panic(err) 561 } 562 563 func 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 591 func (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 608 func (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 626 func (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 634 func (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 653 func (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 674 func (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 694 func (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 723 func (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 734 func (ls *LState) rawFrameFuncName(fr *callFrame) string { 735 name, _ := ls.frameFuncName(fr) 736 return name 737 } 738 739 func (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 766 func (ls *LState) isStarted() bool { 767 return ls.currentFrame != nil 768 } 769 770 func (ls *LState) kill() { 771 ls.Dead = true 772 } 773 774 func (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 789 func (ls *LState) currentLocalBase() int { 790 base := 0 791 if ls.currentFrame != nil { 792 base = ls.currentFrame.LocalBase 793 } 794 return base 795 } 796 797 func (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 807 func (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 820 func (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 827 func (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 844 func (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 871 func (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 897 func (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 906 func (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 922 func (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 932 func (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 1008 func (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 1025 func (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 1055 func (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 1086 func (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 1117 func (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 1149 func (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 1185 func 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 1216 func (ls *LState) IsClosed() bool { 1217 return ls.stack == nil 1218 } 1219 1220 func (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 1233 func (ls *LState) GetTop() int { 1234 return ls.reg.Top() - ls.currentLocalBase() 1235 } 1236 1237 func (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 1247 func (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 1292 func (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 1331 func (ls *LState) Push(value LValue) { 1332 ls.reg.Push(value) 1333 } 1334 1335 func (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 1344 func (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 1361 func (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 1383 func (ls *LState) NewTable() *LTable { 1384 return newLTable(defaultArrayCap, defaultHashCap) 1385 } 1386 1387 func (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. 1393 func (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 1405 func (ls *LState) NewFunctionFromProto(proto *FunctionProto) *LFunction { 1406 return newLFunctionL(proto, ls.Env, int(proto.NumUpvalues)) 1407 } 1408 1409 func (ls *LState) NewUserData() *LUserData { 1410 return &LUserData{ 1411 Env: ls.currentEnv(), 1412 Metatable: LNil, 1413 } 1414 } 1415 1416 func (ls *LState) NewFunction(fn LGFunction) *LFunction { 1417 return newLFunctionG(fn, ls.currentEnv(), 0) 1418 } 1419 1420 func (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 1434 func (ls *LState) ToBool(n int) bool { 1435 return LVAsBool(ls.Get(n)) 1436 } 1437 1438 func (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 1450 func (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 1462 func (ls *LState) ToNumber(n int) LNumber { 1463 return LVAsNumber(ls.Get(n)) 1464 } 1465 1466 func (ls *LState) ToString(n int) string { 1467 return LVAsString(ls.Get(n)) 1468 } 1469 1470 func (ls *LState) ToTable(n int) *LTable { 1471 if lv, ok := ls.Get(n).(*LTable); ok { 1472 return lv 1473 } 1474 return nil 1475 } 1476 1477 func (ls *LState) ToFunction(n int) *LFunction { 1478 if lv, ok := ls.Get(n).(*LFunction); ok { 1479 return lv 1480 } 1481 return nil 1482 } 1483 1484 func (ls *LState) ToUserData(n int) *LUserData { 1485 if lv, ok := ls.Get(n).(*LUserData); ok { 1486 return lv 1487 } 1488 return nil 1489 } 1490 1491 func (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 1502 func (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 ). 1507 func (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 ). 1512 func (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 1524 func (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 1581 func (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 1598 func (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 1606 func (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 1615 func (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 1627 func (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 func (ls *LState) SetHook(callback *LFunction, event string, count int) error { 1641 frame := ls.stack.At(0) 1642 if count > 0 { 1643 ls.cthook = newCTHook(callback, count) 1644 } 1645 for _, c := range event { 1646 switch c { 1647 case 'l': 1648 ls.lhook = newLHook(callback, frame.Fn.Proto.DbgSourcePositions[frame.Pc-1]) 1649 case 'c': 1650 ls.chook = newCHook(callback) 1651 case 'r': 1652 ls.rhook = newRHook(callback) 1653 default: 1654 return newApiErrorS(ApiErrorRun, fmt.Sprintf("invalid hook event: %c", c)) 1655 } 1656 } 1657 return nil 1658 } 1659 1660 /* }}} */ 1661 1662 /* env operations {{{ */ 1663 1664 func (ls *LState) GetFEnv(obj LValue) LValue { 1665 switch lv := obj.(type) { 1666 case *LFunction: 1667 return lv.Env 1668 case *LUserData: 1669 return lv.Env 1670 case *LState: 1671 return lv.Env 1672 } 1673 return LNil 1674 } 1675 1676 func (ls *LState) SetFEnv(obj LValue, env LValue) { 1677 tb, ok := env.(*LTable) 1678 if !ok { 1679 ls.RaiseError("cannot use %v as an environment", env.Type().String()) 1680 } 1681 1682 switch lv := obj.(type) { 1683 case *LFunction: 1684 lv.Env = tb 1685 case *LUserData: 1686 lv.Env = tb 1687 case *LState: 1688 lv.Env = tb 1689 } 1690 /* do nothing */ 1691 } 1692 1693 /* }}} */ 1694 1695 /* table operations {{{ */ 1696 1697 func (ls *LState) RawGet(tb *LTable, key LValue) LValue { 1698 return tb.RawGet(key) 1699 } 1700 1701 func (ls *LState) RawGetInt(tb *LTable, key int) LValue { 1702 return tb.RawGetInt(key) 1703 } 1704 1705 func (ls *LState) GetField(obj LValue, skey string) LValue { 1706 return ls.getFieldString(obj, skey) 1707 } 1708 1709 func (ls *LState) GetTable(obj LValue, key LValue) LValue { 1710 return ls.getField(obj, key) 1711 } 1712 1713 func (ls *LState) RawSet(tb *LTable, key LValue, value LValue) { 1714 if n, ok := key.(LNumber); ok && math.IsNaN(float64(n)) { 1715 ls.RaiseError("table index is NaN") 1716 } else if key == LNil { 1717 ls.RaiseError("table index is nil") 1718 } 1719 tb.RawSet(key, value) 1720 } 1721 1722 func (ls *LState) RawSetInt(tb *LTable, key int, value LValue) { 1723 tb.RawSetInt(key, value) 1724 } 1725 1726 func (ls *LState) SetField(obj LValue, key string, value LValue) { 1727 ls.setFieldString(obj, key, value) 1728 } 1729 1730 func (ls *LState) SetTable(obj LValue, key LValue, value LValue) { 1731 ls.setField(obj, key, value) 1732 } 1733 1734 func (ls *LState) ForEach(tb *LTable, cb func(LValue, LValue)) { 1735 tb.ForEach(cb) 1736 } 1737 1738 func (ls *LState) GetGlobal(name string) LValue { 1739 return ls.GetField(ls.Get(GlobalsIndex), name) 1740 } 1741 1742 func (ls *LState) SetGlobal(name string, value LValue) { 1743 ls.SetField(ls.Get(GlobalsIndex), name, value) 1744 } 1745 1746 func (ls *LState) Next(tb *LTable, key LValue) (LValue, LValue) { 1747 return tb.Next(key) 1748 } 1749 1750 /* }}} */ 1751 1752 /* unary operations {{{ */ 1753 1754 func (ls *LState) ObjLen(v1 LValue) int { 1755 if v1.Type() == LTString { 1756 return len(string(v1.(LString))) 1757 } 1758 op := ls.metaOp1(v1, "__len") 1759 if op.Type() == LTFunction { 1760 ls.Push(op) 1761 ls.Push(v1) 1762 ls.Call(1, 1) 1763 ret := ls.reg.Pop() 1764 if ret.Type() == LTNumber { 1765 return int(ret.(LNumber)) 1766 } 1767 } else if v1.Type() == LTTable { 1768 return v1.(*LTable).Len() 1769 } 1770 return 0 1771 } 1772 1773 /* }}} */ 1774 1775 /* binary operations {{{ */ 1776 1777 func (ls *LState) Concat(values ...LValue) string { 1778 top := ls.reg.Top() 1779 for _, value := range values { 1780 ls.reg.Push(value) 1781 } 1782 ret := stringConcat(ls, len(values), ls.reg.Top()-1) 1783 ls.reg.SetTop(top) 1784 return LVAsString(ret) 1785 } 1786 1787 func (ls *LState) LessThan(lhs, rhs LValue) bool { 1788 return lessThan(ls, lhs, rhs) 1789 } 1790 1791 func (ls *LState) Equal(lhs, rhs LValue) bool { 1792 return equals(ls, lhs, rhs, false) 1793 } 1794 1795 func (ls *LState) RawEqual(lhs, rhs LValue) bool { 1796 return equals(ls, lhs, rhs, true) 1797 } 1798 1799 /* }}} */ 1800 1801 /* register operations {{{ */ 1802 1803 func (ls *LState) Register(name string, fn LGFunction) { 1804 ls.SetGlobal(name, ls.NewFunction(fn)) 1805 } 1806 1807 /* }}} */ 1808 1809 /* load and function call operations {{{ */ 1810 1811 func (ls *LState) Load(reader io.Reader, name string) (*LFunction, error) { 1812 chunk, err := parse.Parse(reader, name) 1813 if err != nil { 1814 return nil, newApiErrorE(ApiErrorSyntax, err) 1815 } 1816 proto, err := Compile(chunk, name) 1817 if err != nil { 1818 return nil, newApiErrorE(ApiErrorSyntax, err) 1819 } 1820 return newLFunctionL(proto, ls.currentEnv(), 0), nil 1821 } 1822 1823 func (ls *LState) Call(nargs, nret int) { 1824 ls.callR(nargs, nret, -1) 1825 } 1826 1827 func (ls *LState) PCall(nargs, nret int, errfunc *LFunction) (err error) { 1828 err = nil 1829 sp := ls.stack.Sp() 1830 base := ls.reg.Top() - nargs - 1 1831 oldpanic := ls.Panic 1832 ls.Panic = panicWithoutTraceback 1833 if errfunc != nil { 1834 ls.hasErrorFunc = true 1835 } 1836 defer func() { 1837 ls.Panic = oldpanic 1838 ls.hasErrorFunc = false 1839 rcv := recover() 1840 if rcv != nil { 1841 if _, ok := rcv.(*ApiError); !ok { 1842 err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv)) 1843 if ls.Options.IncludeGoStackTrace { 1844 buf := make([]byte, 4096) 1845 runtime.Stack(buf, false) 1846 err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + "\n" + ls.stackTrace(0) 1847 } 1848 } else { 1849 err = rcv.(*ApiError) 1850 } 1851 if errfunc != nil { 1852 ls.Push(errfunc) 1853 ls.Push(err.(*ApiError).Object) 1854 ls.Panic = panicWithoutTraceback 1855 defer func() { 1856 ls.Panic = oldpanic 1857 rcv := recover() 1858 if rcv != nil { 1859 if _, ok := rcv.(*ApiError); !ok { 1860 err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv)) 1861 if ls.Options.IncludeGoStackTrace { 1862 buf := make([]byte, 4096) 1863 runtime.Stack(buf, false) 1864 err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + ls.stackTrace(0) 1865 } 1866 } else { 1867 err = rcv.(*ApiError) 1868 err.(*ApiError).StackTrace = ls.stackTrace(0) 1869 } 1870 } 1871 }() 1872 ls.Call(1, 1) 1873 err = newApiError(ApiErrorError, ls.Get(-1)) 1874 } else if len(err.(*ApiError).StackTrace) == 0 { 1875 err.(*ApiError).StackTrace = ls.stackTrace(0) 1876 } 1877 ls.stack.SetSp(sp) 1878 ls.currentFrame = ls.stack.Last() 1879 ls.reg.SetTop(base) 1880 } 1881 ls.stack.SetSp(sp) 1882 if sp == 0 { 1883 ls.currentFrame = nil 1884 } 1885 }() 1886 1887 ls.Call(nargs, nret) 1888 1889 return 1890 } 1891 1892 func (ls *LState) GPCall(fn LGFunction, data LValue) error { 1893 ls.Push(newLFunctionG(fn, ls.currentEnv(), 0)) 1894 ls.Push(data) 1895 return ls.PCall(1, MultRet, nil) 1896 } 1897 1898 func (ls *LState) CallByParam(cp P, args ...LValue) error { 1899 ls.Push(cp.Fn) 1900 for _, arg := range args { 1901 ls.Push(arg) 1902 } 1903 1904 if cp.Protect { 1905 return ls.PCall(len(args), cp.NRet, cp.Handler) 1906 } 1907 ls.Call(len(args), cp.NRet) 1908 return nil 1909 } 1910 1911 /* }}} */ 1912 1913 /* metatable operations {{{ */ 1914 1915 func (ls *LState) GetMetatable(obj LValue) LValue { 1916 return ls.metatable(obj, false) 1917 } 1918 1919 func (ls *LState) SetMetatable(obj LValue, mt LValue) { 1920 switch mt.(type) { 1921 case *LNilType, *LTable: 1922 default: 1923 ls.RaiseError("metatable must be a table or nil, but got %v", mt.Type().String()) 1924 } 1925 1926 switch v := obj.(type) { 1927 case *LTable: 1928 v.Metatable = mt 1929 case *LUserData: 1930 v.Metatable = mt 1931 default: 1932 ls.G.builtinMts[int(obj.Type())] = mt 1933 } 1934 } 1935 1936 /* }}} */ 1937 1938 /* coroutine operations {{{ */ 1939 1940 func (ls *LState) Status(th *LState) string { 1941 status := "suspended" 1942 if th.Dead { 1943 status = "dead" 1944 } else if ls.G.CurrentThread == th { 1945 status = "running" 1946 } else if ls.Parent == th { 1947 status = "normal" 1948 } 1949 return status 1950 } 1951 1952 func (ls *LState) Resume(th *LState, fn *LFunction, args ...LValue) (ResumeState, error, []LValue) { 1953 isstarted := th.isStarted() 1954 if !isstarted { 1955 base := 0 1956 th.stack.Push(callFrame{ 1957 Fn: fn, 1958 Pc: 0, 1959 Base: base, 1960 LocalBase: base + 1, 1961 ReturnBase: base, 1962 NArgs: 0, 1963 NRet: MultRet, 1964 Parent: nil, 1965 TailCall: 0, 1966 }) 1967 } 1968 1969 if ls.G.CurrentThread == th { 1970 return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a running thread"), nil 1971 } 1972 if th.Dead { 1973 return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a dead thread"), nil 1974 } 1975 th.Parent = ls 1976 ls.G.CurrentThread = th 1977 if !isstarted { 1978 cf := th.stack.Last() 1979 th.currentFrame = cf 1980 th.SetTop(0) 1981 for _, arg := range args { 1982 th.Push(arg) 1983 } 1984 cf.NArgs = len(args) 1985 th.initCallFrame(cf) 1986 th.Panic = panicWithoutTraceback 1987 } else { 1988 for _, arg := range args { 1989 th.Push(arg) 1990 } 1991 } 1992 top := ls.GetTop() 1993 threadRun(th) 1994 haserror := LVIsFalse(ls.Get(top + 1)) 1995 ret := make([]LValue, 0, ls.GetTop()) 1996 for idx := top + 2; idx <= ls.GetTop(); idx++ { 1997 ret = append(ret, ls.Get(idx)) 1998 } 1999 if len(ret) == 0 { 2000 ret = append(ret, LNil) 2001 } 2002 ls.SetTop(top) 2003 2004 if haserror { 2005 return ResumeError, newApiError(ApiErrorRun, ret[0]), nil 2006 } else if th.stack.IsEmpty() { 2007 return ResumeOK, nil, ret 2008 } 2009 return ResumeYield, nil, ret 2010 } 2011 2012 func (ls *LState) Yield(values ...LValue) int { 2013 ls.SetTop(0) 2014 for _, lv := range values { 2015 ls.Push(lv) 2016 } 2017 return -1 2018 } 2019 2020 func (ls *LState) XMoveTo(other *LState, n int) { 2021 if ls == other { 2022 return 2023 } 2024 top := ls.GetTop() 2025 n = intMin(n, top) 2026 for i := n; i > 0; i-- { 2027 other.Push(ls.Get(top - i + 1)) 2028 } 2029 ls.SetTop(top - n) 2030 } 2031 2032 /* }}} */ 2033 2034 /* GopherLua original APIs {{{ */ 2035 2036 // Set maximum memory size. This function can only be called from the main thread. 2037 func (ls *LState) SetMx(mx int) { 2038 if ls.Parent != nil { 2039 ls.RaiseError("sub threads are not allowed to set a memory limit") 2040 } 2041 go func() { 2042 limit := uint64(mx * 1024 * 1024) //MB 2043 var s runtime.MemStats 2044 for atomic.LoadInt32(&ls.stop) == 0 { 2045 runtime.ReadMemStats(&s) 2046 if s.Alloc >= limit { 2047 fmt.Println("out of memory") 2048 os.Exit(3) 2049 } 2050 time.Sleep(100 * time.Millisecond) 2051 } 2052 }() 2053 } 2054 2055 // SetContext set a context ctx to this LState. The provided ctx must be non-nil. 2056 func (ls *LState) SetContext(ctx context.Context) { 2057 ls.mainLoop = mainLoopWithContext 2058 ls.ctx = ctx 2059 } 2060 2061 // Context returns the LState's context. To change the context, use WithContext. 2062 func (ls *LState) Context() context.Context { 2063 return ls.ctx 2064 } 2065 2066 // RemoveContext removes the context associated with this LState and returns this context. 2067 func (ls *LState) RemoveContext() context.Context { 2068 oldctx := ls.ctx 2069 ls.mainLoop = mainLoop 2070 ls.ctx = nil 2071 return oldctx 2072 } 2073 2074 // Converts the Lua value at the given acceptable index to the chan LValue. 2075 func (ls *LState) ToChannel(n int) chan LValue { 2076 if lv, ok := ls.Get(n).(LChannel); ok { 2077 return (chan LValue)(lv) 2078 } 2079 return nil 2080 } 2081 2082 // RemoveCallerFrame removes the stack frame above the current stack frame. This is useful in tail calls. It returns 2083 // the new current frame. 2084 func (ls *LState) RemoveCallerFrame() *callFrame { 2085 cs := ls.stack 2086 sp := cs.Sp() 2087 parentFrame := cs.At(sp - 2) 2088 currentFrame := cs.At(sp - 1) 2089 parentsParentFrame := parentFrame.Parent 2090 *parentFrame = *currentFrame 2091 parentFrame.Parent = parentsParentFrame 2092 parentFrame.Idx = sp - 2 2093 cs.Pop() 2094 return parentFrame 2095 } 2096 2097 /* }}} */ 2098 2099 /* }}} */ 2100 2101 //