github.com/xrash/gopher-lua@v0.0.0-20160304065408-e5faab4db06a/value.go (about)

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