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