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