github.com/guardangely/gopher-lua@v0.0.0-20200324075529-f92e6f279f59/auxlib.go (about) 1 package lua 2 3 import ( 4 "bufio" 5 "fmt" 6 "io" 7 "os" 8 "strings" 9 ) 10 11 /* checkType {{{ */ 12 13 func (ls *LState) CheckAny(n int) LValue { 14 if n > ls.GetTop() { 15 ls.ArgError(n, "value expected") 16 } 17 return ls.Get(n) 18 } 19 20 func (ls *LState) CheckInt(n int) int { 21 v := ls.Get(n) 22 if intv, ok := v.(LNumber); ok { 23 return int(intv) 24 } 25 ls.TypeError(n, LTNumber) 26 return 0 27 } 28 29 func (ls *LState) CheckInt64(n int) int64 { 30 v := ls.Get(n) 31 if intv, ok := v.(LNumber); ok { 32 return int64(intv) 33 } 34 ls.TypeError(n, LTNumber) 35 return 0 36 } 37 38 func (ls *LState) CheckNumber(n int) LNumber { 39 v := ls.Get(n) 40 if lv, ok := v.(LNumber); ok { 41 return lv 42 } 43 ls.TypeError(n, LTNumber) 44 return 0 45 } 46 47 func (ls *LState) CheckString(n int) string { 48 v := ls.Get(n) 49 if lv, ok := v.(LString); ok { 50 return string(lv) 51 } 52 ls.TypeError(n, LTString) 53 return "" 54 } 55 56 func (ls *LState) CheckBool(n int) bool { 57 v := ls.Get(n) 58 if lv, ok := v.(LBool); ok { 59 return bool(lv) 60 } 61 ls.TypeError(n, LTBool) 62 return false 63 } 64 65 func (ls *LState) CheckTable(n int) *LTable { 66 v := ls.Get(n) 67 if lv, ok := v.(*LTable); ok { 68 return lv 69 } 70 ls.TypeError(n, LTTable) 71 return nil 72 } 73 74 func (ls *LState) CheckFunction(n int) *LFunction { 75 v := ls.Get(n) 76 if lv, ok := v.(*LFunction); ok { 77 return lv 78 } 79 ls.TypeError(n, LTFunction) 80 return nil 81 } 82 83 func (ls *LState) CheckUserData(n int) *LUserData { 84 v := ls.Get(n) 85 if lv, ok := v.(*LUserData); ok { 86 return lv 87 } 88 ls.TypeError(n, LTUserData) 89 return nil 90 } 91 92 func (ls *LState) CheckThread(n int) *LState { 93 v := ls.Get(n) 94 if lv, ok := v.(*LState); ok { 95 return lv 96 } 97 ls.TypeError(n, LTThread) 98 return nil 99 } 100 101 func (ls *LState) CheckType(n int, typ LValueType) { 102 v := ls.Get(n) 103 if v.Type() != typ { 104 ls.TypeError(n, typ) 105 } 106 } 107 108 func (ls *LState) CheckTypes(n int, typs ...LValueType) { 109 vt := ls.Get(n).Type() 110 for _, typ := range typs { 111 if vt == typ { 112 return 113 } 114 } 115 buf := []string{} 116 for _, typ := range typs { 117 buf = append(buf, typ.String()) 118 } 119 ls.ArgError(n, strings.Join(buf, " or ")+" expected, got "+ls.Get(n).Type().String()) 120 } 121 122 func (ls *LState) CheckOption(n int, options []string) int { 123 str := ls.CheckString(n) 124 for i, v := range options { 125 if v == str { 126 return i 127 } 128 } 129 ls.ArgError(n, fmt.Sprintf("invalid option: %s (must be one of %s)", str, strings.Join(options, ","))) 130 return 0 131 } 132 133 /* }}} */ 134 135 /* optType {{{ */ 136 137 func (ls *LState) OptInt(n int, d int) int { 138 v := ls.Get(n) 139 if v == LNil { 140 return d 141 } 142 if intv, ok := v.(LNumber); ok { 143 return int(intv) 144 } 145 ls.TypeError(n, LTNumber) 146 return 0 147 } 148 149 func (ls *LState) OptInt64(n int, d int64) int64 { 150 v := ls.Get(n) 151 if v == LNil { 152 return d 153 } 154 if intv, ok := v.(LNumber); ok { 155 return int64(intv) 156 } 157 ls.TypeError(n, LTNumber) 158 return 0 159 } 160 161 func (ls *LState) OptNumber(n int, d LNumber) LNumber { 162 v := ls.Get(n) 163 if v == LNil { 164 return d 165 } 166 if lv, ok := v.(LNumber); ok { 167 return lv 168 } 169 ls.TypeError(n, LTNumber) 170 return 0 171 } 172 173 func (ls *LState) OptString(n int, d string) string { 174 v := ls.Get(n) 175 if v == LNil { 176 return d 177 } 178 if lv, ok := v.(LString); ok { 179 return string(lv) 180 } 181 ls.TypeError(n, LTString) 182 return "" 183 } 184 185 func (ls *LState) OptBool(n int, d bool) bool { 186 v := ls.Get(n) 187 if v == LNil { 188 return d 189 } 190 if lv, ok := v.(LBool); ok { 191 return bool(lv) 192 } 193 ls.TypeError(n, LTBool) 194 return false 195 } 196 197 func (ls *LState) OptTable(n int, d *LTable) *LTable { 198 v := ls.Get(n) 199 if v == LNil { 200 return d 201 } 202 if lv, ok := v.(*LTable); ok { 203 return lv 204 } 205 ls.TypeError(n, LTTable) 206 return nil 207 } 208 209 func (ls *LState) OptFunction(n int, d *LFunction) *LFunction { 210 v := ls.Get(n) 211 if v == LNil { 212 return d 213 } 214 if lv, ok := v.(*LFunction); ok { 215 return lv 216 } 217 ls.TypeError(n, LTFunction) 218 return nil 219 } 220 221 func (ls *LState) OptUserData(n int, d *LUserData) *LUserData { 222 v := ls.Get(n) 223 if v == LNil { 224 return d 225 } 226 if lv, ok := v.(*LUserData); ok { 227 return lv 228 } 229 ls.TypeError(n, LTUserData) 230 return nil 231 } 232 233 /* }}} */ 234 235 /* error operations {{{ */ 236 237 func (ls *LState) ArgError(n int, message string) { 238 ls.RaiseError("bad argument #%v to %v (%v)", n, ls.rawFrameFuncName(ls.currentFrame), message) 239 } 240 241 func (ls *LState) TypeError(n int, typ LValueType) { 242 ls.RaiseError("bad argument #%v to %v (%v expected, got %v)", n, ls.rawFrameFuncName(ls.currentFrame), typ.String(), ls.Get(n).Type().String()) 243 } 244 245 /* }}} */ 246 247 /* debug operations {{{ */ 248 249 func (ls *LState) Where(level int) string { 250 return ls.where(level, false) 251 } 252 253 /* }}} */ 254 255 /* table operations {{{ */ 256 257 func (ls *LState) FindTable(obj *LTable, n string, size int) LValue { 258 names := strings.Split(n, ".") 259 curobj := obj 260 for _, name := range names { 261 if curobj.Type() != LTTable { 262 return LNil 263 } 264 nextobj := ls.RawGet(curobj, LString(name)) 265 if nextobj == LNil { 266 tb := ls.CreateTable(0, size) 267 ls.RawSet(curobj, LString(name), tb) 268 curobj = tb 269 } else if nextobj.Type() != LTTable { 270 return LNil 271 } else { 272 curobj = nextobj.(*LTable) 273 } 274 } 275 return curobj 276 } 277 278 /* }}} */ 279 280 /* register operations {{{ */ 281 282 func (ls *LState) RegisterModule(name string, funcs map[string]LGFunction) LValue { 283 tb := ls.FindTable(ls.Get(RegistryIndex).(*LTable), "_LOADED", 1) 284 mod := ls.GetField(tb, name) 285 if mod.Type() != LTTable { 286 newmod := ls.FindTable(ls.Get(GlobalsIndex).(*LTable), name, len(funcs)) 287 if newmodtb, ok := newmod.(*LTable); !ok { 288 ls.RaiseError("name conflict for module(%v)", name) 289 } else { 290 for fname, fn := range funcs { 291 newmodtb.RawSetString(fname, ls.NewFunction(fn)) 292 } 293 ls.SetField(tb, name, newmodtb) 294 return newmodtb 295 } 296 } 297 return mod 298 } 299 300 func (ls *LState) SetFuncs(tb *LTable, funcs map[string]LGFunction, upvalues ...LValue) *LTable { 301 for fname, fn := range funcs { 302 tb.RawSetString(fname, ls.NewClosure(fn, upvalues...)) 303 } 304 return tb 305 } 306 307 /* }}} */ 308 309 /* metatable operations {{{ */ 310 311 func (ls *LState) NewTypeMetatable(typ string) *LTable { 312 regtable := ls.Get(RegistryIndex) 313 mt := ls.GetField(regtable, typ) 314 if tb, ok := mt.(*LTable); ok { 315 return tb 316 } 317 mtnew := ls.NewTable() 318 ls.SetField(regtable, typ, mtnew) 319 return mtnew 320 } 321 322 func (ls *LState) GetMetaField(obj LValue, event string) LValue { 323 return ls.metaOp1(obj, event) 324 } 325 326 func (ls *LState) GetTypeMetatable(typ string) LValue { 327 return ls.GetField(ls.Get(RegistryIndex), typ) 328 } 329 330 func (ls *LState) CallMeta(obj LValue, event string) LValue { 331 op := ls.metaOp1(obj, event) 332 if op.Type() == LTFunction { 333 ls.reg.Push(op) 334 ls.reg.Push(obj) 335 ls.Call(1, 1) 336 return ls.reg.Pop() 337 } 338 return LNil 339 } 340 341 /* }}} */ 342 343 /* load and function call operations {{{ */ 344 345 func (ls *LState) LoadFile(path string) (*LFunction, error) { 346 var file *os.File 347 var err error 348 if len(path) == 0 { 349 file = os.Stdin 350 } else { 351 file, err = os.Open(path) 352 defer file.Close() 353 if err != nil { 354 return nil, newApiErrorE(ApiErrorFile, err) 355 } 356 } 357 358 reader := bufio.NewReader(file) 359 // get the first character. 360 c, err := reader.ReadByte() 361 if err != nil && err != io.EOF { 362 return nil, newApiErrorE(ApiErrorFile, err) 363 } 364 if c == byte('#') { 365 // Unix exec. file? 366 // skip first line 367 _, err, _ = readBufioLine(reader) 368 if err != nil { 369 return nil, newApiErrorE(ApiErrorFile, err) 370 } 371 } 372 373 if err != io.EOF { 374 // if the file is not empty, 375 // unread the first character of the file or newline character(readBufioLine's last byte). 376 err = reader.UnreadByte() 377 if err != nil { 378 return nil, newApiErrorE(ApiErrorFile, err) 379 } 380 } 381 382 return ls.Load(reader, path) 383 } 384 385 func (ls *LState) LoadString(source string) (*LFunction, error) { 386 return ls.Load(strings.NewReader(source), "<string>") 387 } 388 389 func (ls *LState) DoFile(path string) error { 390 if fn, err := ls.LoadFile(path); err != nil { 391 return err 392 } else { 393 ls.Push(fn) 394 return ls.PCall(0, MultRet, nil) 395 } 396 } 397 398 func (ls *LState) DoString(source string) error { 399 if fn, err := ls.LoadString(source); err != nil { 400 return err 401 } else { 402 ls.Push(fn) 403 return ls.PCall(0, MultRet, nil) 404 } 405 } 406 407 /* }}} */ 408 409 /* GopherLua original APIs {{{ */ 410 411 // ToStringMeta returns string representation of given LValue. 412 // This method calls the `__tostring` meta method if defined. 413 func (ls *LState) ToStringMeta(lv LValue) LValue { 414 if fn, ok := ls.metaOp1(lv, "__tostring").assertFunction(); ok { 415 ls.Push(fn) 416 ls.Push(lv) 417 ls.Call(1, 1) 418 return ls.reg.Pop() 419 } else { 420 return LString(lv.String()) 421 } 422 } 423 424 // Set a module loader to the package.preload table. 425 func (ls *LState) PreloadModule(name string, loader LGFunction) { 426 preload := ls.GetField(ls.GetField(ls.Get(EnvironIndex), "package"), "preload") 427 if _, ok := preload.(*LTable); !ok { 428 ls.RaiseError("package.preload must be a table") 429 } 430 ls.SetField(preload, name, ls.NewFunction(loader)) 431 } 432 433 // Checks whether the given index is an LChannel and returns this channel. 434 func (ls *LState) CheckChannel(n int) chan LValue { 435 v := ls.Get(n) 436 if ch, ok := v.(LChannel); ok { 437 return (chan LValue)(ch) 438 } 439 ls.TypeError(n, LTChannel) 440 return nil 441 } 442 443 // If the given index is a LChannel, returns this channel. If this argument is absent or is nil, returns ch. Otherwise, raises an error. 444 func (ls *LState) OptChannel(n int, ch chan LValue) chan LValue { 445 v := ls.Get(n) 446 if v == LNil { 447 return ch 448 } 449 if ch, ok := v.(LChannel); ok { 450 return (chan LValue)(ch) 451 } 452 ls.TypeError(n, LTChannel) 453 return nil 454 } 455 456 /* }}} */ 457 458 //