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