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		newSize := cf.LocalBase + np
986		// this section is inlined by go-inline
987		// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
988		{
989			rg := ls.reg
990			requiredSize := newSize
991			if requiredSize > cap(rg.array) {
992				rg.resize(requiredSize)
993			}
994		}
995		for i := nargs; i < np; i++ {
996			ls.reg.array[cf.LocalBase+i] = LNil
997			nargs = np
998		}
999
1000		if (proto.IsVarArg & VarArgIsVarArg) == 0 {
1001			if nargs < int(proto.NumUsedRegisters) {
1002				nargs = int(proto.NumUsedRegisters)
1003			}
1004			newSize = cf.LocalBase + nargs
1005			// this section is inlined by go-inline
1006			// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
1007			{
1008				rg := ls.reg
1009				requiredSize := newSize
1010				if requiredSize > cap(rg.array) {
1011					rg.resize(requiredSize)
1012				}
1013			}
1014			for i := np; i < nargs; i++ {
1015				ls.reg.array[cf.LocalBase+i] = LNil
1016			}
1017			ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters)
1018		} else {
1019			/* swap vararg positions:
1020					   closure
1021					   namedparam1 <- lbase
1022					   namedparam2
1023					   vararg1
1024					   vararg2
1025
1026			           TO
1027
1028					   closure
1029					   nil
1030					   nil
1031					   vararg1
1032					   vararg2
1033					   namedparam1 <- lbase
1034					   namedparam2
1035			*/
1036			nvarargs := nargs - np
1037			if nvarargs < 0 {
1038				nvarargs = 0
1039			}
1040
1041			ls.reg.SetTop(cf.LocalBase + nargs + np)
1042			for i := 0; i < np; i++ {
1043				//ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i))
1044				ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i]
1045				//ls.reg.Set(cf.LocalBase+i, LNil)
1046				ls.reg.array[cf.LocalBase+i] = LNil
1047			}
1048
1049			if CompatVarArg {
1050				ls.reg.SetTop(cf.LocalBase + nargs + np + 1)
1051				if (proto.IsVarArg & VarArgNeedsArg) != 0 {
1052					argtb := newLTable(nvarargs, 0)
1053					for i := 0; i < nvarargs; i++ {
1054						argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i))
1055					}
1056					argtb.RawSetString("n", LNumber(nvarargs))
1057					//ls.reg.Set(cf.LocalBase+nargs+np, argtb)
1058					ls.reg.array[cf.LocalBase+nargs+np] = argtb
1059				} else {
1060					ls.reg.array[cf.LocalBase+nargs+np] = LNil
1061				}
1062			}
1063			cf.LocalBase += nargs
1064			maxreg := cf.LocalBase + int(proto.NumUsedRegisters)
1065			ls.reg.SetTop(maxreg)
1066		}
1067	}
1068} // +inline-end
1069
1070func (ls *LState) pushCallFrame(cf callFrame, fn LValue, meta bool) { // +inline-start
1071	if meta {
1072		cf.NArgs++
1073		ls.reg.Insert(fn, cf.LocalBase)
1074	}
1075	if cf.Fn == nil {
1076		ls.RaiseError("attempt to call a non-function object")
1077	}
1078	if ls.stack.IsFull() {
1079		ls.RaiseError("stack overflow")
1080	}
1081	ls.stack.Push(cf)
1082	newcf := ls.stack.Last()
1083	// this section is inlined by go-inline
1084	// source function is 'func (ls *LState) initCallFrame(cf *callFrame) ' in '_state.go'
1085	{
1086		cf := newcf
1087		if cf.Fn.IsG {
1088			ls.reg.SetTop(cf.LocalBase + cf.NArgs)
1089		} else {
1090			proto := cf.Fn.Proto
1091			nargs := cf.NArgs
1092			np := int(proto.NumParameters)
1093			newSize := cf.LocalBase + np
1094			// this section is inlined by go-inline
1095			// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
1096			{
1097				rg := ls.reg
1098				requiredSize := newSize
1099				if requiredSize > cap(rg.array) {
1100					rg.resize(requiredSize)
1101				}
1102			}
1103			for i := nargs; i < np; i++ {
1104				ls.reg.array[cf.LocalBase+i] = LNil
1105				nargs = np
1106			}
1107
1108			if (proto.IsVarArg & VarArgIsVarArg) == 0 {
1109				if nargs < int(proto.NumUsedRegisters) {
1110					nargs = int(proto.NumUsedRegisters)
1111				}
1112				newSize = cf.LocalBase + nargs
1113				// this section is inlined by go-inline
1114				// source function is 'func (rg *registry) checkSize(requiredSize int) ' in '_state.go'
1115				{
1116					rg := ls.reg
1117					requiredSize := newSize
1118					if requiredSize > cap(rg.array) {
1119						rg.resize(requiredSize)
1120					}
1121				}
1122				for i := np; i < nargs; i++ {
1123					ls.reg.array[cf.LocalBase+i] = LNil
1124				}
1125				ls.reg.top = cf.LocalBase + int(proto.NumUsedRegisters)
1126			} else {
1127				/* swap vararg positions:
1128						   closure
1129						   namedparam1 <- lbase
1130						   namedparam2
1131						   vararg1
1132						   vararg2
1133
1134				           TO
1135
1136						   closure
1137						   nil
1138						   nil
1139						   vararg1
1140						   vararg2
1141						   namedparam1 <- lbase
1142						   namedparam2
1143				*/
1144				nvarargs := nargs - np
1145				if nvarargs < 0 {
1146					nvarargs = 0
1147				}
1148
1149				ls.reg.SetTop(cf.LocalBase + nargs + np)
1150				for i := 0; i < np; i++ {
1151					//ls.reg.Set(cf.LocalBase+nargs+i, ls.reg.Get(cf.LocalBase+i))
1152					ls.reg.array[cf.LocalBase+nargs+i] = ls.reg.array[cf.LocalBase+i]
1153					//ls.reg.Set(cf.LocalBase+i, LNil)
1154					ls.reg.array[cf.LocalBase+i] = LNil
1155				}
1156
1157				if CompatVarArg {
1158					ls.reg.SetTop(cf.LocalBase + nargs + np + 1)
1159					if (proto.IsVarArg & VarArgNeedsArg) != 0 {
1160						argtb := newLTable(nvarargs, 0)
1161						for i := 0; i < nvarargs; i++ {
1162							argtb.RawSetInt(i+1, ls.reg.Get(cf.LocalBase+np+i))
1163						}
1164						argtb.RawSetString("n", LNumber(nvarargs))
1165						//ls.reg.Set(cf.LocalBase+nargs+np, argtb)
1166						ls.reg.array[cf.LocalBase+nargs+np] = argtb
1167					} else {
1168						ls.reg.array[cf.LocalBase+nargs+np] = LNil
1169					}
1170				}
1171				cf.LocalBase += nargs
1172				maxreg := cf.LocalBase + int(proto.NumUsedRegisters)
1173				ls.reg.SetTop(maxreg)
1174			}
1175		}
1176	}
1177	ls.currentFrame = newcf
1178} // +inline-end
1179
1180func (ls *LState) callR(nargs, nret, rbase int) {
1181	base := ls.reg.Top() - nargs - 1
1182	if rbase < 0 {
1183		rbase = base
1184	}
1185	lv := ls.reg.Get(base)
1186	fn, meta := ls.metaCall(lv)
1187	ls.pushCallFrame(callFrame{
1188		Fn:         fn,
1189		Pc:         0,
1190		Base:       base,
1191		LocalBase:  base + 1,
1192		ReturnBase: rbase,
1193		NArgs:      nargs,
1194		NRet:       nret,
1195		Parent:     ls.currentFrame,
1196		TailCall:   0,
1197	}, lv, meta)
1198	if ls.G.MainThread == nil {
1199		ls.G.MainThread = ls
1200		ls.G.CurrentThread = ls
1201		ls.mainLoop(ls, nil)
1202	} else {
1203		ls.mainLoop(ls, ls.currentFrame)
1204	}
1205	if nret != MultRet {
1206		ls.reg.SetTop(rbase + nret)
1207	}
1208}
1209
1210func (ls *LState) getField(obj LValue, key LValue) LValue {
1211	curobj := obj
1212	for i := 0; i < MaxTableGetLoop; i++ {
1213		tb, istable := curobj.(*LTable)
1214		if istable {
1215			ret := tb.RawGet(key)
1216			if ret != LNil {
1217				return ret
1218			}
1219		}
1220		metaindex := ls.metaOp1(curobj, "__index")
1221		if metaindex == LNil {
1222			if !istable {
1223				ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key.String())
1224			}
1225			return LNil
1226		}
1227		if metaindex.Type() == LTFunction {
1228			ls.reg.Push(metaindex)
1229			ls.reg.Push(curobj)
1230			ls.reg.Push(key)
1231			ls.Call(2, 1)
1232			return ls.reg.Pop()
1233		} else {
1234			curobj = metaindex
1235		}
1236	}
1237	ls.RaiseError("too many recursions in gettable")
1238	return nil
1239}
1240
1241func (ls *LState) getFieldString(obj LValue, key string) LValue {
1242	curobj := obj
1243	for i := 0; i < MaxTableGetLoop; i++ {
1244		tb, istable := curobj.(*LTable)
1245		if istable {
1246			ret := tb.RawGetString(key)
1247			if ret != LNil {
1248				return ret
1249			}
1250		}
1251		metaindex := ls.metaOp1(curobj, "__index")
1252		if metaindex == LNil {
1253			if !istable {
1254				ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key)
1255			}
1256			return LNil
1257		}
1258		if metaindex.Type() == LTFunction {
1259			ls.reg.Push(metaindex)
1260			ls.reg.Push(curobj)
1261			ls.reg.Push(LString(key))
1262			ls.Call(2, 1)
1263			return ls.reg.Pop()
1264		} else {
1265			curobj = metaindex
1266		}
1267	}
1268	ls.RaiseError("too many recursions in gettable")
1269	return nil
1270}
1271
1272func (ls *LState) setField(obj LValue, key LValue, value LValue) {
1273	curobj := obj
1274	for i := 0; i < MaxTableGetLoop; i++ {
1275		tb, istable := curobj.(*LTable)
1276		if istable {
1277			if tb.RawGet(key) != LNil {
1278				ls.RawSet(tb, key, value)
1279				return
1280			}
1281		}
1282		metaindex := ls.metaOp1(curobj, "__newindex")
1283		if metaindex == LNil {
1284			if !istable {
1285				ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key.String())
1286			}
1287			ls.RawSet(tb, key, value)
1288			return
1289		}
1290		if metaindex.Type() == LTFunction {
1291			ls.reg.Push(metaindex)
1292			ls.reg.Push(curobj)
1293			ls.reg.Push(key)
1294			ls.reg.Push(value)
1295			ls.Call(3, 0)
1296			return
1297		} else {
1298			curobj = metaindex
1299		}
1300	}
1301	ls.RaiseError("too many recursions in settable")
1302}
1303
1304func (ls *LState) setFieldString(obj LValue, key string, value LValue) {
1305	curobj := obj
1306	for i := 0; i < MaxTableGetLoop; i++ {
1307		tb, istable := curobj.(*LTable)
1308		if istable {
1309			if tb.RawGetString(key) != LNil {
1310				tb.RawSetString(key, value)
1311				return
1312			}
1313		}
1314		metaindex := ls.metaOp1(curobj, "__newindex")
1315		if metaindex == LNil {
1316			if !istable {
1317				ls.RaiseError("attempt to index a non-table object(%v) with key '%s'", curobj.Type().String(), key)
1318			}
1319			tb.RawSetString(key, value)
1320			return
1321		}
1322		if metaindex.Type() == LTFunction {
1323			ls.reg.Push(metaindex)
1324			ls.reg.Push(curobj)
1325			ls.reg.Push(LString(key))
1326			ls.reg.Push(value)
1327			ls.Call(3, 0)
1328			return
1329		} else {
1330			curobj = metaindex
1331		}
1332	}
1333	ls.RaiseError("too many recursions in settable")
1334}
1335
1336/* }}} */
1337
1338/* api methods {{{ */
1339
1340func NewState(opts ...Options) *LState {
1341	var ls *LState
1342	if len(opts) == 0 {
1343		ls = newLState(Options{
1344			CallStackSize: CallStackSize,
1345			RegistrySize:  RegistrySize,
1346		})
1347		ls.OpenLibs()
1348	} else {
1349		if opts[0].CallStackSize < 1 {
1350			opts[0].CallStackSize = CallStackSize
1351		}
1352		if opts[0].RegistrySize < 128 {
1353			opts[0].RegistrySize = RegistrySize
1354		}
1355		if opts[0].RegistryMaxSize < opts[0].RegistrySize {
1356			opts[0].RegistryMaxSize = 0 // disable growth if max size is smaller than initial size
1357		} else {
1358			// if growth enabled, grow step is set
1359			if opts[0].RegistryGrowStep < 1 {
1360				opts[0].RegistryGrowStep = RegistryGrowStep
1361			}
1362		}
1363		ls = newLState(opts[0])
1364		if !opts[0].SkipOpenLibs {
1365			ls.OpenLibs()
1366		}
1367	}
1368	return ls
1369}
1370
1371func (ls *LState) IsClosed() bool {
1372	return ls.stack == nil
1373}
1374
1375func (ls *LState) Close() {
1376	atomic.AddInt32(&ls.stop, 1)
1377	for _, file := range ls.G.tempFiles {
1378		// ignore errors in these operations
1379		file.Close()
1380		os.Remove(file.Name())
1381	}
1382	ls.stack.FreeAll()
1383	ls.stack = nil
1384}
1385
1386/* registry operations {{{ */
1387
1388func (ls *LState) GetTop() int {
1389	return ls.reg.Top() - ls.currentLocalBase()
1390}
1391
1392func (ls *LState) SetTop(idx int) {
1393	base := ls.currentLocalBase()
1394	newtop := ls.indexToReg(idx) + 1
1395	if newtop < base {
1396		ls.reg.SetTop(base)
1397	} else {
1398		ls.reg.SetTop(newtop)
1399	}
1400}
1401
1402func (ls *LState) Replace(idx int, value LValue) {
1403	base := ls.currentLocalBase()
1404	if idx > 0 {
1405		reg := base + idx - 1
1406		if reg < ls.reg.Top() {
1407			ls.reg.Set(reg, value)
1408		}
1409	} else if idx == 0 {
1410	} else if idx > RegistryIndex {
1411		if tidx := ls.reg.Top() + idx; tidx >= base {
1412			ls.reg.Set(tidx, value)
1413		}
1414	} else {
1415		switch idx {
1416		case RegistryIndex:
1417			if tb, ok := value.(*LTable); ok {
1418				ls.G.Registry = tb
1419			} else {
1420				ls.RaiseError("registry must be a table(%v)", value.Type().String())
1421			}
1422		case EnvironIndex:
1423			if ls.currentFrame == nil {
1424				ls.RaiseError("no calling environment")
1425			}
1426			if tb, ok := value.(*LTable); ok {
1427				ls.currentFrame.Fn.Env = tb
1428			} else {
1429				ls.RaiseError("environment must be a table(%v)", value.Type().String())
1430			}
1431		case GlobalsIndex:
1432			if tb, ok := value.(*LTable); ok {
1433				ls.G.Global = tb
1434			} else {
1435				ls.RaiseError("_G must be a table(%v)", value.Type().String())
1436			}
1437		default:
1438			fn := ls.currentFrame.Fn
1439			index := GlobalsIndex - idx - 1
1440			if index < len(fn.Upvalues) {
1441				fn.Upvalues[index].SetValue(value)
1442			}
1443		}
1444	}
1445}
1446
1447func (ls *LState) Get(idx int) LValue {
1448	base := ls.currentLocalBase()
1449	if idx > 0 {
1450		reg := base + idx - 1
1451		if reg < ls.reg.Top() {
1452			return ls.reg.Get(reg)
1453		}
1454		return LNil
1455	} else if idx == 0 {
1456		return LNil
1457	} else if idx > RegistryIndex {
1458		tidx := ls.reg.Top() + idx
1459		if tidx < base {
1460			return LNil
1461		}
1462		return ls.reg.Get(tidx)
1463	} else {
1464		switch idx {
1465		case RegistryIndex:
1466			return ls.G.Registry
1467		case EnvironIndex:
1468			if ls.currentFrame == nil {
1469				return ls.Env
1470			}
1471			return ls.currentFrame.Fn.Env
1472		case GlobalsIndex:
1473			return ls.G.Global
1474		default:
1475			fn := ls.currentFrame.Fn
1476			index := GlobalsIndex - idx - 1
1477			if index < len(fn.Upvalues) {
1478				return fn.Upvalues[index].Value()
1479			}
1480			return LNil
1481		}
1482	}
1483	return LNil
1484}
1485
1486func (ls *LState) Push(value LValue) {
1487	ls.reg.Push(value)
1488}
1489
1490func (ls *LState) Pop(n int) {
1491	for i := 0; i < n; i++ {
1492		if ls.GetTop() == 0 {
1493			ls.RaiseError("register underflow")
1494		}
1495		ls.reg.Pop()
1496	}
1497}
1498
1499func (ls *LState) Insert(value LValue, index int) {
1500	reg := ls.indexToReg(index)
1501	top := ls.reg.Top()
1502	if reg >= top {
1503		ls.reg.Set(reg, value)
1504		return
1505	}
1506	if reg <= ls.currentLocalBase() {
1507		reg = ls.currentLocalBase()
1508	}
1509	top--
1510	for ; top >= reg; top-- {
1511		ls.reg.Set(top+1, ls.reg.Get(top))
1512	}
1513	ls.reg.Set(reg, value)
1514}
1515
1516func (ls *LState) Remove(index int) {
1517	reg := ls.indexToReg(index)
1518	top := ls.reg.Top()
1519	switch {
1520	case reg >= top:
1521		return
1522	case reg < ls.currentLocalBase():
1523		return
1524	case reg == top-1:
1525		ls.Pop(1)
1526		return
1527	}
1528	for i := reg; i < top-1; i++ {
1529		ls.reg.Set(i, ls.reg.Get(i+1))
1530	}
1531	ls.reg.SetTop(top - 1)
1532}
1533
1534/* }}} */
1535
1536/* object allocation {{{ */
1537
1538func (ls *LState) NewTable() *LTable {
1539	return newLTable(defaultArrayCap, defaultHashCap)
1540}
1541
1542func (ls *LState) CreateTable(acap, hcap int) *LTable {
1543	return newLTable(acap, hcap)
1544}
1545
1546// NewThread returns a new LState that shares with the original state all global objects.
1547// 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.
1548func (ls *LState) NewThread() (*LState, context.CancelFunc) {
1549	thread := newLState(ls.Options)
1550	thread.G = ls.G
1551	thread.Env = ls.Env
1552	var f context.CancelFunc = nil
1553	if ls.ctx != nil {
1554		thread.mainLoop = mainLoopWithContext
1555		thread.ctx, f = context.WithCancel(ls.ctx)
1556	}
1557	return thread, f
1558}
1559
1560func (ls *LState) NewFunctionFromProto(proto *FunctionProto) *LFunction {
1561	return newLFunctionL(proto, ls.Env, int(proto.NumUpvalues))
1562}
1563
1564func (ls *LState) NewUserData() *LUserData {
1565	return &LUserData{
1566		Env:       ls.currentEnv(),
1567		Metatable: LNil,
1568	}
1569}
1570
1571func (ls *LState) NewFunction(fn LGFunction) *LFunction {
1572	return newLFunctionG(fn, ls.currentEnv(), 0)
1573}
1574
1575func (ls *LState) NewClosure(fn LGFunction, upvalues ...LValue) *LFunction {
1576	cl := newLFunctionG(fn, ls.currentEnv(), len(upvalues))
1577	for i, lv := range upvalues {
1578		cl.Upvalues[i] = &Upvalue{}
1579		cl.Upvalues[i].Close()
1580		cl.Upvalues[i].SetValue(lv)
1581	}
1582	return cl
1583}
1584
1585/* }}} */
1586
1587/* toType {{{ */
1588
1589func (ls *LState) ToBool(n int) bool {
1590	return LVAsBool(ls.Get(n))
1591}
1592
1593func (ls *LState) ToInt(n int) int {
1594	if lv, ok := ls.Get(n).(LNumber); ok {
1595		return int(lv)
1596	}
1597	if lv, ok := ls.Get(n).(LString); ok {
1598		if num, err := parseNumber(string(lv)); err == nil {
1599			return int(num)
1600		}
1601	}
1602	return 0
1603}
1604
1605func (ls *LState) ToInt64(n int) int64 {
1606	if lv, ok := ls.Get(n).(LNumber); ok {
1607		return int64(lv)
1608	}
1609	if lv, ok := ls.Get(n).(LString); ok {
1610		if num, err := parseNumber(string(lv)); err == nil {
1611			return int64(num)
1612		}
1613	}
1614	return 0
1615}
1616
1617func (ls *LState) ToNumber(n int) LNumber {
1618	return LVAsNumber(ls.Get(n))
1619}
1620
1621func (ls *LState) ToString(n int) string {
1622	return LVAsString(ls.Get(n))
1623}
1624
1625func (ls *LState) ToTable(n int) *LTable {
1626	if lv, ok := ls.Get(n).(*LTable); ok {
1627		return lv
1628	}
1629	return nil
1630}
1631
1632func (ls *LState) ToFunction(n int) *LFunction {
1633	if lv, ok := ls.Get(n).(*LFunction); ok {
1634		return lv
1635	}
1636	return nil
1637}
1638
1639func (ls *LState) ToUserData(n int) *LUserData {
1640	if lv, ok := ls.Get(n).(*LUserData); ok {
1641		return lv
1642	}
1643	return nil
1644}
1645
1646func (ls *LState) ToThread(n int) *LState {
1647	if lv, ok := ls.Get(n).(*LState); ok {
1648		return lv
1649	}
1650	return nil
1651}
1652
1653/* }}} */
1654
1655/* error & debug operations {{{ */
1656
1657func (ls *LState) registryOverflow() {
1658	ls.RaiseError("registry overflow")
1659}
1660
1661// This function is equivalent to luaL_error( http://www.lua.org/manual/5.1/manual.html#luaL_error ).
1662func (ls *LState) RaiseError(format string, args ...interface{}) {
1663	ls.raiseError(1, format, args...)
1664}
1665
1666// This function is equivalent to lua_error( http://www.lua.org/manual/5.1/manual.html#lua_error ).
1667func (ls *LState) Error(lv LValue, level int) {
1668	if str, ok := lv.(LString); ok {
1669		ls.raiseError(level, string(str))
1670	} else {
1671		if !ls.hasErrorFunc {
1672			ls.closeAllUpvalues()
1673		}
1674		ls.Push(lv)
1675		ls.Panic(ls)
1676	}
1677}
1678
1679func (ls *LState) GetInfo(what string, dbg *Debug, fn LValue) (LValue, error) {
1680	if !strings.HasPrefix(what, ">") {
1681		fn = dbg.frame.Fn
1682	} else {
1683		what = what[1:]
1684	}
1685	f, ok := fn.(*LFunction)
1686	if !ok {
1687		return LNil, newApiErrorS(ApiErrorRun, "can not get debug info(an object in not a function)")
1688	}
1689
1690	retfn := false
1691	for _, c := range what {
1692		switch c {
1693		case 'f':
1694			retfn = true
1695		case 'S':
1696			if dbg.frame != nil && dbg.frame.Parent == nil {
1697				dbg.What = "main"
1698			} else if f.IsG {
1699				dbg.What = "G"
1700			} else if dbg.frame != nil && dbg.frame.TailCall > 0 {
1701				dbg.What = "tail"
1702			} else {
1703				dbg.What = "Lua"
1704			}
1705			if !f.IsG {
1706				dbg.Source = f.Proto.SourceName
1707				dbg.LineDefined = f.Proto.LineDefined
1708				dbg.LastLineDefined = f.Proto.LastLineDefined
1709			}
1710		case 'l':
1711			if !f.IsG && dbg.frame != nil {
1712				if dbg.frame.Pc > 0 {
1713					dbg.CurrentLine = f.Proto.DbgSourcePositions[dbg.frame.Pc-1]
1714				}
1715			} else {
1716				dbg.CurrentLine = -1
1717			}
1718		case 'u':
1719			dbg.NUpvalues = len(f.Upvalues)
1720		case 'n':
1721			if dbg.frame != nil {
1722				dbg.Name = ls.rawFrameFuncName(dbg.frame)
1723			}
1724		default:
1725			return LNil, newApiErrorS(ApiErrorRun, "invalid what: "+string(c))
1726		}
1727	}
1728
1729	if retfn {
1730		return f, nil
1731	}
1732	return LNil, nil
1733
1734}
1735
1736func (ls *LState) GetStack(level int) (*Debug, bool) {
1737	frame := ls.currentFrame
1738	for ; level > 0 && frame != nil; frame = frame.Parent {
1739		level--
1740		if !frame.Fn.IsG {
1741			level -= frame.TailCall
1742		}
1743	}
1744
1745	if level == 0 && frame != nil {
1746		return &Debug{frame: frame}, true
1747	} else if level < 0 && ls.stack.Sp() > 0 {
1748		return &Debug{frame: ls.stack.At(0)}, true
1749	}
1750	return &Debug{}, false
1751}
1752
1753func (ls *LState) GetLocal(dbg *Debug, no int) (string, LValue) {
1754	frame := dbg.frame
1755	if name := ls.findLocal(frame, no); len(name) > 0 {
1756		return name, ls.reg.Get(frame.LocalBase + no - 1)
1757	}
1758	return "", LNil
1759}
1760
1761func (ls *LState) SetLocal(dbg *Debug, no int, lv LValue) string {
1762	frame := dbg.frame
1763	if name := ls.findLocal(frame, no); len(name) > 0 {
1764		ls.reg.Set(frame.LocalBase+no-1, lv)
1765		return name
1766	}
1767	return ""
1768}
1769
1770func (ls *LState) GetUpvalue(fn *LFunction, no int) (string, LValue) {
1771	if fn.IsG {
1772		return "", LNil
1773	}
1774
1775	no--
1776	if no >= 0 && no < len(fn.Upvalues) {
1777		return fn.Proto.DbgUpvalues[no], fn.Upvalues[no].Value()
1778	}
1779	return "", LNil
1780}
1781
1782func (ls *LState) SetUpvalue(fn *LFunction, no int, lv LValue) string {
1783	if fn.IsG {
1784		return ""
1785	}
1786
1787	no--
1788	if no >= 0 && no < len(fn.Upvalues) {
1789		fn.Upvalues[no].SetValue(lv)
1790		return fn.Proto.DbgUpvalues[no]
1791	}
1792	return ""
1793}
1794
1795/* }}} */
1796
1797/* env operations {{{ */
1798
1799func (ls *LState) GetFEnv(obj LValue) LValue {
1800	switch lv := obj.(type) {
1801	case *LFunction:
1802		return lv.Env
1803	case *LUserData:
1804		return lv.Env
1805	case *LState:
1806		return lv.Env
1807	}
1808	return LNil
1809}
1810
1811func (ls *LState) SetFEnv(obj LValue, env LValue) {
1812	tb, ok := env.(*LTable)
1813	if !ok {
1814		ls.RaiseError("cannot use %v as an environment", env.Type().String())
1815	}
1816
1817	switch lv := obj.(type) {
1818	case *LFunction:
1819		lv.Env = tb
1820	case *LUserData:
1821		lv.Env = tb
1822	case *LState:
1823		lv.Env = tb
1824	}
1825	/* do nothing */
1826}
1827
1828/* }}} */
1829
1830/* table operations {{{ */
1831
1832func (ls *LState) RawGet(tb *LTable, key LValue) LValue {
1833	return tb.RawGet(key)
1834}
1835
1836func (ls *LState) RawGetInt(tb *LTable, key int) LValue {
1837	return tb.RawGetInt(key)
1838}
1839
1840func (ls *LState) GetField(obj LValue, skey string) LValue {
1841	return ls.getFieldString(obj, skey)
1842}
1843
1844func (ls *LState) GetTable(obj LValue, key LValue) LValue {
1845	return ls.getField(obj, key)
1846}
1847
1848func (ls *LState) RawSet(tb *LTable, key LValue, value LValue) {
1849	if n, ok := key.(LNumber); ok && math.IsNaN(float64(n)) {
1850		ls.RaiseError("table index is NaN")
1851	} else if key == LNil {
1852		ls.RaiseError("table index is nil")
1853	}
1854	tb.RawSet(key, value)
1855}
1856
1857func (ls *LState) RawSetInt(tb *LTable, key int, value LValue) {
1858	tb.RawSetInt(key, value)
1859}
1860
1861func (ls *LState) SetField(obj LValue, key string, value LValue) {
1862	ls.setFieldString(obj, key, value)
1863}
1864
1865func (ls *LState) SetTable(obj LValue, key LValue, value LValue) {
1866	ls.setField(obj, key, value)
1867}
1868
1869func (ls *LState) ForEach(tb *LTable, cb func(LValue, LValue)) {
1870	tb.ForEach(cb)
1871}
1872
1873func (ls *LState) GetGlobal(name string) LValue {
1874	return ls.GetField(ls.Get(GlobalsIndex), name)
1875}
1876
1877func (ls *LState) SetGlobal(name string, value LValue) {
1878	ls.SetField(ls.Get(GlobalsIndex), name, value)
1879}
1880
1881func (ls *LState) Next(tb *LTable, key LValue) (LValue, LValue) {
1882	return tb.Next(key)
1883}
1884
1885/* }}} */
1886
1887/* unary operations {{{ */
1888
1889func (ls *LState) ObjLen(v1 LValue) int {
1890	if v1.Type() == LTString {
1891		return len(string(v1.(LString)))
1892	}
1893	op := ls.metaOp1(v1, "__len")
1894	if op.Type() == LTFunction {
1895		ls.Push(op)
1896		ls.Push(v1)
1897		ls.Call(1, 1)
1898		ret := ls.reg.Pop()
1899		if ret.Type() == LTNumber {
1900			return int(ret.(LNumber))
1901		}
1902	} else if v1.Type() == LTTable {
1903		return v1.(*LTable).Len()
1904	}
1905	return 0
1906}
1907
1908/* }}} */
1909
1910/* binary operations {{{ */
1911
1912func (ls *LState) Concat(values ...LValue) string {
1913	top := ls.reg.Top()
1914	for _, value := range values {
1915		ls.reg.Push(value)
1916	}
1917	ret := stringConcat(ls, len(values), ls.reg.Top()-1)
1918	ls.reg.SetTop(top)
1919	return LVAsString(ret)
1920}
1921
1922func (ls *LState) LessThan(lhs, rhs LValue) bool {
1923	return lessThan(ls, lhs, rhs)
1924}
1925
1926func (ls *LState) Equal(lhs, rhs LValue) bool {
1927	return equals(ls, lhs, rhs, false)
1928}
1929
1930func (ls *LState) RawEqual(lhs, rhs LValue) bool {
1931	return equals(ls, lhs, rhs, true)
1932}
1933
1934/* }}} */
1935
1936/* register operations {{{ */
1937
1938func (ls *LState) Register(name string, fn LGFunction) {
1939	ls.SetGlobal(name, ls.NewFunction(fn))
1940}
1941
1942/* }}} */
1943
1944/* load and function call operations {{{ */
1945
1946func (ls *LState) Load(reader io.Reader, name string) (*LFunction, error) {
1947	chunk, err := parse.Parse(reader, name)
1948	if err != nil {
1949		return nil, newApiErrorE(ApiErrorSyntax, err)
1950	}
1951	proto, err := Compile(chunk, name)
1952	if err != nil {
1953		return nil, newApiErrorE(ApiErrorSyntax, err)
1954	}
1955	return newLFunctionL(proto, ls.currentEnv(), 0), nil
1956}
1957
1958func (ls *LState) Call(nargs, nret int) {
1959	ls.callR(nargs, nret, -1)
1960}
1961
1962func (ls *LState) PCall(nargs, nret int, errfunc *LFunction) (err error) {
1963	err = nil
1964	sp := ls.stack.Sp()
1965	base := ls.reg.Top() - nargs - 1
1966	oldpanic := ls.Panic
1967	ls.Panic = panicWithoutTraceback
1968	if errfunc != nil {
1969		ls.hasErrorFunc = true
1970	}
1971	defer func() {
1972		ls.Panic = oldpanic
1973		ls.hasErrorFunc = false
1974		rcv := recover()
1975		if rcv != nil {
1976			if _, ok := rcv.(*ApiError); !ok {
1977				err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv))
1978				if ls.Options.IncludeGoStackTrace {
1979					buf := make([]byte, 4096)
1980					runtime.Stack(buf, false)
1981					err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + "\n" + ls.stackTrace(0)
1982				}
1983			} else {
1984				err = rcv.(*ApiError)
1985			}
1986			if errfunc != nil {
1987				ls.Push(errfunc)
1988				ls.Push(err.(*ApiError).Object)
1989				ls.Panic = panicWithoutTraceback
1990				defer func() {
1991					ls.Panic = oldpanic
1992					rcv := recover()
1993					if rcv != nil {
1994						if _, ok := rcv.(*ApiError); !ok {
1995							err = newApiErrorS(ApiErrorPanic, fmt.Sprint(rcv))
1996							if ls.Options.IncludeGoStackTrace {
1997								buf := make([]byte, 4096)
1998								runtime.Stack(buf, false)
1999								err.(*ApiError).StackTrace = strings.Trim(string(buf), "\000") + ls.stackTrace(0)
2000							}
2001						} else {
2002							err = rcv.(*ApiError)
2003							err.(*ApiError).StackTrace = ls.stackTrace(0)
2004						}
2005					}
2006				}()
2007				ls.Call(1, 1)
2008				err = newApiError(ApiErrorError, ls.Get(-1))
2009			} else if len(err.(*ApiError).StackTrace) == 0 {
2010				err.(*ApiError).StackTrace = ls.stackTrace(0)
2011			}
2012			ls.stack.SetSp(sp)
2013			ls.currentFrame = ls.stack.Last()
2014			ls.reg.SetTop(base)
2015		}
2016		ls.stack.SetSp(sp)
2017		if sp == 0 {
2018			ls.currentFrame = nil
2019		}
2020	}()
2021
2022	ls.Call(nargs, nret)
2023
2024	return
2025}
2026
2027func (ls *LState) GPCall(fn LGFunction, data LValue) error {
2028	ls.Push(newLFunctionG(fn, ls.currentEnv(), 0))
2029	ls.Push(data)
2030	return ls.PCall(1, MultRet, nil)
2031}
2032
2033func (ls *LState) CallByParam(cp P, args ...LValue) error {
2034	ls.Push(cp.Fn)
2035	for _, arg := range args {
2036		ls.Push(arg)
2037	}
2038
2039	if cp.Protect {
2040		return ls.PCall(len(args), cp.NRet, cp.Handler)
2041	}
2042	ls.Call(len(args), cp.NRet)
2043	return nil
2044}
2045
2046/* }}} */
2047
2048/* metatable operations {{{ */
2049
2050func (ls *LState) GetMetatable(obj LValue) LValue {
2051	return ls.metatable(obj, false)
2052}
2053
2054func (ls *LState) SetMetatable(obj LValue, mt LValue) {
2055	switch mt.(type) {
2056	case *LNilType, *LTable:
2057	default:
2058		ls.RaiseError("metatable must be a table or nil, but got %v", mt.Type().String())
2059	}
2060
2061	switch v := obj.(type) {
2062	case *LTable:
2063		v.Metatable = mt
2064	case *LUserData:
2065		v.Metatable = mt
2066	default:
2067		ls.G.builtinMts[int(obj.Type())] = mt
2068	}
2069}
2070
2071/* }}} */
2072
2073/* coroutine operations {{{ */
2074
2075func (ls *LState) Status(th *LState) string {
2076	status := "suspended"
2077	if th.Dead {
2078		status = "dead"
2079	} else if ls.G.CurrentThread == th {
2080		status = "running"
2081	} else if ls.Parent == th {
2082		status = "normal"
2083	}
2084	return status
2085}
2086
2087func (ls *LState) Resume(th *LState, fn *LFunction, args ...LValue) (ResumeState, error, []LValue) {
2088	isstarted := th.isStarted()
2089	if !isstarted {
2090		base := 0
2091		th.stack.Push(callFrame{
2092			Fn:         fn,
2093			Pc:         0,
2094			Base:       base,
2095			LocalBase:  base + 1,
2096			ReturnBase: base,
2097			NArgs:      0,
2098			NRet:       MultRet,
2099			Parent:     nil,
2100			TailCall:   0,
2101		})
2102	}
2103
2104	if ls.G.CurrentThread == th {
2105		return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a running thread"), nil
2106	}
2107	if th.Dead {
2108		return ResumeError, newApiErrorS(ApiErrorRun, "can not resume a dead thread"), nil
2109	}
2110	th.Parent = ls
2111	ls.G.CurrentThread = th
2112	if !isstarted {
2113		cf := th.stack.Last()
2114		th.currentFrame = cf
2115		th.SetTop(0)
2116		for _, arg := range args {
2117			th.Push(arg)
2118		}
2119		cf.NArgs = len(args)
2120		th.initCallFrame(cf)
2121		th.Panic = panicWithoutTraceback
2122	} else {
2123		for _, arg := range args {
2124			th.Push(arg)
2125		}
2126	}
2127	top := ls.GetTop()
2128	threadRun(th)
2129	haserror := LVIsFalse(ls.Get(top + 1))
2130	ret := make([]LValue, 0, ls.GetTop())
2131	for idx := top + 2; idx <= ls.GetTop(); idx++ {
2132		ret = append(ret, ls.Get(idx))
2133	}
2134	if len(ret) == 0 {
2135		ret = append(ret, LNil)
2136	}
2137	ls.SetTop(top)
2138
2139	if haserror {
2140		return ResumeError, newApiError(ApiErrorRun, ret[0]), nil
2141	} else if th.stack.IsEmpty() {
2142		return ResumeOK, nil, ret
2143	}
2144	return ResumeYield, nil, ret
2145}
2146
2147func (ls *LState) Yield(values ...LValue) int {
2148	ls.SetTop(0)
2149	for _, lv := range values {
2150		ls.Push(lv)
2151	}
2152	return -1
2153}
2154
2155func (ls *LState) XMoveTo(other *LState, n int) {
2156	if ls == other {
2157		return
2158	}
2159	top := ls.GetTop()
2160	n = intMin(n, top)
2161	for i := n; i > 0; i-- {
2162		other.Push(ls.Get(top - i + 1))
2163	}
2164	ls.SetTop(top - n)
2165}
2166
2167/* }}} */
2168
2169/* GopherLua original APIs {{{ */
2170
2171// Set maximum memory size. This function can only be called from the main thread.
2172func (ls *LState) SetMx(mx int) {
2173	if ls.Parent != nil {
2174		ls.RaiseError("sub threads are not allowed to set a memory limit")
2175	}
2176	go func() {
2177		limit := uint64(mx * 1024 * 1024) //MB
2178		var s runtime.MemStats
2179		for atomic.LoadInt32(&ls.stop) == 0 {
2180			runtime.ReadMemStats(&s)
2181			if s.Alloc >= limit {
2182				fmt.Println("out of memory")
2183				os.Exit(3)
2184			}
2185			time.Sleep(100 * time.Millisecond)
2186		}
2187	}()
2188}
2189
2190// SetContext set a context ctx to this LState. The provided ctx must be non-nil.
2191func (ls *LState) SetContext(ctx context.Context) {
2192	ls.mainLoop = mainLoopWithContext
2193	ls.ctx = ctx
2194}
2195
2196// Context returns the LState's context. To change the context, use WithContext.
2197func (ls *LState) Context() context.Context {
2198	return ls.ctx
2199}
2200
2201// RemoveContext removes the context associated with this LState and returns this context.
2202func (ls *LState) RemoveContext() context.Context {
2203	oldctx := ls.ctx
2204	ls.mainLoop = mainLoop
2205	ls.ctx = nil
2206	return oldctx
2207}
2208
2209// Converts the Lua value at the given acceptable index to the chan LValue.
2210func (ls *LState) ToChannel(n int) chan LValue {
2211	if lv, ok := ls.Get(n).(LChannel); ok {
2212		return (chan LValue)(lv)
2213	}
2214	return nil
2215}
2216
2217// RemoveCallerFrame removes the stack frame above the current stack frame. This is useful in tail calls. It returns
2218// the new current frame.
2219func (ls *LState) RemoveCallerFrame() *callFrame {
2220	cs := ls.stack
2221	sp := cs.Sp()
2222	parentFrame := cs.At(sp - 2)
2223	currentFrame := cs.At(sp - 1)
2224	parentsParentFrame := parentFrame.Parent
2225	*parentFrame = *currentFrame
2226	parentFrame.Parent = parentsParentFrame
2227	parentFrame.Idx = sp - 2
2228	cs.Pop()
2229	return parentFrame
2230}
2231
2232/* }}} */
2233
2234/* }}} */
2235
2236//
2237