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