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