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