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