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