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