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