zombiezen.com/go/lua@v0.0.0-20231013005828-290725fb9140/internal/lua54/lua.go (about)

     1  // Copyright 2023 Ross Light
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy of
     4  // this software and associated documentation files (the “Software”), to deal in
     5  // the Software without restriction, including without limitation the rights to
     6  // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
     7  // the Software, and to permit persons to whom the Software is furnished to do so,
     8  // subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in all
    11  // copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
    15  // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
    16  // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
    17  // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    18  // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    19  //
    20  // SPDX-License-Identifier: MIT
    21  
    22  package lua54
    23  
    24  import (
    25  	"errors"
    26  	"fmt"
    27  	"io"
    28  	"runtime/cgo"
    29  	"strings"
    30  	"unsafe"
    31  )
    32  
    33  // #cgo unix CFLAGS: -DLUA_USE_POSIX
    34  // #cgo unix LDFLAGS: -lm
    35  // #include <stdlib.h>
    36  // #include <stddef.h>
    37  // #include <stdint.h>
    38  // #include <string.h>
    39  // #include "lua.h"
    40  // #include "lauxlib.h"
    41  // #include "lualib.h"
    42  //
    43  // char *zombiezen_lua_readercb(lua_State *L, void *data, size_t *size);
    44  // int zombiezen_lua_writercb(lua_State *L, const void *p, size_t size, void *ud);
    45  // int zombiezen_lua_gocb(lua_State *L);
    46  // int zombiezen_lua_gcfunc(lua_State *L);
    47  //
    48  // static int trampoline(lua_State *L) {
    49  //   int nresults = zombiezen_lua_gocb(L);
    50  //   if (nresults < 0) {
    51  //     lua_error(L);
    52  //   }
    53  //   return nresults;
    54  // }
    55  //
    56  // static void pushclosure(lua_State *L, uint64_t funcID, int n) {
    57  //   uint8_t *data = lua_newuserdatauv(L, 8, 0);
    58  //   data[0] = (uint8_t)funcID;
    59  //   data[1] = (uint8_t)(funcID >> 8);
    60  //   data[2] = (uint8_t)(funcID >> 16);
    61  //   data[3] = (uint8_t)(funcID >> 24);
    62  //   data[4] = (uint8_t)(funcID >> 32);
    63  //   data[5] = (uint8_t)(funcID >> 40);
    64  //   data[6] = (uint8_t)(funcID >> 48);
    65  //   data[7] = (uint8_t)(funcID >> 56);
    66  //
    67  //   if (luaL_newmetatable(L, "zombiezen.com/go/lua.Function")) {
    68  //     lua_pushcfunction(L, zombiezen_lua_gcfunc);
    69  //     lua_setfield(L, -2, "__gc");
    70  //     lua_pushboolean(L, 0);
    71  //     lua_setfield(L, -2, "__metatable");
    72  //   }
    73  //   lua_setmetatable(L, -2);
    74  //   lua_insert(L, -1 - n);
    75  //   lua_pushcclosure(L, trampoline, 1 + n);
    76  // }
    77  //
    78  // void zombiezen_lua_pushstring(lua_State *L, _GoString_ s) {
    79  //   lua_pushlstring(L, _GoStringPtr(s), _GoStringLen(s));
    80  // }
    81  //
    82  // const char *zombiezen_lua_reader(lua_State *L, void *data, size_t *size) {
    83  //   const char *p = zombiezen_lua_readercb(L, data, size);
    84  //   if (p == NULL) {
    85  //     lua_error(L);
    86  //   }
    87  //   return p;
    88  // }
    89  //
    90  // struct readStringData {
    91  //   _GoString_ s;
    92  //   int done;
    93  // };
    94  //
    95  // static const char *readstring(lua_State *L, void *data, size_t *size) {
    96  //   struct readStringData *myData = (struct readStringData*)(data);
    97  //   if (myData->done) {
    98  //     *size = 0;
    99  //     return NULL;
   100  //   }
   101  //   *size = _GoStringLen(myData->s);
   102  //   myData->done = 1;
   103  //   return _GoStringPtr(myData->s);
   104  // }
   105  //
   106  // static int loadstring(lua_State *L, _GoString_ s, const char* chunkname, const char* mode) {
   107  //   struct readStringData myData = {s, 0};
   108  //   return lua_load(L, readstring, &myData, chunkname, mode);
   109  // }
   110  //
   111  // static int gettablecb(lua_State *L) {
   112  //   lua_gettable(L, 1);
   113  //   return 1;
   114  // }
   115  //
   116  // static int gettable(lua_State *L, int index, int msgh, int *tp) {
   117  //   index = lua_absindex(L, index);
   118  //   msgh = msgh != 0 ? lua_absindex(L, msgh) : 0;
   119  //   lua_pushcfunction(L, gettablecb);
   120  //   lua_pushvalue(L, index);
   121  //   lua_rotate(L, -3, -1);
   122  //   int ret = lua_pcall(L, 2, 1, msgh);
   123  //   if (tp != NULL) {
   124  //     *tp = ret == LUA_OK ? lua_type(L, -1) : LUA_TNIL;
   125  //   }
   126  //   return ret;
   127  // }
   128  //
   129  // static int settablecb(lua_State *L) {
   130  //   lua_settable(L, 1);
   131  //   return 0;
   132  // }
   133  //
   134  // static int settable(lua_State *L, int index, int msgh) {
   135  //   index = lua_absindex(L, index);
   136  //   msgh = msgh != 0 ? lua_absindex(L, msgh) : 0;
   137  //   lua_pushcfunction(L, settablecb);
   138  //   lua_pushvalue(L, index);
   139  //   lua_rotate(L, -4, -2);
   140  //   return lua_pcall(L, 3, 0, msgh);
   141  // }
   142  //
   143  // static void pushlightuserdata(lua_State *L, uintptr_t p) {
   144  //   lua_pushlightuserdata(L, (void *)p);
   145  // }
   146  //
   147  // static int lencb(lua_State *L) {
   148  //   lua_len(L, 1);
   149  //   return 1;
   150  // }
   151  //
   152  // static void pushlenfunction(lua_State *L) {
   153  //   lua_pushcfunction(L, lencb);
   154  // }
   155  //
   156  // static void *newuserdata(lua_State *L, size_t size, int nuvalue) {
   157  //   void *ptr = lua_newuserdatauv(L, size, nuvalue);
   158  //   memset(ptr, 0, size);
   159  //   return ptr;
   160  // }
   161  //
   162  // static size_t userdatalen(lua_State *L, int index) {
   163  //   if (lua_type(L, index) != LUA_TUSERDATA) {
   164  //     return 0;
   165  //   }
   166  //   return (size_t)lua_rawlen(L, index);
   167  // }
   168  //
   169  // static lua_State *newstate(uintptr_t id) {
   170  //   lua_State *L = luaL_newstate();
   171  //   if (L == NULL) {
   172  //     return NULL;
   173  //   }
   174  //   lua_setwarnf(L, NULL, NULL);
   175  //   *(uintptr_t *)(lua_getextraspace(L)) = id;
   176  //   return L;
   177  // }
   178  //
   179  // static uintptr_t stateid(lua_State *L) {
   180  //   return *(uintptr_t *)(lua_getextraspace(L));
   181  // }
   182  //
   183  // static int gcniladic(lua_State *L, int what) {
   184  //   return lua_gc(L, what);
   185  // }
   186  //
   187  // static int gcstep(lua_State *L, int stepsize) {
   188  //   return lua_gc(L, LUA_GCSTEP, stepsize);
   189  // }
   190  //
   191  // static int gcinc(lua_State *L, int pause, int stepmul, int stepsize) {
   192  //   return lua_gc(L, LUA_GCINC, pause, stepmul, stepsize);
   193  // }
   194  //
   195  // static int gcgen(lua_State *L, int minormul, int majormul) {
   196  //   return lua_gc(L, LUA_GCGEN, minormul, majormul);
   197  // }
   198  import "C"
   199  
   200  const (
   201  	VersionMajor   = C.LUA_VERSION_MAJOR
   202  	VersionMinor   = C.LUA_VERSION_MINOR
   203  	VersionRelease = C.LUA_VERSION_RELEASE
   204  
   205  	VersionNum        = C.LUA_VERSION_NUM
   206  	VersionReleaseNum = C.LUA_VERSION_RELEASE_NUM
   207  
   208  	Version   = C.LUA_VERSION
   209  	Release   = C.LUA_RELEASE
   210  	Copyright = C.LUA_COPYRIGHT
   211  	Authors   = C.LUA_AUTHORS
   212  )
   213  
   214  const RegistryIndex int = C.LUA_REGISTRYINDEX
   215  
   216  const (
   217  	RegistryIndexMainThread int64 = C.LUA_RIDX_MAINTHREAD
   218  	RegistryIndexGlobals    int64 = C.LUA_RIDX_GLOBALS
   219  )
   220  
   221  const (
   222  	LoadedTable  = C.LUA_LOADED_TABLE
   223  	PreloadTable = C.LUA_PRELOAD_TABLE
   224  )
   225  
   226  type Type C.int
   227  
   228  const (
   229  	TypeNone          Type = C.LUA_TNONE
   230  	TypeNil           Type = C.LUA_TNIL
   231  	TypeBoolean       Type = C.LUA_TBOOLEAN
   232  	TypeLightUserdata Type = C.LUA_TLIGHTUSERDATA
   233  	TypeNumber        Type = C.LUA_TNUMBER
   234  	TypeString        Type = C.LUA_TSTRING
   235  	TypeTable         Type = C.LUA_TTABLE
   236  	TypeFunction      Type = C.LUA_TFUNCTION
   237  	TypeUserdata      Type = C.LUA_TUSERDATA
   238  	TypeThread        Type = C.LUA_TTHREAD
   239  )
   240  
   241  func (tp Type) String() string {
   242  	switch tp {
   243  	case TypeNone:
   244  		return "no value"
   245  	case TypeNil:
   246  		return "nil"
   247  	case TypeBoolean:
   248  		return "boolean"
   249  	case TypeLightUserdata, TypeUserdata:
   250  		return "userdata"
   251  	case TypeNumber:
   252  		return "number"
   253  	case TypeString:
   254  		return "string"
   255  	case TypeTable:
   256  		return "table"
   257  	case TypeFunction:
   258  		return "function"
   259  	case TypeThread:
   260  		return "thread"
   261  	default:
   262  		return fmt.Sprintf("lua.Type(%d)", C.int(tp))
   263  	}
   264  }
   265  
   266  type State struct {
   267  	ptr  *C.lua_State
   268  	top  int
   269  	cap  int
   270  	main bool
   271  }
   272  
   273  type stateData struct {
   274  	nextID   uint64
   275  	closures map[uint64]Function
   276  }
   277  
   278  // stateForCallback returns a new State for the given *lua_State.
   279  // stateForCallback assumes that it is called
   280  // before any other functions are called on the *lua_State.
   281  func stateForCallback(ptr *C.lua_State) *State {
   282  	l := &State{
   283  		ptr: ptr,
   284  		top: int(C.lua_gettop(ptr)),
   285  	}
   286  	l.cap = l.top + C.LUA_MINSTACK
   287  	return l
   288  }
   289  
   290  func (l *State) init() {
   291  	if l.ptr == nil {
   292  		data := cgo.NewHandle(&stateData{
   293  			nextID:   1,
   294  			closures: make(map[uint64]Function),
   295  		})
   296  		l.ptr = C.newstate(C.uintptr_t(data))
   297  		if l == nil {
   298  			panic("could not allocate memory for new state")
   299  		}
   300  		l.top = 0
   301  		l.cap = C.LUA_MINSTACK
   302  		l.main = true
   303  	}
   304  }
   305  
   306  func (l *State) Close() error {
   307  	if l.ptr != nil {
   308  		if !l.main {
   309  			return errors.New("lua: cannot close non-main thread")
   310  		}
   311  		data := cgo.Handle(C.stateid(l.ptr))
   312  		C.lua_close(l.ptr)
   313  		data.Delete()
   314  		*l = State{}
   315  	}
   316  	return nil
   317  }
   318  
   319  // data returns the interpreter-wide data.
   320  func (l *State) data() *stateData {
   321  	return cgo.Handle(C.stateid(l.ptr)).Value().(*stateData)
   322  }
   323  
   324  func (l *State) AbsIndex(idx int) int {
   325  	switch {
   326  	case isPseudo(idx):
   327  		return idx
   328  	case idx == 0 || idx < -l.top || idx > l.cap:
   329  		panic("unacceptable index")
   330  	case idx < 0:
   331  		return l.top + idx + 1
   332  	default:
   333  		return idx
   334  	}
   335  }
   336  
   337  func (l *State) isValidIndex(idx int) bool {
   338  	if idx == goClosureUpvalueIndex {
   339  		// Forbid users of the package from accessing the GoClosure upvalue.
   340  		return false
   341  	}
   342  	if isPseudo(idx) {
   343  		return true
   344  	}
   345  	if idx < 0 {
   346  		idx = -idx
   347  	}
   348  	return 1 <= idx && idx <= l.top
   349  }
   350  
   351  func (l *State) isAcceptableIndex(idx int) bool {
   352  	return l.isValidIndex(idx) || l.top <= idx && idx <= l.cap
   353  }
   354  
   355  func (l *State) checkElems(n int) {
   356  	if l.top < n {
   357  		panic("not enough elements in the stack")
   358  	}
   359  }
   360  
   361  func (l *State) checkMessageHandler(msgHandler int) int {
   362  	switch {
   363  	case msgHandler == 0:
   364  		return 0
   365  	case isPseudo(msgHandler):
   366  		panic("pseudo-indexed message handler")
   367  	case 1 <= msgHandler && msgHandler <= l.top:
   368  		return msgHandler
   369  	case -l.top <= msgHandler && msgHandler <= -1:
   370  		return l.top + msgHandler + 1
   371  	default:
   372  		panic("invalid message handler index")
   373  	}
   374  }
   375  
   376  func (l *State) Top() int {
   377  	return l.top
   378  }
   379  
   380  func (l *State) SetTop(idx int) {
   381  	// lua_settop can raise errors, which will be undefined behavior,
   382  	// but only if we mark stack slots as to-be-closed.
   383  	// We have a simple solution: don't let the user do that.
   384  
   385  	switch {
   386  	case isPseudo(idx):
   387  		panic("pseudo-index invalid for top")
   388  	case idx == 0:
   389  		if l.ptr != nil {
   390  			C.lua_settop(l.ptr, 0)
   391  			l.top = 0
   392  		}
   393  		return
   394  	case idx < 0:
   395  		idx += l.top + 1
   396  		if idx < 0 {
   397  			panic("stack underflow")
   398  		}
   399  	case idx > l.cap:
   400  		panic("stack overflow")
   401  	}
   402  	l.init()
   403  
   404  	C.lua_settop(l.ptr, C.int(idx))
   405  	l.top = idx
   406  }
   407  
   408  func (l *State) Pop(n int) {
   409  	l.SetTop(-n - 1)
   410  }
   411  
   412  func (l *State) PushValue(idx int) {
   413  	l.init()
   414  	if l.top >= l.cap {
   415  		panic("stack overflow")
   416  	}
   417  	C.lua_pushvalue(l.ptr, C.int(idx))
   418  	l.top++
   419  }
   420  
   421  func (l *State) Rotate(idx, n int) {
   422  	l.init()
   423  	if !l.isValidIndex(idx) || isPseudo(idx) {
   424  		panic("invalid index")
   425  	}
   426  	idx = l.AbsIndex(idx)
   427  	absN := n
   428  	if n < 0 {
   429  		absN = -n
   430  	}
   431  	if absN > l.top-idx+1 {
   432  		panic("invalid rotation")
   433  	}
   434  	C.lua_rotate(l.ptr, C.int(idx), C.int(n))
   435  }
   436  
   437  func (l *State) Remove(idx int) {
   438  	l.Rotate(idx, -1)
   439  	l.Pop(1)
   440  }
   441  
   442  func (l *State) Insert(idx int) {
   443  	l.Rotate(idx, 1)
   444  }
   445  
   446  func (l *State) Copy(fromIdx, toIdx int) {
   447  	l.init()
   448  	if !l.isAcceptableIndex(fromIdx) || !l.isAcceptableIndex(toIdx) {
   449  		panic("unacceptable index")
   450  	}
   451  	C.lua_copy(l.ptr, C.int(fromIdx), C.int(toIdx))
   452  }
   453  
   454  func (l *State) Replace(idx int) {
   455  	l.Copy(-1, idx)
   456  	l.Pop(1)
   457  }
   458  
   459  func (l *State) CheckStack(n int) bool {
   460  	if l.top+n <= l.cap {
   461  		return true
   462  	}
   463  	l.init()
   464  	ok := C.lua_checkstack(l.ptr, C.int(n)) != 0
   465  	if ok {
   466  		l.cap = max(l.cap, l.top+n)
   467  	}
   468  	return ok
   469  }
   470  
   471  func (l *State) IsNumber(idx int) bool {
   472  	if l.ptr == nil {
   473  		return false
   474  	}
   475  	if !l.isAcceptableIndex(idx) {
   476  		panic("unacceptable index")
   477  	}
   478  	return C.lua_isnumber(l.ptr, C.int(idx)) != 0
   479  }
   480  
   481  func (l *State) IsString(idx int) bool {
   482  	if l.ptr == nil {
   483  		return false
   484  	}
   485  	if !l.isAcceptableIndex(idx) {
   486  		panic("unacceptable index")
   487  	}
   488  	return C.lua_isstring(l.ptr, C.int(idx)) != 0
   489  }
   490  
   491  func (l *State) IsNativeFunction(idx int) bool {
   492  	if l.ptr == nil {
   493  		return false
   494  	}
   495  	if !l.isAcceptableIndex(idx) {
   496  		panic("unacceptable index")
   497  	}
   498  	return C.lua_iscfunction(l.ptr, C.int(idx)) != 0
   499  }
   500  
   501  func (l *State) IsInteger(idx int) bool {
   502  	if l.ptr == nil {
   503  		return false
   504  	}
   505  	if !l.isAcceptableIndex(idx) {
   506  		panic("unacceptable index")
   507  	}
   508  	return C.lua_isinteger(l.ptr, C.int(idx)) != 0
   509  }
   510  
   511  func (l *State) IsUserdata(idx int) bool {
   512  	if l.ptr == nil {
   513  		return false
   514  	}
   515  	if !l.isAcceptableIndex(idx) {
   516  		panic("unacceptable index")
   517  	}
   518  	return C.lua_isuserdata(l.ptr, C.int(idx)) != 0
   519  }
   520  
   521  func (l *State) Type(idx int) Type {
   522  	if l.ptr == nil {
   523  		return TypeNone
   524  	}
   525  	if !l.isAcceptableIndex(idx) {
   526  		panic("unacceptable index")
   527  	}
   528  	return Type(C.lua_type(l.ptr, C.int(idx)))
   529  }
   530  
   531  func (l *State) IsFunction(idx int) bool { return l.Type(idx) == TypeFunction }
   532  func (l *State) IsTable(idx int) bool    { return l.Type(idx) == TypeTable }
   533  func (l *State) IsNil(idx int) bool      { return l.Type(idx) == TypeNil }
   534  func (l *State) IsBoolean(idx int) bool  { return l.Type(idx) == TypeBoolean }
   535  func (l *State) IsThread(idx int) bool   { return l.Type(idx) == TypeThread }
   536  func (l *State) IsNone(idx int) bool     { return l.Type(idx) == TypeNone }
   537  
   538  func (l *State) IsNoneOrNil(idx int) bool {
   539  	tp := l.Type(idx)
   540  	return tp == TypeNone || tp == TypeNil
   541  }
   542  
   543  func (l *State) ToNumber(idx int) (n float64, ok bool) {
   544  	if l.ptr == nil {
   545  		return 0, false
   546  	}
   547  	if !l.isAcceptableIndex(idx) {
   548  		panic("unacceptable index")
   549  	}
   550  	var isNum C.int
   551  	n = float64(C.lua_tonumberx(l.ptr, C.int(idx), &isNum))
   552  	return n, isNum != 0
   553  }
   554  
   555  func (l *State) ToInteger(idx int) (n int64, ok bool) {
   556  	if l.ptr == nil {
   557  		return 0, false
   558  	}
   559  	if !l.isAcceptableIndex(idx) {
   560  		panic("unacceptable index")
   561  	}
   562  	var isNum C.int
   563  	n = int64(C.lua_tointegerx(l.ptr, C.int(idx), &isNum))
   564  	return n, isNum != 0
   565  }
   566  
   567  func (l *State) ToBoolean(idx int) bool {
   568  	if l.ptr == nil {
   569  		return false
   570  	}
   571  	if !l.isAcceptableIndex(idx) {
   572  		panic("unacceptable index")
   573  	}
   574  	return C.lua_toboolean(l.ptr, C.int(idx)) != 0
   575  }
   576  
   577  func (l *State) ToString(idx int) (s string, ok bool) {
   578  	if l.ptr == nil {
   579  		return "", false
   580  	}
   581  	if !l.isAcceptableIndex(idx) {
   582  		panic("unacceptable index")
   583  	}
   584  	var len C.size_t
   585  	ptr := C.lua_tolstring(l.ptr, C.int(idx), &len)
   586  	if ptr == nil {
   587  		return "", false
   588  	}
   589  	return C.GoStringN(ptr, C.int(len)), true
   590  }
   591  
   592  func (l *State) RawLen(idx int) uint64 {
   593  	if l.ptr == nil {
   594  		return 0
   595  	}
   596  	if !l.isAcceptableIndex(idx) {
   597  		panic("unacceptable index")
   598  	}
   599  	return uint64(C.lua_rawlen(l.ptr, C.int(idx)))
   600  }
   601  
   602  func (l *State) CopyUserdata(dst []byte, idx, start int) int {
   603  	if l.ptr == nil {
   604  		return 0
   605  	}
   606  	if !l.isAcceptableIndex(idx) {
   607  		panic("unacceptable index")
   608  	}
   609  	return l.copyUserdata(dst, idx, start)
   610  }
   611  
   612  func (l *State) copyUserdata(dst []byte, idx, start int) int {
   613  	if start < 0 {
   614  		panic("negative userdata start")
   615  	}
   616  	size := int(C.userdatalen(l.ptr, C.int(idx)))
   617  	if start >= size {
   618  		return 0
   619  	}
   620  	src := unsafe.Slice((*byte)(C.lua_touserdata(l.ptr, C.int(idx))), size)
   621  	return copy(dst, src[start:])
   622  }
   623  
   624  func (l *State) ToPointer(idx int) uintptr {
   625  	if l.ptr == nil {
   626  		return 0
   627  	}
   628  	if !l.isAcceptableIndex(idx) {
   629  		panic("unacceptable index")
   630  	}
   631  	return uintptr(C.lua_topointer(l.ptr, C.int(idx)))
   632  }
   633  
   634  func (l *State) RawEqual(idx1, idx2 int) bool {
   635  	if l.ptr == nil {
   636  		return false
   637  	}
   638  	if !l.isAcceptableIndex(idx1) || !l.isAcceptableIndex(idx2) {
   639  		panic("unacceptable index")
   640  	}
   641  	return C.lua_rawequal(l.ptr, C.int(idx1), C.int(idx2)) != 0
   642  }
   643  
   644  func (l *State) PushNil() {
   645  	l.init()
   646  	if l.top >= l.cap {
   647  		panic("stack overflow")
   648  	}
   649  	C.lua_pushnil(l.ptr)
   650  	l.top++
   651  }
   652  
   653  func (l *State) PushNumber(n float64) {
   654  	l.init()
   655  	if l.top >= l.cap {
   656  		panic("stack overflow")
   657  	}
   658  	C.lua_pushnumber(l.ptr, C.lua_Number(n))
   659  	l.top++
   660  }
   661  
   662  func (l *State) PushInteger(n int64) {
   663  	l.init()
   664  	if l.top >= l.cap {
   665  		panic("stack overflow")
   666  	}
   667  	C.lua_pushinteger(l.ptr, C.lua_Integer(n))
   668  	l.top++
   669  }
   670  
   671  func (l *State) PushString(s string) {
   672  	l.init()
   673  	if l.top >= l.cap {
   674  		panic("stack overflow")
   675  	}
   676  	C.zombiezen_lua_pushstring(l.ptr, s)
   677  	l.top++
   678  }
   679  
   680  func (l *State) PushBoolean(b bool) {
   681  	l.init()
   682  	if l.top >= l.cap {
   683  		panic("stack overflow")
   684  	}
   685  	i := C.int(0)
   686  	if b {
   687  		i = 1
   688  	}
   689  	C.lua_pushboolean(l.ptr, i)
   690  	l.top++
   691  }
   692  
   693  func (l *State) PushLightUserdata(p uintptr) {
   694  	l.init()
   695  	if l.top >= l.cap {
   696  		panic("stack overflow")
   697  	}
   698  	C.pushlightuserdata(l.ptr, C.uintptr_t(p))
   699  	l.top++
   700  }
   701  
   702  type Function = func(*State) (int, error)
   703  
   704  func pcall(f Function, l *State) (nResults int, err error) {
   705  	defer func() {
   706  		if v := recover(); v != nil {
   707  			nResults = 0
   708  			switch v := v.(type) {
   709  			case error:
   710  				err = v
   711  			case string:
   712  				err = errors.New(v)
   713  			default:
   714  				err = fmt.Errorf("%v", v)
   715  			}
   716  		}
   717  	}()
   718  	return f(l)
   719  }
   720  
   721  func (l *State) PushClosure(n int, f Function) {
   722  	if f == nil {
   723  		panic("nil Function")
   724  	}
   725  	if n < 0 || n > 254 {
   726  		panic("invalid upvalue count")
   727  	}
   728  	l.checkElems(n)
   729  	l.init()
   730  	if !l.CheckStack(3) {
   731  		panic("stack overflow")
   732  	}
   733  	data := l.data()
   734  	funcID := data.nextID
   735  	if funcID == 0 {
   736  		panic("ID wrap-around")
   737  	}
   738  	data.nextID++
   739  	data.closures[funcID] = f
   740  
   741  	C.pushclosure(l.ptr, C.uint64_t(funcID), C.int(n))
   742  	// lua_pushcclosure pops n, but pushes 1.
   743  	l.top -= n - 1
   744  }
   745  
   746  func (l *State) Global(name string, msgHandler int) (Type, error) {
   747  	l.init()
   748  	msgHandler = l.checkMessageHandler(msgHandler)
   749  	l.RawIndex(RegistryIndex, RegistryIndexGlobals)
   750  	tp, err := l.Field(-1, name, msgHandler)
   751  	l.Remove(-2) // remove the globals table
   752  	return tp, err
   753  }
   754  
   755  func (l *State) Table(idx, msgHandler int) (Type, error) {
   756  	l.checkElems(1)
   757  	if !l.CheckStack(2) { // gettable needs 2 additional stack slots
   758  		panic("stack overflow")
   759  	}
   760  	if !l.isAcceptableIndex(idx) {
   761  		panic("unacceptable index")
   762  	}
   763  	msgHandler = l.checkMessageHandler(msgHandler)
   764  	var tp C.int
   765  	ret := C.gettable(l.ptr, C.int(idx), C.int(msgHandler), &tp)
   766  	if ret != C.LUA_OK {
   767  		return TypeNil, fmt.Errorf("lua: table lookup: %w", l.newError(ret))
   768  	}
   769  	return Type(tp), nil
   770  }
   771  
   772  func (l *State) Field(idx int, k string, msgHandler int) (Type, error) {
   773  	l.init()
   774  	if !l.CheckStack(3) { // gettable needs 2 additional stack slots
   775  		panic("stack overflow")
   776  	}
   777  	idx = l.AbsIndex(idx)
   778  	msgHandler = l.checkMessageHandler(msgHandler)
   779  	l.PushString(k)
   780  	var tp C.int
   781  	ret := C.gettable(l.ptr, C.int(idx), C.int(msgHandler), &tp)
   782  	if ret != C.LUA_OK {
   783  		return TypeNil, fmt.Errorf("lua: get field %q: %w", k, l.newError(ret))
   784  	}
   785  	return Type(tp), nil
   786  }
   787  
   788  func (l *State) RawGet(idx int) Type {
   789  	l.checkElems(1)
   790  	if !l.isAcceptableIndex(idx) {
   791  		panic("unacceptable index")
   792  	}
   793  	tp := Type(C.lua_rawget(l.ptr, C.int(idx)))
   794  	return tp
   795  }
   796  
   797  func (l *State) RawIndex(idx int, n int64) Type {
   798  	l.init()
   799  	if l.top >= l.cap {
   800  		panic("stack overflow")
   801  	}
   802  	if !l.isAcceptableIndex(idx) {
   803  		panic("unacceptable index")
   804  	}
   805  	tp := Type(C.lua_rawgeti(l.ptr, C.int(idx), C.lua_Integer(n)))
   806  	l.top++
   807  	return tp
   808  }
   809  
   810  func (l *State) RawField(idx int, k string) Type {
   811  	idx = l.AbsIndex(idx)
   812  	l.PushString(k)
   813  	return l.RawGet(idx)
   814  }
   815  
   816  func (l *State) CreateTable(nArr, nRec int) {
   817  	l.init()
   818  	if l.top >= l.cap {
   819  		panic("stack overflow")
   820  	}
   821  	C.lua_createtable(l.ptr, C.int(nArr), C.int(nRec))
   822  	l.top++
   823  }
   824  
   825  func (l *State) NewUserdataUV(size, nUValue int) {
   826  	l.init()
   827  	if l.top >= l.cap {
   828  		panic("stack overflow")
   829  	}
   830  	if size < 0 {
   831  		panic("negative userdata size")
   832  	}
   833  	C.newuserdata(l.ptr, C.size_t(size), C.int(nUValue))
   834  	l.top++
   835  }
   836  
   837  func (l *State) SetUserdata(idx int, start int, src []byte) {
   838  	if !l.isAcceptableIndex(idx) {
   839  		panic("unacceptable index")
   840  	}
   841  	l.setUserdata(idx, start, src)
   842  }
   843  
   844  func (l *State) setUserdata(idx int, start int, src []byte) {
   845  	if start < 0 {
   846  		panic("negative start")
   847  	}
   848  
   849  	size := int(C.userdatalen(l.ptr, C.int(idx)))
   850  	if start+len(src) > size {
   851  		panic("out of userdata bounds")
   852  	}
   853  	if len(src) == 0 {
   854  		return
   855  	}
   856  	dst := unsafe.Slice((*byte)(C.lua_touserdata(l.ptr, C.int(idx))), size)
   857  	copy(dst[start:], src)
   858  }
   859  
   860  func (l *State) Metatable(idx int) bool {
   861  	l.init()
   862  	if l.top >= l.cap {
   863  		panic("stack overflow")
   864  	}
   865  	if !l.isAcceptableIndex(idx) {
   866  		panic("unacceptable index")
   867  	}
   868  	return l.metatable(idx)
   869  }
   870  
   871  func (l *State) metatable(idx int) bool {
   872  	ok := C.lua_getmetatable(l.ptr, C.int(idx)) != 0
   873  	if ok {
   874  		l.top++
   875  	}
   876  	return ok
   877  }
   878  
   879  func (l *State) UserValue(idx int, n int) Type {
   880  	l.init()
   881  	if l.top >= l.cap {
   882  		panic("stack overflow")
   883  	}
   884  	if !l.isAcceptableIndex(idx) {
   885  		panic("unacceptable index")
   886  	}
   887  	tp := TypeNone
   888  	if n < 1 {
   889  		C.lua_pushnil(l.ptr)
   890  	} else {
   891  		tp = Type(C.lua_getiuservalue(l.ptr, C.int(idx), C.int(n)))
   892  	}
   893  	l.top++
   894  	return tp
   895  }
   896  
   897  func (l *State) SetGlobal(name string, msgHandler int) error {
   898  	l.checkElems(1)
   899  	if msgHandler != 0 {
   900  		msgHandler = l.AbsIndex(msgHandler)
   901  	}
   902  	l.RawIndex(RegistryIndex, RegistryIndexGlobals)
   903  	l.Rotate(-2, 1) // swap globals table with value
   904  	err := l.SetField(-2, name, msgHandler)
   905  	l.Pop(1) // remove the globals table
   906  	return err
   907  }
   908  
   909  func (l *State) SetTable(idx, msgHandler int) error {
   910  	l.checkElems(2)
   911  	if !l.CheckStack(2) { // settable needs 2 additional stack slots
   912  		panic("stack overflow")
   913  	}
   914  	if !l.isAcceptableIndex(idx) || msgHandler != 0 && !l.isAcceptableIndex(msgHandler) {
   915  		panic("unacceptable index")
   916  	}
   917  	ret := C.settable(l.ptr, C.int(idx), C.int(msgHandler))
   918  	if ret != C.LUA_OK {
   919  		l.top--
   920  		return fmt.Errorf("lua: set table field: %w", l.newError(ret))
   921  	}
   922  	l.top -= 2
   923  	return nil
   924  }
   925  
   926  func (l *State) SetField(idx int, k string, msgHandler int) error {
   927  	l.checkElems(1)
   928  	if !l.CheckStack(3) { // settable needs 2 additional stack slots
   929  		panic("stack overflow")
   930  	}
   931  
   932  	idx = l.AbsIndex(idx)
   933  	if msgHandler != 0 {
   934  		msgHandler = l.AbsIndex(msgHandler)
   935  	}
   936  
   937  	l.PushString(k)
   938  	l.Rotate(-2, 1)
   939  	ret := C.settable(l.ptr, C.int(idx), C.int(msgHandler))
   940  	if ret != C.LUA_OK {
   941  		l.top--
   942  		return fmt.Errorf("lua: set field %q: %w", k, l.newError(ret))
   943  	}
   944  	l.top -= 2
   945  	return nil
   946  }
   947  
   948  func (l *State) RawSet(idx int) {
   949  	l.checkElems(2)
   950  	if !l.isAcceptableIndex(idx) {
   951  		panic("unacceptable index")
   952  	}
   953  	C.lua_rawset(l.ptr, C.int(idx))
   954  	l.top -= 2
   955  }
   956  
   957  func (l *State) RawSetIndex(idx int, n int64) {
   958  	l.checkElems(1)
   959  	if !l.isAcceptableIndex(idx) {
   960  		panic("unacceptable index")
   961  	}
   962  	C.lua_rawseti(l.ptr, C.int(idx), C.lua_Integer(n))
   963  	l.top--
   964  }
   965  
   966  func (l *State) RawSetField(idx int, k string) {
   967  	idx = l.AbsIndex(idx)
   968  	l.PushString(k)
   969  	l.Rotate(-2, 1)
   970  	l.RawSet(idx)
   971  }
   972  
   973  func (l *State) SetMetatable(objIndex int) {
   974  	l.checkElems(1)
   975  	if !l.isAcceptableIndex(objIndex) {
   976  		panic("unacceptable index")
   977  	}
   978  	C.lua_setmetatable(l.ptr, C.int(objIndex))
   979  	l.top--
   980  }
   981  
   982  func (l *State) SetUserValue(idx int, n int) bool {
   983  	l.init()
   984  	if l.top >= l.cap {
   985  		panic("stack overflow")
   986  	}
   987  	if !l.isAcceptableIndex(idx) {
   988  		panic("unacceptable index")
   989  	}
   990  	if n < 1 {
   991  		l.Pop(1)
   992  		return false
   993  	}
   994  	ok := C.lua_setiuservalue(l.ptr, C.int(idx), C.int(n)) != 0
   995  	l.top--
   996  	return ok
   997  }
   998  
   999  func (l *State) Call(nArgs, nResults, msgHandler int) error {
  1000  	if nArgs < 0 {
  1001  		panic("negative arguments")
  1002  	}
  1003  	toPop := 1 + nArgs
  1004  	l.checkElems(toPop)
  1005  	newTop := -1
  1006  	if nResults != MultipleReturns {
  1007  		if nResults < 0 {
  1008  			panic("negative results")
  1009  		}
  1010  		newTop = l.top - toPop + nResults
  1011  		if newTop > l.cap {
  1012  			panic("stack overflow")
  1013  		}
  1014  	}
  1015  	msgHandler = l.checkMessageHandler(msgHandler)
  1016  
  1017  	ret := C.lua_pcallk(l.ptr, C.int(nArgs), C.int(nResults), C.int(msgHandler), 0, nil)
  1018  	if ret != C.LUA_OK {
  1019  		l.top -= toPop - 1
  1020  		return l.newError(ret)
  1021  	}
  1022  	if newTop >= 0 {
  1023  		l.top = newTop
  1024  	} else {
  1025  		l.top = int(C.lua_gettop(l.ptr))
  1026  		l.cap = max(l.cap, l.top)
  1027  	}
  1028  	return nil
  1029  }
  1030  
  1031  const MultipleReturns int = C.LUA_MULTRET
  1032  
  1033  func (l *State) Load(r io.Reader, chunkName string, mode string) error {
  1034  	l.init()
  1035  	if l.top >= l.cap {
  1036  		panic("stack overflow")
  1037  	}
  1038  
  1039  	modeC, err := loadMode(mode)
  1040  	if err != nil {
  1041  		l.PushString(err.Error())
  1042  		return fmt.Errorf("lua: load %s: %v", formatChunkName(chunkName), err)
  1043  	}
  1044  
  1045  	rr := newReader(r)
  1046  	defer rr.free()
  1047  	handle := cgo.NewHandle(rr)
  1048  	defer handle.Delete()
  1049  
  1050  	chunkNameC := C.CString(chunkName)
  1051  	defer C.free(unsafe.Pointer(chunkNameC))
  1052  
  1053  	ret := C.lua_load(l.ptr, C.lua_Reader(C.zombiezen_lua_reader), unsafe.Pointer(&handle), chunkNameC, modeC)
  1054  	l.top++
  1055  	if ret != C.LUA_OK {
  1056  		return fmt.Errorf("lua: load %s: %w", formatChunkName(chunkName), l.newError(ret))
  1057  	}
  1058  	return nil
  1059  }
  1060  
  1061  func (l *State) LoadString(s string, chunkName string, mode string) error {
  1062  	l.init()
  1063  	if l.top >= l.cap {
  1064  		panic("stack overflow")
  1065  	}
  1066  
  1067  	modeC, err := loadMode(mode)
  1068  	if err != nil {
  1069  		l.PushString(err.Error())
  1070  		return fmt.Errorf("lua: load %s: %v", formatChunkName(chunkName), err)
  1071  	}
  1072  
  1073  	chunkNameC := C.CString(chunkName)
  1074  	defer C.free(unsafe.Pointer(chunkNameC))
  1075  
  1076  	ret := C.loadstring(l.ptr, s, chunkNameC, modeC)
  1077  	l.top++
  1078  	if ret != C.LUA_OK {
  1079  		return fmt.Errorf("lua: load %s: %w", formatChunkName(chunkName), l.newError(ret))
  1080  	}
  1081  	return nil
  1082  }
  1083  
  1084  func formatChunkName(chunkName string) string {
  1085  	if len(chunkName) == 0 || (chunkName[0] != '@' && chunkName[0] != '=') {
  1086  		return "(string)"
  1087  	}
  1088  	return chunkName[1:]
  1089  }
  1090  
  1091  func loadMode(mode string) (*C.char, error) {
  1092  	const modeCStrings = "bt\x00t\x00b\x00"
  1093  	switch mode {
  1094  	case "bt":
  1095  		return (*C.char)(unsafe.Pointer(unsafe.StringData(modeCStrings))), nil
  1096  	case "t":
  1097  		return (*C.char)(unsafe.Pointer(unsafe.StringData(modeCStrings[3:]))), nil
  1098  	case "b":
  1099  		return (*C.char)(unsafe.Pointer(unsafe.StringData(modeCStrings[5:]))), nil
  1100  	default:
  1101  		return nil, fmt.Errorf("unknown load mode %q", mode)
  1102  	}
  1103  }
  1104  
  1105  func (l *State) Dump(w io.Writer, strip bool) (int64, error) {
  1106  	l.checkElems(1)
  1107  	state := &writerState{w: cgo.NewHandle(w)}
  1108  	defer state.w.Delete()
  1109  	stripInt := C.int(0)
  1110  	if strip {
  1111  		stripInt = 1
  1112  	}
  1113  	ret := C.lua_dump(l.ptr, C.lua_Writer(C.zombiezen_lua_writercb), unsafe.Pointer(state), stripInt)
  1114  	var err error
  1115  	switch {
  1116  	case state.err != 0:
  1117  		err = fmt.Errorf("lua: dump function: %w", state.err.Value().(error))
  1118  		state.err.Delete()
  1119  	case ret != 0:
  1120  		err = fmt.Errorf("lua: dump function: not a function")
  1121  	}
  1122  	return state.n, err
  1123  }
  1124  
  1125  func (l *State) GC() {
  1126  	l.init()
  1127  	C.gcniladic(l.ptr, C.LUA_GCCOLLECT)
  1128  }
  1129  
  1130  func (l *State) GCStop() {
  1131  	l.init()
  1132  	C.gcniladic(l.ptr, C.LUA_GCSTOP)
  1133  }
  1134  
  1135  func (l *State) GCRestart() {
  1136  	l.init()
  1137  	C.gcniladic(l.ptr, C.LUA_GCRESTART)
  1138  }
  1139  
  1140  func (l *State) GCCount() int64 {
  1141  	l.init()
  1142  	kb := int64(C.gcniladic(l.ptr, C.LUA_GCCOUNT))
  1143  	b := int64(C.gcniladic(l.ptr, C.LUA_GCCOUNTB))
  1144  	return kb<<10 | b
  1145  }
  1146  
  1147  func (l *State) GCStep(stepSize int) {
  1148  	l.init()
  1149  	C.gcstep(l.ptr, C.int(stepSize))
  1150  }
  1151  
  1152  func (l *State) IsGCRunning() bool {
  1153  	l.init()
  1154  	return C.gcniladic(l.ptr, C.LUA_GCISRUNNING) != 0
  1155  }
  1156  
  1157  func (l *State) GCIncremental(pause, stepMul, stepSize int) {
  1158  	l.init()
  1159  	C.gcinc(l.ptr, C.int(pause), C.int(stepMul), C.int(stepSize))
  1160  }
  1161  
  1162  func (l *State) GCGenerational(minorMul, majorMul int) {
  1163  	l.init()
  1164  	C.gcgen(l.ptr, C.int(minorMul), C.int(majorMul))
  1165  }
  1166  
  1167  func (l *State) Next(idx int) bool {
  1168  	l.checkElems(1)
  1169  	if !l.isAcceptableIndex(idx) {
  1170  		panic("unacceptable index")
  1171  	}
  1172  	ok := C.lua_next(l.ptr, C.int(idx)) != 0
  1173  	if ok {
  1174  		l.top++
  1175  	} else {
  1176  		l.top--
  1177  	}
  1178  	return ok
  1179  }
  1180  
  1181  func (l *State) Len(idx int, msgHandler int) error {
  1182  	l.init()
  1183  	idx = l.AbsIndex(idx)
  1184  	msgHandler = l.checkMessageHandler(msgHandler)
  1185  	C.pushlenfunction(l.ptr)
  1186  	l.top++
  1187  	l.PushValue(idx)
  1188  	if err := l.Call(1, 1, msgHandler); err != nil {
  1189  		return fmt.Errorf("lua: length: %w", err)
  1190  	}
  1191  	return nil
  1192  }
  1193  
  1194  func (l *State) Stack(level int) *ActivationRecord {
  1195  	l.init()
  1196  	ar := new(C.lua_Debug)
  1197  	if C.lua_getstack(l.ptr, C.int(level), ar) == 0 {
  1198  		return nil
  1199  	}
  1200  	return &ActivationRecord{
  1201  		state: l,
  1202  		lptr:  l.ptr,
  1203  		ar:    ar,
  1204  	}
  1205  }
  1206  
  1207  func (l *State) Info(what string) *Debug {
  1208  	l.checkElems(1)
  1209  
  1210  	what = strings.TrimPrefix(what, ">")
  1211  	cwhat := make([]C.char, 0, len(">\x00")+len(what))
  1212  	cwhat = append(cwhat, '>')
  1213  	for _, c := range []byte(what) {
  1214  		cwhat = append(cwhat, C.char(c))
  1215  	}
  1216  	cwhat = append(cwhat, 0)
  1217  
  1218  	var tmp C.lua_Debug
  1219  	return l.getinfo(&cwhat[0], &tmp)
  1220  }
  1221  
  1222  func (l *State) getinfo(what *C.char, ar *C.lua_Debug) *Debug {
  1223  	if *what == '>' {
  1224  		l.top--
  1225  	}
  1226  
  1227  	C.lua_getinfo(l.ptr, what, ar)
  1228  
  1229  	db := &Debug{
  1230  		CurrentLine: -1,
  1231  	}
  1232  	pushFunction := false
  1233  	pushLines := false
  1234  	for ; *what != 0; what = (*C.char)(unsafe.Add(unsafe.Pointer(what), 1)) {
  1235  		switch *what {
  1236  		case 'f':
  1237  			pushFunction = true
  1238  		case 'l':
  1239  			db.CurrentLine = int(ar.currentline)
  1240  		case 'n':
  1241  			if ar.name != nil {
  1242  				db.Name = C.GoString(ar.name)
  1243  			}
  1244  			if ar.namewhat != nil {
  1245  				db.NameWhat = C.GoString(ar.namewhat)
  1246  			}
  1247  		case 'S':
  1248  			if ar.what != nil {
  1249  				db.What = C.GoString(ar.what)
  1250  			}
  1251  			if ar.source != nil {
  1252  				db.Source = C.GoStringN(ar.source, C.int(ar.srclen))
  1253  			}
  1254  			db.LineDefined = int(ar.linedefined)
  1255  			db.LastLineDefined = int(ar.lastlinedefined)
  1256  			db.ShortSource = C.GoString(&ar.short_src[0])
  1257  		case 't':
  1258  			db.IsTailCall = ar.istailcall != 0
  1259  		case 'u':
  1260  			db.NumUpvalues = uint8(ar.nups)
  1261  			db.NumParams = uint8(ar.nparams)
  1262  			db.IsVararg = ar.isvararg != 0
  1263  		case 'L':
  1264  			pushLines = true
  1265  		}
  1266  	}
  1267  	if pushFunction {
  1268  		l.top++
  1269  	}
  1270  	if pushLines {
  1271  		l.top++
  1272  	}
  1273  	return db
  1274  }
  1275  
  1276  type Debug struct {
  1277  	Name            string
  1278  	NameWhat        string
  1279  	What            string
  1280  	Source          string
  1281  	ShortSource     string
  1282  	CurrentLine     int
  1283  	LineDefined     int
  1284  	LastLineDefined int
  1285  	NumUpvalues     uint8
  1286  	NumParams       uint8
  1287  	IsVararg        bool
  1288  	IsTailCall      bool
  1289  }
  1290  
  1291  type ActivationRecord struct {
  1292  	state *State
  1293  	lptr  *C.lua_State
  1294  	ar    *C.lua_Debug
  1295  }
  1296  
  1297  func (ar *ActivationRecord) isValid() bool {
  1298  	return ar != nil && ar.state != nil && ar.state.ptr == ar.lptr
  1299  }
  1300  
  1301  func (ar *ActivationRecord) Info(what string) *Debug {
  1302  	if strings.HasPrefix(what, ">") {
  1303  		panic("what must not start with '>'")
  1304  	}
  1305  	if !ar.isValid() {
  1306  		return nil
  1307  	}
  1308  	cwhat := C.CString(what)
  1309  	defer C.free(unsafe.Pointer(cwhat))
  1310  	return ar.state.getinfo(cwhat, ar.ar)
  1311  }
  1312  
  1313  const (
  1314  	GName = C.LUA_GNAME
  1315  
  1316  	CoroutineLibraryName = C.LUA_COLIBNAME
  1317  	TableLibraryName     = C.LUA_TABLIBNAME
  1318  	IOLibraryName        = C.LUA_IOLIBNAME
  1319  	OSLibraryName        = C.LUA_OSLIBNAME
  1320  	StringLibraryName    = C.LUA_STRLIBNAME
  1321  	UTF8LibraryName      = C.LUA_UTF8LIBNAME
  1322  	MathLibraryName      = C.LUA_MATHLIBNAME
  1323  	DebugLibraryName     = C.LUA_DBLIBNAME
  1324  	PackageLibraryName   = C.LUA_LOADLIBNAME
  1325  )
  1326  
  1327  func PushOpenBase(l *State) {
  1328  	l.init()
  1329  	if l.top >= l.cap {
  1330  		panic("stack overflow")
  1331  	}
  1332  	C.lua_pushcclosure(l.ptr, C.lua_CFunction(C.luaopen_base), 0)
  1333  	l.top++
  1334  }
  1335  
  1336  func PushOpenCoroutine(l *State) {
  1337  	l.init()
  1338  	if l.top >= l.cap {
  1339  		panic("stack overflow")
  1340  	}
  1341  	C.lua_pushcclosure(l.ptr, C.lua_CFunction(C.luaopen_coroutine), 0)
  1342  	l.top++
  1343  }
  1344  
  1345  func PushOpenTable(l *State) {
  1346  	l.init()
  1347  	if l.top >= l.cap {
  1348  		panic("stack overflow")
  1349  	}
  1350  	C.lua_pushcclosure(l.ptr, C.lua_CFunction(C.luaopen_table), 0)
  1351  	l.top++
  1352  }
  1353  
  1354  func PushOpenString(l *State) {
  1355  	l.init()
  1356  	if l.top >= l.cap {
  1357  		panic("stack overflow")
  1358  	}
  1359  	C.lua_pushcclosure(l.ptr, C.lua_CFunction(C.luaopen_string), 0)
  1360  	l.top++
  1361  }
  1362  
  1363  func PushOpenUTF8(l *State) {
  1364  	l.init()
  1365  	if l.top >= l.cap {
  1366  		panic("stack overflow")
  1367  	}
  1368  	C.lua_pushcclosure(l.ptr, C.lua_CFunction(C.luaopen_utf8), 0)
  1369  	l.top++
  1370  }
  1371  
  1372  func PushOpenMath(l *State) {
  1373  	l.init()
  1374  	if l.top >= l.cap {
  1375  		panic("stack overflow")
  1376  	}
  1377  	C.lua_pushcclosure(l.ptr, C.lua_CFunction(C.luaopen_math), 0)
  1378  	l.top++
  1379  }
  1380  
  1381  func PushOpenDebug(l *State) {
  1382  	l.init()
  1383  	if l.top >= l.cap {
  1384  		panic("stack overflow")
  1385  	}
  1386  	C.lua_pushcclosure(l.ptr, C.lua_CFunction(C.luaopen_debug), 0)
  1387  	l.top++
  1388  }
  1389  
  1390  func PushOpenPackage(l *State) {
  1391  	l.init()
  1392  	if l.top >= l.cap {
  1393  		panic("stack overflow")
  1394  	}
  1395  	C.lua_pushcclosure(l.ptr, C.lua_CFunction(C.luaopen_package), 0)
  1396  	l.top++
  1397  }
  1398  
  1399  const readerBufferSize = 4096
  1400  
  1401  type reader struct {
  1402  	r   io.Reader
  1403  	buf *C.char
  1404  }
  1405  
  1406  func newReader(r io.Reader) *reader {
  1407  	return &reader{
  1408  		r:   r,
  1409  		buf: (*C.char)(C.calloc(readerBufferSize, C.size_t(unsafe.Sizeof(C.char(0))))),
  1410  	}
  1411  }
  1412  
  1413  func (r *reader) free() {
  1414  	if r.buf != nil {
  1415  		C.free(unsafe.Pointer(r.buf))
  1416  		r.buf = nil
  1417  	}
  1418  }
  1419  
  1420  func copyUint64(l *State, idx int) uint64 {
  1421  	var buf [8]byte
  1422  	l.copyUserdata(buf[:], idx, 0)
  1423  	var x uint64
  1424  	for i, b := range buf {
  1425  		x |= uint64(b) << (i * 8)
  1426  	}
  1427  	return x
  1428  }
  1429  
  1430  func setUint64(l *State, idx int, x uint64) {
  1431  	var buf [8]byte
  1432  	for i := range buf {
  1433  		buf[i] = byte(x >> (i * 8))
  1434  	}
  1435  	l.setUserdata(idx, 0, buf[:])
  1436  }
  1437  
  1438  // NewMetatable is the auxlib NewMetatable function.
  1439  func NewMetatable(l *State, tname string) bool {
  1440  	if Metatable(l, tname) != TypeNil {
  1441  		// Name already in use.
  1442  		return false
  1443  	}
  1444  	l.Pop(1)
  1445  	l.CreateTable(0, 2)
  1446  	l.PushString(tname)
  1447  	l.RawSetField(-2, "__name") // metatable.__name = tname
  1448  	l.PushValue(-1)
  1449  	l.RawSetField(RegistryIndex, tname)
  1450  	return true
  1451  }
  1452  
  1453  // Metatable is the auxlib Metatable function.
  1454  func Metatable(l *State, tname string) Type {
  1455  	return l.RawField(RegistryIndex, tname)
  1456  }
  1457  
  1458  func isPseudo(i int) bool {
  1459  	return i <= RegistryIndex
  1460  }
  1461  
  1462  const goClosureUpvalueIndex = C.LUA_REGISTRYINDEX - 1
  1463  
  1464  func UpvalueIndex(i int) int {
  1465  	if i < 1 || i > 255 {
  1466  		panic("invalid upvalue index")
  1467  	}
  1468  	return C.LUA_REGISTRYINDEX - (i + 1)
  1469  }
  1470  
  1471  type luaError struct {
  1472  	code C.int
  1473  	msg  string
  1474  }
  1475  
  1476  func (l *State) newError(code C.int) error {
  1477  	e := &luaError{code: code}
  1478  	e.msg, _ = l.ToString(-1)
  1479  	return e
  1480  }
  1481  
  1482  func (e *luaError) Error() string {
  1483  	if e.msg != "" {
  1484  		return e.msg
  1485  	}
  1486  	switch e.code {
  1487  	case C.LUA_ERRRUN:
  1488  		return "runtime error"
  1489  	case C.LUA_ERRMEM:
  1490  		return "memory allocation error"
  1491  	case C.LUA_ERRERR:
  1492  		return "error while running message handler"
  1493  	case C.LUA_ERRSYNTAX:
  1494  		return "syntax error"
  1495  	case C.LUA_YIELD:
  1496  		return "coroutine yield"
  1497  	default:
  1498  		return "unknown error"
  1499  	}
  1500  }
  1501  
  1502  const (
  1503  	ErrRun    int = C.LUA_ERRRUN
  1504  	ErrMem    int = C.LUA_ERRMEM
  1505  	ErrErr    int = C.LUA_ERRERR
  1506  	ErrSyntax int = C.LUA_ERRSYNTAX
  1507  	Yield     int = C.LUA_YIELD
  1508  )
  1509  
  1510  func AsError(err error) (code int, ok bool) {
  1511  	if err == nil {
  1512  		return C.LUA_OK, true
  1513  	}
  1514  	var e *luaError
  1515  	if !errors.As(err, &e) {
  1516  		return 0, false
  1517  	}
  1518  	return int(e.code), true
  1519  }