github.com/hirochachacha/plua@v0.0.0-20170217012138-c82f520cc725/stdlib/base/base.go (about)

     1  package base
     2  
     3  import (
     4  	"fmt"
     5  	"runtime"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/hirochachacha/plua/compiler"
    10  	"github.com/hirochachacha/plua/internal/compiler_pool"
    11  	"github.com/hirochachacha/plua/internal/errors"
    12  	"github.com/hirochachacha/plua/internal/limits"
    13  	"github.com/hirochachacha/plua/internal/version"
    14  	"github.com/hirochachacha/plua/object"
    15  	"github.com/hirochachacha/plua/object/fnutil"
    16  )
    17  
    18  // assert(v [, message], ...) -> ((v [, message], ...) | panic)
    19  func assert(th object.Thread, args ...object.Value) (rets []object.Value, err *object.RuntimeError) {
    20  	ap := fnutil.NewArgParser(th, args)
    21  
    22  	ok, err := ap.ToGoBool(0)
    23  	if err != nil {
    24  		return nil, err
    25  	}
    26  
    27  	if !ok {
    28  		val, ok := ap.Get(1)
    29  		if !ok {
    30  			return nil, object.NewRuntimeError("assertion failed!")
    31  		}
    32  
    33  		return nil, &object.RuntimeError{RawValue: val, Level: 1}
    34  	}
    35  
    36  	return args, nil
    37  }
    38  
    39  // collectgarbage([opt [, arg]])
    40  func collectgarbage(th object.Thread, args ...object.Value) (rets []object.Value, err *object.RuntimeError) {
    41  	ap := fnutil.NewArgParser(th, args)
    42  
    43  	opt := "collect"
    44  
    45  	if len(args) > 0 {
    46  		opt, err = ap.ToGoString(0)
    47  		if err != nil {
    48  			return nil, err
    49  		}
    50  	}
    51  
    52  	switch opt {
    53  	case "collect":
    54  		runtime.GC()
    55  		return []object.Value{object.Integer(0)}, nil
    56  	case "stop":
    57  		return nil, object.NewRuntimeError("not implemented")
    58  	case "restart":
    59  		return nil, object.NewRuntimeError("not implemented")
    60  	case "count":
    61  		m := runtime.MemStats{}
    62  		runtime.ReadMemStats(&m)
    63  		return []object.Value{object.Number(m.Alloc / 1024.0)}, nil
    64  	case "step":
    65  		return nil, object.NewRuntimeError("not implemented")
    66  	case "setpause":
    67  		return nil, object.NewRuntimeError("not implemented")
    68  	case "setstepmul":
    69  		return nil, object.NewRuntimeError("not implemented")
    70  	case "isrunning":
    71  		return []object.Value{object.True}, nil
    72  	}
    73  
    74  	return nil, ap.OptionError(0, opt)
    75  }
    76  
    77  // dofile([filename]) -> (... | panic)
    78  func dofile(th object.Thread, args ...object.Value) (rets []object.Value, err *object.RuntimeError) {
    79  	ap := fnutil.NewArgParser(th, args)
    80  
    81  	fname := ""
    82  
    83  	if len(args) > 0 {
    84  		fname, err = ap.ToGoString(0)
    85  		if err != nil {
    86  			return nil, err
    87  		}
    88  	}
    89  
    90  	p, err := compiler_pool.CompileFile(fname, 0)
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  
    95  	return th.Call(th.NewClosure(p))
    96  }
    97  
    98  // error(message [, level]) -> panic
    99  func _error(th object.Thread, args ...object.Value) (rets []object.Value, err *object.RuntimeError) {
   100  	ap := fnutil.NewArgParser(th, args)
   101  
   102  	val, ok := ap.Get(0)
   103  	if !ok {
   104  		return nil, &object.RuntimeError{RawValue: nil}
   105  	}
   106  
   107  	level, err := ap.OptGoInt(1, 1)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	if _, ok := val.(object.String); ok && level > 0 {
   113  		return nil, &object.RuntimeError{RawValue: val, Level: level}
   114  	}
   115  
   116  	return nil, &object.RuntimeError{RawValue: val}
   117  }
   118  
   119  // getmetatable(object) -> Value
   120  func getmetatable(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   121  	ap := fnutil.NewArgParser(th, args)
   122  
   123  	val, err := ap.ToValue(0)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  
   128  	mt := th.GetMetatable(val)
   129  	if mt != nil {
   130  		if _mt := mt.Get(object.String("__metatable")); _mt != nil {
   131  			return []object.Value{_mt}, nil
   132  		}
   133  	}
   134  
   135  	return []object.Value{mt}, nil
   136  }
   137  
   138  func inext(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   139  	ap := fnutil.NewArgParser(th, args)
   140  
   141  	t, err := ap.ToTable(0)
   142  	if err != nil {
   143  		return nil, err
   144  	}
   145  
   146  	i, err := ap.ToGoInt(1)
   147  	if err != nil {
   148  		return nil, err
   149  	}
   150  
   151  	i++
   152  
   153  	if i <= t.Len() {
   154  		v := t.Get(object.Integer(i))
   155  		if v == nil {
   156  			return nil, nil
   157  		}
   158  		return []object.Value{object.Integer(i), v}, nil
   159  	}
   160  
   161  	return nil, nil
   162  }
   163  
   164  func makeINext(tm object.Value) object.GoFunction {
   165  	inext := func(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   166  		ap := fnutil.NewArgParser(th, args)
   167  
   168  		t, err := ap.ToTable(0)
   169  		if err != nil {
   170  			return nil, err
   171  		}
   172  
   173  		i, err := ap.ToGoInt(1)
   174  		if err != nil {
   175  			return nil, err
   176  		}
   177  
   178  		i++
   179  
   180  		rets, err := th.Call(tm, t, object.Integer(i))
   181  		if err != nil {
   182  			return nil, err
   183  		}
   184  
   185  		if len(rets) == 0 || rets[0] == nil {
   186  			return nil, nil
   187  		}
   188  
   189  		return append([]object.Value{object.Integer(i)}, rets...), nil
   190  	}
   191  
   192  	return object.GoFunction(inext)
   193  }
   194  
   195  // ipairs(t) -> (inext, t, 0)
   196  func ipairs(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   197  	ap := fnutil.NewArgParser(th, args)
   198  
   199  	t, err := ap.ToValue(0)
   200  	if err != nil {
   201  		return nil, err
   202  	}
   203  
   204  	mt := th.GetMetatable(t)
   205  
   206  	if mt == nil {
   207  		return []object.Value{object.GoFunction(inext), t, object.Integer(0)}, nil
   208  	}
   209  
   210  	if tm := mt.Get(object.TM_IPAIRS); tm != nil {
   211  		return th.Call(tm, args...)
   212  	}
   213  
   214  	for i := 0; i < version.MAX_TAG_LOOP; i++ {
   215  		tm := mt.Get(object.TM_INDEX)
   216  		if tm == nil {
   217  			return []object.Value{object.GoFunction(inext), t, object.Integer(0)}, nil
   218  		}
   219  
   220  		if object.ToType(tm) == object.TFUNCTION {
   221  			return []object.Value{makeINext(tm), t, object.Integer(0)}, nil
   222  		}
   223  
   224  		t = tm
   225  	}
   226  
   227  	return nil, object.NewRuntimeError("gettable chain too long; possible loop")
   228  }
   229  
   230  // next(t, key) -> (nkey, val)
   231  func next(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   232  	ap := fnutil.NewArgParser(th, args)
   233  
   234  	t, err := ap.ToTable(0)
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  
   239  	var key object.Value
   240  	if len(args) > 1 {
   241  		key = args[1]
   242  	}
   243  
   244  	k, v, ok := t.Next(key)
   245  	if !ok {
   246  		return nil, object.NewRuntimeError("invalid key to 'next'")
   247  	}
   248  
   249  	if v == nil {
   250  		return nil, nil
   251  	}
   252  
   253  	return []object.Value{k, v}, nil
   254  }
   255  
   256  // pairs(t) -> (next, t, nil)
   257  func pairs(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   258  	ap := fnutil.NewArgParser(th, args)
   259  
   260  	t, err := ap.ToValue(0)
   261  	if err != nil {
   262  		return nil, err
   263  	}
   264  
   265  	if mt := th.GetMetatable(t); mt != nil {
   266  		if tm := mt.Get(object.TM_PAIRS); tm != nil {
   267  			return th.Call(tm, args...)
   268  		}
   269  	}
   270  
   271  	return []object.Value{object.GoFunction(next), t, nil}, nil
   272  }
   273  
   274  // loadfile(fname [, mode [, env]]]) -> (closure | (nil, errmessage))
   275  func loadfile(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   276  	ap := fnutil.NewArgParser(th, args)
   277  
   278  	fname, err := ap.OptGoString(0, "")
   279  	if err != nil {
   280  		return nil, err
   281  	}
   282  
   283  	mode, err := ap.OptGoString(1, "bt")
   284  	if err != nil {
   285  		return nil, err
   286  	}
   287  
   288  	var p *object.Proto
   289  
   290  	switch mode {
   291  	case "b":
   292  		p, err = compiler_pool.CompileFile(fname, compiler.Binary)
   293  	case "t":
   294  		p, err = compiler_pool.CompileFile(fname, compiler.Text)
   295  	case "bt":
   296  		p, err = compiler_pool.CompileFile(fname, 0)
   297  	default:
   298  		return nil, ap.OptionError(1, mode)
   299  	}
   300  
   301  	if err != nil {
   302  		return []object.Value{nil, err.Value()}, nil
   303  	}
   304  
   305  	cl := th.NewClosure(p)
   306  
   307  	if env, ok := ap.Get(2); ok {
   308  		cl.SetUpvalue(0, env)
   309  	}
   310  
   311  	return []object.Value{cl}, nil
   312  }
   313  
   314  // load(chunk [, chunkname [, mode [, env]]]) -> (closure | (nil, errmessage))
   315  func load(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   316  	ap := fnutil.NewArgParser(th, args)
   317  
   318  	s, err := ap.ToTypes(0, object.TSTRING, object.TFUNCTION)
   319  	if err != nil {
   320  		return nil, err
   321  	}
   322  
   323  	var chunk string
   324  	var chunkname string
   325  
   326  	switch s := s.(type) {
   327  	case object.String:
   328  		chunk = string(s)
   329  
   330  		chunkname, err = ap.OptGoString(1, string(s))
   331  		if err != nil {
   332  			return nil, err
   333  		}
   334  	case object.GoFunction, object.Closure:
   335  		for {
   336  			rets, err := th.Call(s)
   337  			if err != nil {
   338  				return []object.Value{nil, err.Value()}, nil
   339  			}
   340  			if len(rets) == 0 || rets[0] == nil {
   341  				break
   342  			}
   343  			s, ok := object.ToGoString(rets[0])
   344  			if !ok {
   345  				return []object.Value{nil, object.String("reader function must return a string")}, nil
   346  			}
   347  			if s == "" {
   348  				break
   349  			}
   350  			chunk += s
   351  		}
   352  
   353  		chunkname, err = ap.OptGoString(1, "=(load)")
   354  		if err != nil {
   355  			return nil, err
   356  		}
   357  	}
   358  
   359  	mode, err := ap.OptGoString(2, "bt")
   360  	if err != nil {
   361  		return nil, err
   362  	}
   363  
   364  	var p *object.Proto
   365  	switch mode {
   366  	case "b":
   367  		p, err = compiler_pool.CompileString(chunk, chunkname, compiler.Binary)
   368  	case "t":
   369  		p, err = compiler_pool.CompileString(chunk, chunkname, compiler.Text)
   370  	case "bt":
   371  		p, err = compiler_pool.CompileString(chunk, chunkname, 0)
   372  	default:
   373  		return nil, ap.OptionError(2, mode)
   374  	}
   375  
   376  	if err != nil {
   377  		return []object.Value{nil, err.Value()}, nil
   378  	}
   379  
   380  	cl := th.NewClosure(p)
   381  
   382  	if env, ok := ap.Get(3); ok {
   383  		cl.SetUpvalue(0, env)
   384  	}
   385  
   386  	return []object.Value{cl}, nil
   387  }
   388  
   389  func _print(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   390  	if len(args) == 0 {
   391  		fmt.Println("")
   392  
   393  		return nil, nil
   394  	}
   395  
   396  	tostring := th.Globals().Get(object.String("tostring"))
   397  
   398  	for _, arg := range args[:len(args)-1] {
   399  		rets, err := th.Call(tostring, arg)
   400  		if err != nil {
   401  			return nil, err
   402  		}
   403  
   404  		if len(rets) == 0 {
   405  			return nil, object.NewRuntimeError("'tostring' must return a string to 'print'")
   406  		}
   407  
   408  		s, ok := object.ToGoString(rets[0])
   409  		if !ok {
   410  			return nil, object.NewRuntimeError("'tostring' must return a string to 'print'")
   411  		}
   412  
   413  		fmt.Print(s)
   414  		fmt.Print("\t")
   415  	}
   416  
   417  	rets, err := th.Call(tostring, args[len(args)-1])
   418  	if err != nil {
   419  		return nil, err
   420  	}
   421  
   422  	if len(rets) == 0 {
   423  		return nil, object.NewRuntimeError("'tostring' must return a string to 'print'")
   424  	}
   425  
   426  	s, ok := object.ToGoString(rets[0])
   427  	if !ok {
   428  		return nil, object.NewRuntimeError("'tostring' must return a string to 'print'")
   429  	}
   430  
   431  	fmt.Println(s)
   432  
   433  	return nil, nil
   434  }
   435  
   436  func pcall(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   437  	ap := fnutil.NewArgParser(th, args)
   438  
   439  	fn, err := ap.ToFunctionOrNil(0)
   440  	if err != nil {
   441  		return nil, err
   442  	}
   443  
   444  	rets, err := th.Call(fn, args[1:]...)
   445  	if err != nil {
   446  		return []object.Value{object.False, err.Value()}, nil
   447  	}
   448  
   449  	return append([]object.Value{object.True}, rets...), nil
   450  }
   451  
   452  func rawequal(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   453  	ap := fnutil.NewArgParser(th, args)
   454  
   455  	x, err := ap.ToValue(0)
   456  	if err != nil {
   457  		return nil, err
   458  	}
   459  
   460  	y, err := ap.ToValue(1)
   461  	if err != nil {
   462  		return nil, err
   463  	}
   464  
   465  	return []object.Value{object.Boolean(object.Equal(x, y))}, nil
   466  }
   467  
   468  func rawlen(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   469  	ap := fnutil.NewArgParser(th, args)
   470  
   471  	x, err := ap.ToTypes(0, object.TSTRING, object.TTABLE)
   472  	if err != nil {
   473  		return nil, err
   474  	}
   475  
   476  	switch x := x.(type) {
   477  	case object.String:
   478  		return []object.Value{object.Integer(len(x))}, nil
   479  	case object.Table:
   480  		return []object.Value{object.Integer(x.Len())}, nil
   481  	}
   482  
   483  	return nil, nil
   484  }
   485  
   486  func rawget(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   487  	ap := fnutil.NewArgParser(th, args)
   488  
   489  	t, err := ap.ToTable(0)
   490  	if err != nil {
   491  		return nil, err
   492  	}
   493  
   494  	key, err := ap.ToValue(1)
   495  	if err != nil {
   496  		return nil, err
   497  	}
   498  
   499  	return []object.Value{t.Get(key)}, nil
   500  }
   501  
   502  func rawset(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   503  	ap := fnutil.NewArgParser(th, args)
   504  
   505  	t, err := ap.ToTable(0)
   506  	if err != nil {
   507  		return nil, err
   508  	}
   509  
   510  	key, err := ap.ToValue(1)
   511  	if err != nil {
   512  		return nil, err
   513  	}
   514  
   515  	if key == nil {
   516  		return nil, errors.NilIndexError()
   517  	}
   518  
   519  	if object.IsNaN(key) {
   520  		return nil, errors.NaNIndexError()
   521  	}
   522  
   523  	val, err := ap.ToValue(2)
   524  	if err != nil {
   525  		return nil, err
   526  	}
   527  
   528  	t.Set(key, val)
   529  
   530  	return []object.Value{t}, nil
   531  }
   532  
   533  func _select(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   534  	ap := fnutil.NewArgParser(th, args)
   535  
   536  	i, err := ap.ToGoInt(0)
   537  	if err != nil {
   538  		if s, e := ap.ToGoString(0); e == nil {
   539  			if s == "#" {
   540  				return []object.Value{object.Integer(len(args) - 1)}, nil
   541  			}
   542  		}
   543  		return nil, err
   544  	}
   545  
   546  	switch {
   547  	case i < 0:
   548  		if len(args) < -i || int64(i) == limits.MinInt {
   549  			return nil, ap.ArgError(0, "index out of range")
   550  		}
   551  
   552  		return args[len(args)+i:], nil
   553  	case i == 0:
   554  		return nil, ap.ArgError(0, "index out of range")
   555  	}
   556  
   557  	if len(args) < i {
   558  		return nil, nil
   559  	}
   560  
   561  	return args[i:], nil
   562  }
   563  
   564  // setmetatable(table, metatable) -> table
   565  func setmetatable(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   566  	ap := fnutil.NewArgParser(th, args)
   567  
   568  	t, err := ap.ToTable(0)
   569  	if err != nil {
   570  		return nil, err
   571  	}
   572  
   573  	mt, err := ap.ToTypes(1, object.TNIL, object.TTABLE)
   574  	if err != nil {
   575  		return nil, err
   576  	}
   577  
   578  	if old := th.GetMetatable(t); old != nil {
   579  		if old.Get(object.TM_METATABLE) != nil {
   580  			return nil, object.NewRuntimeError("cannot change a protected metatable")
   581  		}
   582  	}
   583  
   584  	switch mt := mt.(type) {
   585  	case nil:
   586  		t.SetMetatable(nil)
   587  	case object.Table:
   588  		t.SetMetatable(mt)
   589  	default:
   590  		panic("unreachable")
   591  	}
   592  
   593  	return []object.Value{t}, nil
   594  }
   595  
   596  func tonumber(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   597  	ap := fnutil.NewArgParser(th, args)
   598  
   599  	switch len(args) {
   600  	case 0, 1:
   601  		val, err := ap.ToValue(0)
   602  		if err != nil {
   603  			return nil, err
   604  		}
   605  
   606  		if i, ok := object.ToInteger(val); ok {
   607  			return []object.Value{i}, nil
   608  		}
   609  
   610  		if n, ok := object.ToNumber(val); ok {
   611  			if n == 0 { // for ErrRange
   612  				return []object.Value{object.Integer(0)}, nil
   613  			}
   614  			return []object.Value{n}, nil
   615  		}
   616  
   617  		return []object.Value{nil}, nil
   618  	}
   619  
   620  	base, err := ap.OptGoInt(1, 10)
   621  	if err != nil {
   622  		return nil, err
   623  	}
   624  
   625  	if base < 2 || base > 36 {
   626  		return nil, ap.ArgError(1, "base out of range")
   627  	}
   628  
   629  	s, err := ap.ToGoString(0)
   630  	if err != nil {
   631  		return nil, err
   632  	}
   633  
   634  	if i, err := strconv.ParseInt(strings.TrimSpace(s), base, 64); err == nil {
   635  		return []object.Value{object.Integer(i)}, nil
   636  	}
   637  
   638  	return []object.Value{nil}, nil
   639  }
   640  
   641  func tostring(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   642  	ap := fnutil.NewArgParser(th, args)
   643  
   644  	val, err := ap.ToValue(0)
   645  	if err != nil {
   646  		return nil, err
   647  	}
   648  
   649  	if mt := th.GetMetatable(val); mt != nil {
   650  		if tm := mt.Get(object.TM_TOSTRING); tm != nil {
   651  			return th.Call(tm, val)
   652  		}
   653  	}
   654  
   655  	return []object.Value{object.String(object.Repr(val))}, nil
   656  }
   657  
   658  func _type(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   659  	ap := fnutil.NewArgParser(th, args)
   660  
   661  	val, err := ap.ToValue(0)
   662  	if err != nil {
   663  		return nil, err
   664  	}
   665  
   666  	return []object.Value{object.String(object.ToType(val).String())}, nil
   667  }
   668  
   669  func xpcall(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   670  	ap := fnutil.NewArgParser(th, args)
   671  
   672  	f, err := ap.ToFunction(0)
   673  	if err != nil {
   674  		return nil, err
   675  	}
   676  
   677  	msgh, err := ap.ToFunction(1)
   678  	if err != nil {
   679  		return nil, err
   680  	}
   681  
   682  	rets, err := th.Call(f, args[2:]...)
   683  	if err != nil {
   684  		rets, err = th.Call(msgh, err.Value())
   685  		if err != nil {
   686  			err.RawValue = object.String("error in error handling")
   687  
   688  			return []object.Value{object.False, err.Value()}, nil
   689  		}
   690  		return append([]object.Value{object.False}, rets...), nil
   691  	}
   692  
   693  	return append([]object.Value{object.True}, rets...), nil
   694  }
   695  
   696  func Open(th object.Thread, args ...object.Value) ([]object.Value, *object.RuntimeError) {
   697  	g := th.Globals()
   698  
   699  	g.Set(object.String("_G"), g)
   700  	g.Set(object.String("_VERSION"), object.String(version.LUA_NAME))
   701  	g.Set(object.String("assert"), object.GoFunction(assert))
   702  	g.Set(object.String("collectgarbage"), object.GoFunction(collectgarbage))
   703  	g.Set(object.String("dofile"), object.GoFunction(dofile))
   704  	g.Set(object.String("error"), object.GoFunction(_error))
   705  	g.Set(object.String("getmetatable"), object.GoFunction(getmetatable))
   706  	g.Set(object.String("ipairs"), object.GoFunction(ipairs))
   707  	g.Set(object.String("loadfile"), object.GoFunction(loadfile))
   708  	g.Set(object.String("load"), object.GoFunction(load))
   709  	g.Set(object.String("next"), object.GoFunction(next))
   710  	g.Set(object.String("pairs"), object.GoFunction(pairs))
   711  	g.Set(object.String("pcall"), object.GoFunction(pcall))
   712  	g.Set(object.String("print"), object.GoFunction(_print))
   713  	g.Set(object.String("rawequal"), object.GoFunction(rawequal))
   714  	g.Set(object.String("rawlen"), object.GoFunction(rawlen))
   715  	g.Set(object.String("rawget"), object.GoFunction(rawget))
   716  	g.Set(object.String("rawset"), object.GoFunction(rawset))
   717  	g.Set(object.String("select"), object.GoFunction(_select))
   718  	g.Set(object.String("setmetatable"), object.GoFunction(setmetatable))
   719  	g.Set(object.String("tonumber"), object.GoFunction(tonumber))
   720  	g.Set(object.String("tostring"), object.GoFunction(tostring))
   721  	g.Set(object.String("type"), object.GoFunction(_type))
   722  	g.Set(object.String("xpcall"), object.GoFunction(xpcall))
   723  
   724  	return []object.Value{g}, nil
   725  }