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 }