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