tile38/vendor/github.com/yuin/gopher-lua/state.go

1873 lines
39 KiB
Go
Raw Normal View History

2017-10-05 18:20:40 +03:00
package lua
////////////////////////////////////////////////////////
// This file was generated by go-inline. DO NOT EDIT. //
////////////////////////////////////////////////////////
import (
"context"
"fmt"
"github.com/yuin/gopher-lua/parse"
"io"
"math"
"os"
"runtime"
"strings"
"sync/atomic"
"time"
)
const MultRet = -1
const RegistryIndex = -10000
const EnvironIndex = -10001
const GlobalsIndex = -10002
/* ApiError {{{ */
type ApiError struct {
Type ApiErrorType
Object LValue
StackTrace string
// Underlying error. This attribute is set only if the Type is ApiErrorFile or ApiErrorSyntax
Cause error
}
func newApiError(code ApiErrorType, object LValue) *ApiError {
return &ApiError{code, object, "", nil}
}
func newApiErrorS(code ApiErrorType, message string) *ApiError {
return newApiError(code, LString(message))
}
func newApiErrorE(code ApiErrorType, err error) *ApiError {
return &ApiError{code, LString(err.Error()), "", err}
}
func (e *ApiError) Error() string {
if len(e.StackTrace) > 0 {
return fmt.Sprintf("%s\n%s", e.Object.String(), e.StackTrace)
}
return e.Object.String()
}
type ApiErrorType int
const (
ApiErrorSyntax ApiErrorType = iota
ApiErrorFile
ApiErrorRun
ApiErrorError
ApiErrorPanic
)
/* }}} */
/* ResumeState {{{ */
type ResumeState int
const (
ResumeOK ResumeState = iota
ResumeYield
ResumeError
)
/* }}} */
/* P {{{ */
type P struct {
Fn LValue
NRet int
Protect bool
Handler *LFunction
}
/* }}} */
/* Options {{{ */
// Options is a configuration that is used to create a new LState.
type Options struct {
// Call stack size. This defaults to `lua.CallStackSize`.
CallStackSize int
// Data stack size. This defaults to `lua.RegistrySize`.
RegistrySize int
// Controls whether or not libraries are opened by default
SkipOpenLibs bool
// Tells whether a Go stacktrace should be included in a Lua stacktrace when panics occur.
IncludeGoStackTrace bool
}
/* }}} */
/* Debug {{{ */
type Debug struct {
frame *callFrame
Name string
What string
Source string
CurrentLine int
NUpvalues int
LineDefined int
LastLineDefined int
}
/* }}} */
/* callFrame {{{ */
type callFrame struct {
Idx int
Fn *LFunction
Parent *callFrame
Pc int
Base int
LocalBase int
ReturnBase int
NArgs int
NRet int
TailCall int
}
type callFrameStack struct {
array []callFrame
sp int
}
func newCallFrameStack(size int) *callFrameStack {
return &callFrameStack{
array: make([]callFrame, size),
sp: 0,
}
}
func (cs *callFrameStack) IsEmpty() bool { return cs.sp == 0 }
func (cs *callFrameStack) Clear() {
cs.sp = 0
}
func (cs *callFrameStack) Push(v callFrame) { // +inline-start
cs.array[cs.sp] = v
cs.array[cs.sp].Idx = cs.sp
cs.sp++
} // +inline-end
func (cs *callFrameStack) Remove(sp int) {
psp := sp - 1
nsp := sp + 1
var pre *callFrame
var next *callFrame
if psp > 0 {
pre = &cs.array[psp]
}
if nsp < cs.sp {
next = &cs.array[nsp]
}
if next != nil {
next.Parent = pre
}
for i := sp; i+1 < cs.sp; i++ {
cs.array[i] = cs.array[i+1]
cs.array[i].Idx = i
cs.sp = i
}
cs.sp++
}
func (cs *callFrameStack) Sp() int {
return cs.sp
}
func (cs *callFrameStack) SetSp(sp int) {
cs.sp = sp
}
func (cs *callFrameStack) Last() *callFrame {
if cs.sp == 0 {
return nil
}
return &cs.array[cs.sp-1]
}
func (cs *callFrameStack) At(sp int) *callFrame {
return &cs.array[sp]
}
func (cs *callFrameStack) Pop() *callFrame {
cs.sp--
return &cs.array[cs.sp]
}
/* }}} */
/* registry {{{ */
type registry struct {
array []LValue
top int
alloc *allocator
}
func newRegistry(size int, alloc *allocator) *registry {
return &registry{make([]LValue, size), 0, alloc}
}
func (rg *registry) SetTop(top int) {
oldtop := rg.top
rg.top = top
for i := oldtop; i < rg.top; i++ {
rg.array[i] = LNil
}
for i := rg.top; i < oldtop; i++ {
rg.array[i] = LNil
}
}
func (rg *registry) Top() int {
return rg.top
}
func (rg *registry) Push(v LValue) {
rg.array[rg.top] = v
rg.top++
}
func (rg *registry) Pop() LValue {
v := rg.array[rg.top-1]
rg.array[rg.top-1] = LNil
rg.top--
return v
}
func (rg *registry) Get(reg int) LValue {
return rg.array[reg]
}
func (rg *registry) CopyRange(regv, start, limit, n int) { // +inline-start
for i := 0; i < n; i++ {
if tidx := start + i; tidx >= rg.top || limit > -1 && tidx >= limit || tidx < 0 {
rg.array[regv+i] = LNil
} else {
rg.array[regv+i] = rg.array[tidx]
}
}
rg.top = regv + n
} // +inline-end
func (rg *registry) FillNil(regm, n int) { // +inline-start
for i := 0; i < n; i++ {
rg.array[regm+i] = LNil
}
rg.top = regm + n
} // +inline-end
func (rg *registry) Insert(value LValue, reg int) {
top := rg.Top()
if reg >= top {
rg.Set(reg, value)
return
}
top--
for ; top >= reg; top-- {
rg.Set(top+1, rg.Get(top))
}
rg.Set(reg, value)
}
func (rg *registry) Set(reg int, val LValue) {
rg.array[reg] = val
if reg >= rg.top {
rg.top = reg + 1
}
}
func (rg *registry) SetNumber(reg int, val LNumber) {
rg.array[reg] = rg.alloc.LNumber2I(val)
if reg >= rg.top {
rg.top = reg + 1
}
} /* }}} */
/* Global {{{ */
func newGlobal() *Global {
return &Global{
MainThread: nil,
Registry: newLTable(0, 32),
Global: newLTable(0, 64),
builtinMts: make(map[int]LValue),
tempFiles: make([]*os.File, 0, 10),
}
}
/* }}} */
/* package local methods {{{ */
func panicWithTraceback(L *LState) {
err := newApiError(ApiErrorRun, L.Get(-1))
err.StackTrace = L.stackTrace(0)
panic(err)
}
func panicWithoutTraceback(L *LState) {
err := newApiError(ApiErrorRun, L.Get(-1))
panic(err)
}
func newLState(options Options) *LState {
al := newAllocator(32)
ls := &LState{
G: newGlobal(),
Parent: nil,
Panic: panicWithTraceback,
Dead: false,
Options: options,
stop: 0,
reg: newRegistry(options.RegistrySize, al),
stack: newCallFrameStack(options.CallStackSize),
alloc: al,
currentFrame: nil,
wrapped: false,
uvcache: nil,
hasErrorFunc: false,
mainLoop: mainLoop,
ctx: nil,
}
ls.Env = ls.G.Global
return ls
}
func (ls *LState) printReg() {
println("-------------------------")
println("thread:", ls)
println("top:", ls.reg.Top())
if ls.currentFrame != nil {
println("function base:", ls.currentFrame.Base)
println("return base:", ls.currentFrame.ReturnBase)
} else {
println("(vm not started)")
}
println("local base:", ls.currentLocalBase())
for i := 0; i < ls.reg.Top(); i++ {
println(i, ls.reg.Get(i).String())
}
println("-------------------------")
}
func (ls *LState) printCallStack() {
println("-------------------------")
for i := 0; i < ls.stack.Sp(); i++ {
print(i)
print(" ")
frame := ls.stack.At(i)
if frame == nil {
break
}
if frame.Fn.IsG {
println("IsG:", true, "Frame:", frame, "Fn:", frame.Fn)
} else {
println("IsG:", false, "Frame:", frame, "Fn:", frame.Fn, "pc:", frame.Pc)
}
}
println("-------------------------")
}
func (ls *LState) closeAllUpvalues() { // +inline-start
for cf := ls.currentFrame; cf != nil; cf = cf.Parent {
if !cf.Fn.IsG {
ls.closeUpvalues(cf.LocalBase)
}
}
} // +inline-end
func (ls *LState) raiseError(level int, format string, args ...interface{}) {
if !ls.hasErrorFunc {
ls.closeAllUpvalues()
}
message := format
if len(args) > 0 {
message = fmt.Sprintf(format, args...)
}
if level > 0 {
message = fmt.Sprintf("%v %v", ls.where(level-1, true), message)
}
ls.reg.Push(LString(message))
ls.Panic(ls)
}
func (ls *LState) findLocal(frame *callFrame, no int) string {
fn := frame.Fn
if !fn.IsG {
if name, ok := fn.LocalName(no, frame.Pc-1); ok {
return name
}
}
var top int
if ls.currentFrame == frame {
top = ls.reg.Top()
} else if frame.Idx+1 < ls.stack.Sp() {
top = ls.stack.At(frame.Idx + 1).Base
} else {
return ""
}
if top-frame.LocalBase >= no {
return "(*temporary)"
}
return ""
}
func (ls *LState) where(level int, skipg bool) string {
dbg, ok := ls.GetStack(level)
if !ok {
return ""
}
cf := dbg.frame
proto := cf.Fn.Proto
sourcename := "[G]"
if proto != nil {
sourcename = proto.SourceName
} else if skipg {
return ls.where(level+1, skipg)
}
line := ""
if proto != nil {
line = fmt.Sprintf("%v:", proto.DbgSourcePositions[cf.Pc-1])
}
return fmt.Sprintf("%v:%v", sourcename, line)
}
func (ls *LState) stackTrace(level int) string {
buf := []string{}
header := "stack traceback:"
if ls.currentFrame != nil {
i := 0
for dbg, ok := ls.GetStack(i); ok; dbg, ok = ls.GetStack(i) {
cf := dbg.frame
buf = append(buf, fmt.Sprintf("\t%v in %v", ls.Where(i), ls.formattedFrameFuncName(cf)))
if !cf.Fn.IsG && cf.TailCall > 0 {
for tc := cf.TailCall; tc > 0; tc-- {
buf = append(buf, "\t(tailcall): ?")
i++
}
}
i++
}
}
buf = append(buf, fmt.Sprintf("\t%v: %v", "[G]", "?"))
buf = buf[intMax(0, intMin(level, len(buf))):len(buf)]
if len(buf) > 20 {
newbuf := make([]string, 0, 20)
newbuf = append(newbuf, buf[0:7]...)
newbuf = append(newbuf, "\t...")
newbuf = append(newbuf, buf[len(buf)-7:len(buf)]...)
buf = newbuf
}
return fmt.Sprintf("%s\n%s", header, strings.Join(buf, "\n"))
}
func (ls *LState) formattedFrameFuncName(fr *callFrame) string {
name, ischunk := ls.frameFuncName(fr)
if ischunk {
return name
}
if name[0] != '(' && name[0] != '<' {
return fmt.Sprintf("function '%s'", name)
}
return fmt.Sprintf("function %s", name)
}
func (ls *LState) rawFrameFuncName(fr *callFrame) string {
name, _ := ls.frameFuncName(fr)
return name
}
func (ls *LState) frameFuncName(fr *callFrame) (string, bool) {
frame := fr.Parent
if frame == nil {
if ls.Parent == nil {
return "main chunk", true
} else {
return "corountine", true
}
}
if !frame.Fn.IsG {
pc := frame.Pc - 1
for _, call := range frame.Fn.Proto.DbgCalls {
if call.Pc == pc {
name := call.Name
if (name == "?" || fr.TailCall > 0) && !fr.Fn.IsG {
name = fmt.Sprintf("<%v:%v>", fr.Fn.Proto.SourceName, fr.Fn.Proto.LineDefined)
}
return name, false
}
}
}
if !fr.Fn.IsG {
return fmt.Sprintf("<%v:%v>", fr.Fn.Proto.SourceName, fr.Fn.Proto.LineDefined), false
}
return "(anonymous)", false
}
func (ls *LState) isStarted() bool {
return ls.currentFrame != nil
}
func (ls *LState) kill() {
ls.Dead = true
}
func (ls *LState) indexToReg(idx int) int {
base := ls.currentLocalBase()
if idx > 0 {
return base + idx - 1
} else if idx == 0 {
return -1
} else {