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