route/vendor/github.com/yuin/gopher-lua/value.go

248 lines
7.3 KiB
Go

package lua
import (
"context"
"fmt"
"os"
)
type LValueType int
const (
LTNil LValueType = iota
LTBool
LTNumber
LTString
LTFunction
LTUserData
LTThread
LTTable
LTChannel
)
var lValueNames = [9]string{"nil", "boolean", "number", "string", "function", "userdata", "thread", "table", "channel"}
func (vt LValueType) String() string {
return lValueNames[int(vt)]
}
type LValue interface {
String() string
Type() LValueType
// to reduce `runtime.assertI2T2` costs, this method should be used instead of the type assertion in heavy paths(typically inside the VM).
assertFloat64() (float64, bool)
// to reduce `runtime.assertI2T2` costs, this method should be used instead of the type assertion in heavy paths(typically inside the VM).
assertString() (string, bool)
// to reduce `runtime.assertI2T2` costs, this method should be used instead of the type assertion in heavy paths(typically inside the VM).
assertFunction() (*LFunction, bool)
}
// LVIsFalse returns true if a given LValue is a nil or false otherwise false.
func LVIsFalse(v LValue) bool { return v == LNil || v == LFalse }
// LVIsFalse returns false if a given LValue is a nil or false otherwise true.
func LVAsBool(v LValue) bool { return v != LNil && v != LFalse }
// LVAsString returns string representation of a given LValue
// if the LValue is a string or number, otherwise an empty string.
func LVAsString(v LValue) string {
switch sn := v.(type) {
case LString, LNumber:
return sn.String()
default:
return ""
}
}
// LVCanConvToString returns true if a given LValue is a string or number
// otherwise false.
func LVCanConvToString(v LValue) bool {
switch v.(type) {
case LString, LNumber:
return true
default:
return false
}
}
// LVAsNumber tries to convert a given LValue to a number.
func LVAsNumber(v LValue) LNumber {
switch lv := v.(type) {
case LNumber:
return lv
case LString:
if num, err := parseNumber(string(lv)); err == nil {
return num
}
}
return LNumber(0)
}
type LNilType struct{}
func (nl *LNilType) String() string { return "nil" }
func (nl *LNilType) Type() LValueType { return LTNil }
func (nl *LNilType) assertFloat64() (float64, bool) { return 0, false }
func (nl *LNilType) assertString() (string, bool) { return "", false }
func (nl *LNilType) assertFunction() (*LFunction, bool) { return nil, false }
var LNil = LValue(&LNilType{})
type LBool bool
func (bl LBool) String() string {
if bool(bl) {
return "true"
}
return "false"
}
func (bl LBool) Type() LValueType { return LTBool }
func (bl LBool) assertFloat64() (float64, bool) { return 0, false }
func (bl LBool) assertString() (string, bool) { return "", false }
func (bl LBool) assertFunction() (*LFunction, bool) { return nil, false }
var LTrue = LBool(true)
var LFalse = LBool(false)
type LString string
func (st LString) String() string { return string(st) }
func (st LString) Type() LValueType { return LTString }
func (st LString) assertFloat64() (float64, bool) { return 0, false }
func (st LString) assertString() (string, bool) { return string(st), true }
func (st LString) assertFunction() (*LFunction, bool) { return nil, false }
// fmt.Formatter interface
func (st LString) Format(f fmt.State, c rune) {
switch c {
case 'd', 'i':
if nm, err := parseNumber(string(st)); err != nil {
defaultFormat(nm, f, 'd')
} else {
defaultFormat(string(st), f, 's')
}
default:
defaultFormat(string(st), f, c)
}
}
func (nm LNumber) String() string {
if isInteger(nm) {
return fmt.Sprint(int64(nm))
}
return fmt.Sprint(float64(nm))
}
func (nm LNumber) Type() LValueType { return LTNumber }
func (nm LNumber) assertFloat64() (float64, bool) { return float64(nm), true }
func (nm LNumber) assertString() (string, bool) { return "", false }
func (nm LNumber) assertFunction() (*LFunction, bool) { return nil, false }
// fmt.Formatter interface
func (nm LNumber) Format(f fmt.State, c rune) {
switch c {
case 'q', 's':
defaultFormat(nm.String(), f, c)
case 'b', 'c', 'd', 'o', 'x', 'X', 'U':
defaultFormat(int64(nm), f, c)
case 'e', 'E', 'f', 'F', 'g', 'G':
defaultFormat(float64(nm), f, c)
case 'i':
defaultFormat(int64(nm), f, 'd')
default:
if isInteger(nm) {
defaultFormat(int64(nm), f, c)
} else {
defaultFormat(float64(nm), f, c)
}
}
}
type LTable struct {
Metatable LValue
array []LValue
dict map[LValue]LValue
strdict map[string]LValue
keys []LValue
k2i map[LValue]int
}
func (tb *LTable) String() string { return fmt.Sprintf("table: %p", tb) }
func (tb *LTable) Type() LValueType { return LTTable }
func (tb *LTable) assertFloat64() (float64, bool) { return 0, false }
func (tb *LTable) assertString() (string, bool) { return "", false }
func (tb *LTable) assertFunction() (*LFunction, bool) { return nil, false }
type LFunction struct {
IsG bool
Env *LTable
Proto *FunctionProto
GFunction LGFunction
Upvalues []*Upvalue
}
type LGFunction func(*LState) int
func (fn *LFunction) String() string { return fmt.Sprintf("function: %p", fn) }
func (fn *LFunction) Type() LValueType { return LTFunction }
func (fn *LFunction) assertFloat64() (float64, bool) { return 0, false }
func (fn *LFunction) assertString() (string, bool) { return "", false }
func (fn *LFunction) assertFunction() (*LFunction, bool) { return fn, true }
type Global struct {
MainThread *LState
CurrentThread *LState
Registry *LTable
Global *LTable
builtinMts map[int]LValue
tempFiles []*os.File
gccount int32
}
type LState struct {
G *Global
Parent *LState
Env *LTable
Panic func(*LState)
Dead bool
Options Options
stop int32
reg *registry
stack *callFrameStack
alloc *allocator
currentFrame *callFrame
wrapped bool
uvcache *Upvalue
hasErrorFunc bool
mainLoop func(*LState, *callFrame)
ctx context.Context
}
func (ls *LState) String() string { return fmt.Sprintf("thread: %p", ls) }
func (ls *LState) Type() LValueType { return LTThread }
func (ls *LState) assertFloat64() (float64, bool) { return 0, false }
func (ls *LState) assertString() (string, bool) { return "", false }
func (ls *LState) assertFunction() (*LFunction, bool) { return nil, false }
type LUserData struct {
Value interface{}
Env *LTable
Metatable LValue
}
func (ud *LUserData) String() string { return fmt.Sprintf("userdata: %p", ud) }
func (ud *LUserData) Type() LValueType { return LTUserData }
func (ud *LUserData) assertFloat64() (float64, bool) { return 0, false }
func (ud *LUserData) assertString() (string, bool) { return "", false }
func (ud *LUserData) assertFunction() (*LFunction, bool) { return nil, false }
type LChannel chan LValue
func (ch LChannel) String() string { return fmt.Sprintf("channel: %p", ch) }
func (ch LChannel) Type() LValueType { return LTChannel }
func (ch LChannel) assertFloat64() (float64, bool) { return 0, false }
func (ch LChannel) assertString() (string, bool) { return "", false }
func (ch LChannel) assertFunction() (*LFunction, bool) { return nil, false }