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