github.com/suixinio/gopher-lua@v0.0.0-20230314172526-3c6bff009a9a/value.go (about)

     1  package lua
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"os"
     7  )
     8  
     9  type LValueType int
    10  
    11  const (
    12  	LTNil LValueType = iota
    13  	LTBool
    14  	LTNumber
    15  	LTString
    16  	LTFunction
    17  	LTUserData
    18  	LTThread
    19  	LTTable
    20  	LTChannel
    21  )
    22  
    23  var lValueNames = [9]string{"nil", "boolean", "number", "string", "function", "userdata", "thread", "table", "channel"}
    24  
    25  func (vt LValueType) String() string {
    26  	return lValueNames[int(vt)]
    27  }
    28  
    29  type LValue interface {
    30  	String() string
    31  	Type() LValueType
    32  	// to reduce `runtime.assertI2T2` costs, this method should be used instead of the type assertion in heavy paths(typically inside the VM).
    33  	assertFloat64() (float64, bool)
    34  	// to reduce `runtime.assertI2T2` costs, this method should be used instead of the type assertion in heavy paths(typically inside the VM).
    35  	assertString() (string, bool)
    36  	// to reduce `runtime.assertI2T2` costs, this method should be used instead of the type assertion in heavy paths(typically inside the VM).
    37  	assertFunction() (*LFunction, bool)
    38  }
    39  
    40  // LVIsFalse returns true if a given LValue is a nil or false otherwise false.
    41  func LVIsFalse(v LValue) bool { return v == LNil || v == LFalse }
    42  
    43  // LVIsFalse returns false if a given LValue is a nil or false otherwise true.
    44  func LVAsBool(v LValue) bool { return v != LNil && v != LFalse }
    45  
    46  // LVAsString returns string representation of a given LValue
    47  // if the LValue is a string or number, otherwise an empty string.
    48  func LVAsString(v LValue) string {
    49  	switch sn := v.(type) {
    50  	case LString, LNumber:
    51  		return sn.String()
    52  	default:
    53  		return ""
    54  	}
    55  }
    56  
    57  // LVCanConvToString returns true if a given LValue is a string or number
    58  // otherwise false.
    59  func LVCanConvToString(v LValue) bool {
    60  	switch v.(type) {
    61  	case LString, LNumber:
    62  		return true
    63  	default:
    64  		return false
    65  	}
    66  }
    67  
    68  // LVAsNumber tries to convert a given LValue to a number.
    69  func LVAsNumber(v LValue) LNumber {
    70  	switch lv := v.(type) {
    71  	case LNumber:
    72  		return lv
    73  	case LString:
    74  		if num, err := parseNumber(string(lv)); err == nil {
    75  			return num
    76  		}
    77  	}
    78  	return LNumber(0)
    79  }
    80  
    81  type LNilType struct{}
    82  
    83  func (nl *LNilType) String() string                     { return "nil" }
    84  func (nl *LNilType) Type() LValueType                   { return LTNil }
    85  func (nl *LNilType) assertFloat64() (float64, bool)     { return 0, false }
    86  func (nl *LNilType) assertString() (string, bool)       { return "", false }
    87  func (nl *LNilType) assertFunction() (*LFunction, bool) { return nil, false }
    88  
    89  var LNil = LValue(&LNilType{})
    90  
    91  type LBool bool
    92  
    93  func (bl LBool) String() string {
    94  	if bool(bl) {
    95  		return "true"
    96  	}
    97  	return "false"
    98  }
    99  func (bl LBool) Type() LValueType                   { return LTBool }
   100  func (bl LBool) assertFloat64() (float64, bool)     { return 0, false }
   101  func (bl LBool) assertString() (string, bool)       { return "", false }
   102  func (bl LBool) assertFunction() (*LFunction, bool) { return nil, false }
   103  
   104  var LTrue = LBool(true)
   105  var LFalse = LBool(false)
   106  
   107  type LString string
   108  
   109  func (st LString) String() string                     { return string(st) }
   110  func (st LString) Type() LValueType                   { return LTString }
   111  func (st LString) assertFloat64() (float64, bool)     { return 0, false }
   112  func (st LString) assertString() (string, bool)       { return string(st), true }
   113  func (st LString) assertFunction() (*LFunction, bool) { return nil, false }
   114  
   115  // fmt.Formatter interface
   116  func (st LString) Format(f fmt.State, c rune) {
   117  	switch c {
   118  	case 'd', 'i':
   119  		if nm, err := parseNumber(string(st)); err != nil {
   120  			defaultFormat(nm, f, 'd')
   121  		} else {
   122  			defaultFormat(string(st), f, 's')
   123  		}
   124  	default:
   125  		defaultFormat(string(st), f, c)
   126  	}
   127  }
   128  
   129  func (nm LNumber) String() string {
   130  	if isInteger(nm) {
   131  		return fmt.Sprint(int64(nm))
   132  	}
   133  	return fmt.Sprint(float64(nm))
   134  }
   135  
   136  func (nm LNumber) Type() LValueType                   { return LTNumber }
   137  func (nm LNumber) assertFloat64() (float64, bool)     { return float64(nm), true }
   138  func (nm LNumber) assertString() (string, bool)       { return "", false }
   139  func (nm LNumber) assertFunction() (*LFunction, bool) { return nil, false }
   140  
   141  // fmt.Formatter interface
   142  func (nm LNumber) Format(f fmt.State, c rune) {
   143  	switch c {
   144  	case 'q', 's':
   145  		defaultFormat(nm.String(), f, c)
   146  	case 'b', 'c', 'd', 'o', 'x', 'X', 'U':
   147  		defaultFormat(int64(nm), f, c)
   148  	case 'e', 'E', 'f', 'F', 'g', 'G':
   149  		defaultFormat(float64(nm), f, c)
   150  	case 'i':
   151  		defaultFormat(int64(nm), f, 'd')
   152  	default:
   153  		if isInteger(nm) {
   154  			defaultFormat(int64(nm), f, c)
   155  		} else {
   156  			defaultFormat(float64(nm), f, c)
   157  		}
   158  	}
   159  }
   160  
   161  type LTable struct {
   162  	Metatable LValue
   163  
   164  	array   []LValue
   165  	dict    map[LValue]LValue
   166  	strdict map[string]LValue
   167  	keys    []LValue
   168  	k2i     map[LValue]int
   169  }
   170  
   171  func (tb *LTable) String() string                     { return fmt.Sprintf("table: %p", tb) }
   172  func (tb *LTable) Type() LValueType                   { return LTTable }
   173  func (tb *LTable) assertFloat64() (float64, bool)     { return 0, false }
   174  func (tb *LTable) assertString() (string, bool)       { return "", false }
   175  func (tb *LTable) assertFunction() (*LFunction, bool) { return nil, false }
   176  
   177  type LFunction struct {
   178  	IsG       bool
   179  	Env       *LTable
   180  	Proto     *FunctionProto
   181  	GFunction LGFunction
   182  	Upvalues  []*Upvalue
   183  }
   184  type LGFunction func(*LState) int
   185  
   186  func (fn *LFunction) String() string                     { return fmt.Sprintf("function: %p", fn) }
   187  func (fn *LFunction) Type() LValueType                   { return LTFunction }
   188  func (fn *LFunction) assertFloat64() (float64, bool)     { return 0, false }
   189  func (fn *LFunction) assertString() (string, bool)       { return "", false }
   190  func (fn *LFunction) assertFunction() (*LFunction, bool) { return fn, true }
   191  
   192  type Global struct {
   193  	MainThread    *LState
   194  	CurrentThread *LState
   195  	Registry      *LTable
   196  	Global        *LTable
   197  
   198  	builtinMts map[int]LValue
   199  	tempFiles  []*os.File
   200  	gccount    int32
   201  }
   202  
   203  type LState struct {
   204  	G       *Global
   205  	Parent  *LState
   206  	Env     *LTable
   207  	Panic   func(*LState)
   208  	Dead    bool
   209  	Options Options
   210  
   211  	stop         int32
   212  	reg          *registry
   213  	stack        callFrameStack
   214  	alloc        *allocator
   215  	currentFrame *callFrame
   216  	wrapped      bool
   217  	uvcache      *Upvalue
   218  	hasErrorFunc bool
   219  	mainLoop     func(*LState, *callFrame)
   220  	ctx          context.Context
   221  	interrupted  bool
   222  }
   223  
   224  func (ls *LState) String() string                     { return fmt.Sprintf("thread: %p", ls) }
   225  func (ls *LState) Type() LValueType                   { return LTThread }
   226  func (ls *LState) assertFloat64() (float64, bool)     { return 0, false }
   227  func (ls *LState) assertString() (string, bool)       { return "", false }
   228  func (ls *LState) assertFunction() (*LFunction, bool) { return nil, false }
   229  
   230  type LUserData struct {
   231  	Value     interface{}
   232  	Env       *LTable
   233  	Metatable LValue
   234  }
   235  
   236  func (ud *LUserData) String() string                     { return fmt.Sprintf("userdata: %p", ud) }
   237  func (ud *LUserData) Type() LValueType                   { return LTUserData }
   238  func (ud *LUserData) assertFloat64() (float64, bool)     { return 0, false }
   239  func (ud *LUserData) assertString() (string, bool)       { return "", false }
   240  func (ud *LUserData) assertFunction() (*LFunction, bool) { return nil, false }
   241  
   242  type LChannel chan LValue
   243  
   244  func (ch LChannel) String() string                     { return fmt.Sprintf("channel: %p", ch) }
   245  func (ch LChannel) Type() LValueType                   { return LTChannel }
   246  func (ch LChannel) assertFloat64() (float64, bool)     { return 0, false }
   247  func (ch LChannel) assertString() (string, bool)       { return "", false }
   248  func (ch LChannel) assertFunction() (*LFunction, bool) { return nil, false }