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