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 }