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