├── vendor └── github.com │ ├── aarzilli │ └── golua │ │ ├── TODO │ │ ├── LICENSE │ │ ├── lua │ │ ├── lua │ │ │ ├── lualib.h │ │ │ ├── lauxlib.h │ │ │ ├── lua.h │ │ │ └── luaconf.h │ │ ├── golua.h │ │ ├── lua_defs.go │ │ ├── lauxlib.go │ │ ├── golua.go │ │ ├── lua_test.go │ │ ├── c-golua.c │ │ └── lua.go │ │ └── README.md │ └── stevedonovan │ └── luar │ ├── LICENSE │ ├── doc.go │ ├── README.md │ ├── bench_test.go │ ├── proxyfuncs.go │ ├── proxy.go │ ├── example_test.go │ ├── luaobject.go │ └── proxymm.go ├── luac ├── test.lua └── main.go ├── go-lua ├── test.lua └── main.go ├── gopher-lua ├── test.lua └── main.go ├── luar ├── test.lua └── main.go └── README.md /vendor/github.com/aarzilli/golua/TODO: -------------------------------------------------------------------------------- 1 | - find all calls to lua api that can result in lua_error calls and rework them (for example checkarg stuff) 2 | - lua.go: Dump implementing lua_dump 3 | - lua.go: Load implementing lua_load 4 | - AtPanic slightly broken when nil is passed, if we think passing nil has value to extract the current atpanic function we should also make sure it doesn't break everything 5 | - threads implementation is probably fucked completely should look into it 6 | - lauxlib.go:CheckOption is not implemented -------------------------------------------------------------------------------- /luac/test.lua: -------------------------------------------------------------------------------- 1 | ---- LUAC TEST FILE ----- 2 | 3 | GLOBAL_VAR = "this is a global var" 4 | 5 | function test_go_string(fn, val) 6 | local str = fn(val) 7 | print("Type: " .. str) 8 | end 9 | 10 | function square(m) 11 | return m^2 12 | end 13 | 14 | function account_test() 15 | local acc = Account.create(1000) 16 | acc:withdrawl(100) 17 | print(acc) 18 | print(acc:__tostring()) 19 | print(acc:balance()) 20 | print(Account.balance(acc)) 21 | 22 | local acc2 = Account.create(900) 23 | print(acc2 == acc) 24 | end 25 | 26 | -------------------------------------------------------------------------------- /go-lua/test.lua: -------------------------------------------------------------------------------- 1 | ---- go-lua TEST FILE ----- 2 | 3 | GLOBAL_VAR = "this is a global var" 4 | 5 | function test_go_string(fn, val) 6 | local str = fn(val) 7 | print("Type: " .. str) 8 | end 9 | 10 | function square(m) 11 | return m^2 12 | end 13 | 14 | function account_test() 15 | local acc = Account.create(1000) 16 | 17 | print(acc) 18 | 19 | acc:withdrawl(100) 20 | print(acc:__tostring()) 21 | print(acc:balance()) 22 | print(Account.balance(acc)) 23 | 24 | local acc2 = Account.create(900) 25 | print(acc2 == acc) 26 | end 27 | 28 | -------------------------------------------------------------------------------- /gopher-lua/test.lua: -------------------------------------------------------------------------------- 1 | ---- go-lua TEST FILE ----- 2 | 3 | GLOBAL_VAR = "this is a global var" 4 | 5 | function test_go_string(fn, val) 6 | local str = fn(val) 7 | print("Type: " .. str) 8 | end 9 | 10 | function square(m) 11 | return m^2 12 | end 13 | 14 | function account_test() 15 | local acc = Account.create(1000) 16 | 17 | print(acc) 18 | 19 | acc:withdrawl(100) 20 | print(acc:__tostring()) 21 | print(acc:balance()) 22 | print(Account.balance(acc)) 23 | 24 | local acc2 = Account.create(900) 25 | print(acc2 == acc) 26 | end 27 | 28 | -------------------------------------------------------------------------------- /luar/test.lua: -------------------------------------------------------------------------------- 1 | ---- LUAR TEST FILE ----- 2 | 3 | function pretty_json(val) 4 | -- call a global function defined that prints pretty json -- 5 | local str = json.pretty(val) 6 | print("pretty json:\n" .. str) 7 | end 8 | 9 | function member_test() 10 | local p = person.new("rick") 11 | pretty_json(p) 12 | print(p) 13 | print("-----") 14 | print(p:Name()) 15 | print("-----") 16 | print(p.Name()) 17 | 18 | end 19 | 20 | function test_struct(obj) 21 | print(obj.test()) 22 | print(obj:test()) 23 | print(obj.rick) 24 | print(obj['rick']) 25 | print(obj) 26 | print(obj.name) 27 | print(obj['name']) 28 | 29 | obj:add("1") 30 | obj:add("2") 31 | 32 | end 33 | -------------------------------------------------------------------------------- /vendor/github.com/stevedonovan/luar/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010-2016 Steve Donovan 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all 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, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /vendor/github.com/aarzilli/golua/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2010 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /vendor/github.com/aarzilli/golua/lua/lua/lualib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Lua standard libraries 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #ifndef lualib_h 9 | #define lualib_h 10 | 11 | #include "lua.h" 12 | 13 | 14 | /* Key to file-handle type */ 15 | #define LUA_FILEHANDLE "FILE*" 16 | 17 | 18 | #define LUA_COLIBNAME "coroutine" 19 | LUALIB_API int (luaopen_base) (lua_State *L); 20 | 21 | #define LUA_TABLIBNAME "table" 22 | LUALIB_API int (luaopen_table) (lua_State *L); 23 | 24 | #define LUA_IOLIBNAME "io" 25 | LUALIB_API int (luaopen_io) (lua_State *L); 26 | 27 | #define LUA_OSLIBNAME "os" 28 | LUALIB_API int (luaopen_os) (lua_State *L); 29 | 30 | #define LUA_STRLIBNAME "string" 31 | LUALIB_API int (luaopen_string) (lua_State *L); 32 | 33 | #define LUA_MATHLIBNAME "math" 34 | LUALIB_API int (luaopen_math) (lua_State *L); 35 | 36 | #define LUA_DBLIBNAME "debug" 37 | LUALIB_API int (luaopen_debug) (lua_State *L); 38 | 39 | #define LUA_LOADLIBNAME "package" 40 | LUALIB_API int (luaopen_package) (lua_State *L); 41 | 42 | 43 | /* open all previous libraries */ 44 | LUALIB_API void (luaL_openlibs) (lua_State *L); 45 | 46 | 47 | 48 | #ifndef lua_assert 49 | #define lua_assert(x) ((void)0) 50 | #endif 51 | 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /vendor/github.com/aarzilli/golua/lua/golua.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct { void *t; void *v; } GoInterface; 4 | 5 | #define GOLUA_DEFAULT_MSGHANDLER "golua_default_msghandler" 6 | 7 | /* function to setup metatables, etc */ 8 | void clua_initstate(lua_State* L); 9 | void clua_hide_pcall(lua_State *L); 10 | 11 | unsigned int clua_togofunction(lua_State* L, int index); 12 | unsigned int clua_togostruct(lua_State *L, int index); 13 | void clua_pushcallback(lua_State* L); 14 | void clua_pushgofunction(lua_State* L, unsigned int fid); 15 | void clua_pushgostruct(lua_State *L, unsigned int fid); 16 | void clua_setgostate(lua_State* L, size_t gostateindex); 17 | size_t clua_getgostate(lua_State* L); 18 | GoInterface clua_atpanic(lua_State* L, unsigned int panicf_id); 19 | int clua_callluacfunc(lua_State* L, lua_CFunction f); 20 | lua_State* clua_newstate(void* goallocf); 21 | void clua_setallocf(lua_State* L, void* goallocf); 22 | 23 | void clua_openbase(lua_State* L); 24 | void clua_openio(lua_State* L); 25 | void clua_openmath(lua_State* L); 26 | void clua_openpackage(lua_State* L); 27 | void clua_openstring(lua_State* L); 28 | void clua_opentable(lua_State* L); 29 | void clua_openos(lua_State* L); 30 | void clua_setexecutionlimit(lua_State* L, int n); 31 | 32 | int clua_isgofunction(lua_State *L, int n); 33 | int clua_isgostruct(lua_State *L, int n); 34 | 35 | -------------------------------------------------------------------------------- /vendor/github.com/aarzilli/golua/lua/lua_defs.go: -------------------------------------------------------------------------------- 1 | package lua 2 | 3 | /* 4 | #include 5 | #include 6 | #include 7 | 8 | */ 9 | import "C" 10 | 11 | type LuaValType int 12 | 13 | const ( 14 | LUA_TNIL = LuaValType(C.LUA_TNIL) 15 | LUA_TNUMBER = LuaValType(C.LUA_TNUMBER) 16 | LUA_TBOOLEAN = LuaValType(C.LUA_TBOOLEAN) 17 | LUA_TSTRING = LuaValType(C.LUA_TSTRING) 18 | LUA_TTABLE = LuaValType(C.LUA_TTABLE) 19 | LUA_TFUNCTION = LuaValType(C.LUA_TFUNCTION) 20 | LUA_TUSERDATA = LuaValType(C.LUA_TUSERDATA) 21 | LUA_TTHREAD = LuaValType(C.LUA_TTHREAD) 22 | LUA_TLIGHTUSERDATA = LuaValType(C.LUA_TLIGHTUSERDATA) 23 | ) 24 | 25 | const ( 26 | LUA_VERSION = C.LUA_VERSION 27 | LUA_RELEASE = C.LUA_RELEASE 28 | LUA_VERSION_NUM = C.LUA_VERSION_NUM 29 | LUA_COPYRIGHT = C.LUA_COPYRIGHT 30 | LUA_AUTHORS = C.LUA_AUTHORS 31 | LUA_MULTRET = C.LUA_MULTRET 32 | LUA_REGISTRYINDEX = C.LUA_REGISTRYINDEX 33 | LUA_ENVIRONINDEX = C.LUA_ENVIRONINDEX 34 | LUA_GLOBALSINDEX = C.LUA_GLOBALSINDEX 35 | LUA_YIELD = C.LUA_YIELD 36 | LUA_ERRRUN = C.LUA_ERRRUN 37 | LUA_ERRSYNTAX = C.LUA_ERRSYNTAX 38 | LUA_ERRMEM = C.LUA_ERRMEM 39 | LUA_ERRERR = C.LUA_ERRERR 40 | LUA_TNONE = C.LUA_TNONE 41 | LUA_MINSTACK = C.LUA_MINSTACK 42 | LUA_GCSTOP = C.LUA_GCSTOP 43 | LUA_GCRESTART = C.LUA_GCRESTART 44 | LUA_GCCOLLECT = C.LUA_GCCOLLECT 45 | LUA_GCCOUNT = C.LUA_GCCOUNT 46 | LUA_GCCOUNTB = C.LUA_GCCOUNTB 47 | LUA_GCSTEP = C.LUA_GCSTEP 48 | LUA_GCSETPAUSE = C.LUA_GCSETPAUSE 49 | LUA_GCSETSTEPMUL = C.LUA_GCSETSTEPMUL 50 | LUA_HOOKCALL = C.LUA_HOOKCALL 51 | LUA_HOOKRET = C.LUA_HOOKRET 52 | LUA_HOOKLINE = C.LUA_HOOKLINE 53 | LUA_HOOKCOUNT = C.LUA_HOOKCOUNT 54 | LUA_HOOKTAILRET = C.LUA_HOOKTAILRET 55 | LUA_MASKCALL = C.LUA_MASKCALL 56 | LUA_MASKRET = C.LUA_MASKRET 57 | LUA_MASKLINE = C.LUA_MASKLINE 58 | LUA_MASKCOUNT = C.LUA_MASKCOUNT 59 | LUA_ERRFILE = C.LUA_ERRFILE 60 | LUA_NOREF = C.LUA_NOREF 61 | LUA_REFNIL = C.LUA_REFNIL 62 | LUA_FILEHANDLE = C.LUA_FILEHANDLE 63 | LUA_COLIBNAME = C.LUA_COLIBNAME 64 | LUA_TABLIBNAME = C.LUA_TABLIBNAME 65 | LUA_IOLIBNAME = C.LUA_IOLIBNAME 66 | LUA_OSLIBNAME = C.LUA_OSLIBNAME 67 | LUA_STRLIBNAME = C.LUA_STRLIBNAME 68 | LUA_MATHLIBNAME = C.LUA_MATHLIBNAME 69 | LUA_DBLIBNAME = C.LUA_DBLIBNAME 70 | LUA_LOADLIBNAME = C.LUA_LOADLIBNAME 71 | ) 72 | -------------------------------------------------------------------------------- /vendor/github.com/stevedonovan/luar/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Package luar provides a convenient interface between Lua and Go. 3 | 4 | It uses Alessandro Arzilli's golua (https://github.com/aarzilli/golua). 5 | 6 | Most Go values can be passed to Lua: basic types, strings, complex numbers, 7 | user-defined types, pointers, composite types, functions, channels, etc. 8 | Conversely, most Lua values can be converted to Go values. 9 | 10 | Composite types are processed recursively. 11 | 12 | Methods can be called on user-defined types. These methods will be callable 13 | using _dot-notation_ rather than colon notation. 14 | 15 | Arrays, slices, maps and structs can be copied as tables, or alternatively 16 | passed over as Lua proxy objects which can be naturally indexed. 17 | 18 | In the case of structs and string maps, fields have priority over methods. Use 19 | 'luar.method(, )(...)' to call shadowed methods. 20 | 21 | Unexported struct fields are ignored. The "lua" tag is used to match fields in 22 | struct conversion. 23 | 24 | You may pass a Lua table to an imported Go function; if the table is 25 | 'array-like' then it is converted to a Go slice; if it is 'map-like' then it 26 | is converted to a Go map. 27 | 28 | Pointer values encode as the value pointed to when unproxified. 29 | 30 | Usual operators (arithmetic, string concatenation, pairs/ipairs, etc.) work on 31 | proxies too. The type of the result depends on the type of the operands. The 32 | rules are as follows: 33 | 34 | - If the operands are of the same type, use this type. 35 | 36 | - If one type is a Lua number, use the other, user-defined type. 37 | 38 | - If the types are different and not Lua numbers, convert to a complex proxy, a 39 | Lua number, or a Lua string according to the result kind. 40 | 41 | 42 | Channels 43 | 44 | Channel proxies can be manipulated with the following methods: 45 | 46 | - close(): Close the channel. 47 | 48 | - recv() value: Fetch and return a value from the channel. 49 | 50 | - send(x value): Send a value in the channel. 51 | 52 | 53 | Complex numbers 54 | 55 | Complex proxies can be manipulated with the following attributes: 56 | 57 | - real: The real part. 58 | 59 | - imag: The imaginary part. 60 | 61 | 62 | Slices 63 | 64 | Slice proxies can be manipulated with the following methods/attributes: 65 | 66 | - append(x ...value) sliceProxy: Append the elements and return the new 67 | slice. The elements must be convertible to the slice element type. 68 | 69 | - cap: The capacity of the slice. 70 | 71 | - slice(i, j integer) sliceProxy: Return the sub-slice that ranges from 'i' to 'j' 72 | excluded, starting from 1. 73 | 74 | 75 | Strings 76 | 77 | String proxies can be browsed rune by rune with the pairs/ipairs functions. 78 | These runes are encoded as strings in Lua. 79 | 80 | Indexing a string proxy (starting from 1) will return the corresponding byte as 81 | a Lua string. 82 | 83 | String proxies can be manipulated with the following method: 84 | 85 | - slice(i, j integer) sliceProxy: Return the sub-string that ranges from 'i' to 'j' 86 | excluded, starting from 1. 87 | 88 | */ 89 | package luar 90 | -------------------------------------------------------------------------------- /vendor/github.com/stevedonovan/luar/README.md: -------------------------------------------------------------------------------- 1 | # Luar: Lua reflection bindings for Go 2 | 3 | Luar is designed to make using Lua from Go more convenient. Go structs, slices 4 | and maps can be automatically converted to Lua tables and vice-versa. The 5 | resulting conversion can either be a copy or a proxy. In the latter case, any change 6 | made to the result will reflect on the source. 7 | 8 | Any Go function can be made available to Lua scripts, without having to write 9 | C-style wrappers. 10 | 11 | Luar support cyclic structures (`map[string]interface{}`, lists, etc.). 12 | 13 | User-defined types can be made available to Lua as well: their exported methods 14 | can be called and usual operations such as indexing or arithmetic can be 15 | performed. 16 | 17 | See the [documentation](http://godoc.org/github.com/stevedonovan/luar) for usage 18 | instructions and examples. 19 | 20 | # Installation 21 | 22 | Install with 23 | 24 | go get /luar 25 | 26 | Luar uses Alessandro Arzilli's [golua](https://github.com/aarzilli/golua). 27 | See golua's homepage for further installation details. 28 | 29 | # REPL 30 | 31 | An example REPL is available in the `cmd` folder. 32 | 33 | 34 | # Version 2 35 | 36 | This is a rewrite of 1.0 with extended features and a cleaner API. 37 | 38 | Warning: This is a development version, the API might change in the future. 39 | 40 | ## Compatibility notice 41 | 42 | The main differences with the previous version: 43 | 44 | - The function prototypes of `GoToLua` and `LuaToGo` are simpler and do not 45 | require the use of reflection from the callers. The `dontproxify` argument is 46 | gone, use `GoToLuaProxy` to control proxification. 47 | 48 | - The `Copy*` functions and `GoLuaFunc` are gone, use `GoToLua` and `LuaToGo` instead. 49 | 50 | - Use `Register` instead of `RawRegister`. 51 | 52 | - `InitProxies` is gone since it was not needed. 53 | 54 | - The `LuaObject` and `LuaTableIter` structure fields are unexported. 55 | 56 | - LuaObject methods not only work on Lua functions but also on anything with a 57 | `__call` metamethods. Idem for tables and the `__index`/`__newindex` 58 | metamethods. 59 | 60 | - Use `NewLuaObjectFromName(L, "_G")` instead of `Global`. 61 | 62 | - `Lookup` and `Geti` gone. Instead the `Get` and `GetObject` functions are 63 | variadic: each subfield argument can be any valid Lua key (string, integer...). 64 | 65 | - Use `(*LuaObject) Call` instead of `(*LuaObject) Callf`. The protoype of 66 | `(*LuaObject) Call` has changed in a fashion similar to `GoToLua` and `LuaToGo`. 67 | `Types` is gone as it is no longer needed. 68 | 69 | - Register `ProxyIpairs` and `ProxyPairs` instead of calling `LuarSetup`. 70 | 71 | - Register and use `Unproxify` instead of `ArrayToTable`, `MapToTable`, 72 | `ProxyRaw`, `SliceToTable` and `StructToTable`. 73 | 74 | - `ComplexReal` and `ComplexImag` have been replaced by the proxy attributes 75 | `real` and `imag`, respectively. 76 | 77 | - `SliceSub` and `SliceAppend` have been replaced by the proxy methods 78 | `slice` and `append`, respectively. 79 | Slice proxies have the `cap` metamethod alongside `append` and `slice`. 80 | 81 | - String proxies have a `slice` method just like slice proxies. They can be 82 | looped rune-by-rune over with `ipairs`. 83 | 84 | The range of supported conversion has been extended: 85 | 86 | - LuaToGo can convert to interfaces and pointers with several levels of indirection. 87 | 88 | - LuaToGo can convert to non-empty maps and structs. 89 | -------------------------------------------------------------------------------- /luar/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "log" 7 | 8 | "github.com/aarzilli/golua/lua" 9 | "github.com/stevedonovan/luar" 10 | ) 11 | 12 | type Person struct { 13 | Name string `lua:"name"` 14 | } 15 | 16 | func (p *Person) F1(L *lua.State) int { 17 | val := L.ToString(-1) 18 | p.Name = val 19 | 20 | return 0 21 | } 22 | 23 | func (p *Person) F2(L *lua.State) int { 24 | L.PushString(p.Name) 25 | 26 | return 1 27 | } 28 | 29 | func (p Person) String() string { 30 | return fmt.Sprintf("Person{Name: %s}", p.Name) 31 | } 32 | 33 | func prettyJson(L *lua.State) { 34 | // load our global function to the stack 35 | L.GetGlobal("pretty_json") 36 | // add a struct to the stack 37 | luar.GoToLua(L, struct{ Name, Value string }{Name: "Rick", Value: "TEST"}) 38 | // call our function 39 | L.Call(1, 0) 40 | } 41 | 42 | func memberTest(L *lua.State) { 43 | L.GetGlobal("member_test") 44 | L.Call(0, 0) 45 | } 46 | 47 | func addFunc(L *lua.State, key string, f func(*lua.State) int) { 48 | L.PushString(key) 49 | L.PushGoFunction(f) 50 | L.SetTable(-3) 51 | } 52 | 53 | func addString(L *lua.State, key, val string) { 54 | L.PushString(key) 55 | L.PushString(val) 56 | L.SetTable(-3) 57 | } 58 | 59 | func runStructTest(L *lua.State) { 60 | L.GetGlobal("test_struct") 61 | L.CreateTable(1, 0) 62 | // L.PushString("__index") 63 | // L.PushValue(-2) 64 | // L.SetTable(-3) 65 | 66 | addFunc(L, "test", func(L *lua.State) int { 67 | L.PushString("Asdf") 68 | return 1 69 | }) 70 | 71 | addString(L, "rick", "test") 72 | if err := L.Call(1, 0); err != nil { 73 | log.Println(err) 74 | } 75 | } 76 | 77 | func runStructTest2(L *lua.State) { 78 | L.GetGlobal("test_struct") 79 | person := &Person{"RICK"} 80 | luar.GoToLua(L, person) 81 | 82 | addFunc(L, "test", func(L *lua.State) int { 83 | L.PushString("Asdf") 84 | return 1 85 | }) 86 | 87 | str := []string{} 88 | 89 | addFunc(L, "add", func(L *lua.State) int { 90 | str = append(str, L.ToString(-1)) 91 | return 0 92 | }) 93 | 94 | if err := L.Call(1, 0); err != nil { 95 | log.Println(err) 96 | } 97 | 98 | fmt.Printf("%#v\n", str) 99 | } 100 | 101 | func runLuar(filename string) { 102 | log.Println("Running LUAC with LuaR bindings") 103 | 104 | L := lua.NewState() 105 | defer L.Close() 106 | L.OpenLibs() 107 | 108 | L.DoFile(filename) 109 | 110 | // // enable unicode otherwise things like string count will be invalid with multi-byte chars 111 | // unicode.GoLuaReplaceFuncs(L) 112 | 113 | // // setup constants and functions 114 | // luar.Register(L, "", luar.Map{ 115 | // // default functions 116 | // "ipairs": luar.ProxyIpairs, 117 | // "pairs": luar.ProxyPairs, 118 | // "type": luar.ProxyType, 119 | // }) 120 | 121 | // JSON pretty function... 122 | luar.Register(L, "json", luar.Map{ 123 | "pretty": func(value interface{}) (string, error) { 124 | data, err := json.MarshalIndent(value, "", "\t") 125 | return string(data), err 126 | }, 127 | }) 128 | 129 | luar.Register(L, "person", luar.Map{ 130 | "new": func(name string) *Person { 131 | return &Person{Name: name} 132 | }, 133 | }) 134 | 135 | // prettyJson(L) 136 | // memberTest(L) 137 | 138 | fmt.Println("--------------------") 139 | runStructTest(L) 140 | runStructTest2(L) 141 | 142 | fmt.Printf("top: %d\n", L.GetTop()) 143 | 144 | } 145 | 146 | func main() { 147 | runLuar("test.lua") 148 | } 149 | -------------------------------------------------------------------------------- /vendor/github.com/stevedonovan/luar/bench_test.go: -------------------------------------------------------------------------------- 1 | package luar 2 | 3 | // TODO: v2 seems to be somewhat slower than v1. Profile and optimize. 4 | 5 | import ( 6 | "fmt" 7 | "testing" 8 | ) 9 | 10 | func BenchmarkLuaToGoSliceInt(b *testing.B) { 11 | L := Init() 12 | defer L.Close() 13 | 14 | var output []interface{} 15 | L.DoString(`t={}; for i = 1,100 do t[i]=i; end`) 16 | L.GetGlobal("t") 17 | b.ResetTimer() 18 | for n := 0; n < b.N; n++ { 19 | LuaToGo(L, -1, &output) 20 | } 21 | } 22 | 23 | func BenchmarkLuaToGoSliceMap(b *testing.B) { 24 | L := Init() 25 | defer L.Close() 26 | 27 | var output []interface{} 28 | L.DoString(`t={}; s={17}; for i = 1,100 do t[i]=s; end`) 29 | L.GetGlobal("t") 30 | b.ResetTimer() 31 | for n := 0; n < b.N; n++ { 32 | LuaToGo(L, -1, &output) 33 | } 34 | } 35 | 36 | func BenchmarkLuaToGoSliceMapUnique(b *testing.B) { 37 | L := Init() 38 | defer L.Close() 39 | 40 | var output []interface{} 41 | L.DoString(`t={}`) 42 | for i := 0; i < 100; i++ { 43 | L.DoString(fmt.Sprintf(`s%[1]d={17}; t[%[1]d]=s%[1]d`, i)) 44 | } 45 | L.GetGlobal("t") 46 | b.ResetTimer() 47 | for n := 0; n < b.N; n++ { 48 | LuaToGo(L, -1, &output) 49 | } 50 | } 51 | 52 | func BenchmarkLuaToGoMapInt(b *testing.B) { 53 | L := Init() 54 | defer L.Close() 55 | 56 | var output map[string]interface{} 57 | L.DoString(`t={}; for i = 1,100 do t[tostring(i)]=i; end`) 58 | L.GetGlobal("t") 59 | b.ResetTimer() 60 | for n := 0; n < b.N; n++ { 61 | LuaToGo(L, -1, &output) 62 | } 63 | } 64 | 65 | func BenchmarkLuaToGoMapSlice(b *testing.B) { 66 | L := Init() 67 | defer L.Close() 68 | 69 | var output map[string]interface{} 70 | L.DoString(`t={}; s={17}; for i = 1,100 do t[tostring(i)]=s; end`) 71 | L.GetGlobal("t") 72 | b.ResetTimer() 73 | for n := 0; n < b.N; n++ { 74 | LuaToGo(L, -1, &output) 75 | } 76 | } 77 | 78 | func BenchmarkLuaToGoMapSliceUnique(b *testing.B) { 79 | L := Init() 80 | defer L.Close() 81 | 82 | var output map[string]interface{} 83 | L.DoString(`t={}`) 84 | for i := 0; i < 100; i++ { 85 | L.DoString(fmt.Sprintf(`s%[1]d={17}; t["%[1]d"]=s%[1]d`, i)) 86 | } 87 | L.GetGlobal("t") 88 | b.ResetTimer() 89 | for n := 0; n < b.N; n++ { 90 | LuaToGo(L, -1, &output) 91 | } 92 | } 93 | 94 | func BenchmarkGoToLuaSliceInt(b *testing.B) { 95 | L := Init() 96 | defer L.Close() 97 | 98 | input := make([]int, 100) 99 | for i := 0; i < 100; i++ { 100 | input[i] = i 101 | } 102 | b.ResetTimer() 103 | for n := 0; n < b.N; n++ { 104 | GoToLua(L, input) 105 | L.SetTop(0) 106 | } 107 | } 108 | 109 | func BenchmarkGoToLuaSliceSlice(b *testing.B) { 110 | L := Init() 111 | defer L.Close() 112 | 113 | sub := []int{17} 114 | input := make([][]int, 100) 115 | for i := 0; i < 100; i++ { 116 | input[i] = sub 117 | } 118 | b.ResetTimer() 119 | for n := 0; n < b.N; n++ { 120 | GoToLua(L, input) 121 | L.SetTop(0) 122 | } 123 | } 124 | 125 | func BenchmarkGoToLuaSliceSliceUnique(b *testing.B) { 126 | L := Init() 127 | defer L.Close() 128 | 129 | input := make([][]int, 100) 130 | for i := 0; i < 100; i++ { 131 | input[i] = []int{17} 132 | } 133 | b.ResetTimer() 134 | for n := 0; n < b.N; n++ { 135 | GoToLua(L, input) 136 | L.SetTop(0) 137 | } 138 | } 139 | 140 | func BenchmarkGoToLuaMapInt(b *testing.B) { 141 | L := Init() 142 | defer L.Close() 143 | 144 | input := map[int]int{} 145 | for i := 0; i < 100; i++ { 146 | input[i] = i 147 | } 148 | b.ResetTimer() 149 | for n := 0; n < b.N; n++ { 150 | GoToLua(L, input) 151 | L.SetTop(0) 152 | } 153 | } 154 | 155 | func BenchmarkGoToLuaMapSlice(b *testing.B) { 156 | L := Init() 157 | defer L.Close() 158 | 159 | sub := []int{17} 160 | input := map[int][]int{} 161 | for i := 0; i < 100; i++ { 162 | input[i] = sub 163 | } 164 | b.ResetTimer() 165 | for n := 0; n < b.N; n++ { 166 | GoToLua(L, input) 167 | L.SetTop(0) 168 | } 169 | } 170 | 171 | func BenchmarkGoToLuaMapSliceUnique(b *testing.B) { 172 | L := Init() 173 | defer L.Close() 174 | 175 | input := map[int][]int{} 176 | for i := 0; i < 100; i++ { 177 | input[i] = []int{17} 178 | } 179 | b.ResetTimer() 180 | for n := 0; n < b.N; n++ { 181 | GoToLua(L, input) 182 | L.SetTop(0) 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /vendor/github.com/stevedonovan/luar/proxyfuncs.go: -------------------------------------------------------------------------------- 1 | package luar 2 | 3 | // Those functions are meant to be registered in Lua to manipulate proxies. 4 | 5 | import ( 6 | "reflect" 7 | 8 | "github.com/aarzilli/golua/lua" 9 | ) 10 | 11 | // Complex pushes a proxy to a Go complex on the stack. 12 | // 13 | // Arguments: real (number), imag (number) 14 | // 15 | // Returns: proxy (complex128) 16 | func Complex(L *lua.State) int { 17 | v1, _ := luaToGoValue(L, 1) 18 | v2, _ := luaToGoValue(L, 2) 19 | result := complex(valueToNumber(L, v1), valueToNumber(L, v2)) 20 | makeValueProxy(L, reflect.ValueOf(result), cComplexMeta) 21 | return 1 22 | } 23 | 24 | // MakeChan creates a 'chan interface{}' proxy and pushes it on the stack. 25 | // 26 | // Optional argument: size (number) 27 | // 28 | // Returns: proxy (chan interface{}) 29 | func MakeChan(L *lua.State) int { 30 | n := L.OptInteger(1, 0) 31 | ch := make(chan interface{}, n) 32 | makeValueProxy(L, reflect.ValueOf(ch), cChannelMeta) 33 | return 1 34 | } 35 | 36 | // MakeMap creates a 'map[string]interface{}' proxy and pushes it on the stack. 37 | // 38 | // Returns: proxy (map[string]interface{}) 39 | func MakeMap(L *lua.State) int { 40 | m := reflect.MakeMap(tmap) 41 | makeValueProxy(L, m, cMapMeta) 42 | return 1 43 | } 44 | 45 | // MakeSlice creates a '[]interface{}' proxy and pushes it on the stack. 46 | // 47 | // Optional argument: size (number) 48 | // 49 | // Returns: proxy ([]interface{}) 50 | func MakeSlice(L *lua.State) int { 51 | n := L.OptInteger(1, 0) 52 | s := reflect.MakeSlice(tslice, n, n+1) 53 | makeValueProxy(L, s, cSliceMeta) 54 | return 1 55 | } 56 | 57 | func ipairsAux(L *lua.State) int { 58 | i := L.CheckInteger(2) + 1 59 | L.PushInteger(int64(i)) 60 | L.PushInteger(int64(i)) 61 | L.GetTable(1) 62 | if L.Type(-1) == lua.LUA_TNIL { 63 | return 1 64 | } 65 | return 2 66 | } 67 | 68 | // ProxyIpairs implements Lua 5.2 'ipairs' functions. 69 | // It respects the __ipairs metamethod. 70 | // 71 | // It is only useful for compatibility with Lua 5.1. 72 | func ProxyIpairs(L *lua.State) int { 73 | // See Lua >=5.2 source code. 74 | if L.GetMetaField(1, "__ipairs") { 75 | L.PushValue(1) 76 | L.Call(1, 3) 77 | return 3 78 | } 79 | 80 | L.CheckType(1, lua.LUA_TTABLE) 81 | L.PushGoFunction(ipairsAux) 82 | L.PushValue(1) 83 | L.PushInteger(0) 84 | return 3 85 | } 86 | 87 | // ProxyMethod pushes the proxy method on the stack. 88 | // 89 | // Argument: proxy 90 | // 91 | // Returns: method (function) 92 | func ProxyMethod(L *lua.State) int { 93 | if !isValueProxy(L, 1) { 94 | L.PushNil() 95 | return 1 96 | } 97 | v, _ := valueOfProxy(L, 1) 98 | name := L.ToString(2) 99 | pushGoMethod(L, name, v) 100 | return 1 101 | } 102 | 103 | func pairsAux(L *lua.State) int { 104 | L.CheckType(1, lua.LUA_TTABLE) 105 | L.SetTop(2) // Create a 2nd argument if there isn't one. 106 | if L.Next(1) != 0 { 107 | return 2 108 | } 109 | L.PushNil() 110 | return 1 111 | } 112 | 113 | // ProxyPairs implements Lua 5.2 'pairs' functions. 114 | // It respects the __pairs metamethod. 115 | // 116 | // It is only useful for compatibility with Lua 5.1. 117 | func ProxyPairs(L *lua.State) int { 118 | // See Lua >=5.2 source code. 119 | if L.GetMetaField(1, "__pairs") { 120 | L.PushValue(1) 121 | L.Call(1, 3) 122 | return 3 123 | } 124 | 125 | L.CheckType(1, lua.LUA_TTABLE) 126 | L.PushGoFunction(pairsAux) 127 | L.PushValue(1) 128 | L.PushNil() 129 | return 3 130 | } 131 | 132 | // ProxyType pushes the proxy type on the stack. 133 | // 134 | // It behaves like Lua's "type" except for proxies for which it returns 135 | // 'table', 'string' or 'number' with TYPE being the go type. 136 | // 137 | // Argument: proxy 138 | // 139 | // Returns: type (string) 140 | func ProxyType(L *lua.State) int { 141 | if !isValueProxy(L, 1) { 142 | L.PushString(L.LTypename(1)) 143 | return 1 144 | } 145 | v, _ := valueOfProxy(L, 1) 146 | 147 | for v.Kind() == reflect.Ptr { 148 | v = v.Elem() 149 | } 150 | 151 | prefix := "userdata" 152 | switch unsizedKind(v) { 153 | case reflect.Array, reflect.Map, reflect.Slice, reflect.Struct: 154 | prefix = "table" 155 | case reflect.String: 156 | prefix = "string" 157 | case reflect.Uint64, reflect.Int64, reflect.Float64, reflect.Complex128: 158 | prefix = "number" 159 | } 160 | 161 | L.PushString(prefix + "<" + v.Type().String() + ">") 162 | return 1 163 | } 164 | 165 | // Unproxify converts a proxy to an unproxified Lua value. 166 | // 167 | // Argument: proxy 168 | // 169 | // Returns: value (Lua value) 170 | func Unproxify(L *lua.State) int { 171 | if !isValueProxy(L, 1) { 172 | L.PushNil() 173 | return 1 174 | } 175 | v, _ := valueOfProxy(L, 1) 176 | GoToLua(L, v) 177 | return 1 178 | } 179 | -------------------------------------------------------------------------------- /vendor/github.com/aarzilli/golua/README.md: -------------------------------------------------------------------------------- 1 | Go Bindings for the lua C API 2 | ========================= 3 | 4 | Simplest way to install: 5 | 6 | # go get -u github.com/aarzilli/golua/lua 7 | 8 | Will work as long as your compiler can find a shared object called lua5.1 on linux, or lua anywhere else. 9 | If your linux system uses "lua" as the shared object name for lua (for example, Fedora Core does this) you can install using: 10 | 11 | # go get -u -tags llua github.com/aarzilli/golua/lua 12 | 13 | 14 | You can then try to run the examples: 15 | 16 | $ cd /usr/local/go/src/pkg/github.com/aarzilli/golua/example/ 17 | $ go run basic.go 18 | $ go run alloc.go 19 | $ go run panic.go 20 | $ go run userdata.go 21 | 22 | QUICK START 23 | --------------------- 24 | 25 | Create a new Virtual Machine with: 26 | 27 | ```go 28 | L := lua.NewState() 29 | L.OpenLibs() 30 | defer L.Close() 31 | ``` 32 | 33 | Lua's Virtual Machine is stack based, you can call lua functions like this: 34 | 35 | ```go 36 | // push "print" function on the stack 37 | L.GetField(lua.LUA_GLOBALSINDEX, "print") 38 | // push the string "Hello World!" on the stack 39 | L.PushString("Hello World!") 40 | // call print with one argument, expecting no results 41 | L.Call(1, 0) 42 | ``` 43 | 44 | Of course this isn't very useful, more useful is executing lua code from a file or from a string: 45 | 46 | ```go 47 | // executes a string of lua code 48 | err := L.DoString("...") 49 | // executes a file 50 | err = L.DoFile(filename) 51 | ``` 52 | 53 | You will also probably want to publish go functions to the virtual machine, you can do it by: 54 | 55 | ```go 56 | func adder(L *lua.State) int { 57 | a := L.ToInteger(1) 58 | b := L.ToInteger(2) 59 | L.PushInteger(a + b) 60 | return 1 // number of return values 61 | } 62 | 63 | func main() { 64 | L := lua.NewState() 65 | defer L.Close() 66 | L.OpenLibs() 67 | 68 | L.Register("adder", adder) 69 | L.DoString("print(adder(2, 2))") 70 | } 71 | ``` 72 | 73 | ON ERROR HANDLING 74 | --------------------- 75 | 76 | Lua's exceptions are incompatible with Go, golua works around this incompatibility by setting up protected execution environments in `lua.State.DoString`, `lua.State.DoFile` and lua.State.Call and turning every exception into a Go panic. 77 | 78 | This means that: 79 | 80 | 1. In general you can't do any exception handling from Lua, `pcall` and `xpcall` are renamed to `unsafe_pcall` and `unsafe_xpcall`. They are only safe to be called from Lua code that never calls back to Go. Use at your own risk. 81 | 82 | 2. The call to lua.State.Error, present in previous versions of this library, has been removed as it is nonsensical 83 | 84 | 3. Method calls on a newly created `lua.State` happen in an unprotected environment, if Lua throws an exception as a result your program will be terminated. If this is undesirable perform your initialization like this: 85 | 86 | ```go 87 | func LuaStateInit(L *lua.State) int { 88 | … initialization goes here… 89 | return 0 90 | } 91 | 92 | … 93 | L.PushGoFunction(LuaStateInit) 94 | err := L.Call(0, 0) 95 | … 96 | ``` 97 | 98 | ON THREADS AND COROUTINES 99 | --------------------- 100 | 101 | 'lua.State' is not thread safe, but the library itself is. Lua's coroutines exist but (to my knowledge) have never been tested and are likely to encounter the same problems that errors have, use at your own peril. 102 | 103 | ODDS AND ENDS 104 | --------------------- 105 | 106 | * Support for lua 5.2 is in the lua5.2 branch, this branch only supports lua5.1. 107 | * Compiling from source yields only a static link library (liblua.a), you can either produce the dynamic link library on your own or use the `luaa` build tag. 108 | 109 | LUAJIT 110 | --------------------- 111 | 112 | To link with [luajit-2.0.x](http://luajit.org/luajit.html), you can use CGO_CFLAGS and CGO_LDFLAGS environment variables 113 | 114 | ``` 115 | $ CGO_CFLAGS=`pkg-config luajit --cflags` 116 | $ CGO_LDFLAGS=`pkg-config luajit --libs` 117 | $ go get -f -u github.com/aarzilli/golua/lua 118 | ``` 119 | 120 | CONTRIBUTORS 121 | --------------------- 122 | 123 | * Adam Fitzgerald (original author) 124 | * Alessandro Arzilli 125 | * Steve Donovan 126 | * Harley Laue 127 | * James Nurmi 128 | * Ruitao 129 | * Xushiwei 130 | * Isaint 131 | * hsinhoyeh 132 | * Viktor Palmkvist 133 | * HongZhen Peng 134 | * Admin36 135 | * Pierre Neidhardt (@Ambrevar) 136 | 137 | SEE ALSO 138 | --------------------- 139 | 140 | - [Luar](https://github.com/stevedonovan/luar/) is a reflection layer on top of golua API providing a simplified way to publish go functions to a Lua VM. 141 | - [Golua unicode](https://bitbucket.org/ambrevar/golua/) is an extension library that adds unicode support to golua and replaces lua regular expressions with re2. 142 | 143 | Licensing 144 | ------------- 145 | GoLua is released under the MIT license. 146 | Please see the LICENSE file for more information. 147 | 148 | Lua is Copyright (c) Lua.org, PUC-Rio. All rights reserved. 149 | -------------------------------------------------------------------------------- /gopher-lua/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | lua "github.com/yuin/gopher-lua" 8 | ) 9 | 10 | func runGlobalVar(L *lua.LState) { 11 | fmt.Printf("runGlobalVar, top stack: %d\n", L.GetTop()) 12 | 13 | // Lua is a stack, so we get the object and check it's value off of it. 14 | val := L.GetGlobal("GLOBAL_VAR") // Load our global variable 15 | log.Printf("GLOBAL_VAR = %s\n", val) 16 | } 17 | 18 | func runInvalidVar(L *lua.LState) { 19 | fmt.Printf("runInvalidVar, top stack: %d\n", L.GetTop()) 20 | 21 | // Lua is a stack, so we get the object and check it's value off of it. 22 | val := L.GetGlobal("ASDF_VAR") // Load our global variable 23 | if val.Type() != lua.LTNil { 24 | panic("this should not happen...") 25 | } 26 | } 27 | 28 | func runSquare(L *lua.LState) { 29 | fmt.Printf("runSquare, top stack: %d\n", L.GetTop()) 30 | 31 | // call our square(int) function 32 | // if this function exists, we'll run it... 33 | if err := L.CallByParam(lua.P{ 34 | Fn: L.GetGlobal("square"), 35 | NRet: 1, // 1 return value 36 | Protect: true, // false return panic 37 | }, lua.LNumber(5)); err != nil { 38 | log.Fatalf("Error running square(5): %s", err) 39 | } 40 | 41 | ret := L.ToInt(-1) // returned value 42 | log.Printf("square(5) = %d\n", ret) 43 | 44 | L.Pop(1) // remove received value 45 | 46 | } 47 | 48 | func runGoTestFunc(L *lua.LState) { 49 | // show us the current index of the stack... 50 | fmt.Printf("runGoTestFunc, top stack: %d\n", L.GetTop()) 51 | 52 | // Our simple function here will return true if it is a string, false if it isn't... 53 | ourSimpleFn := func(L *lua.LState) int { 54 | lv := L.Get(-1) 55 | switch lv.Type() { 56 | case lua.LTNumber: 57 | val, _ := lv.(lua.LNumber) 58 | log.Printf("fn(%d)\n", val) 59 | L.Push(lua.LString("int")) 60 | case lua.LTString: 61 | val, _ := lv.(lua.LString) 62 | log.Printf("fn(%s)\n", val) 63 | L.Push(lua.LString("string")) 64 | default: 65 | log.Printf("fn(%#v)\n", lv) 66 | L.Push(lua.LString("unknown")) 67 | } 68 | 69 | return 1 // number of return variables... 70 | } 71 | 72 | if err := L.CallByParam(lua.P{ 73 | Fn: L.GetGlobal("test_go_string"), 74 | NRet: 0, // 0 return value 75 | Protect: true, // false will panic 76 | }, L.NewClosure(ourSimpleFn), lua.LString("Hello, World!")); err != nil { 77 | log.Fatalf("Error running test_go_string: %s", err) 78 | } 79 | 80 | if err := L.CallByParam(lua.P{ 81 | Fn: L.GetGlobal("test_go_string"), 82 | NRet: 0, // 0 return value 83 | Protect: true, // false return panic 84 | }, L.NewClosure(ourSimpleFn), lua.LNumber(5)); err != nil { 85 | log.Fatalf("Error running test_go_string: %s", err) 86 | } 87 | 88 | } 89 | 90 | const accountName = "Account" 91 | 92 | type Account struct { 93 | Balance int 94 | } 95 | 96 | func createAccount(L *lua.LState) int { 97 | log.Println("createAccount") 98 | 99 | account := &Account{Balance: L.CheckInt(1)} 100 | ud := L.NewUserData() 101 | ud.Value = account 102 | L.SetMetatable(ud, L.GetTypeMetatable(accountName)) 103 | L.Push(ud) 104 | 105 | return 1 106 | } 107 | 108 | func accountToString(L *lua.LState) int { 109 | log.Println("accountToString") 110 | 111 | account := L.CheckUserData(1).Value.(*Account) 112 | L.Push(lua.LString(fmt.Sprintf("account(balance=%d)", account.Balance))) 113 | 114 | return 1 115 | } 116 | 117 | func accountEq(L *lua.LState) int { 118 | log.Println("accountEq") 119 | 120 | account1 := L.CheckUserData(1).Value.(*Account) 121 | account2 := L.CheckUserData(2).Value.(*Account) 122 | L.Push(lua.LBool(account1.Balance == account2.Balance)) 123 | 124 | return 1 125 | } 126 | 127 | func accountWithdrawl(L *lua.LState) int { 128 | log.Println("accountWithdrawl") 129 | 130 | account := L.CheckUserData(1).Value.(*Account) 131 | account.Balance -= L.CheckInt(-1) 132 | 133 | return 0 134 | } 135 | 136 | func accountBalance(L *lua.LState) int { 137 | account := L.CheckUserData(1).Value.(*Account) 138 | L.Push(lua.LNumber(account.Balance)) 139 | 140 | return 1 141 | } 142 | 143 | // http://stackoverflow.com/questions/34841773/golua-declaring-lua-class-with-defined-methods/34859174 144 | func registerAccountType(L *lua.LState) { 145 | // Account = {} 146 | mt := L.NewTypeMetatable(accountName) 147 | 148 | L.SetGlobal(accountName, mt) 149 | // static attributes 150 | L.SetField(mt, "create", L.NewFunction(createAccount)) 151 | L.SetField(mt, "balance", L.NewFunction(accountBalance)) 152 | L.SetField(mt, "withdrawl", L.NewFunction(accountWithdrawl)) 153 | L.SetField(mt, "__tostring", L.NewFunction(accountToString)) 154 | L.SetField(mt, "__eq", L.NewFunction(accountEq)) 155 | L.SetField(mt, "__index", mt) 156 | } 157 | 158 | func runMemberTest(L *lua.LState) { 159 | // register our type 160 | registerAccountType(L) 161 | 162 | fmt.Printf("runMemberTest, top stack: %d\n", L.GetTop()) 163 | 164 | if err := L.CallByParam(lua.P{ 165 | Fn: L.GetGlobal("account_test"), 166 | NRet: 0, // 0 return value 167 | Protect: true, // false return panic 168 | }); err != nil { 169 | log.Fatalf("Error running account_test: %s", err) 170 | } 171 | 172 | } 173 | 174 | func main() { 175 | L := lua.NewState() 176 | L.OpenLibs() 177 | if err := L.DoFile("test.lua"); err != nil { 178 | log.Fatalf("Error loading file: %s", err) 179 | } 180 | 181 | runGlobalVar(L) 182 | 183 | runInvalidVar(L) 184 | 185 | runSquare(L) 186 | 187 | runGoTestFunc(L) 188 | 189 | runMemberTest(L) 190 | 191 | fmt.Printf("top stack: %d\n", L.GetTop()) 192 | 193 | } 194 | -------------------------------------------------------------------------------- /vendor/github.com/aarzilli/golua/lua/lauxlib.go: -------------------------------------------------------------------------------- 1 | package lua 2 | 3 | //#include 4 | //#include 5 | //#include 6 | //#include 7 | //#include "golua.h" 8 | import "C" 9 | import "unsafe" 10 | 11 | type LuaError struct { 12 | code int 13 | message string 14 | stackTrace []LuaStackEntry 15 | } 16 | 17 | func (err *LuaError) Error() string { 18 | return err.message 19 | } 20 | 21 | func (err *LuaError) Code() int { 22 | return err.code 23 | } 24 | 25 | func (err *LuaError) StackTrace() []LuaStackEntry { 26 | return err.stackTrace 27 | } 28 | 29 | // luaL_argcheck 30 | // WARNING: before b30b2c62c6712c6683a9d22ff0abfa54c8267863 the function ArgCheck had the opposite behaviour 31 | func (L *State) Argcheck(cond bool, narg int, extramsg string) { 32 | if !cond { 33 | Cextramsg := C.CString(extramsg) 34 | defer C.free(unsafe.Pointer(Cextramsg)) 35 | C.luaL_argerror(L.s, C.int(narg), Cextramsg) 36 | } 37 | } 38 | 39 | // luaL_argerror 40 | func (L *State) ArgError(narg int, extramsg string) int { 41 | Cextramsg := C.CString(extramsg) 42 | defer C.free(unsafe.Pointer(Cextramsg)) 43 | return int(C.luaL_argerror(L.s, C.int(narg), Cextramsg)) 44 | } 45 | 46 | // luaL_callmeta 47 | func (L *State) CallMeta(obj int, e string) int { 48 | Ce := C.CString(e) 49 | defer C.free(unsafe.Pointer(Ce)) 50 | return int(C.luaL_callmeta(L.s, C.int(obj), Ce)) 51 | } 52 | 53 | // luaL_checkany 54 | func (L *State) CheckAny(narg int) { 55 | C.luaL_checkany(L.s, C.int(narg)) 56 | } 57 | 58 | // luaL_checkinteger 59 | func (L *State) CheckInteger(narg int) int { 60 | return int(C.luaL_checkinteger(L.s, C.int(narg))) 61 | } 62 | 63 | // luaL_checknumber 64 | func (L *State) CheckNumber(narg int) float64 { 65 | return float64(C.luaL_checknumber(L.s, C.int(narg))) 66 | } 67 | 68 | // luaL_checkstring 69 | func (L *State) CheckString(narg int) string { 70 | var length C.size_t 71 | return C.GoString(C.luaL_checklstring(L.s, C.int(narg), &length)) 72 | } 73 | 74 | // luaL_checkoption 75 | // 76 | // BUG(everyone_involved): not implemented 77 | func (L *State) CheckOption(narg int, def string, lst []string) int { 78 | //TODO: complication: lst conversion to const char* lst[] from string slice 79 | return 0 80 | } 81 | 82 | // luaL_checktype 83 | func (L *State) CheckType(narg int, t LuaValType) { 84 | C.luaL_checktype(L.s, C.int(narg), C.int(t)) 85 | } 86 | 87 | // luaL_checkudata 88 | func (L *State) CheckUdata(narg int, tname string) unsafe.Pointer { 89 | Ctname := C.CString(tname) 90 | defer C.free(unsafe.Pointer(Ctname)) 91 | return unsafe.Pointer(C.luaL_checkudata(L.s, C.int(narg), Ctname)) 92 | } 93 | 94 | // Executes file, returns nil for no errors or the lua error string on failure 95 | func (L *State) DoFile(filename string) error { 96 | if r := L.LoadFile(filename); r != 0 { 97 | return &LuaError{r, L.ToString(-1), L.StackTrace()} 98 | } 99 | return L.Call(0, LUA_MULTRET) 100 | } 101 | 102 | // Executes the string, returns nil for no errors or the lua error string on failure 103 | func (L *State) DoString(str string) error { 104 | if r := L.LoadString(str); r != 0 { 105 | return &LuaError{r, L.ToString(-1), L.StackTrace()} 106 | } 107 | return L.Call(0, LUA_MULTRET) 108 | } 109 | 110 | // Like DoString but panics on error 111 | func (L *State) MustDoString(str string) { 112 | if err := L.DoString(str); err != nil { 113 | panic(err) 114 | } 115 | } 116 | 117 | // luaL_getmetafield 118 | func (L *State) GetMetaField(obj int, e string) bool { 119 | Ce := C.CString(e) 120 | defer C.free(unsafe.Pointer(Ce)) 121 | return C.luaL_getmetafield(L.s, C.int(obj), Ce) != 0 122 | } 123 | 124 | // luaL_getmetatable 125 | func (L *State) LGetMetaTable(tname string) { 126 | Ctname := C.CString(tname) 127 | defer C.free(unsafe.Pointer(Ctname)) 128 | C.lua_getfield(L.s, LUA_REGISTRYINDEX, Ctname) 129 | } 130 | 131 | // luaL_gsub 132 | func (L *State) GSub(s string, p string, r string) string { 133 | Cs := C.CString(s) 134 | Cp := C.CString(p) 135 | Cr := C.CString(r) 136 | defer func() { 137 | C.free(unsafe.Pointer(Cs)) 138 | C.free(unsafe.Pointer(Cp)) 139 | C.free(unsafe.Pointer(Cr)) 140 | }() 141 | 142 | return C.GoString(C.luaL_gsub(L.s, Cs, Cp, Cr)) 143 | } 144 | 145 | // luaL_loadfile 146 | func (L *State) LoadFile(filename string) int { 147 | Cfilename := C.CString(filename) 148 | defer C.free(unsafe.Pointer(Cfilename)) 149 | return int(C.luaL_loadfile(L.s, Cfilename)) 150 | } 151 | 152 | // luaL_loadstring 153 | func (L *State) LoadString(s string) int { 154 | Cs := C.CString(s) 155 | defer C.free(unsafe.Pointer(Cs)) 156 | return int(C.luaL_loadstring(L.s, Cs)) 157 | } 158 | 159 | // luaL_newmetatable 160 | func (L *State) NewMetaTable(tname string) bool { 161 | Ctname := C.CString(tname) 162 | defer C.free(unsafe.Pointer(Ctname)) 163 | return C.luaL_newmetatable(L.s, Ctname) != 0 164 | } 165 | 166 | // luaL_newstate 167 | func NewState() *State { 168 | ls := (C.luaL_newstate()) 169 | L := newState(ls) 170 | return L 171 | } 172 | 173 | // luaL_openlibs 174 | func (L *State) OpenLibs() { 175 | C.luaL_openlibs(L.s) 176 | C.clua_hide_pcall(L.s) 177 | } 178 | 179 | // luaL_optinteger 180 | func (L *State) OptInteger(narg int, d int) int { 181 | return int(C.luaL_optinteger(L.s, C.int(narg), C.lua_Integer(d))) 182 | } 183 | 184 | // luaL_optnumber 185 | func (L *State) OptNumber(narg int, d float64) float64 { 186 | return float64(C.luaL_optnumber(L.s, C.int(narg), C.lua_Number(d))) 187 | } 188 | 189 | // luaL_optstring 190 | func (L *State) OptString(narg int, d string) string { 191 | var length C.size_t 192 | Cd := C.CString(d) 193 | defer C.free(unsafe.Pointer(Cd)) 194 | return C.GoString(C.luaL_optlstring(L.s, C.int(narg), Cd, &length)) 195 | } 196 | 197 | // luaL_ref 198 | func (L *State) Ref(t int) int { 199 | return int(C.luaL_ref(L.s, C.int(t))) 200 | } 201 | 202 | // luaL_typename 203 | func (L *State) LTypename(index int) string { 204 | return C.GoString(C.lua_typename(L.s, C.lua_type(L.s, C.int(index)))) 205 | } 206 | 207 | // luaL_unref 208 | func (L *State) Unref(t int, ref int) { 209 | C.luaL_unref(L.s, C.int(t), C.int(ref)) 210 | } 211 | 212 | // luaL_where 213 | func (L *State) Where(lvl int) { 214 | C.luaL_where(L.s, C.int(lvl)) 215 | } 216 | -------------------------------------------------------------------------------- /go-lua/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | lua "github.com/Shopify/go-lua" 8 | ) 9 | 10 | func runGlobalVar(L *lua.State) { 11 | fmt.Printf("runGlobalVar, top stack: %d\n", L.Top()) 12 | 13 | // Lua is a stack, so we get the object and check it's value off of it. 14 | L.Global("GLOBAL_VAR") // Load our global variable 15 | // print the value 16 | if globalVarStr, ok := L.ToString(-1); ok { 17 | log.Printf("GLOBAL_VAR = %s\n", globalVarStr) 18 | } 19 | 20 | // clean up the stack... 21 | L.Pop(1) 22 | } 23 | 24 | func runInvalidVar(L *lua.State) { 25 | fmt.Printf("runInvalidVar, top stack: %d\n", L.Top()) 26 | 27 | // Lua is a stack, so we get the object and check it's value off of it. 28 | L.Global("ASDF_VAR") // Load our global variable 29 | if _, ok := L.ToString(-1); ok { 30 | panic("this should not happen...") 31 | } 32 | 33 | // clean up stack... look another way! 34 | L.Remove(-1) 35 | } 36 | 37 | func runSquare(L *lua.State) { 38 | fmt.Printf("runSquare, top stack: %d\n", L.Top()) 39 | 40 | // call our square(int) function 41 | L.Global("square") 42 | // if this function exists, we'll run it... 43 | if L.IsFunction(-1) { 44 | // put an element on the stack, in this case int(5) 45 | L.PushInteger(5) 46 | 47 | // the call function tells the stack that we are passing 48 | // one argument in and expecting one argument back 49 | if err := L.ProtectedCall(1, 1, 0); err != nil { 50 | log.Fatalf("Error running square: %s", err) 51 | } 52 | 53 | // we have a value on the stack we can get now, our result... 54 | if result, ok := L.ToInteger(-1); ok { 55 | log.Printf("square(5) = %d\n", result) 56 | } 57 | } 58 | // clean up the stack... 59 | L.Remove(-1) 60 | } 61 | 62 | func runGoTestFunc(L *lua.State) { 63 | // show us the current index of the stack... 64 | fmt.Printf("runGoTestFunc, top stack: %d\n", L.Top()) 65 | 66 | // call our test go function... 67 | L.Global("test_go_string") 68 | // If this function exists, we'll run it 69 | if L.IsFunction(-1) { 70 | 71 | // Our simple function here will return true if it is a string, false if it isn't... 72 | ourSimpleFn := func(L *lua.State) int { 73 | switch { 74 | case L.IsNumber(-1): 75 | val, _ := L.ToInteger(-1) 76 | log.Printf("fn(%d)\n", val) 77 | L.PushString("int") 78 | case L.IsString(-1): 79 | val, _ := L.ToString(-1) 80 | log.Printf("fn(%s)\n", val) 81 | L.PushString("string") 82 | default: 83 | val := L.ToValue(-1) 84 | log.Printf("fn(%#v)\n", val) 85 | L.PushString("unknown") 86 | } 87 | 88 | return 1 // number of return variables... 89 | } 90 | 91 | // add a closure to the stack 92 | L.PushGoClosure(ourSimpleFn, 0) 93 | // add a string to the stack 94 | L.PushString("Hello, World!") 95 | 96 | // We're passing in 2 arguments, returning none... 97 | // This is equivalent to calling `test_go_string(ourSimpleFn, "Hello, World!")` 98 | if err := L.ProtectedCall(2, 0, 0); err != nil { 99 | log.Fatalf("Lua error: %#v\n", err) 100 | } 101 | 102 | // get our function back on the stack... 103 | L.Global("test_go_string") 104 | // add a closure to the stack 105 | L.PushGoClosure(ourSimpleFn, 0) 106 | // add a int to the stack 107 | L.PushInteger(123) 108 | 109 | // We're passing in 2 arguments, returning none... 110 | // This is equivalent to calling `test_go_string(ourSimpleFn, 123)` 111 | if err := L.ProtectedCall(2, 0, 0); err != nil { 112 | log.Fatalf("Lua error: %#v\n", err) 113 | } 114 | } 115 | } 116 | 117 | const accountName = "Account" 118 | 119 | type Account struct { 120 | Balance int 121 | } 122 | 123 | func createAccount(L *lua.State) int { 124 | log.Println("createAccount") 125 | balance, _ := L.ToInteger(-1) 126 | account := &Account{Balance: balance} 127 | L.PushUserData(account) 128 | lua.SetMetaTableNamed(L, accountName) 129 | 130 | return 1 131 | } 132 | 133 | func accountToString(L *lua.State) int { 134 | log.Println("accountToString") 135 | account := lua.CheckUserData(L, 1, accountName).(*Account) 136 | L.PushString(fmt.Sprintf("account(balance=%d)", account.Balance)) 137 | 138 | return 1 139 | } 140 | 141 | func accountEq(L *lua.State) int { 142 | log.Println("accountEq") 143 | account1 := lua.CheckUserData(L, 1, accountName).(*Account) 144 | account2 := lua.CheckUserData(L, 2, accountName).(*Account) 145 | L.PushBoolean(account1.Balance == account2.Balance) 146 | 147 | return 1 148 | } 149 | 150 | func accountWithdrawl(L *lua.State) int { 151 | log.Println("accountWithdrawl") 152 | account := L.ToUserData(1).(*Account) 153 | if amount, ok := L.ToInteger(-1); ok { 154 | account.Balance -= amount 155 | } else { 156 | lua.Errorf(L, "Invalid argument: %#v", L.ToValue(-1)) 157 | } 158 | 159 | return 0 160 | } 161 | 162 | func accountBalance(L *lua.State) int { 163 | account := L.ToUserData(1).(*Account) 164 | L.PushInteger(account.Balance) 165 | 166 | return 1 167 | } 168 | 169 | // http://stackoverflow.com/questions/34841773/golua-declaring-lua-class-with-defined-methods/34859174 170 | func registerAccountType(L *lua.State) { 171 | // Account = {} 172 | lua.NewMetaTable(L, accountName) 173 | // Account.__index = Account 174 | L.PushValue(-1) 175 | L.SetField(-2, "__index") 176 | 177 | lua.SetFunctions(L, []lua.RegistryFunction{ 178 | {"create", createAccount}, 179 | {"balance", accountBalance}, 180 | {"withdrawl", accountWithdrawl}, 181 | // reserved... 182 | {"__tostring", accountToString}, 183 | {"__eq", accountEq}, 184 | }, 0) 185 | 186 | // Add account to the global stack 187 | L.SetGlobal(accountName) 188 | } 189 | 190 | func runMemberTest(L *lua.State) { 191 | // register our type 192 | registerAccountType(L) 193 | 194 | fmt.Printf("runMemberTest, top stack: %d\n", L.Top()) 195 | 196 | L.Global("account_test") 197 | if err := L.ProtectedCall(0, 0, 0); err != nil { 198 | log.Println(err) 199 | } 200 | } 201 | 202 | func main() { 203 | L := lua.NewState() 204 | lua.OpenLibraries(L) 205 | if err := lua.DoFile(L, "test.lua"); err != nil { 206 | log.Fatalf("Error loading file: %s", err) 207 | } 208 | 209 | runGlobalVar(L) 210 | 211 | runInvalidVar(L) 212 | 213 | runSquare(L) 214 | 215 | runGoTestFunc(L) 216 | 217 | runMemberTest(L) 218 | 219 | fmt.Printf("top stack: %d\n", L.Top()) 220 | 221 | } 222 | -------------------------------------------------------------------------------- /vendor/github.com/aarzilli/golua/lua/lua/lauxlib.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ 3 | ** Auxiliary functions for building Lua libraries 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #ifndef lauxlib_h 9 | #define lauxlib_h 10 | 11 | 12 | #include 13 | #include 14 | 15 | #include "lua.h" 16 | 17 | 18 | #if defined(LUA_COMPAT_GETN) 19 | LUALIB_API int (luaL_getn) (lua_State *L, int t); 20 | LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); 21 | #else 22 | #define luaL_getn(L,i) ((int)lua_objlen(L, i)) 23 | #define luaL_setn(L,i,j) ((void)0) /* no op! */ 24 | #endif 25 | 26 | #if defined(LUA_COMPAT_OPENLIB) 27 | #define luaI_openlib luaL_openlib 28 | #endif 29 | 30 | 31 | /* extra error code for `luaL_load' */ 32 | #define LUA_ERRFILE (LUA_ERRERR+1) 33 | 34 | 35 | typedef struct luaL_Reg { 36 | const char *name; 37 | lua_CFunction func; 38 | } luaL_Reg; 39 | 40 | 41 | 42 | LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, 43 | const luaL_Reg *l, int nup); 44 | LUALIB_API void (luaL_register) (lua_State *L, const char *libname, 45 | const luaL_Reg *l); 46 | LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); 47 | LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); 48 | LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); 49 | LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); 50 | LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, 51 | size_t *l); 52 | LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, 53 | const char *def, size_t *l); 54 | LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); 55 | LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); 56 | 57 | LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); 58 | LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, 59 | lua_Integer def); 60 | 61 | LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); 62 | LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); 63 | LUALIB_API void (luaL_checkany) (lua_State *L, int narg); 64 | 65 | LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); 66 | LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); 67 | 68 | LUALIB_API void (luaL_where) (lua_State *L, int lvl); 69 | LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); 70 | 71 | LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, 72 | const char *const lst[]); 73 | 74 | LUALIB_API int (luaL_ref) (lua_State *L, int t); 75 | LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); 76 | 77 | LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); 78 | LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, 79 | const char *name); 80 | LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); 81 | 82 | LUALIB_API lua_State *(luaL_newstate) (void); 83 | 84 | 85 | LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, 86 | const char *r); 87 | 88 | LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, 89 | const char *fname, int szhint); 90 | 91 | 92 | 93 | 94 | /* 95 | ** =============================================================== 96 | ** some useful macros 97 | ** =============================================================== 98 | */ 99 | 100 | #define luaL_argcheck(L, cond,numarg,extramsg) \ 101 | ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) 102 | #define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) 103 | #define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) 104 | #define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) 105 | #define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) 106 | #define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) 107 | #define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) 108 | 109 | #define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) 110 | 111 | #define luaL_dofile(L, fn) \ 112 | (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) 113 | 114 | #define luaL_dostring(L, s) \ 115 | (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) 116 | 117 | #define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) 118 | 119 | #define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) 120 | 121 | /* 122 | ** {====================================================== 123 | ** Generic Buffer manipulation 124 | ** ======================================================= 125 | */ 126 | 127 | 128 | 129 | typedef struct luaL_Buffer { 130 | char *p; /* current position in buffer */ 131 | int lvl; /* number of strings in the stack (level) */ 132 | lua_State *L; 133 | char buffer[LUAL_BUFFERSIZE]; 134 | } luaL_Buffer; 135 | 136 | #define luaL_addchar(B,c) \ 137 | ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ 138 | (*(B)->p++ = (char)(c))) 139 | 140 | /* compatibility only */ 141 | #define luaL_putchar(B,c) luaL_addchar(B,c) 142 | 143 | #define luaL_addsize(B,n) ((B)->p += (n)) 144 | 145 | LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); 146 | LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); 147 | LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); 148 | LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); 149 | LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); 150 | LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); 151 | 152 | 153 | /* }====================================================== */ 154 | 155 | 156 | /* compatibility with ref system */ 157 | 158 | /* pre-defined references */ 159 | #define LUA_NOREF (-2) 160 | #define LUA_REFNIL (-1) 161 | 162 | #define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ 163 | (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) 164 | 165 | #define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) 166 | 167 | #define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) 168 | 169 | 170 | #define luaL_reg luaL_Reg 171 | 172 | #endif 173 | 174 | 175 | -------------------------------------------------------------------------------- /vendor/github.com/aarzilli/golua/lua/golua.go: -------------------------------------------------------------------------------- 1 | package lua 2 | 3 | /* 4 | #cgo CFLAGS: -Ilua 5 | 6 | #include 7 | #include 8 | #include 9 | */ 10 | import "C" 11 | 12 | import ( 13 | "reflect" 14 | "sync" 15 | "unsafe" 16 | ) 17 | 18 | // Type of allocation functions to use with NewStateAlloc 19 | type Alloc func(ptr unsafe.Pointer, osize uint, nsize uint) unsafe.Pointer 20 | 21 | // This is the type of go function that can be registered as lua functions 22 | type LuaGoFunction func(L *State) int 23 | 24 | // Wrapper to keep cgo from complaining about incomplete ptr type 25 | //export State 26 | type State struct { 27 | // Wrapped lua_State object 28 | s *C.lua_State 29 | 30 | // index of this object inside the goStates array 31 | Index uintptr 32 | 33 | // Registry of go object that have been pushed to Lua VM 34 | registry []interface{} 35 | 36 | // Freelist for funcs indices, to allow for freeing 37 | freeIndices []uint 38 | } 39 | 40 | var goStates map[uintptr]*State 41 | var goStatesMutex sync.Mutex 42 | 43 | func init() { 44 | goStates = make(map[uintptr]*State, 16) 45 | } 46 | 47 | func registerGoState(L *State) { 48 | goStatesMutex.Lock() 49 | defer goStatesMutex.Unlock() 50 | L.Index = uintptr(unsafe.Pointer(L)) 51 | goStates[L.Index] = L 52 | } 53 | 54 | func unregisterGoState(L *State) { 55 | goStatesMutex.Lock() 56 | defer goStatesMutex.Unlock() 57 | delete(goStates, L.Index) 58 | } 59 | 60 | func getGoState(gostateindex uintptr) *State { 61 | goStatesMutex.Lock() 62 | defer goStatesMutex.Unlock() 63 | return goStates[gostateindex] 64 | } 65 | 66 | //export golua_callgofunction 67 | func golua_callgofunction(gostateindex uintptr, fid uint) int { 68 | L1 := getGoState(gostateindex) 69 | if fid < 0 { 70 | panic(&LuaError{0, "Requested execution of an unknown function", L1.StackTrace()}) 71 | } 72 | f := L1.registry[fid].(LuaGoFunction) 73 | return f(L1) 74 | } 75 | 76 | var typeOfBytes = reflect.TypeOf([]byte(nil)) 77 | 78 | //export golua_interface_newindex_callback 79 | func golua_interface_newindex_callback(gostateindex uintptr, iid uint, field_name_cstr *C.char) int { 80 | L := getGoState(gostateindex) 81 | iface := L.registry[iid] 82 | ifacevalue := reflect.ValueOf(iface).Elem() 83 | 84 | field_name := C.GoString(field_name_cstr) 85 | 86 | fval := ifacevalue.FieldByName(field_name) 87 | 88 | if fval.Kind() == reflect.Ptr { 89 | fval = fval.Elem() 90 | } 91 | 92 | luatype := LuaValType(C.lua_type(L.s, 3)) 93 | 94 | switch fval.Kind() { 95 | case reflect.Bool: 96 | if luatype == LUA_TBOOLEAN { 97 | fval.SetBool(int(C.lua_toboolean(L.s, 3)) != 0) 98 | return 1 99 | } else { 100 | L.PushString("Wrong assignment to field " + field_name) 101 | return -1 102 | } 103 | 104 | case reflect.Int: 105 | fallthrough 106 | case reflect.Int8: 107 | fallthrough 108 | case reflect.Int16: 109 | fallthrough 110 | case reflect.Int32: 111 | fallthrough 112 | case reflect.Int64: 113 | if luatype == LUA_TNUMBER { 114 | fval.SetInt(int64(C.lua_tointeger(L.s, 3))) 115 | return 1 116 | } else { 117 | L.PushString("Wrong assignment to field " + field_name) 118 | return -1 119 | } 120 | 121 | case reflect.Uint: 122 | fallthrough 123 | case reflect.Uint8: 124 | fallthrough 125 | case reflect.Uint16: 126 | fallthrough 127 | case reflect.Uint32: 128 | fallthrough 129 | case reflect.Uint64: 130 | if luatype == LUA_TNUMBER { 131 | fval.SetUint(uint64(C.lua_tointeger(L.s, 3))) 132 | return 1 133 | } else { 134 | L.PushString("Wrong assignment to field " + field_name) 135 | return -1 136 | } 137 | 138 | case reflect.String: 139 | if luatype == LUA_TSTRING { 140 | fval.SetString(C.GoString(C.lua_tolstring(L.s, 3, nil))) 141 | return 1 142 | } else { 143 | L.PushString("Wrong assignment to field " + field_name) 144 | return -1 145 | } 146 | 147 | case reflect.Float32: 148 | fallthrough 149 | case reflect.Float64: 150 | if luatype == LUA_TNUMBER { 151 | fval.SetFloat(float64(C.lua_tonumber(L.s, 3))) 152 | return 1 153 | } else { 154 | L.PushString("Wrong assignment to field " + field_name) 155 | return -1 156 | } 157 | case reflect.Slice: 158 | if fval.Type() == typeOfBytes { 159 | if luatype == LUA_TSTRING { 160 | fval.SetBytes(L.ToBytes(3)) 161 | return 1 162 | } else { 163 | L.PushString("Wrong assignment to field " + field_name) 164 | return -1 165 | } 166 | } 167 | } 168 | 169 | L.PushString("Unsupported type of field " + field_name + ": " + fval.Type().String()) 170 | return -1 171 | } 172 | 173 | //export golua_interface_index_callback 174 | func golua_interface_index_callback(gostateindex uintptr, iid uint, field_name *C.char) int { 175 | L := getGoState(gostateindex) 176 | iface := L.registry[iid] 177 | ifacevalue := reflect.ValueOf(iface).Elem() 178 | 179 | fval := ifacevalue.FieldByName(C.GoString(field_name)) 180 | 181 | if fval.Kind() == reflect.Ptr { 182 | fval = fval.Elem() 183 | } 184 | 185 | switch fval.Kind() { 186 | case reflect.Bool: 187 | L.PushBoolean(fval.Bool()) 188 | return 1 189 | 190 | case reflect.Int: 191 | fallthrough 192 | case reflect.Int8: 193 | fallthrough 194 | case reflect.Int16: 195 | fallthrough 196 | case reflect.Int32: 197 | fallthrough 198 | case reflect.Int64: 199 | L.PushInteger(fval.Int()) 200 | return 1 201 | 202 | case reflect.Uint: 203 | fallthrough 204 | case reflect.Uint8: 205 | fallthrough 206 | case reflect.Uint16: 207 | fallthrough 208 | case reflect.Uint32: 209 | fallthrough 210 | case reflect.Uint64: 211 | L.PushInteger(int64(fval.Uint())) 212 | return 1 213 | 214 | case reflect.String: 215 | L.PushString(fval.String()) 216 | return 1 217 | 218 | case reflect.Float32: 219 | fallthrough 220 | case reflect.Float64: 221 | L.PushNumber(fval.Float()) 222 | return 1 223 | case reflect.Slice: 224 | if fval.Type() == typeOfBytes { 225 | L.PushBytes(fval.Bytes()) 226 | return 1 227 | } 228 | } 229 | 230 | L.PushString("Unsupported type of field: " + fval.Type().String()) 231 | return -1 232 | } 233 | 234 | //export golua_gchook 235 | func golua_gchook(gostateindex uintptr, id uint) int { 236 | L1 := getGoState(gostateindex) 237 | L1.unregister(id) 238 | return 0 239 | } 240 | 241 | //export golua_callpanicfunction 242 | func golua_callpanicfunction(gostateindex uintptr, id uint) int { 243 | L1 := getGoState(gostateindex) 244 | f := L1.registry[id].(LuaGoFunction) 245 | return f(L1) 246 | } 247 | 248 | //export golua_idtointerface 249 | func golua_idtointerface(id uint) interface{} { 250 | return id 251 | } 252 | 253 | //export golua_cfunctiontointerface 254 | func golua_cfunctiontointerface(f *uintptr) interface{} { 255 | return f 256 | } 257 | 258 | //export golua_callallocf 259 | func golua_callallocf(fp uintptr, ptr uintptr, osize uint, nsize uint) uintptr { 260 | return uintptr((*((*Alloc)(unsafe.Pointer(fp))))(unsafe.Pointer(ptr), osize, nsize)) 261 | } 262 | 263 | //export go_panic_msghandler 264 | func go_panic_msghandler(gostateindex uintptr, z *C.char) { 265 | L := getGoState(gostateindex) 266 | s := C.GoString(z) 267 | 268 | panic(&LuaError{LUA_ERRERR, s, L.StackTrace()}) 269 | } 270 | -------------------------------------------------------------------------------- /luac/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "unsafe" 7 | 8 | "github.com/aarzilli/golua/lua" 9 | ) 10 | 11 | // Lua documentation: http://www.lua.org/manual/5.1/manual.html 12 | // Simple classes in Lua: http://lua-users.org/wiki/SimpleLuaClasses 13 | 14 | func runGlobalVar(L *lua.State) { 15 | fmt.Printf("runGlobalVar, top stack: %d\n", L.GetTop()) 16 | 17 | // Lua is a stack, so we get the object and check it's value off of it. 18 | L.GetGlobal("GLOBAL_VAR") // Load our global variable 19 | if L.IsString(-1) { 20 | // print the value 21 | globalVarStr := L.ToString(-1) 22 | log.Printf("GLOBAL_VAR = %s\n", globalVarStr) 23 | } 24 | // clean up the stack... 25 | L.Remove(-1) 26 | } 27 | 28 | func runInvalidVar(L *lua.State) { 29 | fmt.Printf("runInvalidVar, top stack: %d\n", L.GetTop()) 30 | 31 | // Lua is a stack, so we get the object and check it's value off of it. 32 | L.GetGlobal("ASDF_VAR") // Load our global variable 33 | if !L.IsNil(-1) { 34 | panic("this should not happen...") 35 | } 36 | L.Remove(-1) 37 | } 38 | 39 | func runSquare(L *lua.State) { 40 | fmt.Printf("runSquare, top stack: %d\n", L.GetTop()) 41 | 42 | // call our square(int) function 43 | L.GetGlobal("square") 44 | // if this function exists, we'll run it... 45 | if L.IsFunction(-1) { 46 | // put an element on the stack, in this case int(5) 47 | L.PushInteger(5) 48 | 49 | // the call function tells the stack that we are passing 50 | // one argument in and expecting one argument back 51 | if err := L.Call(1, 1); err != nil { 52 | // if err isn't nil, it's a special type - it will be *lua.LuaError 53 | if luaErr, ok := err.(*lua.LuaError); ok { 54 | log.Fatalf("Lua error: %#v\n", luaErr) 55 | } 56 | } 57 | 58 | // we have a value on the stack we can get now, our result... 59 | if L.IsNumber(-1) { 60 | log.Printf("square(5) = %d\n", L.ToInteger(-1)) 61 | } 62 | } 63 | // clean up the stack... 64 | L.Remove(-1) 65 | } 66 | 67 | func runGoTestFunc(L *lua.State) { 68 | // show us the current index of the stack... 69 | fmt.Printf("runGoTestFunc, top stack: %d\n", L.GetTop()) 70 | 71 | // call our test go function... 72 | L.GetGlobal("test_go_string") 73 | // If this function exists, we'll run it 74 | if L.IsFunction(-1) { 75 | 76 | // Our simple function here will return true if it is a string, false if it isn't... 77 | ourSimpleFn := func(L *lua.State) int { 78 | switch { 79 | case L.IsNumber(-1): 80 | log.Printf("fn(%d)\n", L.ToInteger(-1)) 81 | L.PushString("int") 82 | case L.IsString(-1): 83 | log.Printf("fn(%s)\n", L.ToString(-1)) 84 | L.PushString("string") 85 | default: 86 | log.Printf("fn(%#v)\n", L.ToGoStruct(-1)) 87 | L.PushString("unknown") 88 | } 89 | 90 | return 1 // number of return variables... 91 | } 92 | 93 | // add a closure to the stack 94 | L.PushGoClosure(ourSimpleFn) 95 | // add a string to the stack 96 | L.PushString("Hello, World!") 97 | 98 | // We're passing in 2 arguments, returning none... 99 | // This is equivalent to calling `test_go_string(ourSimpleFn, "Hello, World!")` 100 | if err := L.Call(2, 0); err != nil { 101 | // if err isn't nil, it's a special type - it will be *lua.LuaError 102 | if luaErr, ok := err.(*lua.LuaError); ok { 103 | log.Fatalf("Lua error: %#v\n", luaErr) 104 | } 105 | } 106 | 107 | // get our function back on the stack... 108 | L.GetGlobal("test_go_string") 109 | // add a closure to the stack 110 | L.PushGoClosure(ourSimpleFn) 111 | // add a int to the stack 112 | L.PushInteger(123) 113 | 114 | // We're passing in 2 arguments, returning none... 115 | // This is equivalent to calling `test_go_string(ourSimpleFn, 123)` 116 | if err := L.Call(2, 0); err != nil { 117 | // if err isn't nil, it's a special type - it will be *lua.LuaError 118 | if luaErr, ok := err.(*lua.LuaError); ok { 119 | log.Fatalf("Lua error: %#v\n", luaErr) 120 | } 121 | } 122 | } 123 | // no need to call remove, nothing added to the stack by call... 124 | } 125 | 126 | const accountName = "Account" 127 | 128 | type Account struct { 129 | Balance int64 130 | } 131 | 132 | func createAccount(L *lua.State) int { 133 | log.Println("createAccount") 134 | 135 | balance := L.ToInteger(-1) 136 | 137 | account := (*Account)(L.NewUserdata(uintptr(unsafe.Sizeof(Account{})))) 138 | L.LGetMetaTable(accountName) 139 | L.SetMetaTable(-2) 140 | 141 | account.Balance = int64(balance) 142 | 143 | return 1 144 | } 145 | 146 | func accountToString(L *lua.State) int { 147 | log.Println("accountToString") 148 | 149 | account := (*Account)(L.ToUserdata(1)) 150 | L.PushString(fmt.Sprintf("account(balance=%d)", account.Balance)) 151 | 152 | return 1 153 | } 154 | 155 | // If you are doing some global caching of objects, when the VM runs 156 | // garbage collection this runs... 157 | func accountGC(L *lua.State) int { 158 | log.Println("accountGC") 159 | 160 | account := (*Account)(L.ToUserdata(1)) 161 | log.Printf("(account(balance = %d)).__gc()\n", account.Balance) 162 | 163 | return 0 164 | } 165 | 166 | func accountEq(L *lua.State) int { 167 | log.Println("accountEq") 168 | 169 | account1 := (*Account)(L.ToUserdata(1)) 170 | account2 := (*Account)(L.ToUserdata(2)) 171 | L.PushBoolean(account1.Balance == account2.Balance) 172 | 173 | return 1 174 | } 175 | 176 | func accountWithdrawl(L *lua.State) int { 177 | log.Println("accountWithdrawl") 178 | 179 | account := (*Account)(L.ToUserdata(1)) 180 | amount := L.ToInteger(-1) 181 | account.Balance -= int64(amount) 182 | 183 | return 0 184 | } 185 | 186 | func accountBalance(L *lua.State) int { 187 | account := (*Account)(L.ToUserdata(1)) 188 | L.PushInteger(account.Balance) 189 | 190 | return 1 191 | } 192 | 193 | // http://stackoverflow.com/questions/34841773/golua-declaring-lua-class-with-defined-methods/34859174 194 | func registerAccountType(L *lua.State) { 195 | // Account = {} 196 | L.NewMetaTable(accountName) 197 | 198 | // Account.__index = Account 199 | L.LGetMetaTable(accountName) // load Account on stack 200 | L.SetField(-2, "__index") // set index to Account 201 | 202 | // The 2 lines above are the same as the following: 203 | // L.PushString("__index") 204 | // L.PushValue(-2) 205 | // L.SetTable(-3) 206 | 207 | L.SetMetaMethod("create", createAccount) 208 | L.SetMetaMethod("balance", accountBalance) 209 | L.SetMetaMethod("withdrawl", accountWithdrawl) 210 | L.SetMetaMethod("__tostring", accountToString) 211 | L.SetMetaMethod("__gc", accountGC) 212 | L.SetMetaMethod("__eq", accountEq) 213 | 214 | // Add account to the global stack 215 | L.SetGlobal(accountName) 216 | } 217 | 218 | func runMemberTest(L *lua.State) { 219 | // register our type 220 | registerAccountType(L) 221 | 222 | fmt.Printf("runMemberTest, top stack: %d\n", L.GetTop()) 223 | 224 | L.GetGlobal("account_test") 225 | if err := L.Call(0, 0); err != nil { 226 | log.Println(err) 227 | } 228 | } 229 | 230 | func runLuaC(filename string) { 231 | log.Println("Running LUAC bindings") 232 | 233 | // Initialize your state.... 234 | L := lua.NewState() // create a new VM 235 | defer L.Close() // close the VM 236 | 237 | // setup the libraries available and run our lua test file 238 | L.OpenBase() // open base library 239 | L.OpenMath() // open math library 240 | 241 | L.DoFile(filename) // panic if it doesn't compile... 242 | 243 | runGlobalVar(L) 244 | 245 | runInvalidVar(L) 246 | 247 | runSquare(L) 248 | 249 | runGoTestFunc(L) 250 | 251 | runMemberTest(L) 252 | 253 | fmt.Printf("top: %d\n", L.GetTop()) 254 | 255 | } 256 | 257 | func main() { 258 | runLuaC("test.lua") 259 | } 260 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Using Lua in GO 2 | ==================== 3 | 4 | Frustrated by a lack of documentation on the LuaJIT and Go I decided to do a quick project 5 | to test out a couple of the popular libraries I came across. 6 | 7 | 8 | 9 | ## [aarzilli/golua](https://github.com/aarzilli/golua) 10 | 11 | aarzilli/golua is a cgo project wrapping the Lua 5.1 C api. You pair it with 12 | [stevedonovan/luar](https://github.com/stevedonovan/luar) to make your life easier (use `v2` branch!) 13 | since that project will provide proxy functions to go. 14 | 15 | Challenges with this library are that it requires you to have the LuaJIT 5.1 runtime installed in your environment in order to run, and it uses `cgo` extentions to run it. 16 | 17 | This API wraps Lua 5.1, and if you are using OSX, you probably have 5.2 installed. Run the following to install the lua 5.1 JIT using homebrew: 18 | 19 | ```bash 20 | brew install lua51 21 | ``` 22 | 23 | At this point you should be able to kick off the lua5.1 env: 24 | 25 | ```bash 26 | ➜ go-lua-test lua5.1 -v 27 | Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio 28 | ``` 29 | 30 | Next install the bindings: 31 | 32 | ```bash 33 | go get -u github.com/aarzilli/golua/lua 34 | ``` 35 | 36 | #### Code Examples 37 | 38 | LuaJIT is a stack, and we will push our commands onto it to run. This is not thread safe, but you can use pooling to instantiate more than one instance and then close them all when you are done. 39 | 40 | Here's a simple example that initiaites state and then opens the basic libraries: 41 | 42 | ```go 43 | // create a new VM 44 | L := lua.NewState() 45 | // this is a convinience function that opens all standard libraries 46 | L.OpenLibs() 47 | // close the VM 48 | defer L.Close() 49 | ``` 50 | 51 | You may want to white-list the libaries you make available, and that is possible using the restricted library open functions. You can find them in this file: [https://github.com/aarzilli/golua/blob/master/lua/lua.go](https://github.com/aarzilli/golua/blob/master/lua/lua.go) 52 | 53 | Example - open just base and math library: 54 | 55 | ```go 56 | L := lua.NewState() // create a new VM 57 | L.OpenBase() // open base library 58 | L.OpenMath() // open math library 59 | defer L.Close() // close the VM 60 | ``` 61 | 62 | LuaJIT is a stack that you push onto. In order to get a function or variable, you need to pop it into the stack. 63 | 64 | In `luac/test.lua` there is a global variable `GLOBAL_VAR` that is a simple string. If I want to get the value of this string I would execute the following command: 65 | 66 | ```go 67 | // Lua is a stack, so we get the object and check it's value off of it. 68 | // Load our global variable to the stack 69 | L.GetGlobal("GLOBAL_VAR") 70 | // Get the value 71 | globalVarStr := L.ToString(-1) 72 | log.Printf("GLOBAL_VAR = %s\n", globalVarStr) 73 | // Once we're done with our result variable, we're going to want to remove it from the stack. 74 | // If we reuse this state, the stack could continue to grow! 75 | L.Remove(-1) 76 | ``` 77 | 78 | If you want to call a function, you first need to load it in the stack, push the variables you want to the stack, and then call it. 79 | 80 | Example from `luac/test.lua`: 81 | 82 | ```lua 83 | -- return the square of m -- 84 | function square(m) 85 | return m^2 86 | end 87 | ``` 88 | 89 | To call this function: 90 | 91 | ```go 92 | // load our function 93 | L.GetGlobal("square") 94 | // put an element on the stack, in this case int(5) 95 | L.PushInteger(5) 96 | // call the function (sorry ignoring the error...) 97 | // the two integers represent the number of stack variables in, numuber of variables pushed 98 | // to the stack out... in this case, 1 in, 1 out square(5) returns 25 99 | L.Call(1, 1) 100 | // get our result 101 | result := L.ToInteger(-1) 102 | log.Printf("square(5)=%d\n", result) 103 | // Cleanup... 104 | L.Remove(-1) // or L.Pop(1) 105 | ``` 106 | 107 | Now this is a simple use case... But let's try a more exciting example where we pass in a user defined struct variable. I am creating a class `Account` similar to the one in this Lua [example](http://lua-users.org/wiki/SimpleLuaClasses 108 | ): 109 | 110 | ```lua 111 | Account = {} 112 | Account.__index = Account 113 | 114 | function Account.create(balance) 115 | local acnt = {} -- our new object 116 | setmetatable(acnt,Account) -- make Account handle lookup 117 | acnt.balance = balance -- initialize our object 118 | return acnt 119 | end 120 | 121 | function Account:withdraw(amount) 122 | self.balance = self.balance - amount 123 | end 124 | 125 | -- create and use an Account 126 | acc = Account.create(1000) 127 | acc:withdraw(100) 128 | 129 | ``` 130 | Now translate that class into a Go Struct: 131 | 132 | ```go 133 | // Create the global name 134 | const accountName = "Account" 135 | 136 | // Define the struct 137 | type Account struct { 138 | Balance int64 139 | } 140 | 141 | // Now register our struct to the Lua state: 142 | func register(L *lua.State) { 143 | // Account = {} 144 | L.NewMetaTable(accountName) 145 | 146 | // Account.__index = Account 147 | L.LGetMetaTable(accountName) // load Account on stack 148 | L.SetField(-2, "__index") // set index to Account 149 | 150 | // The 2 lines above are the same as the following: 151 | // L.PushString("__index") 152 | // L.PushValue(-2) 153 | // L.SetTable(-3) 154 | 155 | L.SetMetaMethod("create", createAccount) 156 | L.SetMetaMethod("balance", accountBalance) 157 | L.SetMetaMethod("withdrawl", accountWithdrawl) 158 | 159 | // Add account to the global stack 160 | L.SetGlobal(accountName) 161 | } 162 | 163 | func createAccount(L *lua.State) int { 164 | // pop the integer value from the stack 165 | balance := L.ToInteger(-1) 166 | // get the pointer reference to our self object 167 | account := (*Account)(L.NewUserdata(uintptr(unsafe.Sizeof(Account{})))) 168 | L.LGetMetaTable(accountName) 169 | L.SetMetaTable(-2) 170 | // set the value 171 | account.Balance = int64(balance) 172 | // number of args returning 173 | return 1 174 | } 175 | 176 | func accountWithdrawl(L *lua.State) int { 177 | // get the self arg 178 | account := (*Account)(L.ToUserdata(1)) 179 | // get the amount 180 | amount := L.ToInteger(-1) 181 | // set the balance 182 | account.Balance -= int64(amount) 183 | // number of args returning 184 | return 0 185 | } 186 | 187 | func accountBalance(L *lua.State) int { 188 | // get the self arg 189 | account := (*Account)(L.ToUserdata(1)) 190 | // push the value 191 | L.PushInteger(account.Balance) 192 | // number of args returning 193 | return 1 194 | } 195 | ``` 196 | Member variables in Lua are accessed using `act:balance()` This is functionally equivalent to `Account.balance(act)`, where `act == self` 197 | 198 | If you look at `luac/main.go` there are more examples to play with. 199 | 200 | There's a number of helper functions to help you to make sure you can test to see what the type of 201 | 202 | #### LuaR 203 | 204 | [LuaR](https://github.com/stevedonovan/luar/tree/v2) is a helpful library that will wrap some of the terse stack code to make it easy to push/pop functions into the LuaJIT heap. Keep in mind, `v2` branch 205 | is the best one to use. 206 | 207 | There is some sample code wrapping Go/Lua code in `luar/main.go` 208 | 209 | 210 | ## [shopify/go-lua](https://github.com/Shopify/go-lua) 211 | This library has the Lua 5.2 VM implemented entirely in go! Sacraficing some performance for ultimate portability. 212 | 213 | I have implemented the same functions in this embedded VM to show similarities to golua. From their own documentation portability comes at the sacrafice of performance - this is an order of magnitude slower than the C bindings. 214 | 215 | ## [yuin/gopher-lua](https://github.com/yuin/gopher-lua) 216 | This is another all in one library. Since I went through the trouble for go-lua, I figured it couldn't hurt to have some more examples. This library is faster than Shopify's implementation. 217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /vendor/github.com/stevedonovan/luar/proxy.go: -------------------------------------------------------------------------------- 1 | package luar 2 | 3 | import ( 4 | "fmt" 5 | "reflect" 6 | "strconv" 7 | "sync" 8 | 9 | "github.com/aarzilli/golua/lua" 10 | ) 11 | 12 | // Lua proxy objects for Go slices, maps and structs 13 | // TODO: Replace by interface{}? 14 | type valueProxy struct { 15 | v reflect.Value 16 | t reflect.Type 17 | } 18 | 19 | const ( 20 | cNumberMeta = "numberMT" 21 | cComplexMeta = "complexMT" 22 | cStringMeta = "stringMT" 23 | cSliceMeta = "sliceMT" 24 | cMapMeta = "mapMT" 25 | cStructMeta = "structMT" 26 | cInterfaceMeta = "interfaceMT" 27 | cChannelMeta = "channelMT" 28 | ) 29 | 30 | var proxyMap = map[*valueProxy]reflect.Value{} 31 | var proxymu = &sync.Mutex{} 32 | 33 | // commonKind returns the kind to which v1 and v2 can be converted with the 34 | // least information loss. 35 | func commonKind(v1, v2 reflect.Value) reflect.Kind { 36 | k1 := unsizedKind(v1) 37 | k2 := unsizedKind(v2) 38 | if k1 == k2 && (k1 == reflect.Uint64 || k1 == reflect.Int64) { 39 | return k1 40 | } 41 | if k1 == reflect.Complex128 || k2 == reflect.Complex128 { 42 | return reflect.Complex128 43 | } 44 | return reflect.Float64 45 | } 46 | 47 | func isPointerToPrimitive(v reflect.Value) bool { 48 | return v.Kind() == reflect.Ptr && v.Elem().IsValid() && v.Elem().Type() != nil 49 | } 50 | 51 | func isPredeclaredType(t reflect.Type) bool { 52 | return t == reflect.TypeOf(0.0) || t == reflect.TypeOf("") 53 | } 54 | 55 | func isValueProxy(L *lua.State, idx int) bool { 56 | res := false 57 | if L.IsUserdata(idx) { 58 | L.GetMetaTable(idx) 59 | if !L.IsNil(-1) { 60 | L.GetField(-1, "luago.value") 61 | res = !L.IsNil(-1) 62 | L.Pop(1) 63 | } 64 | L.Pop(1) 65 | } 66 | return res 67 | } 68 | 69 | func luaToGoValue(L *lua.State, idx int) (reflect.Value, reflect.Type) { 70 | var a interface{} 71 | err := LuaToGo(L, idx, &a) 72 | if err != nil { 73 | L.RaiseError(err.Error()) 74 | } 75 | return reflect.ValueOf(a), reflect.TypeOf(a) 76 | } 77 | 78 | func makeValueProxy(L *lua.State, v reflect.Value, proxyMT string) { 79 | // The metatable needs be set up in the Lua state before the proxy is created, 80 | // otherwise closing the state will fail on calling the garbage collector. Not 81 | // really sure why this happens though... 82 | L.LGetMetaTable(proxyMT) 83 | if L.IsNil(-1) { 84 | flagValue := func() { 85 | L.SetMetaMethod("__tostring", proxy__tostring) 86 | L.SetMetaMethod("__gc", proxy__gc) 87 | L.SetMetaMethod("__eq", proxy__eq) 88 | L.PushBoolean(true) 89 | L.SetField(-2, "luago.value") 90 | L.Pop(1) 91 | } 92 | switch proxyMT { 93 | case cNumberMeta: 94 | L.NewMetaTable(proxyMT) 95 | L.SetMetaMethod("__index", interface__index) 96 | L.SetMetaMethod("__lt", number__lt) 97 | L.SetMetaMethod("__add", number__add) 98 | L.SetMetaMethod("__sub", number__sub) 99 | L.SetMetaMethod("__mul", number__mul) 100 | L.SetMetaMethod("__div", number__div) 101 | L.SetMetaMethod("__mod", number__mod) 102 | L.SetMetaMethod("__pow", number__pow) 103 | L.SetMetaMethod("__unm", number__unm) 104 | flagValue() 105 | case cComplexMeta: 106 | L.NewMetaTable(proxyMT) 107 | L.SetMetaMethod("__index", complex__index) 108 | L.SetMetaMethod("__add", number__add) 109 | L.SetMetaMethod("__sub", number__sub) 110 | L.SetMetaMethod("__mul", number__mul) 111 | L.SetMetaMethod("__div", number__div) 112 | L.SetMetaMethod("__pow", number__pow) 113 | L.SetMetaMethod("__unm", number__unm) 114 | flagValue() 115 | case cStringMeta: 116 | L.NewMetaTable(proxyMT) 117 | L.SetMetaMethod("__index", string__index) 118 | L.SetMetaMethod("__len", string__len) 119 | L.SetMetaMethod("__lt", string__lt) 120 | L.SetMetaMethod("__concat", string__concat) 121 | L.SetMetaMethod("__ipairs", string__ipairs) 122 | L.SetMetaMethod("__pairs", string__ipairs) 123 | flagValue() 124 | case cSliceMeta: 125 | L.NewMetaTable(proxyMT) 126 | L.SetMetaMethod("__index", slice__index) 127 | L.SetMetaMethod("__newindex", slice__newindex) 128 | L.SetMetaMethod("__len", slicemap__len) 129 | L.SetMetaMethod("__ipairs", slice__ipairs) 130 | L.SetMetaMethod("__pairs", slice__ipairs) 131 | flagValue() 132 | case cMapMeta: 133 | L.NewMetaTable(proxyMT) 134 | L.SetMetaMethod("__index", map__index) 135 | L.SetMetaMethod("__newindex", map__newindex) 136 | L.SetMetaMethod("__len", slicemap__len) 137 | L.SetMetaMethod("__ipairs", map__ipairs) 138 | L.SetMetaMethod("__pairs", map__pairs) 139 | flagValue() 140 | case cStructMeta: 141 | L.NewMetaTable(proxyMT) 142 | L.SetMetaMethod("__index", struct__index) 143 | L.SetMetaMethod("__newindex", struct__newindex) 144 | flagValue() 145 | case cInterfaceMeta: 146 | L.NewMetaTable(proxyMT) 147 | L.SetMetaMethod("__index", interface__index) 148 | flagValue() 149 | case cChannelMeta: 150 | L.NewMetaTable(proxyMT) 151 | L.SetMetaMethod("__index", channel__index) 152 | flagValue() 153 | } 154 | } 155 | L.Pop(1) 156 | rawptr := L.NewUserdata(typeof((*valueProxy)(nil)).Size()) 157 | ptr := (*valueProxy)(rawptr) 158 | ptr.v = v 159 | ptr.t = v.Type() 160 | proxymu.Lock() 161 | proxyMap[ptr] = v 162 | proxymu.Unlock() 163 | L.LGetMetaTable(proxyMT) 164 | L.SetMetaTable(-2) 165 | } 166 | 167 | func pushGoMethod(L *lua.State, name string, v reflect.Value) { 168 | method := v.MethodByName(name) 169 | if !method.IsValid() { 170 | t := v.Type() 171 | // Could not resolve this method. Perhaps it's defined on the pointer? 172 | if t.Kind() != reflect.Ptr { 173 | if v.CanAddr() { 174 | // If we can get a pointer directly. 175 | v = v.Addr() 176 | } else { 177 | // Otherwise create and initialize one. 178 | vp := reflect.New(t) 179 | vp.Elem().Set(v) 180 | v = vp 181 | } 182 | } 183 | method = v.MethodByName(name) 184 | if !method.IsValid() { 185 | L.PushNil() 186 | return 187 | } 188 | } 189 | GoToLua(L, method) 190 | } 191 | 192 | // pushNumberValue pushes the number resulting from an arithmetic operation. 193 | // 194 | // At least one operand must be a proxy for this function to be called. See the 195 | // main documentation for the conversion rules. 196 | func pushNumberValue(L *lua.State, a interface{}, t1, t2 reflect.Type) { 197 | v := reflect.ValueOf(a) 198 | isComplex := unsizedKind(v) == reflect.Complex128 199 | mt := cNumberMeta 200 | if isComplex { 201 | mt = cComplexMeta 202 | } 203 | if t1 == t2 || isPredeclaredType(t2) { 204 | makeValueProxy(L, v.Convert(t1), mt) 205 | } else if isPredeclaredType(t1) { 206 | makeValueProxy(L, v.Convert(t2), mt) 207 | } else if isComplex { 208 | complexType := reflect.TypeOf(0i) 209 | makeValueProxy(L, v.Convert(complexType), cComplexMeta) 210 | } else { 211 | L.PushNumber(valueToNumber(L, v)) 212 | } 213 | } 214 | 215 | func slicer(L *lua.State, v reflect.Value, metatable string) lua.LuaGoFunction { 216 | return func(L *lua.State) int { 217 | L.CheckInteger(1) 218 | L.CheckInteger(2) 219 | i := L.ToInteger(1) - 1 220 | j := L.ToInteger(2) - 1 221 | if i < 0 || i >= v.Len() || i > j || j > v.Len() { 222 | L.RaiseError("slice bounds out of range") 223 | } 224 | vn := v.Slice(i, j) 225 | makeValueProxy(L, vn, metatable) 226 | return 1 227 | } 228 | } 229 | 230 | // Shorthand for kind-switches. 231 | func unsizedKind(v reflect.Value) reflect.Kind { 232 | switch v.Kind() { 233 | case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 234 | return reflect.Int64 235 | case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 236 | return reflect.Uint64 237 | case reflect.Float64, reflect.Float32: 238 | return reflect.Float64 239 | case reflect.Complex128, reflect.Complex64: 240 | return reflect.Complex128 241 | } 242 | return v.Kind() 243 | } 244 | 245 | func valueOfProxy(L *lua.State, idx int) (reflect.Value, reflect.Type) { 246 | proxy := (*valueProxy)(L.ToUserdata(idx)) 247 | return proxy.v, proxy.t 248 | } 249 | 250 | func valueToComplex(L *lua.State, v reflect.Value) complex128 { 251 | if unsizedKind(v) == reflect.Complex128 { 252 | return v.Complex() 253 | } 254 | return complex(valueToNumber(L, v), 0) 255 | } 256 | 257 | func valueToNumber(L *lua.State, v reflect.Value) float64 { 258 | switch unsizedKind(v) { 259 | case reflect.Int64: 260 | return float64(v.Int()) 261 | case reflect.Uint64: 262 | return float64(v.Uint()) 263 | case reflect.Float64: 264 | return v.Float() 265 | case reflect.String: 266 | if f, err := strconv.ParseFloat(v.String(), 64); err == nil { 267 | return f 268 | } 269 | } 270 | L.RaiseError(fmt.Sprintf("cannot convert %#v to number", v)) 271 | return 0 272 | } 273 | 274 | func valueToString(L *lua.State, v reflect.Value) string { 275 | switch unsizedKind(v) { 276 | case reflect.Uint64, reflect.Int64, reflect.Float64: 277 | return fmt.Sprintf("%v", valueToNumber(L, v)) 278 | case reflect.String: 279 | return v.String() 280 | } 281 | L.RaiseError("cannot convert to string") 282 | return "" 283 | } 284 | -------------------------------------------------------------------------------- /vendor/github.com/aarzilli/golua/lua/lua_test.go: -------------------------------------------------------------------------------- 1 | package lua 2 | 3 | import ( 4 | "testing" 5 | "unsafe" 6 | ) 7 | 8 | type TestStruct struct { 9 | IntField int 10 | StringField string 11 | FloatField float64 12 | } 13 | 14 | func TestGoStruct(t *testing.T) { 15 | L := NewState() 16 | L.OpenLibs() 17 | defer L.Close() 18 | 19 | ts := &TestStruct{10, "test", 2.3} 20 | 21 | L.CheckStack(1) 22 | 23 | L.PushGoStruct(ts) 24 | L.SetGlobal("t") 25 | 26 | L.GetGlobal("t") 27 | if !L.IsGoStruct(-1) { 28 | t.Fatal("Not go struct") 29 | } 30 | 31 | tsr := L.ToGoStruct(-1).(*TestStruct) 32 | if tsr != ts { 33 | t.Fatal("Retrieved something different from what we inserted") 34 | } 35 | 36 | L.Pop(1) 37 | 38 | L.PushString("This is not a struct") 39 | if L.ToGoStruct(-1) != nil { 40 | t.Fatal("Non-GoStruct value attempted to convert into GoStruct should result in nil") 41 | } 42 | 43 | L.Pop(1) 44 | } 45 | 46 | func TestCheckStringSuccess(t *testing.T) { 47 | L := NewState() 48 | L.OpenLibs() 49 | defer L.Close() 50 | 51 | Test := func(L *State) int { 52 | L.PushString("this is a test") 53 | L.CheckString(-1) 54 | return 0 55 | } 56 | 57 | L.Register("test", Test) 58 | err := L.DoString("test()") 59 | if err != nil { 60 | t.Fatalf("DoString did return an error: %v\n", err.Error()) 61 | } 62 | } 63 | 64 | func TestCheckStringFail(t *testing.T) { 65 | L := NewState() 66 | L.OpenLibs() 67 | defer L.Close() 68 | 69 | Test := func(L *State) int { 70 | L.CheckString(-1) 71 | return 0 72 | } 73 | 74 | L.Register("test", Test) 75 | err := L.DoString("test();") 76 | if err == nil { 77 | t.Fatal("DoString did not return an error\n") 78 | } 79 | } 80 | 81 | func TestPCallHidden(t *testing.T) { 82 | L := NewState() 83 | L.OpenLibs() 84 | defer L.Close() 85 | 86 | err := L.DoString("pcall(print, \"ciao\")") 87 | if err == nil { 88 | t.Fatal("Can use pcall\n") 89 | } 90 | 91 | err = L.DoString("unsafe_pcall(print, \"ciao\")") 92 | if err != nil { 93 | t.Fatal("Can not use unsafe_pcall\n") 94 | } 95 | } 96 | 97 | func TestCall(t *testing.T) { 98 | L := NewState() 99 | L.OpenLibs() 100 | defer L.Close() 101 | 102 | test := func(L *State) int { 103 | arg1 := L.ToString(1) 104 | arg2 := L.ToString(2) 105 | arg3 := L.ToString(3) 106 | 107 | if arg1 != "Argument1" { 108 | t.Fatal("Got wrong argument (1)") 109 | } 110 | 111 | if arg2 != "Argument2" { 112 | t.Fatal("Got wrong argument (2)") 113 | } 114 | 115 | if arg3 != "Argument3" { 116 | t.Fatal("Got wrong argument (3)") 117 | } 118 | 119 | L.PushString("Return1") 120 | L.PushString("Return2") 121 | 122 | return 2 123 | } 124 | 125 | L.Register("test", test) 126 | 127 | L.PushString("Dummy") 128 | L.GetGlobal("test") 129 | L.PushString("Argument1") 130 | L.PushString("Argument2") 131 | L.PushString("Argument3") 132 | err := L.Call(3, 2) 133 | 134 | if err != nil { 135 | t.Fatalf("Error executing call: %v\n", err) 136 | } 137 | 138 | dummy := L.ToString(1) 139 | ret1 := L.ToString(2) 140 | ret2 := L.ToString(3) 141 | 142 | if dummy != "Dummy" { 143 | t.Fatal("The stack was disturbed") 144 | } 145 | 146 | if ret1 != "Return1" { 147 | t.Fatalf("Wrong return value (1) got: <%s>", ret1) 148 | } 149 | 150 | if ret2 != "Return2" { 151 | t.Fatalf("Wrong return value (2) got: <%s>", ret2) 152 | } 153 | } 154 | 155 | // equivalent to basic.go 156 | func TestLikeBasic(t *testing.T) { 157 | L := NewState() 158 | defer L.Close() 159 | L.OpenLibs() 160 | 161 | testCalled := 0 162 | 163 | test := func(L *State) int { 164 | testCalled++ 165 | return 0 166 | } 167 | 168 | test2Arg := -1 169 | test2Argfrombottom := -1 170 | test2 := func(L *State) int { 171 | test2Arg = L.CheckInteger(-1) 172 | test2Argfrombottom = L.CheckInteger(1) 173 | return 0 174 | } 175 | 176 | L.GetField(LUA_GLOBALSINDEX, "print") 177 | L.PushString("Hello World!") 178 | if err := L.Call(1, 0); err != nil { 179 | t.Fatalf("Call to print returned error") 180 | } 181 | 182 | L.PushGoFunction(test) 183 | L.PushGoFunction(test) 184 | L.PushGoFunction(test) 185 | L.PushGoFunction(test2) 186 | L.PushInteger(42) 187 | if err := L.Call(1, 0); err != nil { 188 | t.Fatalf("Call to print returned error") 189 | } 190 | if (test2Arg != 42) || (test2Argfrombottom != 42) { 191 | t.Fatalf("Call to test2 didn't work") 192 | } 193 | 194 | if err := L.Call(0, 0); err != nil { 195 | t.Fatalf("Call to print returned error") 196 | } 197 | if err := L.Call(0, 0); err != nil { 198 | t.Fatalf("Call to print returned error") 199 | } 200 | if err := L.Call(0, 0); err != nil { 201 | t.Fatalf("Call to print returned error") 202 | } 203 | if testCalled != 3 { 204 | t.Fatalf("Test function not called the correct number of times: %d\n", testCalled) 205 | } 206 | 207 | // this will fail as we didn't register test2 function 208 | if err := L.DoString("test2(42)"); err == nil { 209 | t.Fatal("No error when calling unregistered function") 210 | } 211 | } 212 | 213 | // equivalent to quickstart.go 214 | func TestLikeQuickstart(t *testing.T) { 215 | adder := func(L *State) int { 216 | a := L.ToInteger(1) 217 | b := L.ToInteger(2) 218 | L.PushInteger(int64(a + b)) 219 | return 1 220 | } 221 | 222 | L := NewState() 223 | defer L.Close() 224 | L.OpenLibs() 225 | 226 | L.Register("adder", adder) 227 | 228 | if err := L.DoString("return adder(2, 2)"); err != nil { 229 | t.Fatalf("Error during call to adder: %v\n", err) 230 | } 231 | if r := L.ToInteger(1); r != 4 { 232 | t.Fatalf("Wrong return value from adder (was: %d)\n", r) 233 | } 234 | } 235 | 236 | // equivalent to userdata.go 237 | func TestLikeUserdata(t *testing.T) { 238 | type Userdata struct { 239 | a, b int 240 | } 241 | 242 | userDataProper := func(L *State) { 243 | rawptr := L.NewUserdata(uintptr(unsafe.Sizeof(Userdata{}))) 244 | var ptr *Userdata 245 | ptr = (*Userdata)(rawptr) 246 | ptr.a = 2 247 | ptr.b = 3 248 | 249 | rawptr2 := L.ToUserdata(-1) 250 | ptr2 := (*Userdata)(rawptr2) 251 | 252 | if ptr != ptr2 { 253 | t.Fatalf("Failed to create userdata\n") 254 | } 255 | } 256 | 257 | testCalled := 0 258 | test := func(L *State) int { 259 | testCalled++ 260 | return 0 261 | } 262 | 263 | goDefinedFunctions := func(L *State) { 264 | // example_function is registered inside Lua VM 265 | L.Register("test", test) 266 | 267 | // This code demonstrates checking that a value on the stack is a go function 268 | L.CheckStack(1) 269 | L.GetGlobal("test") 270 | if !L.IsGoFunction(-1) { 271 | t.Fatalf("IsGoFunction failed to recognize a Go function object") 272 | } 273 | L.Pop(1) 274 | 275 | // We call example_function from inside Lua VM 276 | testCalled = 0 277 | if err := L.DoString("test()"); err != nil { 278 | t.Fatalf("Error executing test function: %v\n", err) 279 | } 280 | if testCalled != 1 { 281 | t.Fatalf("It appears the test function wasn't actually called\n") 282 | } 283 | } 284 | 285 | type TestObject struct { 286 | AField int 287 | } 288 | 289 | goDefinedObjects := func(L *State) { 290 | z := &TestObject{42} 291 | 292 | L.PushGoStruct(z) 293 | L.SetGlobal("z") 294 | 295 | // This code demonstrates checking that a value on the stack is a go object 296 | L.CheckStack(1) 297 | L.GetGlobal("z") 298 | if !L.IsGoStruct(-1) { 299 | t.Fatal("IsGoStruct failed to recognize a Go struct\n") 300 | } 301 | L.Pop(1) 302 | 303 | // This code demonstrates access and assignment to a field of a go object 304 | if err := L.DoString("return z.AField"); err != nil { 305 | t.Fatal("Couldn't execute code") 306 | } 307 | before := L.ToInteger(-1) 308 | L.Pop(1) 309 | if before != 42 { 310 | t.Fatalf("Wrong value of z.AField before change (%d)\n", before) 311 | } 312 | if err := L.DoString("z.AField = 10;"); err != nil { 313 | t.Fatal("Couldn't execute code") 314 | } 315 | if err := L.DoString("return z.AField"); err != nil { 316 | t.Fatal("Couldn't execute code") 317 | } 318 | after := L.ToInteger(-1) 319 | L.Pop(1) 320 | if after != 10 { 321 | t.Fatalf("Wrong value of z.AField after change (%d)\n", after) 322 | } 323 | } 324 | 325 | L := NewState() 326 | defer L.Close() 327 | L.OpenLibs() 328 | 329 | userDataProper(L) 330 | goDefinedFunctions(L) 331 | goDefinedObjects(L) 332 | } 333 | 334 | func TestStackTrace(t *testing.T) { 335 | L := NewState() 336 | defer L.Close() 337 | L.OpenLibs() 338 | 339 | err := L.DoFile("../example/calls.lua") 340 | if err == nil { 341 | t.Fatal("No error returned from the execution of calls.lua") 342 | } 343 | 344 | le := err.(*LuaError) 345 | 346 | if le.Code() != LUA_ERRERR { 347 | t.Fatalf("Wrong kind of error encountered running calls.lua: %v (%d %d)\n", le, le.Code(), LUA_ERRERR) 348 | } 349 | 350 | if len(le.StackTrace()) != 6 { 351 | t.Fatalf("Wrong size of stack trace (%v)\n", le.StackTrace()) 352 | } 353 | } 354 | 355 | func TestConv(t *testing.T) { 356 | L := NewState() 357 | defer L.Close() 358 | L.OpenLibs() 359 | 360 | L.PushString("10") 361 | n := L.ToNumber(-1) 362 | if n != 10 { 363 | t.Fatalf("Wrong conversion (str -> int)") 364 | } 365 | if L.Type(-1) != LUA_TSTRING { 366 | t.Fatalf("Wrong type (str)") 367 | } 368 | 369 | L.Pop(1) 370 | 371 | L.PushInteger(10) 372 | s := L.ToString(-1) 373 | if s != "10" { 374 | t.Fatalf("Wrong conversion (int -> str)") 375 | } 376 | 377 | L.Pop(1) 378 | 379 | L.PushString("a\000test") 380 | s = L.ToString(-1) 381 | if s != "a\000test" { 382 | t.Fatalf("Wrong conversion (str -> str): <%s>", s) 383 | } 384 | } 385 | -------------------------------------------------------------------------------- /vendor/github.com/aarzilli/golua/lua/c-golua.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "_cgo_export.h" 7 | 8 | #define MT_GOFUNCTION "GoLua.GoFunction" 9 | #define MT_GOINTERFACE "GoLua.GoInterface" 10 | 11 | #define GOLUA_DEFAULT_MSGHANDLER "golua_default_msghandler" 12 | 13 | static const char GoStateRegistryKey = 'k'; //golua registry key 14 | static const char PanicFIDRegistryKey = 'k'; 15 | 16 | /* taken from lua5.2 source */ 17 | void *testudata(lua_State *L, int ud, const char *tname) 18 | { 19 | void *p = lua_touserdata(L, ud); 20 | if (p != NULL) 21 | { /* value is a userdata? */ 22 | if (lua_getmetatable(L, ud)) 23 | { /* does it have a metatable? */ 24 | luaL_getmetatable(L, tname); /* get correct metatable */ 25 | if (!lua_rawequal(L, -1, -2)) /* not the same? */ 26 | p = NULL; /* value is a userdata with wrong metatable */ 27 | lua_pop(L, 2); /* remove both metatables */ 28 | return p; 29 | } 30 | } 31 | return NULL; /* value is not a userdata with a metatable */ 32 | } 33 | 34 | int clua_isgofunction(lua_State *L, int n) 35 | { 36 | return testudata(L, n, MT_GOFUNCTION) != NULL; 37 | } 38 | 39 | int clua_isgostruct(lua_State *L, int n) 40 | { 41 | return testudata(L, n, MT_GOINTERFACE) != NULL; 42 | } 43 | 44 | unsigned int* clua_checkgosomething(lua_State* L, int index, const char *desired_metatable) 45 | { 46 | if (desired_metatable != NULL) 47 | { 48 | return testudata(L, index, desired_metatable); 49 | } 50 | else 51 | { 52 | unsigned int *sid = testudata(L, index, MT_GOFUNCTION); 53 | if (sid != NULL) return sid; 54 | return testudata(L, index, MT_GOINTERFACE); 55 | } 56 | } 57 | 58 | size_t clua_getgostate(lua_State* L) 59 | { 60 | size_t gostateindex; 61 | //get gostate from registry entry 62 | lua_pushlightuserdata(L,(void*)&GoStateRegistryKey); 63 | lua_gettable(L, LUA_REGISTRYINDEX); 64 | gostateindex = (size_t)lua_touserdata(L,-1); 65 | lua_pop(L,1); 66 | return gostateindex; 67 | } 68 | 69 | 70 | //wrapper for callgofunction 71 | int callback_function(lua_State* L) 72 | { 73 | int r; 74 | unsigned int *fid = clua_checkgosomething(L, 1, MT_GOFUNCTION); 75 | size_t gostateindex = clua_getgostate(L); 76 | //remove the go function from the stack (to present same behavior as lua_CFunctions) 77 | lua_remove(L,1); 78 | return golua_callgofunction(gostateindex, fid!=NULL ? *fid : -1); 79 | } 80 | 81 | //wrapper for gchook 82 | int gchook_wrapper(lua_State* L) 83 | { 84 | //printf("Garbage collection wrapper\n"); 85 | unsigned int* fid = clua_checkgosomething(L, -1, NULL); 86 | size_t gostateindex = clua_getgostate(L); 87 | if (fid != NULL) 88 | return golua_gchook(gostateindex,*fid); 89 | return 0; 90 | } 91 | 92 | unsigned int clua_togofunction(lua_State* L, int index) 93 | { 94 | unsigned int *r = clua_checkgosomething(L, index, MT_GOFUNCTION); 95 | return (r != NULL) ? *r : -1; 96 | } 97 | 98 | unsigned int clua_togostruct(lua_State *L, int index) 99 | { 100 | unsigned int *r = clua_checkgosomething(L, index, MT_GOINTERFACE); 101 | return (r != NULL) ? *r : -1; 102 | } 103 | 104 | void clua_pushgofunction(lua_State* L, unsigned int fid) 105 | { 106 | unsigned int* fidptr = (unsigned int *)lua_newuserdata(L, sizeof(unsigned int)); 107 | *fidptr = fid; 108 | luaL_getmetatable(L, MT_GOFUNCTION); 109 | lua_setmetatable(L, -2); 110 | } 111 | 112 | static int callback_c (lua_State* L) 113 | { 114 | int fid = clua_togofunction(L,lua_upvalueindex(1)); 115 | size_t gostateindex = clua_getgostate(L); 116 | return golua_callgofunction(gostateindex,fid); 117 | } 118 | 119 | void clua_pushcallback(lua_State* L) 120 | { 121 | lua_pushcclosure(L,callback_c,1); 122 | } 123 | 124 | void clua_pushgostruct(lua_State* L, unsigned int iid) 125 | { 126 | unsigned int* iidptr = (unsigned int *)lua_newuserdata(L, sizeof(unsigned int)); 127 | *iidptr = iid; 128 | luaL_getmetatable(L, MT_GOINTERFACE); 129 | lua_setmetatable(L,-2); 130 | } 131 | 132 | int default_panicf(lua_State *L) 133 | { 134 | const char *s = lua_tostring(L, -1); 135 | printf("Lua unprotected panic: %s\n", s); 136 | abort(); 137 | } 138 | 139 | void clua_setgostate(lua_State* L, size_t gostateindex) 140 | { 141 | lua_atpanic(L, default_panicf); 142 | lua_pushlightuserdata(L,(void*)&GoStateRegistryKey); 143 | lua_pushlightuserdata(L, (void*)gostateindex); 144 | //set into registry table 145 | lua_settable(L, LUA_REGISTRYINDEX); 146 | } 147 | 148 | /* called when lua code attempts to access a field of a published go object */ 149 | int interface_index_callback(lua_State *L) 150 | { 151 | unsigned int *iid = clua_checkgosomething(L, 1, MT_GOINTERFACE); 152 | if (iid == NULL) 153 | { 154 | lua_pushnil(L); 155 | return 1; 156 | } 157 | 158 | char *field_name = (char *)lua_tostring(L, 2); 159 | if (field_name == NULL) 160 | { 161 | lua_pushnil(L); 162 | return 1; 163 | } 164 | 165 | size_t gostateindex = clua_getgostate(L); 166 | 167 | int r = golua_interface_index_callback(gostateindex, *iid, field_name); 168 | 169 | if (r < 0) 170 | { 171 | lua_error(L); 172 | return 0; 173 | } 174 | else 175 | { 176 | return r; 177 | } 178 | } 179 | 180 | /* called when lua code attempts to set a field of a published go object */ 181 | int interface_newindex_callback(lua_State *L) 182 | { 183 | unsigned int *iid = clua_checkgosomething(L, 1, MT_GOINTERFACE); 184 | if (iid == NULL) 185 | { 186 | lua_pushnil(L); 187 | return 1; 188 | } 189 | 190 | char *field_name = (char *)lua_tostring(L, 2); 191 | if (field_name == NULL) 192 | { 193 | lua_pushnil(L); 194 | return 1; 195 | } 196 | 197 | size_t gostateindex = clua_getgostate(L); 198 | 199 | int r = golua_interface_newindex_callback(gostateindex, *iid, field_name); 200 | 201 | if (r < 0) 202 | { 203 | lua_error(L); 204 | return 0; 205 | } 206 | else 207 | { 208 | return r; 209 | } 210 | } 211 | 212 | int panic_msghandler(lua_State *L) 213 | { 214 | size_t gostateindex = clua_getgostate(L); 215 | go_panic_msghandler(gostateindex, (char *)lua_tolstring(L, -1, NULL)); 216 | return 0; 217 | } 218 | 219 | void clua_hide_pcall(lua_State *L) 220 | { 221 | lua_getglobal(L, "pcall"); 222 | lua_setglobal(L, "unsafe_pcall"); 223 | lua_pushnil(L); 224 | lua_setglobal(L, "pcall"); 225 | 226 | lua_getglobal(L, "xpcall"); 227 | lua_setglobal(L, "unsafe_xpcall"); 228 | lua_pushnil(L); 229 | lua_setglobal(L, "xpcall"); 230 | } 231 | 232 | void clua_initstate(lua_State* L) 233 | { 234 | /* create the GoLua.GoFunction metatable */ 235 | luaL_newmetatable(L, MT_GOFUNCTION); 236 | 237 | // gofunction_metatable[__call] = &callback_function 238 | lua_pushliteral(L,"__call"); 239 | lua_pushcfunction(L,&callback_function); 240 | lua_settable(L,-3); 241 | 242 | // gofunction_metatable[__gc] = &gchook_wrapper 243 | lua_pushliteral(L,"__gc"); 244 | lua_pushcfunction(L,&gchook_wrapper); 245 | lua_settable(L,-3); 246 | lua_pop(L,1); 247 | 248 | luaL_newmetatable(L, MT_GOINTERFACE); 249 | 250 | // gointerface_metatable[__gc] = &gchook_wrapper 251 | lua_pushliteral(L, "__gc"); 252 | lua_pushcfunction(L, &gchook_wrapper); 253 | lua_settable(L, -3); 254 | 255 | // gointerface_metatable[__index] = &interface_index_callback 256 | lua_pushliteral(L, "__index"); 257 | lua_pushcfunction(L, &interface_index_callback); 258 | lua_settable(L, -3); 259 | 260 | // gointerface_metatable[__newindex] = &interface_newindex_callback 261 | lua_pushliteral(L, "__newindex"); 262 | lua_pushcfunction(L, &interface_newindex_callback); 263 | lua_settable(L, -3); 264 | 265 | lua_register(L, GOLUA_DEFAULT_MSGHANDLER, &panic_msghandler); 266 | lua_pop(L, 1); 267 | } 268 | 269 | 270 | int callback_panicf(lua_State* L) 271 | { 272 | lua_pushlightuserdata(L,(void*)&PanicFIDRegistryKey); 273 | lua_gettable(L,LUA_REGISTRYINDEX); 274 | unsigned int fid = lua_tointeger(L,-1); 275 | lua_pop(L,1); 276 | size_t gostateindex = clua_getgostate(L); 277 | return golua_callpanicfunction(gostateindex,fid); 278 | 279 | } 280 | 281 | //TODO: currently setting garbage when panicf set to null 282 | GoInterface clua_atpanic(lua_State* L, unsigned int panicf_id) 283 | { 284 | //get old panicfid 285 | unsigned int old_id; 286 | lua_pushlightuserdata(L, (void*)&PanicFIDRegistryKey); 287 | lua_gettable(L,LUA_REGISTRYINDEX); 288 | if(lua_isnil(L, -1) == 0) 289 | old_id = lua_tointeger(L,-1); 290 | lua_pop(L, 1); 291 | 292 | //set registry key for function id of go panic function 293 | lua_pushlightuserdata(L, (void*)&PanicFIDRegistryKey); 294 | //push id value 295 | lua_pushinteger(L, panicf_id); 296 | //set into registry table 297 | lua_settable(L, LUA_REGISTRYINDEX); 298 | 299 | //now set the panic function 300 | lua_CFunction pf = lua_atpanic(L,&callback_panicf); 301 | //make a GoInterface with a wrapped C panicf or the original go panicf 302 | if(pf == &callback_panicf) 303 | { 304 | return golua_idtointerface(old_id); 305 | } 306 | else 307 | { 308 | //TODO: technically UB, function ptr -> non function ptr 309 | return golua_cfunctiontointerface((GoUintptr *)pf); 310 | } 311 | } 312 | 313 | int clua_callluacfunc(lua_State* L, lua_CFunction f) 314 | { 315 | return f(L); 316 | } 317 | 318 | void* allocwrapper(void* ud, void *ptr, size_t osize, size_t nsize) 319 | { 320 | return (void*)golua_callallocf((GoUintptr)ud,(GoUintptr)ptr,osize,nsize); 321 | } 322 | 323 | lua_State* clua_newstate(void* goallocf) 324 | { 325 | return lua_newstate(&allocwrapper,goallocf); 326 | } 327 | 328 | void clua_setallocf(lua_State* L, void* goallocf) 329 | { 330 | lua_setallocf(L,&allocwrapper,goallocf); 331 | } 332 | 333 | void clua_openbase(lua_State* L) 334 | { 335 | lua_pushcfunction(L,&luaopen_base); 336 | lua_pushstring(L,""); 337 | lua_call(L, 1, 0); 338 | clua_hide_pcall(L); 339 | } 340 | 341 | void clua_openio(lua_State* L) 342 | { 343 | lua_pushcfunction(L,&luaopen_io); 344 | lua_pushstring(L,"io"); 345 | lua_call(L, 1, 0); 346 | } 347 | 348 | void clua_openmath(lua_State* L) 349 | { 350 | lua_pushcfunction(L,&luaopen_math); 351 | lua_pushstring(L,"math"); 352 | lua_call(L, 1, 0); 353 | } 354 | 355 | void clua_openpackage(lua_State* L) 356 | { 357 | lua_pushcfunction(L,&luaopen_package); 358 | lua_pushstring(L,"package"); 359 | lua_call(L, 1, 0); 360 | } 361 | 362 | void clua_openstring(lua_State* L) 363 | { 364 | lua_pushcfunction(L,&luaopen_string); 365 | lua_pushstring(L,"string"); 366 | lua_call(L, 1, 0); 367 | } 368 | 369 | void clua_opentable(lua_State* L) 370 | { 371 | lua_pushcfunction(L,&luaopen_table); 372 | lua_pushstring(L,"table"); 373 | lua_call(L, 1, 0); 374 | } 375 | 376 | void clua_openos(lua_State* L) 377 | { 378 | lua_pushcfunction(L,&luaopen_os); 379 | lua_pushstring(L,"os"); 380 | lua_call(L, 1, 0); 381 | } 382 | 383 | void clua_hook_function(lua_State *L, lua_Debug *ar) 384 | { 385 | lua_checkstack(L, 2); 386 | lua_pushstring(L, "Lua execution quantum exceeded"); 387 | lua_error(L); 388 | } 389 | 390 | void clua_setexecutionlimit(lua_State* L, int n) 391 | { 392 | lua_sethook(L, &clua_hook_function, LUA_MASKCOUNT, n); 393 | } 394 | 395 | 396 | -------------------------------------------------------------------------------- /vendor/github.com/stevedonovan/luar/example_test.go: -------------------------------------------------------------------------------- 1 | package luar_test 2 | 3 | // TODO: Lua's print() function will output to stdout instead of being compared 4 | // to the desired result. Workaround: register one of Go's printing functions 5 | // from the fmt library. 6 | 7 | import ( 8 | "fmt" 9 | "log" 10 | "sort" 11 | "strconv" 12 | "sync" 13 | 14 | "github.com/aarzilli/golua/lua" 15 | "github.com/stevedonovan/luar" 16 | ) 17 | 18 | func Example() { 19 | const test = ` 20 | for i = 1, 3 do 21 | print(msg, i) 22 | end 23 | print(user) 24 | print(user.Name, user.Age) 25 | ` 26 | 27 | type person struct { 28 | Name string 29 | Age int 30 | } 31 | 32 | L := luar.Init() 33 | defer L.Close() 34 | 35 | user := &person{"Dolly", 46} 36 | 37 | luar.Register(L, "", luar.Map{ 38 | // Go functions may be registered directly. 39 | "print": fmt.Println, 40 | // Constants can be registered. 41 | "msg": "foo", 42 | // And other values as well. 43 | "user": user, 44 | }) 45 | 46 | L.DoString(test) 47 | // Output: 48 | // foo 1 49 | // foo 2 50 | // foo 3 51 | // &{Dolly 46} 52 | // Dolly 46 53 | } 54 | 55 | // Pointers to structs and structs within pointers are automatically dereferenced. 56 | func Example_pointers() { 57 | const test = ` 58 | local t = newRef() 59 | print(t.Index, t.Number, t.Title) 60 | ` 61 | 62 | type Ref struct { 63 | Index int 64 | Number *int 65 | Title *string 66 | } 67 | 68 | newRef := func() *Ref { 69 | n := new(int) 70 | *n = 10 71 | t := new(string) 72 | *t = "foo" 73 | return &Ref{Index: 17, Number: n, Title: t} 74 | } 75 | 76 | L := luar.Init() 77 | defer L.Close() 78 | 79 | luar.Register(L, "", luar.Map{ 80 | "print": fmt.Println, 81 | "newRef": newRef, 82 | }) 83 | 84 | L.DoString(test) 85 | // Output: 86 | // 17 10 foo 87 | } 88 | 89 | // Slices must be looped over with 'ipairs'. 90 | func Example_slices() { 91 | const test = ` 92 | for i, v in ipairs(names) do 93 | print(i, v) 94 | end 95 | ` 96 | 97 | L := luar.Init() 98 | defer L.Close() 99 | 100 | names := []string{"alfred", "alice", "bob", "frodo"} 101 | 102 | luar.Register(L, "", luar.Map{ 103 | "print": fmt.Println, 104 | "names": names, 105 | }) 106 | 107 | L.DoString(test) 108 | // Output: 109 | // 1 alfred 110 | // 2 alice 111 | // 3 bob 112 | // 4 frodo 113 | } 114 | 115 | // Init() is not needed when no proxy is involved. 116 | func ExampleGoToLua() { 117 | L := lua.NewState() 118 | defer L.Close() 119 | L.OpenLibs() 120 | 121 | input := "Hello world!" 122 | luar.GoToLua(L, input) 123 | L.SetGlobal("input") 124 | 125 | luar.GoToLua(L, fmt.Println) 126 | L.SetGlobal("print") 127 | L.DoString("print(input)") 128 | // Output: 129 | // Hello world! 130 | } 131 | 132 | // This example shows how Go slices and maps are marshalled to Lua tables and 133 | // vice versa. 134 | // 135 | // An arbitrary Go function is callable from Lua, and list-like tables become 136 | // slices on the Go side. The Go function returns a map, which is wrapped as a 137 | // proxy object. You can copy this proxy to a Lua table explicitly. There is 138 | // also `luar.unproxify` on the Lua side to do this. 139 | // 140 | // We initialize the state with Init() to register Unproxify() as 'luar.unproxify()'. 141 | func ExampleInit() { 142 | const code = ` 143 | -- Lua tables auto-convert to slices in Go-function calls. 144 | local res = foo {10, 20, 30, 40} 145 | 146 | -- The result is a map-proxy. 147 | print(res['1'], res['2']) 148 | 149 | -- Which we may explicitly convert to a table. 150 | res = luar.unproxify(res) 151 | for k,v in pairs(res) do 152 | print(k,v) 153 | end 154 | ` 155 | 156 | foo := func(args []int) (res map[string]int) { 157 | res = make(map[string]int) 158 | for i, val := range args { 159 | res[strconv.Itoa(i)] = val * val 160 | } 161 | return 162 | } 163 | 164 | L := luar.Init() 165 | defer L.Close() 166 | 167 | luar.Register(L, "", luar.Map{ 168 | "foo": foo, 169 | "print": fmt.Println, 170 | }) 171 | 172 | res := L.DoString(code) 173 | if res != nil { 174 | fmt.Println("Error:", res) 175 | } 176 | // Output: 177 | // 400 900 178 | // 1 400 179 | // 0 100 180 | // 3 1600 181 | // 2 900 182 | } 183 | 184 | func ExampleLuaObject_Call() { 185 | L := luar.Init() 186 | defer L.Close() 187 | 188 | const code = ` 189 | function return_strings() 190 | return 'one', luar.null, 'three' 191 | end` 192 | 193 | err := L.DoString(code) 194 | if err != nil { 195 | log.Fatal(err) 196 | } 197 | 198 | fun := luar.NewLuaObjectFromName(L, "return_strings") 199 | defer fun.Close() 200 | 201 | // Using `Call` we would get a generic `[]interface{}`, which is awkward to 202 | // work with. But the return type can be specified: 203 | results := []string{} 204 | err = fun.Call(&results) 205 | if err != nil { 206 | log.Fatal(err) 207 | } 208 | 209 | fmt.Println(results[0]) 210 | // We get an empty string corresponding to a luar.null in a table, 211 | // since that's the empty 'zero' value for a string. 212 | fmt.Println(results[1]) 213 | fmt.Println(results[2]) 214 | // Output: 215 | // one 216 | // 217 | // three 218 | } 219 | 220 | func ExampleMap() { 221 | const code = ` 222 | print(#M) 223 | print(M.one) 224 | print(M.two) 225 | print(M.three) 226 | ` 227 | 228 | L := luar.Init() 229 | defer L.Close() 230 | 231 | M := luar.Map{ 232 | "one": "eins", 233 | "two": "zwei", 234 | "three": "drei", 235 | } 236 | 237 | luar.Register(L, "", luar.Map{ 238 | "M": M, 239 | "print": fmt.Println, 240 | }) 241 | 242 | err := L.DoString(code) 243 | if err != nil { 244 | fmt.Println("error", err.Error()) 245 | } 246 | // Output: 247 | // 3 248 | // eins 249 | // zwei 250 | // drei 251 | } 252 | 253 | func ExampleMakeChan() { 254 | L1 := luar.Init() 255 | defer L1.Close() 256 | L2 := luar.Init() 257 | defer L2.Close() 258 | 259 | luar.MakeChan(L1) 260 | L1.SetGlobal("c") 261 | L1.GetGlobal("c") 262 | var c interface{} 263 | err := luar.LuaToGo(L1, -1, &c) 264 | L1.Pop(1) 265 | if err != nil { 266 | log.Fatal(err) 267 | } 268 | 269 | luar.Register(L2, "", luar.Map{"c": c}) 270 | var wg sync.WaitGroup 271 | wg.Add(1) 272 | 273 | go func() { 274 | err := L1.DoString(`c.send(17)`) 275 | if err != nil { 276 | fmt.Println(err) 277 | } 278 | wg.Done() 279 | }() 280 | 281 | err = L2.DoString(`return c.recv()`) 282 | if err != nil { 283 | fmt.Println(err) 284 | } 285 | fmt.Println(L2.ToNumber(-1)) 286 | L2.Pop(1) 287 | wg.Wait() 288 | // Output: 289 | // 17 290 | } 291 | 292 | // Another way to do parse configs: use a LuaObject to manipulate the table. 293 | func ExampleNewLuaObject() { 294 | L := luar.Init() 295 | defer L.Close() 296 | 297 | const config = `return { 298 | baggins = true, 299 | age = 24, 300 | name = 'dumbo' , 301 | marked = {1,2}, 302 | options = { 303 | leave = true, 304 | cancel = 'always', 305 | tags = {strong=true, foolish=true}, 306 | } 307 | }` 308 | 309 | err := L.DoString(config) 310 | if err != nil { 311 | log.Fatal(err) 312 | } 313 | 314 | lo := luar.NewLuaObject(L, -1) 315 | defer lo.Close() 316 | // Can get the field itself as a Lua object, and so forth. 317 | opts, _ := lo.GetObject("options") 318 | marked, _ := lo.GetObject("marked") 319 | 320 | loPrint := func(lo *luar.LuaObject, subfields ...interface{}) { 321 | var a interface{} 322 | lo.Get(&a, subfields...) 323 | fmt.Printf("%#v\n", a) 324 | } 325 | loPrinti := func(lo *luar.LuaObject, idx int64) { 326 | var a interface{} 327 | lo.Get(&a, idx) 328 | fmt.Printf("%.1f\n", a) 329 | } 330 | loPrint(lo, "baggins") 331 | loPrint(lo, "name") 332 | loPrint(opts, "leave") 333 | // Note that these Get methods understand nested fields. 334 | loPrint(lo, "options", "leave") 335 | loPrint(lo, "options", "tags", "strong") 336 | // Non-existent nested fields don't panic but return nil. 337 | loPrint(lo, "options", "tags", "extra", "flakey") 338 | loPrinti(marked, 1) 339 | 340 | iter, err := lo.Iter() 341 | if err != nil { 342 | log.Fatal(err) 343 | } 344 | keys := []string{} 345 | for key := ""; iter.Next(&key, nil); { 346 | keys = append(keys, key) 347 | } 348 | if iter.Error() != nil { 349 | log.Fatal(iter.Error()) 350 | } 351 | sort.Strings(keys) 352 | 353 | fmt.Println("Keys:") 354 | for _, v := range keys { 355 | fmt.Println(v) 356 | } 357 | // Output: 358 | // true 359 | // "dumbo" 360 | // true 361 | // true 362 | // true 363 | // 364 | // 1.0 365 | // Keys: 366 | // age 367 | // baggins 368 | // marked 369 | // name 370 | // options 371 | 372 | } 373 | 374 | func ExampleNewLuaObjectFromValue() { 375 | L := luar.Init() 376 | defer L.Close() 377 | 378 | gsub := luar.NewLuaObjectFromName(L, "string", "gsub") 379 | defer gsub.Close() 380 | 381 | // We do have to explicitly copy the map to a Lua table, because `gsub` 382 | // will not handle userdata types. 383 | gmap := luar.NewLuaObjectFromValue(L, luar.Map{ 384 | "NAME": "Dolly", 385 | "HOME": "where you belong", 386 | }) 387 | defer gmap.Close() 388 | 389 | var res = new(string) 390 | err := gsub.Call(&res, "Hello $NAME, go $HOME", "%$(%u+)", gmap) 391 | if err != nil { 392 | log.Fatal(err) 393 | } 394 | 395 | fmt.Println(*res) 396 | // Output: 397 | // Hello Dolly, go where you belong 398 | } 399 | 400 | func ExampleLuaTableIter_Next() { 401 | const code = ` 402 | return { 403 | foo = 17, 404 | bar = 18, 405 | } 406 | ` 407 | 408 | L := luar.Init() 409 | defer L.Close() 410 | 411 | err := L.DoString(code) 412 | if err != nil { 413 | log.Fatal(err) 414 | } 415 | 416 | lo := luar.NewLuaObject(L, -1) 417 | defer lo.Close() 418 | 419 | iter, err := lo.Iter() 420 | if err != nil { 421 | log.Fatal(err) 422 | } 423 | keys := []string{} 424 | values := map[string]float64{} 425 | for key, value := "", 0.0; iter.Next(&key, &value); { 426 | keys = append(keys, key) 427 | values[key] = value 428 | } 429 | sort.Strings(keys) 430 | 431 | for _, v := range keys { 432 | fmt.Println(v, values[v]) 433 | } 434 | // Output: 435 | // bar 18 436 | // foo 17 437 | } 438 | 439 | func ExampleRegister_sandbox() { 440 | const code = ` 441 | print("foo") 442 | print(io ~= nil) 443 | print(os == nil) 444 | ` 445 | 446 | L := luar.Init() 447 | defer L.Close() 448 | 449 | res := L.LoadString(code) 450 | if res != 0 { 451 | msg := L.ToString(-1) 452 | fmt.Println("could not compile", msg) 453 | } 454 | 455 | // Create a empty sandbox. 456 | L.NewTable() 457 | // "*" means "use table on top of the stack." 458 | luar.Register(L, "*", luar.Map{ 459 | "print": fmt.Println, 460 | }) 461 | env := luar.NewLuaObject(L, -1) 462 | G := luar.NewLuaObjectFromName(L, "_G") 463 | defer env.Close() 464 | defer G.Close() 465 | 466 | // We can copy any Lua object from "G" to env with 'Set', e.g.: 467 | // env.Set("print", G.Get("print")) 468 | // A more convenient and efficient way is to do a bulk copy with 'Setv': 469 | env.Setv(G, "type", "io", "table") 470 | 471 | // Set up sandbox. 472 | L.SetfEnv(-2) 473 | 474 | // Run 'code' chunk. 475 | err := L.Call(0, 0) 476 | if err != nil { 477 | log.Fatal(err) 478 | } 479 | // Output: 480 | // foo 481 | // true 482 | // true 483 | } 484 | -------------------------------------------------------------------------------- /vendor/github.com/stevedonovan/luar/luaobject.go: -------------------------------------------------------------------------------- 1 | package luar 2 | 3 | import ( 4 | "errors" 5 | "reflect" 6 | 7 | "github.com/aarzilli/golua/lua" 8 | ) 9 | 10 | // LuaObject encapsulates a Lua object like a table or a function. 11 | // 12 | // We do not make the type distinction since metatables can make tables callable 13 | // and functions indexable. 14 | type LuaObject struct { 15 | l *lua.State 16 | ref int 17 | } 18 | 19 | var ( 20 | ErrLuaObjectCallResults = errors.New("results must be a pointer to pointer/slice/struct") 21 | ErrLuaObjectCallable = errors.New("LuaObject must be callable") 22 | ErrLuaObjectIndexable = errors.New("not indexable") 23 | ErrLuaObjectUnsharedState = errors.New("LuaObjects must share the same state") 24 | ) 25 | 26 | // NewLuaObject creates a new LuaObject from stack index. 27 | func NewLuaObject(L *lua.State, idx int) *LuaObject { 28 | L.PushValue(idx) 29 | ref := L.Ref(lua.LUA_REGISTRYINDEX) 30 | return &LuaObject{l: L, ref: ref} 31 | } 32 | 33 | // NewLuaObjectFromName creates a new LuaObject from the object designated by 34 | // the sequence of 'subfields'. 35 | func NewLuaObjectFromName(L *lua.State, subfields ...interface{}) *LuaObject { 36 | L.GetGlobal("_G") 37 | defer L.Pop(1) 38 | err := get(L, subfields...) 39 | if err != nil { 40 | return nil 41 | } 42 | val := NewLuaObject(L, -1) 43 | L.Pop(1) 44 | return val 45 | } 46 | 47 | // NewLuaObjectFromValue creates a new LuaObject from a Go value. 48 | // Note that this will convert any slices or maps into Lua tables. 49 | func NewLuaObjectFromValue(L *lua.State, val interface{}) *LuaObject { 50 | GoToLua(L, val) 51 | return NewLuaObject(L, -1) 52 | } 53 | 54 | // Call calls a Lua function, given the desired results and the arguments. 55 | // 'results' must be a pointer to a pointer/struct/slice. 56 | // 57 | // - If a pointer, then only the first result is stored to that pointer. 58 | // 59 | // - If a struct with 'n' fields, then the first n results are stored in the field. 60 | // 61 | // - If a slice, then all the results are stored in the slice. The slice is re-allocated if necessary. 62 | // 63 | // If the function returns more values than can be stored in the 'results' 64 | // argument, they will be ignored. 65 | // 66 | // If 'results' is nil, results will be discarded. 67 | func (lo *LuaObject) Call(results interface{}, args ...interface{}) error { 68 | L := lo.l 69 | // Push the callable value. 70 | lo.Push() 71 | if !L.IsFunction(-1) { 72 | if !L.GetMetaField(-1, "__call") { 73 | L.Pop(1) 74 | return ErrLuaObjectCallable 75 | } 76 | // We leave the __call metamethod on stack. 77 | L.Remove(-2) 78 | } 79 | 80 | // Push the args. 81 | for _, arg := range args { 82 | GoToLuaProxy(L, arg) 83 | } 84 | 85 | // Special case: discard the results. 86 | if results == nil { 87 | err := L.Call(len(args), 0) 88 | if err != nil { 89 | L.Pop(1) 90 | return err 91 | } 92 | return nil 93 | } 94 | 95 | resptr := reflect.ValueOf(results) 96 | if resptr.Kind() != reflect.Ptr { 97 | return ErrLuaObjectCallResults 98 | } 99 | res := resptr.Elem() 100 | 101 | switch res.Kind() { 102 | case reflect.Ptr: 103 | err := L.Call(len(args), 1) 104 | defer L.Pop(1) 105 | if err != nil { 106 | return err 107 | } 108 | return LuaToGo(L, -1, res.Interface()) 109 | 110 | case reflect.Slice: 111 | residx := L.GetTop() - len(args) 112 | err := L.Call(len(args), lua.LUA_MULTRET) 113 | if err != nil { 114 | L.Pop(1) 115 | return err 116 | } 117 | 118 | nresults := L.GetTop() - residx + 1 119 | defer L.Pop(nresults) 120 | t := res.Type() 121 | 122 | // Adjust the length of the slice. 123 | if res.IsNil() || nresults > res.Len() { 124 | v := reflect.MakeSlice(t, nresults, nresults) 125 | res.Set(v) 126 | } else if nresults < res.Len() { 127 | res.SetLen(nresults) 128 | } 129 | 130 | for i := 0; i < nresults; i++ { 131 | err = LuaToGo(L, residx+i, res.Index(i).Addr().Interface()) 132 | if err != nil { 133 | return err 134 | } 135 | } 136 | 137 | case reflect.Struct: 138 | exportedFields := []reflect.Value{} 139 | for i := 0; i < res.NumField(); i++ { 140 | if res.Field(i).CanInterface() { 141 | exportedFields = append(exportedFields, res.Field(i).Addr()) 142 | } 143 | } 144 | nresults := len(exportedFields) 145 | err := L.Call(len(args), nresults) 146 | if err != nil { 147 | L.Pop(1) 148 | return err 149 | } 150 | defer L.Pop(nresults) 151 | residx := L.GetTop() - nresults + 1 152 | 153 | for i := 0; i < nresults; i++ { 154 | err = LuaToGo(L, residx+i, exportedFields[i].Interface()) 155 | if err != nil { 156 | return err 157 | } 158 | } 159 | 160 | default: 161 | return ErrLuaObjectCallResults 162 | } 163 | 164 | return nil 165 | } 166 | 167 | // Close frees the Lua reference of this object. 168 | func (lo *LuaObject) Close() { 169 | lo.l.Unref(lua.LUA_REGISTRYINDEX, lo.ref) 170 | } 171 | 172 | // get pushes the Lua value indexed at the sequence of 'subfields' from the 173 | // indexable value on top of the stack. 174 | // 175 | // It pushes nothing on error. 176 | // 177 | // Numeric indices start from 1: see Set(). 178 | func get(L *lua.State, subfields ...interface{}) error { 179 | // TODO: See if worth exporting. 180 | 181 | // Duplicate iterable since the following loop removes the last table on stack 182 | // and we don't want to pop it to be consistent with lua.GetField and 183 | // lua.GetTable. 184 | L.PushValue(-1) 185 | 186 | for _, field := range subfields { 187 | if L.IsTable(-1) { 188 | GoToLua(L, field) 189 | L.GetTable(-2) 190 | } else if L.GetMetaField(-1, "__index") { 191 | L.PushValue(-2) 192 | GoToLua(L, field) 193 | err := L.Call(2, 1) 194 | if err != nil { 195 | L.Pop(1) 196 | return err 197 | } 198 | } else { 199 | return ErrLuaObjectIndexable 200 | } 201 | // Remove last iterable. 202 | L.Remove(-2) 203 | } 204 | return nil 205 | } 206 | 207 | // Get stores in 'a' the Lua value indexed at the sequence of 'subfields'. 208 | // 'a' must be a pointer as in LuaToGo. 209 | func (lo *LuaObject) Get(a interface{}, subfields ...interface{}) error { 210 | lo.Push() 211 | defer lo.l.Pop(1) 212 | err := get(lo.l, subfields...) 213 | if err != nil { 214 | return err 215 | } 216 | defer lo.l.Pop(1) 217 | return LuaToGo(lo.l, -1, a) 218 | } 219 | 220 | // GetObject returns the LuaObject indexed at the sequence of 'subfields'. 221 | func (lo *LuaObject) GetObject(subfields ...interface{}) (*LuaObject, error) { 222 | lo.Push() 223 | defer lo.l.Pop(1) 224 | err := get(lo.l, subfields...) 225 | if err != nil { 226 | return nil, err 227 | } 228 | val := NewLuaObject(lo.l, -1) 229 | lo.l.Pop(1) 230 | return val, nil 231 | } 232 | 233 | // Push pushes this LuaObject on the stack. 234 | func (lo *LuaObject) Push() { 235 | lo.l.RawGeti(lua.LUA_REGISTRYINDEX, lo.ref) 236 | } 237 | 238 | // Set sets the value at the sequence of 'subfields' with the value 'a'. 239 | // Numeric indices start from 1, as in Lua: if we started from zero, access to 240 | // index 0 or negative indices would be shifted awkwardly. 241 | func (lo *LuaObject) Set(a interface{}, subfields ...interface{}) error { 242 | parentKeys := subfields[:len(subfields)-1] 243 | parent, err := lo.GetObject(parentKeys...) 244 | if err != nil { 245 | return err 246 | } 247 | 248 | L := parent.l 249 | parent.Push() 250 | defer L.Pop(1) 251 | 252 | lastField := subfields[len(subfields)-1] 253 | if L.IsTable(-1) { 254 | GoToLuaProxy(L, lastField) 255 | GoToLuaProxy(L, a) 256 | L.SetTable(-3) 257 | } else if L.GetMetaField(-1, "__newindex") { 258 | L.PushValue(-2) 259 | GoToLuaProxy(L, lastField) 260 | GoToLuaProxy(L, a) 261 | err := L.Call(3, 0) 262 | if err != nil { 263 | L.Pop(1) 264 | return err 265 | } 266 | } else { 267 | return ErrLuaObjectIndexable 268 | } 269 | return nil 270 | } 271 | 272 | // Setv copies values between two tables in the same Lua state. 273 | // It overwrites existing values. 274 | func (lo *LuaObject) Setv(src *LuaObject, keys ...string) error { 275 | // TODO: Rename? This function seems to be too specialized, is it worth 276 | // keeping at all? 277 | L := lo.l 278 | if L != src.l { 279 | return ErrLuaObjectUnsharedState 280 | } 281 | lo.Push() 282 | defer L.Pop(1) 283 | loIdx := L.GetTop() 284 | 285 | var set func(int, string) 286 | if L.IsTable(loIdx) { 287 | set = L.SetField 288 | } else if L.GetMetaField(loIdx, "__newindex") { 289 | L.Pop(1) 290 | set = func(idx int, key string) { 291 | resultIdx := L.GetTop() 292 | L.GetMetaField(loIdx, "__newindex") 293 | L.PushValue(loIdx) 294 | L.PushString(key) 295 | L.PushValue(resultIdx) 296 | L.Remove(resultIdx) 297 | L.Call(3, 0) 298 | } 299 | } else { 300 | return ErrLuaObjectIndexable 301 | } 302 | 303 | src.Push() 304 | defer src.l.Pop(1) 305 | srcIdx := L.GetTop() 306 | var get func(int, string) 307 | if L.IsTable(srcIdx) { 308 | get = L.GetField 309 | } else if L.GetMetaField(srcIdx, "__index") { 310 | L.Pop(1) 311 | get = func(idx int, key string) { 312 | L.GetMetaField(srcIdx, "__index") 313 | L.PushValue(srcIdx) 314 | L.PushString(key) 315 | L.Call(2, 1) 316 | } 317 | } else { 318 | return ErrLuaObjectIndexable 319 | } 320 | 321 | for _, key := range keys { 322 | get(srcIdx, key) 323 | set(loIdx, key) 324 | } 325 | 326 | return nil 327 | } 328 | 329 | // LuaTableIter is the Go equivalent of a Lua table iterator. 330 | type LuaTableIter struct { 331 | lo *LuaObject 332 | // keyRef is LUA_NOREF before iteration. 333 | keyRef int 334 | // Reference to the iterator in case the metamethod gets changed while 335 | // iterating. 336 | iterRef int 337 | // TODO: See if this is an idiomatic implementation of error storage. 338 | err error 339 | } 340 | 341 | // Error returns the error that happened during last iteration, if any. 342 | func (ti *LuaTableIter) Error() error { 343 | return ti.err 344 | } 345 | 346 | // Iter creates a Lua iterator. 347 | func (lo *LuaObject) Iter() (*LuaTableIter, error) { 348 | L := lo.l 349 | lo.Push() 350 | defer L.Pop(1) 351 | if L.IsTable(-1) { 352 | return &LuaTableIter{lo: lo, keyRef: lua.LUA_NOREF, iterRef: lua.LUA_NOREF}, nil 353 | } else if L.GetMetaField(-1, "__pairs") { 354 | // __pairs(t) = iterator, t, first-key. 355 | L.PushValue(-2) 356 | // Only keep iterator on stack, hence '1' result only. 357 | err := L.Call(1, 1) 358 | if err != nil { 359 | L.Pop(1) 360 | return nil, err 361 | } 362 | ref := L.Ref(lua.LUA_REGISTRYINDEX) 363 | return &LuaTableIter{lo: lo, keyRef: lua.LUA_NOREF, iterRef: ref}, nil 364 | } else { 365 | return nil, ErrLuaObjectIndexable 366 | } 367 | } 368 | 369 | // Next gets the next key/value pair from the indexable value. 370 | // 371 | // 'value' must be a valid argument for LuaToGo. As a special case, 'value' can 372 | // be nil to make it possible to loop over keys without caring about associated 373 | // values. 374 | func (ti *LuaTableIter) Next(key, value interface{}) bool { 375 | if ti.lo == nil { 376 | ti.err = errors.New("empty iterator") 377 | return false 378 | } 379 | L := ti.lo.l 380 | 381 | if ti.iterRef == lua.LUA_NOREF { 382 | // Must be a table. This requires the Iter() function to set 383 | // ref=LUA_NOREF. 384 | 385 | // Push table. 386 | ti.lo.Push() 387 | defer L.Pop(1) 388 | 389 | if ti.keyRef == lua.LUA_NOREF { 390 | L.PushNil() 391 | } else { 392 | L.RawGeti(lua.LUA_REGISTRYINDEX, ti.keyRef) 393 | } 394 | 395 | if L.Next(-2) == 0 { 396 | L.Unref(lua.LUA_REGISTRYINDEX, ti.keyRef) 397 | return false 398 | } 399 | 400 | } else { 401 | L.RawGeti(lua.LUA_REGISTRYINDEX, ti.iterRef) 402 | ti.lo.Push() 403 | 404 | if ti.keyRef == lua.LUA_NOREF { 405 | L.PushNil() 406 | } else { 407 | L.RawGeti(lua.LUA_REGISTRYINDEX, ti.keyRef) 408 | } 409 | 410 | err := L.Call(2, 2) 411 | if err != nil { 412 | L.Pop(1) 413 | ti.err = err 414 | return false 415 | } 416 | if L.IsNil(-2) { 417 | L.Pop(2) 418 | L.Unref(lua.LUA_REGISTRYINDEX, ti.iterRef) 419 | return false 420 | } 421 | } 422 | 423 | err := LuaToGo(L, -2, key) 424 | if err != nil { 425 | ti.err = err 426 | return false 427 | } 428 | if value != nil { 429 | err = LuaToGo(L, -1, value) 430 | if err != nil { 431 | ti.err = err 432 | return false 433 | } 434 | } 435 | 436 | // Drop value, key is now on top. 437 | L.Pop(1) 438 | 439 | // Replace former key reference with new key. 440 | L.Unref(lua.LUA_REGISTRYINDEX, ti.keyRef) 441 | ti.keyRef = L.Ref(lua.LUA_REGISTRYINDEX) 442 | return true 443 | } 444 | -------------------------------------------------------------------------------- /vendor/github.com/aarzilli/golua/lua/lua/lua.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ 3 | ** Lua - An Extensible Extension Language 4 | ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) 5 | ** See Copyright Notice at the end of this file 6 | */ 7 | 8 | 9 | #ifndef lua_h 10 | #define lua_h 11 | 12 | #include 13 | #include 14 | 15 | 16 | #include "luaconf.h" 17 | 18 | 19 | #define LUA_VERSION "Lua 5.1" 20 | #define LUA_RELEASE "Lua 5.1.4" 21 | #define LUA_VERSION_NUM 501 22 | #define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" 23 | #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" 24 | 25 | 26 | /* mark for precompiled code (`Lua') */ 27 | #define LUA_SIGNATURE "\033Lua" 28 | 29 | /* option for multiple returns in `lua_pcall' and `lua_call' */ 30 | #define LUA_MULTRET (-1) 31 | 32 | 33 | /* 34 | ** pseudo-indices 35 | */ 36 | #define LUA_REGISTRYINDEX (-10000) 37 | #define LUA_ENVIRONINDEX (-10001) 38 | #define LUA_GLOBALSINDEX (-10002) 39 | #define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) 40 | 41 | 42 | /* thread status; 0 is OK */ 43 | #define LUA_YIELD 1 44 | #define LUA_ERRRUN 2 45 | #define LUA_ERRSYNTAX 3 46 | #define LUA_ERRMEM 4 47 | #define LUA_ERRERR 5 48 | 49 | 50 | typedef struct lua_State lua_State; 51 | 52 | typedef int (*lua_CFunction) (lua_State *L); 53 | 54 | 55 | /* 56 | ** functions that read/write blocks when loading/dumping Lua chunks 57 | */ 58 | typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); 59 | 60 | typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); 61 | 62 | 63 | /* 64 | ** prototype for memory-allocation functions 65 | */ 66 | typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); 67 | 68 | 69 | /* 70 | ** basic types 71 | */ 72 | #define LUA_TNONE (-1) 73 | 74 | #define LUA_TNIL 0 75 | #define LUA_TBOOLEAN 1 76 | #define LUA_TLIGHTUSERDATA 2 77 | #define LUA_TNUMBER 3 78 | #define LUA_TSTRING 4 79 | #define LUA_TTABLE 5 80 | #define LUA_TFUNCTION 6 81 | #define LUA_TUSERDATA 7 82 | #define LUA_TTHREAD 8 83 | 84 | 85 | 86 | /* minimum Lua stack available to a C function */ 87 | #define LUA_MINSTACK 20 88 | 89 | 90 | /* 91 | ** generic extra include file 92 | */ 93 | #if defined(LUA_USER_H) 94 | #include LUA_USER_H 95 | #endif 96 | 97 | 98 | /* type of numbers in Lua */ 99 | typedef LUA_NUMBER lua_Number; 100 | 101 | 102 | /* type for integer functions */ 103 | typedef LUA_INTEGER lua_Integer; 104 | 105 | 106 | 107 | /* 108 | ** state manipulation 109 | */ 110 | LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); 111 | LUA_API void (lua_close) (lua_State *L); 112 | LUA_API lua_State *(lua_newthread) (lua_State *L); 113 | 114 | LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); 115 | 116 | 117 | /* 118 | ** basic stack manipulation 119 | */ 120 | LUA_API int (lua_gettop) (lua_State *L); 121 | LUA_API void (lua_settop) (lua_State *L, int idx); 122 | LUA_API void (lua_pushvalue) (lua_State *L, int idx); 123 | LUA_API void (lua_remove) (lua_State *L, int idx); 124 | LUA_API void (lua_insert) (lua_State *L, int idx); 125 | LUA_API void (lua_replace) (lua_State *L, int idx); 126 | LUA_API int (lua_checkstack) (lua_State *L, int sz); 127 | 128 | LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); 129 | 130 | 131 | /* 132 | ** access functions (stack -> C) 133 | */ 134 | 135 | LUA_API int (lua_isnumber) (lua_State *L, int idx); 136 | LUA_API int (lua_isstring) (lua_State *L, int idx); 137 | LUA_API int (lua_iscfunction) (lua_State *L, int idx); 138 | LUA_API int (lua_isuserdata) (lua_State *L, int idx); 139 | LUA_API int (lua_type) (lua_State *L, int idx); 140 | LUA_API const char *(lua_typename) (lua_State *L, int tp); 141 | 142 | LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); 143 | LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); 144 | LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); 145 | 146 | LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); 147 | LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); 148 | LUA_API int (lua_toboolean) (lua_State *L, int idx); 149 | LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); 150 | LUA_API size_t (lua_objlen) (lua_State *L, int idx); 151 | LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); 152 | LUA_API void *(lua_touserdata) (lua_State *L, int idx); 153 | LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); 154 | LUA_API const void *(lua_topointer) (lua_State *L, int idx); 155 | 156 | 157 | /* 158 | ** push functions (C -> stack) 159 | */ 160 | LUA_API void (lua_pushnil) (lua_State *L); 161 | LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); 162 | LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); 163 | LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); 164 | LUA_API void (lua_pushstring) (lua_State *L, const char *s); 165 | LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, 166 | va_list argp); 167 | LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); 168 | LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); 169 | LUA_API void (lua_pushboolean) (lua_State *L, int b); 170 | LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); 171 | LUA_API int (lua_pushthread) (lua_State *L); 172 | 173 | 174 | /* 175 | ** get functions (Lua -> stack) 176 | */ 177 | LUA_API void (lua_gettable) (lua_State *L, int idx); 178 | LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); 179 | LUA_API void (lua_rawget) (lua_State *L, int idx); 180 | LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); 181 | LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); 182 | LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); 183 | LUA_API int (lua_getmetatable) (lua_State *L, int objindex); 184 | LUA_API void (lua_getfenv) (lua_State *L, int idx); 185 | 186 | 187 | /* 188 | ** set functions (stack -> Lua) 189 | */ 190 | LUA_API void (lua_settable) (lua_State *L, int idx); 191 | LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); 192 | LUA_API void (lua_rawset) (lua_State *L, int idx); 193 | LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); 194 | LUA_API int (lua_setmetatable) (lua_State *L, int objindex); 195 | LUA_API int (lua_setfenv) (lua_State *L, int idx); 196 | 197 | 198 | /* 199 | ** `load' and `call' functions (load and run Lua code) 200 | */ 201 | LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); 202 | LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); 203 | LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); 204 | LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, 205 | const char *chunkname); 206 | 207 | LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); 208 | 209 | 210 | /* 211 | ** coroutine functions 212 | */ 213 | LUA_API int (lua_yield) (lua_State *L, int nresults); 214 | LUA_API int (lua_resume) (lua_State *L, int narg); 215 | LUA_API int (lua_status) (lua_State *L); 216 | 217 | /* 218 | ** garbage-collection function and options 219 | */ 220 | 221 | #define LUA_GCSTOP 0 222 | #define LUA_GCRESTART 1 223 | #define LUA_GCCOLLECT 2 224 | #define LUA_GCCOUNT 3 225 | #define LUA_GCCOUNTB 4 226 | #define LUA_GCSTEP 5 227 | #define LUA_GCSETPAUSE 6 228 | #define LUA_GCSETSTEPMUL 7 229 | 230 | LUA_API int (lua_gc) (lua_State *L, int what, int data); 231 | 232 | 233 | /* 234 | ** miscellaneous functions 235 | */ 236 | 237 | LUA_API int (lua_error) (lua_State *L); 238 | 239 | LUA_API int (lua_next) (lua_State *L, int idx); 240 | 241 | LUA_API void (lua_concat) (lua_State *L, int n); 242 | 243 | LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); 244 | LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); 245 | 246 | 247 | 248 | /* 249 | ** =============================================================== 250 | ** some useful macros 251 | ** =============================================================== 252 | */ 253 | 254 | #define lua_pop(L,n) lua_settop(L, -(n)-1) 255 | 256 | #define lua_newtable(L) lua_createtable(L, 0, 0) 257 | 258 | #define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) 259 | 260 | #define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) 261 | 262 | #define lua_strlen(L,i) lua_objlen(L, (i)) 263 | 264 | #define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) 265 | #define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) 266 | #define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) 267 | #define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) 268 | #define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) 269 | #define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) 270 | #define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) 271 | #define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) 272 | 273 | #define lua_pushliteral(L, s) \ 274 | lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) 275 | 276 | #define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) 277 | #define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) 278 | 279 | #define lua_tostring(L,i) lua_tolstring(L, (i), NULL) 280 | 281 | 282 | 283 | /* 284 | ** compatibility macros and functions 285 | */ 286 | 287 | #define lua_open() luaL_newstate() 288 | 289 | #define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) 290 | 291 | #define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) 292 | 293 | #define lua_Chunkreader lua_Reader 294 | #define lua_Chunkwriter lua_Writer 295 | 296 | 297 | /* hack */ 298 | LUA_API void lua_setlevel (lua_State *from, lua_State *to); 299 | 300 | 301 | /* 302 | ** {====================================================================== 303 | ** Debug API 304 | ** ======================================================================= 305 | */ 306 | 307 | 308 | /* 309 | ** Event codes 310 | */ 311 | #define LUA_HOOKCALL 0 312 | #define LUA_HOOKRET 1 313 | #define LUA_HOOKLINE 2 314 | #define LUA_HOOKCOUNT 3 315 | #define LUA_HOOKTAILRET 4 316 | 317 | 318 | /* 319 | ** Event masks 320 | */ 321 | #define LUA_MASKCALL (1 << LUA_HOOKCALL) 322 | #define LUA_MASKRET (1 << LUA_HOOKRET) 323 | #define LUA_MASKLINE (1 << LUA_HOOKLINE) 324 | #define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) 325 | 326 | typedef struct lua_Debug lua_Debug; /* activation record */ 327 | 328 | 329 | /* Functions to be called by the debuger in specific events */ 330 | typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); 331 | 332 | 333 | LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); 334 | LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); 335 | LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); 336 | LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); 337 | LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); 338 | LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); 339 | 340 | LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); 341 | LUA_API lua_Hook lua_gethook (lua_State *L); 342 | LUA_API int lua_gethookmask (lua_State *L); 343 | LUA_API int lua_gethookcount (lua_State *L); 344 | 345 | 346 | struct lua_Debug { 347 | int event; 348 | const char *name; /* (n) */ 349 | const char *namewhat; /* (n) `global', `local', `field', `method' */ 350 | const char *what; /* (S) `Lua', `C', `main', `tail' */ 351 | const char *source; /* (S) */ 352 | int currentline; /* (l) */ 353 | int nups; /* (u) number of upvalues */ 354 | int linedefined; /* (S) */ 355 | int lastlinedefined; /* (S) */ 356 | char short_src[LUA_IDSIZE]; /* (S) */ 357 | /* private part */ 358 | int i_ci; /* active function */ 359 | }; 360 | 361 | /* }====================================================================== */ 362 | 363 | 364 | /****************************************************************************** 365 | * Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. 366 | * 367 | * Permission is hereby granted, free of charge, to any person obtaining 368 | * a copy of this software and associated documentation files (the 369 | * "Software"), to deal in the Software without restriction, including 370 | * without limitation the rights to use, copy, modify, merge, publish, 371 | * distribute, sublicense, and/or sell copies of the Software, and to 372 | * permit persons to whom the Software is furnished to do so, subject to 373 | * the following conditions: 374 | * 375 | * The above copyright notice and this permission notice shall be 376 | * included in all copies or substantial portions of the Software. 377 | * 378 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 379 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 380 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 381 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 382 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 383 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 384 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 385 | ******************************************************************************/ 386 | 387 | 388 | #endif 389 | -------------------------------------------------------------------------------- /vendor/github.com/stevedonovan/luar/proxymm.go: -------------------------------------------------------------------------------- 1 | package luar 2 | 3 | // Metamethods. 4 | 5 | // Errors in metamethod will yield a call to RaiseError. 6 | // It is not possible to return an error / bool / message to the caller when 7 | // metamethods are called via Lua operators (e.g. __newindex). 8 | 9 | // TODO: Replicate Go/Lua error messages in RaiseError. 10 | 11 | import ( 12 | "fmt" 13 | "math" 14 | "math/cmplx" 15 | "reflect" 16 | 17 | "github.com/aarzilli/golua/lua" 18 | ) 19 | 20 | func channel__index(L *lua.State) int { 21 | v, t := valueOfProxy(L, 1) 22 | name := L.ToString(2) 23 | switch name { 24 | case "recv": 25 | f := func(L *lua.State) int { 26 | val, ok := v.Recv() 27 | if ok { 28 | GoToLuaProxy(L, val) 29 | return 1 30 | } 31 | return 0 32 | } 33 | L.PushGoFunction(f) 34 | case "send": 35 | f := func(L *lua.State) int { 36 | val := reflect.New(t.Elem()) 37 | err := LuaToGo(L, 1, val.Interface()) 38 | if err != nil { 39 | L.RaiseError(fmt.Sprintf("channel requires %v value type", t.Elem())) 40 | } 41 | v.Send(val.Elem()) 42 | return 0 43 | } 44 | L.PushGoFunction(f) 45 | case "close": 46 | f := func(L *lua.State) int { 47 | v.Close() 48 | return 0 49 | } 50 | L.PushGoFunction(f) 51 | default: 52 | pushGoMethod(L, name, v) 53 | } 54 | return 1 55 | } 56 | 57 | func complex__index(L *lua.State) int { 58 | v, _ := valueOfProxy(L, 1) 59 | name := L.ToString(2) 60 | switch name { 61 | case "real": 62 | L.PushNumber(real(v.Complex())) 63 | case "imag": 64 | L.PushNumber(imag(v.Complex())) 65 | default: 66 | pushGoMethod(L, name, v) 67 | } 68 | return 1 69 | } 70 | 71 | func interface__index(L *lua.State) int { 72 | v, _ := valueOfProxy(L, 1) 73 | name := L.ToString(2) 74 | pushGoMethod(L, name, v) 75 | return 1 76 | } 77 | 78 | // TODO: Should map[string] and struct allow direct method calls? Check if first letter is uppercase? 79 | func map__index(L *lua.State) int { 80 | v, t := valueOfProxy(L, 1) 81 | key := reflect.New(t.Key()) 82 | err := LuaToGo(L, 2, key.Interface()) 83 | if err == nil { 84 | key = key.Elem() 85 | val := v.MapIndex(key) 86 | if val.IsValid() { 87 | GoToLuaProxy(L, val) 88 | return 1 89 | } 90 | } 91 | if !L.IsNumber(2) && L.IsString(2) { 92 | name := L.ToString(2) 93 | pushGoMethod(L, name, v) 94 | return 1 95 | } 96 | if err != nil { 97 | L.RaiseError(fmt.Sprintf("map requires %v key", t.Key())) 98 | } 99 | return 0 100 | } 101 | 102 | func map__ipairs(L *lua.State) int { 103 | v, _ := valueOfProxy(L, 1) 104 | keys := v.MapKeys() 105 | intKeys := map[uint64]reflect.Value{} 106 | 107 | // Filter integer keys. 108 | for _, k := range keys { 109 | if k.Kind() == reflect.Interface { 110 | k = k.Elem() 111 | } 112 | switch unsizedKind(k) { 113 | case reflect.Int64: 114 | i := k.Int() 115 | if i > 0 { 116 | intKeys[uint64(i)] = k 117 | } 118 | case reflect.Uint64: 119 | intKeys[k.Uint()] = k 120 | } 121 | } 122 | 123 | idx := uint64(0) 124 | iter := func(L *lua.State) int { 125 | idx++ 126 | if _, ok := intKeys[idx]; !ok { 127 | return 0 128 | } 129 | GoToLuaProxy(L, idx) 130 | val := v.MapIndex(intKeys[idx]) 131 | GoToLuaProxy(L, val) 132 | return 2 133 | } 134 | L.PushGoFunction(iter) 135 | return 1 136 | } 137 | 138 | func map__newindex(L *lua.State) int { 139 | v, t := valueOfProxy(L, 1) 140 | key := reflect.New(t.Key()) 141 | err := LuaToGo(L, 2, key.Interface()) 142 | if err != nil { 143 | L.RaiseError(fmt.Sprintf("map requires %v key", t.Key())) 144 | } 145 | key = key.Elem() 146 | val := reflect.New(t.Elem()) 147 | err = LuaToGo(L, 3, val.Interface()) 148 | if err != nil { 149 | L.RaiseError(fmt.Sprintf("map requires %v value type", t.Elem())) 150 | } 151 | val = val.Elem() 152 | v.SetMapIndex(key, val) 153 | return 0 154 | } 155 | 156 | func map__pairs(L *lua.State) int { 157 | v, _ := valueOfProxy(L, 1) 158 | keys := v.MapKeys() 159 | idx := -1 160 | n := v.Len() 161 | iter := func(L *lua.State) int { 162 | idx++ 163 | if idx == n { 164 | return 0 165 | } 166 | GoToLuaProxy(L, keys[idx]) 167 | val := v.MapIndex(keys[idx]) 168 | GoToLuaProxy(L, val) 169 | return 2 170 | } 171 | L.PushGoFunction(iter) 172 | return 1 173 | } 174 | 175 | func number__add(L *lua.State) int { 176 | v1, t1 := luaToGoValue(L, 1) 177 | v2, t2 := luaToGoValue(L, 2) 178 | var result interface{} 179 | switch commonKind(v1, v2) { 180 | case reflect.Uint64: 181 | result = v1.Uint() + v2.Uint() 182 | case reflect.Int64: 183 | result = v1.Int() + v2.Int() 184 | case reflect.Float64: 185 | result = valueToNumber(L, v1) + valueToNumber(L, v2) 186 | case reflect.Complex128: 187 | result = valueToComplex(L, v1) + valueToComplex(L, v2) 188 | } 189 | pushNumberValue(L, result, t1, t2) 190 | return 1 191 | } 192 | 193 | func number__div(L *lua.State) int { 194 | v1, t1 := luaToGoValue(L, 1) 195 | v2, t2 := luaToGoValue(L, 2) 196 | var result interface{} 197 | switch commonKind(v1, v2) { 198 | case reflect.Uint64: 199 | result = v1.Uint() / v2.Uint() 200 | case reflect.Int64: 201 | result = v1.Int() / v2.Int() 202 | case reflect.Float64: 203 | result = valueToNumber(L, v1) / valueToNumber(L, v2) 204 | case reflect.Complex128: 205 | result = valueToComplex(L, v1) / valueToComplex(L, v2) 206 | } 207 | pushNumberValue(L, result, t1, t2) 208 | return 1 209 | } 210 | 211 | func number__lt(L *lua.State) int { 212 | v1, _ := luaToGoValue(L, 1) 213 | v2, _ := luaToGoValue(L, 2) 214 | switch commonKind(v1, v2) { 215 | case reflect.Uint64: 216 | L.PushBoolean(v1.Uint() < v2.Uint()) 217 | case reflect.Int64: 218 | L.PushBoolean(v1.Int() < v2.Int()) 219 | case reflect.Float64: 220 | L.PushBoolean(valueToNumber(L, v1) < valueToNumber(L, v2)) 221 | } 222 | return 1 223 | } 224 | 225 | func number__mod(L *lua.State) int { 226 | v1, t1 := luaToGoValue(L, 1) 227 | v2, t2 := luaToGoValue(L, 2) 228 | var result interface{} 229 | switch commonKind(v1, v2) { 230 | case reflect.Uint64: 231 | result = v1.Uint() % v2.Uint() 232 | case reflect.Int64: 233 | result = v1.Int() % v2.Int() 234 | case reflect.Float64: 235 | result = math.Mod(valueToNumber(L, v1), valueToNumber(L, v2)) 236 | } 237 | pushNumberValue(L, result, t1, t2) 238 | return 1 239 | } 240 | 241 | func number__mul(L *lua.State) int { 242 | v1, t1 := luaToGoValue(L, 1) 243 | v2, t2 := luaToGoValue(L, 2) 244 | var result interface{} 245 | switch commonKind(v1, v2) { 246 | case reflect.Uint64: 247 | result = v1.Uint() * v2.Uint() 248 | case reflect.Int64: 249 | result = v1.Int() * v2.Int() 250 | case reflect.Float64: 251 | result = valueToNumber(L, v1) * valueToNumber(L, v2) 252 | case reflect.Complex128: 253 | result = valueToComplex(L, v1) * valueToComplex(L, v2) 254 | } 255 | pushNumberValue(L, result, t1, t2) 256 | return 1 257 | } 258 | 259 | func number__pow(L *lua.State) int { 260 | v1, t1 := luaToGoValue(L, 1) 261 | v2, t2 := luaToGoValue(L, 2) 262 | var result interface{} 263 | switch commonKind(v1, v2) { 264 | case reflect.Uint64: 265 | result = math.Pow(float64(v1.Uint()), float64(v2.Uint())) 266 | case reflect.Int64: 267 | result = math.Pow(float64(v1.Int()), float64(v2.Int())) 268 | case reflect.Float64: 269 | result = math.Pow(valueToNumber(L, v1), valueToNumber(L, v2)) 270 | case reflect.Complex128: 271 | result = cmplx.Pow(valueToComplex(L, v1), valueToComplex(L, v2)) 272 | } 273 | pushNumberValue(L, result, t1, t2) 274 | return 1 275 | } 276 | 277 | func number__sub(L *lua.State) int { 278 | v1, t1 := luaToGoValue(L, 1) 279 | v2, t2 := luaToGoValue(L, 2) 280 | var result interface{} 281 | switch commonKind(v1, v2) { 282 | case reflect.Uint64: 283 | result = v1.Uint() - v2.Uint() 284 | case reflect.Int64: 285 | result = v1.Int() - v2.Int() 286 | case reflect.Float64: 287 | result = valueToNumber(L, v1) - valueToNumber(L, v2) 288 | case reflect.Complex128: 289 | result = valueToComplex(L, v1) - valueToComplex(L, v2) 290 | } 291 | pushNumberValue(L, result, t1, t2) 292 | return 1 293 | } 294 | 295 | func number__unm(L *lua.State) int { 296 | v1, t1 := luaToGoValue(L, 1) 297 | var result interface{} 298 | switch unsizedKind(v1) { 299 | case reflect.Uint64: 300 | result = -v1.Uint() 301 | case reflect.Int64: 302 | result = -v1.Int() 303 | case reflect.Float64, reflect.String: 304 | result = -valueToNumber(L, v1) 305 | case reflect.Complex128: 306 | result = -v1.Complex() 307 | } 308 | v := reflect.ValueOf(result) 309 | if unsizedKind(v1) == reflect.Complex128 { 310 | makeValueProxy(L, v.Convert(t1), cComplexMeta) 311 | } else if isNewType(t1) { 312 | makeValueProxy(L, v.Convert(t1), cNumberMeta) 313 | } else { 314 | L.PushNumber(v.Float()) 315 | } 316 | return 1 317 | } 318 | 319 | // From Lua's specs: "A metamethod only is selected when both objects being 320 | // compared have the same type and the same metamethod for the selected 321 | // operation." Thus both arguments must be proxies for this function to be 322 | // called. No need to check for type equality: Go's "==" operator will do it for 323 | // us. 324 | func proxy__eq(L *lua.State) int { 325 | var a1 interface{} 326 | _ = LuaToGo(L, 1, &a1) 327 | var a2 interface{} 328 | _ = LuaToGo(L, 2, &a2) 329 | L.PushBoolean(a1 == a2) 330 | return 1 331 | } 332 | 333 | func proxy__gc(L *lua.State) int { 334 | proxy := (*valueProxy)(L.ToUserdata(1)) 335 | proxymu.Lock() 336 | delete(proxyMap, proxy) 337 | proxymu.Unlock() 338 | return 0 339 | } 340 | 341 | func proxy__tostring(L *lua.State) int { 342 | v, _ := valueOfProxy(L, 1) 343 | L.PushString(fmt.Sprintf("%v", v)) 344 | return 1 345 | } 346 | 347 | func slice__index(L *lua.State) int { 348 | v, _ := valueOfProxy(L, 1) 349 | for v.Kind() == reflect.Ptr { 350 | // For arrays. 351 | v = v.Elem() 352 | } 353 | if L.IsNumber(2) { 354 | idx := L.ToInteger(2) 355 | if idx < 1 || idx > v.Len() { 356 | L.RaiseError("slice/array get: index out of range") 357 | } 358 | v := v.Index(idx - 1) 359 | GoToLuaProxy(L, v) 360 | } else if L.IsString(2) { 361 | name := L.ToString(2) 362 | if v.Kind() == reflect.Array { 363 | pushGoMethod(L, name, v) 364 | return 1 365 | } 366 | switch name { 367 | case "append": 368 | f := func(L *lua.State) int { 369 | narg := L.GetTop() 370 | args := []reflect.Value{} 371 | for i := 1; i <= narg; i++ { 372 | elem := reflect.New(v.Type().Elem()) 373 | err := LuaToGo(L, i, elem.Interface()) 374 | if err != nil { 375 | L.RaiseError(fmt.Sprintf("slice requires %v value type", v.Type().Elem())) 376 | } 377 | args = append(args, elem.Elem()) 378 | } 379 | newslice := reflect.Append(v, args...) 380 | makeValueProxy(L, newslice, cSliceMeta) 381 | return 1 382 | } 383 | L.PushGoFunction(f) 384 | case "cap": 385 | L.PushInteger(int64(v.Cap())) 386 | case "slice": 387 | L.PushGoFunction(slicer(L, v, cSliceMeta)) 388 | default: 389 | pushGoMethod(L, name, v) 390 | } 391 | } else { 392 | L.RaiseError("non-integer slice/array index") 393 | } 394 | return 1 395 | } 396 | 397 | func slice__ipairs(L *lua.State) int { 398 | v, _ := valueOfProxy(L, 1) 399 | for v.Kind() == reflect.Ptr { 400 | v = v.Elem() 401 | } 402 | n := v.Len() 403 | idx := -1 404 | iter := func(L *lua.State) int { 405 | idx++ 406 | if idx == n { 407 | return 0 408 | } 409 | GoToLuaProxy(L, idx+1) // report as 1-based index 410 | val := v.Index(idx) 411 | GoToLuaProxy(L, val) 412 | return 2 413 | } 414 | L.PushGoFunction(iter) 415 | return 1 416 | } 417 | 418 | func slice__newindex(L *lua.State) int { 419 | v, t := valueOfProxy(L, 1) 420 | for v.Kind() == reflect.Ptr { 421 | // For arrays. 422 | v = v.Elem() 423 | t = t.Elem() 424 | } 425 | idx := L.ToInteger(2) 426 | val := reflect.New(t.Elem()) 427 | err := LuaToGo(L, 3, val.Interface()) 428 | if err != nil { 429 | L.RaiseError(fmt.Sprintf("slice requires %v value type", t.Elem())) 430 | } 431 | val = val.Elem() 432 | if idx < 1 || idx > v.Len() { 433 | L.RaiseError("slice/array set: index out of range") 434 | } 435 | v.Index(idx - 1).Set(val) 436 | return 0 437 | } 438 | 439 | func slicemap__len(L *lua.State) int { 440 | v, _ := valueOfProxy(L, 1) 441 | for v.Kind() == reflect.Ptr { 442 | // For arrays. 443 | v = v.Elem() 444 | } 445 | L.PushInteger(int64(v.Len())) 446 | return 1 447 | } 448 | 449 | // Lua accepts concatenation with string and number. 450 | func string__concat(L *lua.State) int { 451 | v1, t1 := luaToGoValue(L, 1) 452 | v2, t2 := luaToGoValue(L, 2) 453 | s1 := valueToString(L, v1) 454 | s2 := valueToString(L, v2) 455 | result := s1 + s2 456 | 457 | if t1 == t2 || isPredeclaredType(t2) { 458 | v := reflect.ValueOf(result) 459 | makeValueProxy(L, v.Convert(t1), cStringMeta) 460 | } else if isPredeclaredType(t1) { 461 | v := reflect.ValueOf(result) 462 | makeValueProxy(L, v.Convert(t2), cStringMeta) 463 | } else { 464 | L.PushString(result) 465 | } 466 | 467 | return 1 468 | } 469 | 470 | func string__index(L *lua.State) int { 471 | v, _ := valueOfProxy(L, 1) 472 | if L.IsNumber(2) { 473 | idx := L.ToInteger(2) 474 | if idx < 1 || idx > v.Len() { 475 | L.RaiseError("index out of range") 476 | } 477 | v := v.Index(idx - 1).Convert(reflect.TypeOf("")) 478 | GoToLuaProxy(L, v) 479 | } else if L.IsString(2) { 480 | name := L.ToString(2) 481 | if name == "slice" { 482 | L.PushGoFunction(slicer(L, v, cStringMeta)) 483 | } else { 484 | pushGoMethod(L, name, v) 485 | } 486 | } else { 487 | L.RaiseError("non-integer string index") 488 | } 489 | return 1 490 | } 491 | 492 | func string__ipairs(L *lua.State) int { 493 | v, _ := valueOfProxy(L, 1) 494 | for v.Kind() == reflect.Ptr { 495 | v = v.Elem() 496 | } 497 | r := []rune(v.String()) 498 | n := len(r) 499 | idx := -1 500 | iter := func(L *lua.State) int { 501 | idx++ 502 | if idx == n { 503 | return 0 504 | } 505 | GoToLuaProxy(L, idx+1) // report as 1-based index 506 | GoToLuaProxy(L, string(r[idx])) 507 | return 2 508 | } 509 | L.PushGoFunction(iter) 510 | return 1 511 | } 512 | 513 | func string__len(L *lua.State) int { 514 | v1, _ := luaToGoValue(L, 1) 515 | L.PushInteger(int64(v1.Len())) 516 | return 1 517 | } 518 | 519 | func string__lt(L *lua.State) int { 520 | v1, _ := luaToGoValue(L, 1) 521 | v2, _ := luaToGoValue(L, 2) 522 | L.PushBoolean(v1.String() < v2.String()) 523 | return 1 524 | } 525 | 526 | func struct__index(L *lua.State) int { 527 | v, t := valueOfProxy(L, 1) 528 | name := L.ToString(2) 529 | vp := v 530 | if t.Kind() == reflect.Ptr { 531 | v = v.Elem() 532 | } 533 | field := v.FieldByName(name) 534 | if !field.IsValid() || !field.CanSet() { 535 | // No such exported field, try for method. 536 | pushGoMethod(L, name, vp) 537 | } else { 538 | if isPointerToPrimitive(field) { 539 | // TODO: Why dereferencing the pointer? 540 | GoToLuaProxy(L, field.Elem()) 541 | } else { 542 | GoToLuaProxy(L, field) 543 | } 544 | } 545 | return 1 546 | } 547 | 548 | func struct__newindex(L *lua.State) int { 549 | v, t := valueOfProxy(L, 1) 550 | name := L.ToString(2) 551 | if t.Kind() == reflect.Ptr { 552 | v = v.Elem() 553 | } 554 | field := v.FieldByName(name) 555 | if !field.IsValid() { 556 | L.RaiseError(fmt.Sprintf("no field named `%s` for type %s", name, v.Type())) 557 | } 558 | val := reflect.New(field.Type()) 559 | err := LuaToGo(L, 3, val.Interface()) 560 | if err != nil { 561 | L.RaiseError(fmt.Sprintf("struct field %v requires %v value type", name, field.Type())) 562 | } 563 | val = val.Elem() 564 | if isPointerToPrimitive(field) { 565 | // TODO: Why dereferencing the pointer? 566 | field.Elem().Set(val) 567 | } else { 568 | field.Set(val) 569 | } 570 | return 0 571 | } 572 | -------------------------------------------------------------------------------- /vendor/github.com/aarzilli/golua/lua/lua.go: -------------------------------------------------------------------------------- 1 | // This package provides access to the excellent lua language interpreter from go code. 2 | // 3 | // Access to most of the functions in lua.h and lauxlib.h is provided as well as additional convenience functions to publish Go objects and functions to lua code. 4 | // 5 | // The documentation of this package is no substitute for the official lua documentation and in many instances methods are described only with the name of their C equivalent 6 | package lua 7 | 8 | /* 9 | #cgo CFLAGS: -Ilua 10 | #cgo llua LDFLAGS: -llua 11 | #cgo luaa LDFLAGS: -llua -lm -ldl 12 | #cgo linux,!llua,!luaa LDFLAGS: -llua5.1 13 | #cgo darwin,!luaa pkg-config: lua5.1 14 | #cgo freebsd,!luaa LDFLAGS: -llua-5.1 15 | 16 | #include 17 | #include 18 | 19 | #include "golua.h" 20 | 21 | */ 22 | import "C" 23 | import "unsafe" 24 | 25 | import "fmt" 26 | 27 | type LuaStackEntry struct { 28 | Name string 29 | Source string 30 | ShortSource string 31 | CurrentLine int 32 | } 33 | 34 | func newState(L *C.lua_State) *State { 35 | newstate := &State{L, 0, make([]interface{}, 0, 8), make([]uint, 0, 8)} 36 | registerGoState(newstate) 37 | C.clua_setgostate(L, C.size_t(newstate.Index)) 38 | C.clua_initstate(L) 39 | return newstate 40 | } 41 | 42 | func (L *State) addFreeIndex(i uint) { 43 | freelen := len(L.freeIndices) 44 | //reallocate if necessary 45 | if freelen+1 > cap(L.freeIndices) { 46 | newSlice := make([]uint, freelen, cap(L.freeIndices)*2) 47 | copy(newSlice, L.freeIndices) 48 | L.freeIndices = newSlice 49 | } 50 | //reslice 51 | L.freeIndices = L.freeIndices[0 : freelen+1] 52 | L.freeIndices[freelen] = i 53 | } 54 | 55 | func (L *State) getFreeIndex() (index uint, ok bool) { 56 | freelen := len(L.freeIndices) 57 | //if there exist entries in the freelist 58 | if freelen > 0 { 59 | i := L.freeIndices[freelen-1] //get index 60 | //fmt.Printf("Free indices before: %v\n", L.freeIndices) 61 | L.freeIndices = L.freeIndices[0 : freelen-1] //'pop' index from list 62 | //fmt.Printf("Free indices after: %v\n", L.freeIndices) 63 | return i, true 64 | } 65 | return 0, false 66 | } 67 | 68 | //returns the registered function id 69 | func (L *State) register(f interface{}) uint { 70 | //fmt.Printf("Registering %v\n") 71 | index, ok := L.getFreeIndex() 72 | //fmt.Printf("\tfreeindex: index = %v, ok = %v\n", index, ok) 73 | //if not ok, then we need to add new index by extending the slice 74 | if !ok { 75 | index = uint(len(L.registry)) 76 | //reallocate backing array if necessary 77 | if index+1 > uint(cap(L.registry)) { 78 | newSlice := make([]interface{}, index, cap(L.registry)*2) 79 | copy(newSlice, L.registry) 80 | L.registry = newSlice 81 | } 82 | //reslice 83 | L.registry = L.registry[0 : index+1] 84 | } 85 | //fmt.Printf("\tregistering %d %v\n", index, f) 86 | L.registry[index] = f 87 | return index 88 | } 89 | 90 | func (L *State) unregister(fid uint) { 91 | //fmt.Printf("Unregistering %d (len: %d, value: %v)\n", fid, len(L.registry), L.registry[fid]) 92 | if (fid < uint(len(L.registry))) && (L.registry[fid] != nil) { 93 | L.registry[fid] = nil 94 | L.addFreeIndex(fid) 95 | } 96 | } 97 | 98 | // Like lua_pushcfunction pushes onto the stack a go function as user data 99 | func (L *State) PushGoFunction(f LuaGoFunction) { 100 | fid := L.register(f) 101 | C.clua_pushgofunction(L.s, C.uint(fid)) 102 | } 103 | 104 | // PushGoClosure pushes a lua.LuaGoFunction to the stack wrapped in a Closure. 105 | // this permits the go function to reflect lua type 'function' when checking with type() 106 | // this implements behaviour akin to lua_pushcfunction() in lua C API. 107 | func (L *State) PushGoClosure(f LuaGoFunction) { 108 | L.PushGoFunction(f) // leaves Go function userdata on stack 109 | C.clua_pushcallback(L.s) // wraps the userdata object with a closure making it into a function 110 | } 111 | 112 | // Sets a metamethod to execute a go function 113 | // 114 | // The code: 115 | // 116 | // L.LGetMetaTable(tableName) 117 | // L.SetMetaMethod(methodName, function) 118 | // 119 | // is the logical equivalent of: 120 | // 121 | // L.LGetMetaTable(tableName) 122 | // L.PushGoFunction(function) 123 | // L.SetField(-2, methodName) 124 | // 125 | // except this wouldn't work because pushing a go function results in user data not a cfunction 126 | func (L *State) SetMetaMethod(methodName string, f LuaGoFunction) { 127 | L.PushGoFunction(f) // leaves Go function userdata on stack 128 | C.clua_pushcallback(L.s) // wraps the userdata object with a closure making it into a function 129 | L.SetField(-2, methodName) 130 | } 131 | 132 | // Pushes a Go struct onto the stack as user data. 133 | // 134 | // The user data will be rigged so that lua code can access and change to public members of simple types directly 135 | func (L *State) PushGoStruct(iface interface{}) { 136 | iid := L.register(iface) 137 | C.clua_pushgostruct(L.s, C.uint(iid)) 138 | } 139 | 140 | // Push a pointer onto the stack as user data. 141 | // 142 | // This function doesn't save a reference to the interface, it is the responsibility of the caller of this function to insure that the interface outlasts the lifetime of the lua object that this function creates. 143 | func (L *State) PushLightUserdata(ud *interface{}) { 144 | //push 145 | C.lua_pushlightuserdata(L.s, unsafe.Pointer(ud)) 146 | } 147 | 148 | // Creates a new user data object of specified size and returns it 149 | func (L *State) NewUserdata(size uintptr) unsafe.Pointer { 150 | return unsafe.Pointer(C.lua_newuserdata(L.s, C.size_t(size))) 151 | } 152 | 153 | // Sets the AtPanic function, returns the old one 154 | // 155 | // BUG(everyone_involved): passing nil causes serious problems 156 | func (L *State) AtPanic(panicf LuaGoFunction) (oldpanicf LuaGoFunction) { 157 | fid := uint(0) 158 | if panicf != nil { 159 | fid = L.register(panicf) 160 | } 161 | oldres := interface{}(C.clua_atpanic(L.s, C.uint(fid))) 162 | switch i := oldres.(type) { 163 | case C.uint: 164 | f := L.registry[uint(i)].(LuaGoFunction) 165 | //free registry entry 166 | L.unregister(uint(i)) 167 | return f 168 | case C.lua_CFunction: 169 | return func(L1 *State) int { 170 | return int(C.clua_callluacfunc(L1.s, i)) 171 | } 172 | } 173 | //generally we only get here if the panicf got set to something like nil 174 | //potentially dangerous because we may silently fail 175 | return nil 176 | } 177 | 178 | func (L *State) pcall(nargs, nresults, errfunc int) int { 179 | return int(C.lua_pcall(L.s, C.int(nargs), C.int(nresults), C.int(errfunc))) 180 | } 181 | 182 | func (L *State) callEx(nargs, nresults int, catch bool) (err error) { 183 | if catch { 184 | defer func() { 185 | if err2 := recover(); err2 != nil { 186 | if _, ok := err2.(error); ok { 187 | err = err2.(error) 188 | } 189 | return 190 | } 191 | }() 192 | } 193 | 194 | L.GetGlobal(C.GOLUA_DEFAULT_MSGHANDLER) 195 | // We must record where we put the error handler in the stack otherwise it will be impossible to remove after the pcall when nresults == LUA_MULTRET 196 | erridx := L.GetTop() - nargs - 1 197 | L.Insert(erridx) 198 | r := L.pcall(nargs, nresults, erridx) 199 | L.Remove(erridx) 200 | if r != 0 { 201 | err = &LuaError{r, L.ToString(-1), L.StackTrace()} 202 | if !catch { 203 | panic(err) 204 | } 205 | } 206 | return 207 | } 208 | 209 | // lua_call 210 | func (L *State) Call(nargs, nresults int) (err error) { 211 | return L.callEx(nargs, nresults, true) 212 | } 213 | 214 | // Like lua_call but panics on errors 215 | func (L *State) MustCall(nargs, nresults int) { 216 | L.callEx(nargs, nresults, false) 217 | } 218 | 219 | // lua_checkstack 220 | func (L *State) CheckStack(extra int) bool { 221 | return C.lua_checkstack(L.s, C.int(extra)) != 0 222 | } 223 | 224 | // lua_close 225 | func (L *State) Close() { 226 | C.lua_close(L.s) 227 | unregisterGoState(L) 228 | } 229 | 230 | // lua_concat 231 | func (L *State) Concat(n int) { 232 | C.lua_concat(L.s, C.int(n)) 233 | } 234 | 235 | // lua_createtable 236 | func (L *State) CreateTable(narr int, nrec int) { 237 | C.lua_createtable(L.s, C.int(narr), C.int(nrec)) 238 | } 239 | 240 | // lua_equal 241 | func (L *State) Equal(index1, index2 int) bool { 242 | return C.lua_equal(L.s, C.int(index1), C.int(index2)) == 1 243 | } 244 | 245 | // lua_gc 246 | func (L *State) GC(what, data int) int { return int(C.lua_gc(L.s, C.int(what), C.int(data))) } 247 | 248 | // lua_getfenv 249 | func (L *State) GetfEnv(index int) { C.lua_getfenv(L.s, C.int(index)) } 250 | 251 | // lua_getfield 252 | func (L *State) GetField(index int, k string) { 253 | Ck := C.CString(k) 254 | defer C.free(unsafe.Pointer(Ck)) 255 | C.lua_getfield(L.s, C.int(index), Ck) 256 | } 257 | 258 | // Pushes on the stack the value of a global variable (lua_getglobal) 259 | func (L *State) GetGlobal(name string) { L.GetField(LUA_GLOBALSINDEX, name) } 260 | 261 | // lua_getmetatable 262 | func (L *State) GetMetaTable(index int) bool { 263 | return C.lua_getmetatable(L.s, C.int(index)) != 0 264 | } 265 | 266 | // lua_gettable 267 | func (L *State) GetTable(index int) { C.lua_gettable(L.s, C.int(index)) } 268 | 269 | // lua_gettop 270 | func (L *State) GetTop() int { return int(C.lua_gettop(L.s)) } 271 | 272 | // lua_insert 273 | func (L *State) Insert(index int) { C.lua_insert(L.s, C.int(index)) } 274 | 275 | // Returns true if lua_type == LUA_TBOOLEAN 276 | func (L *State) IsBoolean(index int) bool { 277 | return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TBOOLEAN 278 | } 279 | 280 | // Returns true if the value at index is a LuaGoFunction 281 | func (L *State) IsGoFunction(index int) bool { 282 | return C.clua_isgofunction(L.s, C.int(index)) != 0 283 | } 284 | 285 | // Returns true if the value at index is user data pushed with PushGoStruct 286 | func (L *State) IsGoStruct(index int) bool { 287 | return C.clua_isgostruct(L.s, C.int(index)) != 0 288 | } 289 | 290 | // Returns true if the value at index is user data pushed with PushGoFunction 291 | func (L *State) IsFunction(index int) bool { 292 | return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TFUNCTION 293 | } 294 | 295 | // Returns true if the value at index is light user data 296 | func (L *State) IsLightUserdata(index int) bool { 297 | return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TLIGHTUSERDATA 298 | } 299 | 300 | // lua_isnil 301 | func (L *State) IsNil(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TNIL } 302 | 303 | // lua_isnone 304 | func (L *State) IsNone(index int) bool { return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TNONE } 305 | 306 | // lua_isnoneornil 307 | func (L *State) IsNoneOrNil(index int) bool { return int(C.lua_type(L.s, C.int(index))) <= 0 } 308 | 309 | // lua_isnumber 310 | func (L *State) IsNumber(index int) bool { return C.lua_isnumber(L.s, C.int(index)) == 1 } 311 | 312 | // lua_isstring 313 | func (L *State) IsString(index int) bool { return C.lua_isstring(L.s, C.int(index)) == 1 } 314 | 315 | // lua_istable 316 | func (L *State) IsTable(index int) bool { 317 | return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TTABLE 318 | } 319 | 320 | // lua_isthread 321 | func (L *State) IsThread(index int) bool { 322 | return LuaValType(C.lua_type(L.s, C.int(index))) == LUA_TTHREAD 323 | } 324 | 325 | // lua_isuserdata 326 | func (L *State) IsUserdata(index int) bool { return C.lua_isuserdata(L.s, C.int(index)) == 1 } 327 | 328 | // lua_lessthan 329 | func (L *State) LessThan(index1, index2 int) bool { 330 | return C.lua_lessthan(L.s, C.int(index1), C.int(index2)) == 1 331 | } 332 | 333 | // Creates a new lua interpreter state with the given allocation function 334 | func NewStateAlloc(f Alloc) *State { 335 | ls := C.clua_newstate(unsafe.Pointer(&f)) 336 | return newState(ls) 337 | } 338 | 339 | // lua_newtable 340 | func (L *State) NewTable() { 341 | C.lua_createtable(L.s, 0, 0) 342 | } 343 | 344 | // lua_newthread 345 | func (L *State) NewThread() *State { 346 | //TODO: call newState with result from C.lua_newthread and return it 347 | //TODO: should have same lists as parent 348 | // but may complicate gc 349 | s := C.lua_newthread(L.s) 350 | return &State{s, 0, nil, nil} 351 | } 352 | 353 | // lua_next 354 | func (L *State) Next(index int) int { 355 | return int(C.lua_next(L.s, C.int(index))) 356 | } 357 | 358 | // lua_objlen 359 | func (L *State) ObjLen(index int) uint { 360 | return uint(C.lua_objlen(L.s, C.int(index))) 361 | } 362 | 363 | // lua_pop 364 | func (L *State) Pop(n int) { 365 | //Why is this implemented this way? I don't get it... 366 | //C.lua_pop(L.s, C.int(n)); 367 | C.lua_settop(L.s, C.int(-n-1)) 368 | } 369 | 370 | // lua_pushboolean 371 | func (L *State) PushBoolean(b bool) { 372 | var bint int 373 | if b { 374 | bint = 1 375 | } else { 376 | bint = 0 377 | } 378 | C.lua_pushboolean(L.s, C.int(bint)) 379 | } 380 | 381 | // lua_pushstring 382 | func (L *State) PushString(str string) { 383 | Cstr := C.CString(str) 384 | defer C.free(unsafe.Pointer(Cstr)) 385 | C.lua_pushlstring(L.s, Cstr, C.size_t(len(str))) 386 | } 387 | 388 | func (L *State) PushBytes(b []byte) { 389 | C.lua_pushlstring(L.s, (*C.char)(unsafe.Pointer(&b[0])), C.size_t(len(b))) 390 | } 391 | 392 | // lua_pushinteger 393 | func (L *State) PushInteger(n int64) { 394 | C.lua_pushinteger(L.s, C.lua_Integer(n)) 395 | } 396 | 397 | // lua_pushnil 398 | func (L *State) PushNil() { 399 | C.lua_pushnil(L.s) 400 | } 401 | 402 | // lua_pushnumber 403 | func (L *State) PushNumber(n float64) { 404 | C.lua_pushnumber(L.s, C.lua_Number(n)) 405 | } 406 | 407 | // lua_pushthread 408 | func (L *State) PushThread() (isMain bool) { 409 | return C.lua_pushthread(L.s) != 0 410 | } 411 | 412 | // lua_pushvalue 413 | func (L *State) PushValue(index int) { 414 | C.lua_pushvalue(L.s, C.int(index)) 415 | } 416 | 417 | // lua_rawequal 418 | func (L *State) RawEqual(index1 int, index2 int) bool { 419 | return C.lua_rawequal(L.s, C.int(index1), C.int(index2)) != 0 420 | } 421 | 422 | // lua_rawget 423 | func (L *State) RawGet(index int) { 424 | C.lua_rawget(L.s, C.int(index)) 425 | } 426 | 427 | // lua_rawgeti 428 | func (L *State) RawGeti(index int, n int) { 429 | C.lua_rawgeti(L.s, C.int(index), C.int(n)) 430 | } 431 | 432 | // lua_rawset 433 | func (L *State) RawSet(index int) { 434 | C.lua_rawset(L.s, C.int(index)) 435 | } 436 | 437 | // lua_rawseti 438 | func (L *State) RawSeti(index int, n int) { 439 | C.lua_rawseti(L.s, C.int(index), C.int(n)) 440 | } 441 | 442 | // Registers a Go function as a global variable 443 | func (L *State) Register(name string, f LuaGoFunction) { 444 | L.PushGoFunction(f) 445 | L.SetGlobal(name) 446 | } 447 | 448 | // lua_remove 449 | func (L *State) Remove(index int) { 450 | C.lua_remove(L.s, C.int(index)) 451 | } 452 | 453 | // lua_replace 454 | func (L *State) Replace(index int) { 455 | C.lua_replace(L.s, C.int(index)) 456 | } 457 | 458 | // lua_resume 459 | func (L *State) Resume(narg int) int { 460 | return int(C.lua_resume(L.s, C.int(narg))) 461 | } 462 | 463 | // lua_setallocf 464 | func (L *State) SetAllocf(f Alloc) { 465 | C.clua_setallocf(L.s, unsafe.Pointer(&f)) 466 | } 467 | 468 | // lua_setfenv 469 | func (L *State) SetfEnv(index int) { 470 | C.lua_setfenv(L.s, C.int(index)) 471 | } 472 | 473 | // lua_setfield 474 | func (L *State) SetField(index int, k string) { 475 | Ck := C.CString(k) 476 | defer C.free(unsafe.Pointer(Ck)) 477 | C.lua_setfield(L.s, C.int(index), Ck) 478 | } 479 | 480 | // lua_setglobal 481 | func (L *State) SetGlobal(name string) { 482 | Cname := C.CString(name) 483 | defer C.free(unsafe.Pointer(Cname)) 484 | C.lua_setfield(L.s, C.int(LUA_GLOBALSINDEX), Cname) 485 | } 486 | 487 | // lua_setmetatable 488 | func (L *State) SetMetaTable(index int) { 489 | C.lua_setmetatable(L.s, C.int(index)) 490 | } 491 | 492 | // lua_settable 493 | func (L *State) SetTable(index int) { 494 | C.lua_settable(L.s, C.int(index)) 495 | } 496 | 497 | // lua_settop 498 | func (L *State) SetTop(index int) { 499 | C.lua_settop(L.s, C.int(index)) 500 | } 501 | 502 | // lua_status 503 | func (L *State) Status() int { 504 | return int(C.lua_status(L.s)) 505 | } 506 | 507 | // lua_toboolean 508 | func (L *State) ToBoolean(index int) bool { 509 | return C.lua_toboolean(L.s, C.int(index)) != 0 510 | } 511 | 512 | // Returns the value at index as a Go function (it must be something pushed with PushGoFunction) 513 | func (L *State) ToGoFunction(index int) (f LuaGoFunction) { 514 | if !L.IsGoFunction(index) { 515 | return nil 516 | } 517 | fid := C.clua_togofunction(L.s, C.int(index)) 518 | if fid < 0 { 519 | return nil 520 | } 521 | return L.registry[fid].(LuaGoFunction) 522 | } 523 | 524 | // Returns the value at index as a Go Struct (it must be something pushed with PushGoStruct) 525 | func (L *State) ToGoStruct(index int) (f interface{}) { 526 | if !L.IsGoStruct(index) { 527 | return nil 528 | } 529 | fid := C.clua_togostruct(L.s, C.int(index)) 530 | if fid < 0 { 531 | return nil 532 | } 533 | return L.registry[fid] 534 | } 535 | 536 | // lua_tostring 537 | func (L *State) ToString(index int) string { 538 | var size C.size_t 539 | r := C.lua_tolstring(L.s, C.int(index), &size) 540 | return C.GoStringN(r, C.int(size)) 541 | } 542 | 543 | func (L *State) ToBytes(index int) []byte { 544 | var size C.size_t 545 | b := C.lua_tolstring(L.s, C.int(index), &size) 546 | return C.GoBytes(unsafe.Pointer(b), C.int(size)) 547 | } 548 | 549 | // lua_tointeger 550 | func (L *State) ToInteger(index int) int { 551 | return int(C.lua_tointeger(L.s, C.int(index))) 552 | } 553 | 554 | // lua_tonumber 555 | func (L *State) ToNumber(index int) float64 { 556 | return float64(C.lua_tonumber(L.s, C.int(index))) 557 | } 558 | 559 | // lua_topointer 560 | func (L *State) ToPointer(index int) uintptr { 561 | return uintptr(C.lua_topointer(L.s, C.int(index))) 562 | } 563 | 564 | // lua_tothread 565 | func (L *State) ToThread(index int) *State { 566 | //TODO: find a way to link lua_State* to existing *State, return that 567 | return &State{} 568 | } 569 | 570 | // lua_touserdata 571 | func (L *State) ToUserdata(index int) unsafe.Pointer { 572 | return unsafe.Pointer(C.lua_touserdata(L.s, C.int(index))) 573 | } 574 | 575 | // lua_type 576 | func (L *State) Type(index int) LuaValType { 577 | return LuaValType(C.lua_type(L.s, C.int(index))) 578 | } 579 | 580 | // lua_typename 581 | func (L *State) Typename(tp int) string { 582 | return C.GoString(C.lua_typename(L.s, C.int(tp))) 583 | } 584 | 585 | // lua_xmove 586 | func XMove(from *State, to *State, n int) { 587 | C.lua_xmove(from.s, to.s, C.int(n)) 588 | } 589 | 590 | // lua_yield 591 | func (L *State) Yield(nresults int) int { 592 | return int(C.lua_yield(L.s, C.int(nresults))) 593 | } 594 | 595 | // Restricted library opens 596 | 597 | // Calls luaopen_base 598 | func (L *State) OpenBase() { 599 | C.clua_openbase(L.s) 600 | } 601 | 602 | // Calls luaopen_io 603 | func (L *State) OpenIO() { 604 | C.clua_openio(L.s) 605 | } 606 | 607 | // Calls luaopen_math 608 | func (L *State) OpenMath() { 609 | C.clua_openmath(L.s) 610 | } 611 | 612 | // Calls luaopen_package 613 | func (L *State) OpenPackage() { 614 | C.clua_openpackage(L.s) 615 | } 616 | 617 | // Calls luaopen_string 618 | func (L *State) OpenString() { 619 | C.clua_openstring(L.s) 620 | } 621 | 622 | // Calls luaopen_table 623 | func (L *State) OpenTable() { 624 | C.clua_opentable(L.s) 625 | } 626 | 627 | // Calls luaopen_os 628 | func (L *State) OpenOS() { 629 | C.clua_openos(L.s) 630 | } 631 | 632 | // Sets the maximum number of operations to execute at instrNumber, after this the execution ends 633 | func (L *State) SetExecutionLimit(instrNumber int) { 634 | C.clua_setexecutionlimit(L.s, C.int(instrNumber)) 635 | } 636 | 637 | // Returns the current stack trace 638 | func (L *State) StackTrace() []LuaStackEntry { 639 | r := []LuaStackEntry{} 640 | var d C.lua_Debug 641 | Sln := C.CString("Sln") 642 | defer C.free(unsafe.Pointer(Sln)) 643 | 644 | for depth := 0; C.lua_getstack(L.s, C.int(depth), &d) > 0; depth++ { 645 | C.lua_getinfo(L.s, Sln, &d) 646 | ssb := make([]byte, C.LUA_IDSIZE) 647 | for i := 0; i < C.LUA_IDSIZE; i++ { 648 | ssb[i] = byte(d.short_src[i]) 649 | if ssb[i] == 0 { 650 | ssb = ssb[:i] 651 | break 652 | } 653 | } 654 | ss := string(ssb) 655 | 656 | r = append(r, LuaStackEntry{C.GoString(d.name), C.GoString(d.source), ss, int(d.currentline)}) 657 | } 658 | 659 | return r 660 | } 661 | 662 | func (L *State) RaiseError(msg string) { 663 | st := L.StackTrace() 664 | prefix := "" 665 | if len(st) >= 1 { 666 | prefix = fmt.Sprintf("%s:%d: ", st[1].ShortSource, st[1].CurrentLine) 667 | } 668 | panic(&LuaError{0, prefix + msg, st}) 669 | } 670 | 671 | func (L *State) NewError(msg string) *LuaError { 672 | return &LuaError{0, msg, L.StackTrace()} 673 | } 674 | -------------------------------------------------------------------------------- /vendor/github.com/aarzilli/golua/lua/lua/luaconf.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ 3 | ** Configuration file for Lua 4 | ** See Copyright Notice in lua.h 5 | */ 6 | 7 | 8 | #ifndef lconfig_h 9 | #define lconfig_h 10 | 11 | #include 12 | #include 13 | 14 | 15 | /* 16 | ** ================================================================== 17 | ** Search for "@@" to find all configurable definitions. 18 | ** =================================================================== 19 | */ 20 | 21 | 22 | /* 23 | @@ LUA_ANSI controls the use of non-ansi features. 24 | ** CHANGE it (define it) if you want Lua to avoid the use of any 25 | ** non-ansi feature or library. 26 | */ 27 | #if defined(__STRICT_ANSI__) 28 | #define LUA_ANSI 29 | #endif 30 | 31 | 32 | #if !defined(LUA_ANSI) && defined(_WIN32) 33 | #define LUA_WIN 34 | #endif 35 | 36 | #if defined(LUA_USE_LINUX) 37 | #define LUA_USE_POSIX 38 | #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ 39 | #define LUA_USE_READLINE /* needs some extra libraries */ 40 | #endif 41 | 42 | #if defined(LUA_USE_MACOSX) 43 | #define LUA_USE_POSIX 44 | #define LUA_DL_DYLD /* does not need extra library */ 45 | #endif 46 | 47 | 48 | 49 | /* 50 | @@ LUA_USE_POSIX includes all functionallity listed as X/Open System 51 | @* Interfaces Extension (XSI). 52 | ** CHANGE it (define it) if your system is XSI compatible. 53 | */ 54 | #if defined(LUA_USE_POSIX) 55 | #define LUA_USE_MKSTEMP 56 | #define LUA_USE_ISATTY 57 | #define LUA_USE_POPEN 58 | #define LUA_USE_ULONGJMP 59 | #endif 60 | 61 | 62 | /* 63 | @@ LUA_PATH and LUA_CPATH are the names of the environment variables that 64 | @* Lua check to set its paths. 65 | @@ LUA_INIT is the name of the environment variable that Lua 66 | @* checks for initialization code. 67 | ** CHANGE them if you want different names. 68 | */ 69 | #define LUA_PATH "LUA_PATH" 70 | #define LUA_CPATH "LUA_CPATH" 71 | #define LUA_INIT "LUA_INIT" 72 | 73 | 74 | /* 75 | @@ LUA_PATH_DEFAULT is the default path that Lua uses to look for 76 | @* Lua libraries. 77 | @@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for 78 | @* C libraries. 79 | ** CHANGE them if your machine has a non-conventional directory 80 | ** hierarchy or if you want to install your libraries in 81 | ** non-conventional directories. 82 | */ 83 | #if defined(_WIN32) 84 | /* 85 | ** In Windows, any exclamation mark ('!') in the path is replaced by the 86 | ** path of the directory of the executable file of the current process. 87 | */ 88 | #define LUA_LDIR "!\\lua\\" 89 | #define LUA_CDIR "!\\" 90 | #define LUA_PATH_DEFAULT \ 91 | ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ 92 | LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" 93 | #define LUA_CPATH_DEFAULT \ 94 | ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" 95 | 96 | #else 97 | #define LUA_ROOT "/usr/local/" 98 | #define LUA_ROOT2 "/usr/" 99 | #define LUA_LDIR LUA_ROOT "share/lua/5.1/" 100 | #define LUA_LDIR2 LUA_ROOT2 "share/lua/5.1/" 101 | #define LUA_CDIR LUA_ROOT "lib/lua/5.1/" 102 | #define LUA_CDIR2 LUA_ROOT2 "lib/lua/5.1/" 103 | #define LUA_PATH_DEFAULT \ 104 | "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ 105 | LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ 106 | LUA_LDIR2"?.lua;" LUA_LDIR2"?/init.lua" 107 | #define LUA_CPATH_DEFAULT \ 108 | "./?.so;" LUA_CDIR"?.so;" LUA_CDIR2"?.so;" LUA_CDIR"loadall.so" 109 | #endif 110 | 111 | 112 | /* 113 | @@ LUA_DIRSEP is the directory separator (for submodules). 114 | ** CHANGE it if your machine does not use "/" as the directory separator 115 | ** and is not Windows. (On Windows Lua automatically uses "\".) 116 | */ 117 | #if defined(_WIN32) 118 | #define LUA_DIRSEP "\\" 119 | #else 120 | #define LUA_DIRSEP "/" 121 | #endif 122 | 123 | 124 | /* 125 | @@ LUA_PATHSEP is the character that separates templates in a path. 126 | @@ LUA_PATH_MARK is the string that marks the substitution points in a 127 | @* template. 128 | @@ LUA_EXECDIR in a Windows path is replaced by the executable's 129 | @* directory. 130 | @@ LUA_IGMARK is a mark to ignore all before it when bulding the 131 | @* luaopen_ function name. 132 | ** CHANGE them if for some reason your system cannot use those 133 | ** characters. (E.g., if one of those characters is a common character 134 | ** in file/directory names.) Probably you do not need to change them. 135 | */ 136 | #define LUA_PATHSEP ";" 137 | #define LUA_PATH_MARK "?" 138 | #define LUA_EXECDIR "!" 139 | #define LUA_IGMARK "-" 140 | 141 | 142 | /* 143 | @@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. 144 | ** CHANGE that if ptrdiff_t is not adequate on your machine. (On most 145 | ** machines, ptrdiff_t gives a good choice between int or long.) 146 | */ 147 | #define LUA_INTEGER ptrdiff_t 148 | 149 | 150 | /* 151 | @@ LUA_API is a mark for all core API functions. 152 | @@ LUALIB_API is a mark for all standard library functions. 153 | ** CHANGE them if you need to define those functions in some special way. 154 | ** For instance, if you want to create one Windows DLL with the core and 155 | ** the libraries, you may want to use the following definition (define 156 | ** LUA_BUILD_AS_DLL to get it). 157 | */ 158 | #if defined(LUA_BUILD_AS_DLL) 159 | 160 | #if defined(LUA_CORE) || defined(LUA_LIB) 161 | #define LUA_API __declspec(dllexport) 162 | #else 163 | #define LUA_API __declspec(dllimport) 164 | #endif 165 | 166 | #else 167 | 168 | #define LUA_API extern 169 | 170 | #endif 171 | 172 | /* more often than not the libs go together with the core */ 173 | #define LUALIB_API LUA_API 174 | 175 | 176 | /* 177 | @@ LUAI_FUNC is a mark for all extern functions that are not to be 178 | @* exported to outside modules. 179 | @@ LUAI_DATA is a mark for all extern (const) variables that are not to 180 | @* be exported to outside modules. 181 | ** CHANGE them if you need to mark them in some special way. Elf/gcc 182 | ** (versions 3.2 and later) mark them as "hidden" to optimize access 183 | ** when Lua is compiled as a shared library. 184 | */ 185 | #if defined(luaall_c) 186 | #define LUAI_FUNC static 187 | #define LUAI_DATA /* empty */ 188 | 189 | #elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ 190 | defined(__ELF__) 191 | #define LUAI_FUNC __attribute__((visibility("hidden"))) extern 192 | #define LUAI_DATA LUAI_FUNC 193 | 194 | #else 195 | #define LUAI_FUNC extern 196 | #define LUAI_DATA extern 197 | #endif 198 | 199 | 200 | 201 | /* 202 | @@ LUA_QL describes how error messages quote program elements. 203 | ** CHANGE it if you want a different appearance. 204 | */ 205 | #define LUA_QL(x) "'" x "'" 206 | #define LUA_QS LUA_QL("%s") 207 | 208 | 209 | /* 210 | @@ LUA_IDSIZE gives the maximum size for the description of the source 211 | @* of a function in debug information. 212 | ** CHANGE it if you want a different size. 213 | */ 214 | #define LUA_IDSIZE 60 215 | 216 | 217 | /* 218 | ** {================================================================== 219 | ** Stand-alone configuration 220 | ** =================================================================== 221 | */ 222 | 223 | #if defined(lua_c) || defined(luaall_c) 224 | 225 | /* 226 | @@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that 227 | @* is, whether we're running lua interactively). 228 | ** CHANGE it if you have a better definition for non-POSIX/non-Windows 229 | ** systems. 230 | */ 231 | #if defined(LUA_USE_ISATTY) 232 | #include 233 | #define lua_stdin_is_tty() isatty(0) 234 | #elif defined(LUA_WIN) 235 | #include 236 | #include 237 | #define lua_stdin_is_tty() _isatty(_fileno(stdin)) 238 | #else 239 | #define lua_stdin_is_tty() 1 /* assume stdin is a tty */ 240 | #endif 241 | 242 | 243 | /* 244 | @@ LUA_PROMPT is the default prompt used by stand-alone Lua. 245 | @@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. 246 | ** CHANGE them if you want different prompts. (You can also change the 247 | ** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) 248 | */ 249 | #define LUA_PROMPT "> " 250 | #define LUA_PROMPT2 ">> " 251 | 252 | 253 | /* 254 | @@ LUA_PROGNAME is the default name for the stand-alone Lua program. 255 | ** CHANGE it if your stand-alone interpreter has a different name and 256 | ** your system is not able to detect that name automatically. 257 | */ 258 | #define LUA_PROGNAME "lua" 259 | 260 | 261 | /* 262 | @@ LUA_MAXINPUT is the maximum length for an input line in the 263 | @* stand-alone interpreter. 264 | ** CHANGE it if you need longer lines. 265 | */ 266 | #define LUA_MAXINPUT 512 267 | 268 | 269 | /* 270 | @@ lua_readline defines how to show a prompt and then read a line from 271 | @* the standard input. 272 | @@ lua_saveline defines how to "save" a read line in a "history". 273 | @@ lua_freeline defines how to free a line read by lua_readline. 274 | ** CHANGE them if you want to improve this functionality (e.g., by using 275 | ** GNU readline and history facilities). 276 | */ 277 | #if defined(LUA_USE_READLINE) 278 | #include 279 | #include 280 | #include 281 | #define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) 282 | #define lua_saveline(L,idx) \ 283 | if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ 284 | add_history(lua_tostring(L, idx)); /* add it to history */ 285 | #define lua_freeline(L,b) ((void)L, free(b)) 286 | #else 287 | #define lua_readline(L,b,p) \ 288 | ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ 289 | fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ 290 | #define lua_saveline(L,idx) { (void)L; (void)idx; } 291 | #define lua_freeline(L,b) { (void)L; (void)b; } 292 | #endif 293 | 294 | #endif 295 | 296 | /* }================================================================== */ 297 | 298 | 299 | /* 300 | @@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles 301 | @* as a percentage. 302 | ** CHANGE it if you want the GC to run faster or slower (higher values 303 | ** mean larger pauses which mean slower collection.) You can also change 304 | ** this value dynamically. 305 | */ 306 | #define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ 307 | 308 | 309 | /* 310 | @@ LUAI_GCMUL defines the default speed of garbage collection relative to 311 | @* memory allocation as a percentage. 312 | ** CHANGE it if you want to change the granularity of the garbage 313 | ** collection. (Higher values mean coarser collections. 0 represents 314 | ** infinity, where each step performs a full collection.) You can also 315 | ** change this value dynamically. 316 | */ 317 | #define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ 318 | 319 | 320 | 321 | /* 322 | @@ LUA_COMPAT_GETN controls compatibility with old getn behavior. 323 | ** CHANGE it (define it) if you want exact compatibility with the 324 | ** behavior of setn/getn in Lua 5.0. 325 | */ 326 | #undef LUA_COMPAT_GETN 327 | 328 | /* 329 | @@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. 330 | ** CHANGE it to undefined as soon as you do not need a global 'loadlib' 331 | ** function (the function is still available as 'package.loadlib'). 332 | */ 333 | #undef LUA_COMPAT_LOADLIB 334 | 335 | /* 336 | @@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. 337 | ** CHANGE it to undefined as soon as your programs use only '...' to 338 | ** access vararg parameters (instead of the old 'arg' table). 339 | */ 340 | #define LUA_COMPAT_VARARG 341 | 342 | /* 343 | @@ LUA_COMPAT_MOD controls compatibility with old math.mod function. 344 | ** CHANGE it to undefined as soon as your programs use 'math.fmod' or 345 | ** the new '%' operator instead of 'math.mod'. 346 | */ 347 | #define LUA_COMPAT_MOD 348 | 349 | /* 350 | @@ LUA_COMPAT_LSTR controls compatibility with old long string nesting 351 | @* facility. 352 | ** CHANGE it to 2 if you want the old behaviour, or undefine it to turn 353 | ** off the advisory error when nesting [[...]]. 354 | */ 355 | #define LUA_COMPAT_LSTR 1 356 | 357 | /* 358 | @@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. 359 | ** CHANGE it to undefined as soon as you rename 'string.gfind' to 360 | ** 'string.gmatch'. 361 | */ 362 | #define LUA_COMPAT_GFIND 363 | 364 | /* 365 | @@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' 366 | @* behavior. 367 | ** CHANGE it to undefined as soon as you replace to 'luaL_register' 368 | ** your uses of 'luaL_openlib' 369 | */ 370 | #define LUA_COMPAT_OPENLIB 371 | 372 | 373 | 374 | /* 375 | @@ luai_apicheck is the assert macro used by the Lua-C API. 376 | ** CHANGE luai_apicheck if you want Lua to perform some checks in the 377 | ** parameters it gets from API calls. This may slow down the interpreter 378 | ** a bit, but may be quite useful when debugging C code that interfaces 379 | ** with Lua. A useful redefinition is to use assert.h. 380 | */ 381 | #if defined(LUA_USE_APICHECK) 382 | #include 383 | #define luai_apicheck(L,o) { (void)L; assert(o); } 384 | #else 385 | #define luai_apicheck(L,o) { (void)L; } 386 | #endif 387 | 388 | 389 | /* 390 | @@ LUAI_BITSINT defines the number of bits in an int. 391 | ** CHANGE here if Lua cannot automatically detect the number of bits of 392 | ** your machine. Probably you do not need to change this. 393 | */ 394 | /* avoid overflows in comparison */ 395 | #if INT_MAX-20 < 32760 396 | #define LUAI_BITSINT 16 397 | #elif INT_MAX > 2147483640L 398 | /* int has at least 32 bits */ 399 | #define LUAI_BITSINT 32 400 | #else 401 | #error "you must define LUA_BITSINT with number of bits in an integer" 402 | #endif 403 | 404 | 405 | /* 406 | @@ LUAI_UINT32 is an unsigned integer with at least 32 bits. 407 | @@ LUAI_INT32 is an signed integer with at least 32 bits. 408 | @@ LUAI_UMEM is an unsigned integer big enough to count the total 409 | @* memory used by Lua. 410 | @@ LUAI_MEM is a signed integer big enough to count the total memory 411 | @* used by Lua. 412 | ** CHANGE here if for some weird reason the default definitions are not 413 | ** good enough for your machine. (The definitions in the 'else' 414 | ** part always works, but may waste space on machines with 64-bit 415 | ** longs.) Probably you do not need to change this. 416 | */ 417 | #if LUAI_BITSINT >= 32 418 | #define LUAI_UINT32 unsigned int 419 | #define LUAI_INT32 int 420 | #define LUAI_MAXINT32 INT_MAX 421 | #define LUAI_UMEM size_t 422 | #define LUAI_MEM ptrdiff_t 423 | #else 424 | /* 16-bit ints */ 425 | #define LUAI_UINT32 unsigned long 426 | #define LUAI_INT32 long 427 | #define LUAI_MAXINT32 LONG_MAX 428 | #define LUAI_UMEM unsigned long 429 | #define LUAI_MEM long 430 | #endif 431 | 432 | 433 | /* 434 | @@ LUAI_MAXCALLS limits the number of nested calls. 435 | ** CHANGE it if you need really deep recursive calls. This limit is 436 | ** arbitrary; its only purpose is to stop infinite recursion before 437 | ** exhausting memory. 438 | */ 439 | #define LUAI_MAXCALLS 20000 440 | 441 | 442 | /* 443 | @@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function 444 | @* can use. 445 | ** CHANGE it if you need lots of (Lua) stack space for your C 446 | ** functions. This limit is arbitrary; its only purpose is to stop C 447 | ** functions to consume unlimited stack space. (must be smaller than 448 | ** -LUA_REGISTRYINDEX) 449 | */ 450 | #define LUAI_MAXCSTACK 8000 451 | 452 | 453 | 454 | /* 455 | ** {================================================================== 456 | ** CHANGE (to smaller values) the following definitions if your system 457 | ** has a small C stack. (Or you may want to change them to larger 458 | ** values if your system has a large C stack and these limits are 459 | ** too rigid for you.) Some of these constants control the size of 460 | ** stack-allocated arrays used by the compiler or the interpreter, while 461 | ** others limit the maximum number of recursive calls that the compiler 462 | ** or the interpreter can perform. Values too large may cause a C stack 463 | ** overflow for some forms of deep constructs. 464 | ** =================================================================== 465 | */ 466 | 467 | 468 | /* 469 | @@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and 470 | @* syntactical nested non-terminals in a program. 471 | */ 472 | #define LUAI_MAXCCALLS 200 473 | 474 | 475 | /* 476 | @@ LUAI_MAXVARS is the maximum number of local variables per function 477 | @* (must be smaller than 250). 478 | */ 479 | #define LUAI_MAXVARS 200 480 | 481 | 482 | /* 483 | @@ LUAI_MAXUPVALUES is the maximum number of upvalues per function 484 | @* (must be smaller than 250). 485 | */ 486 | #define LUAI_MAXUPVALUES 60 487 | 488 | 489 | /* 490 | @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. 491 | */ 492 | #define LUAL_BUFFERSIZE BUFSIZ 493 | 494 | /* }================================================================== */ 495 | 496 | 497 | 498 | 499 | /* 500 | ** {================================================================== 501 | @@ LUA_NUMBER is the type of numbers in Lua. 502 | ** CHANGE the following definitions only if you want to build Lua 503 | ** with a number type different from double. You may also need to 504 | ** change lua_number2int & lua_number2integer. 505 | ** =================================================================== 506 | */ 507 | 508 | #define LUA_NUMBER_DOUBLE 509 | #define LUA_NUMBER double 510 | 511 | /* 512 | @@ LUAI_UACNUMBER is the result of an 'usual argument conversion' 513 | @* over a number. 514 | */ 515 | #define LUAI_UACNUMBER double 516 | 517 | 518 | /* 519 | @@ LUA_NUMBER_SCAN is the format for reading numbers. 520 | @@ LUA_NUMBER_FMT is the format for writing numbers. 521 | @@ lua_number2str converts a number to a string. 522 | @@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. 523 | @@ lua_str2number converts a string to a number. 524 | */ 525 | #define LUA_NUMBER_SCAN "%lf" 526 | #define LUA_NUMBER_FMT "%.14g" 527 | #define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) 528 | #define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ 529 | #define lua_str2number(s,p) strtod((s), (p)) 530 | 531 | 532 | /* 533 | @@ The luai_num* macros define the primitive operations over numbers. 534 | */ 535 | #if defined(LUA_CORE) 536 | #include 537 | #define luai_numadd(a,b) ((a)+(b)) 538 | #define luai_numsub(a,b) ((a)-(b)) 539 | #define luai_nummul(a,b) ((a)*(b)) 540 | #define luai_numdiv(a,b) ((a)/(b)) 541 | #define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) 542 | #define luai_numpow(a,b) (pow(a,b)) 543 | #define luai_numunm(a) (-(a)) 544 | #define luai_numeq(a,b) ((a)==(b)) 545 | #define luai_numlt(a,b) ((a)<(b)) 546 | #define luai_numle(a,b) ((a)<=(b)) 547 | #define luai_numisnan(a) (!luai_numeq((a), (a))) 548 | #endif 549 | 550 | 551 | /* 552 | @@ lua_number2int is a macro to convert lua_Number to int. 553 | @@ lua_number2integer is a macro to convert lua_Number to lua_Integer. 554 | ** CHANGE them if you know a faster way to convert a lua_Number to 555 | ** int (with any rounding method and without throwing errors) in your 556 | ** system. In Pentium machines, a naive typecast from double to int 557 | ** in C is extremely slow, so any alternative is worth trying. 558 | */ 559 | 560 | /* On a Pentium, resort to a trick */ 561 | #if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ 562 | (defined(__i386) || defined (_M_IX86) || defined(__i386__)) 563 | 564 | /* On a Microsoft compiler, use assembler */ 565 | #if defined(_MSC_VER) 566 | 567 | #define lua_number2int(i,d) __asm fld d __asm fistp i 568 | #define lua_number2integer(i,n) lua_number2int(i, n) 569 | 570 | /* the next trick should work on any Pentium, but sometimes clashes 571 | with a DirectX idiosyncrasy */ 572 | #else 573 | 574 | union luai_Cast { double l_d; long l_l; }; 575 | #define lua_number2int(i,d) \ 576 | { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } 577 | #define lua_number2integer(i,n) lua_number2int(i, n) 578 | 579 | #endif 580 | 581 | 582 | /* this option always works, but may be slow */ 583 | #else 584 | #define lua_number2int(i,d) ((i)=(int)(d)) 585 | #define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) 586 | 587 | #endif 588 | 589 | /* }================================================================== */ 590 | 591 | 592 | /* 593 | @@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. 594 | ** CHANGE it if your system requires alignments larger than double. (For 595 | ** instance, if your system supports long doubles and they must be 596 | ** aligned in 16-byte boundaries, then you should add long double in the 597 | ** union.) Probably you do not need to change this. 598 | */ 599 | #define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } 600 | 601 | 602 | /* 603 | @@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. 604 | ** CHANGE them if you prefer to use longjmp/setjmp even with C++ 605 | ** or if want/don't to use _longjmp/_setjmp instead of regular 606 | ** longjmp/setjmp. By default, Lua handles errors with exceptions when 607 | ** compiling as C++ code, with _longjmp/_setjmp when asked to use them, 608 | ** and with longjmp/setjmp otherwise. 609 | */ 610 | #if defined(__cplusplus) 611 | /* C++ exceptions */ 612 | #define LUAI_THROW(L,c) throw(c) 613 | #define LUAI_TRY(L,c,a) try { a } catch(...) \ 614 | { if ((c)->status == 0) (c)->status = -1; } 615 | #define luai_jmpbuf int /* dummy variable */ 616 | 617 | #elif defined(LUA_USE_ULONGJMP) 618 | /* in Unix, try _longjmp/_setjmp (more efficient) */ 619 | #define LUAI_THROW(L,c) _longjmp((c)->b, 1) 620 | #define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } 621 | #define luai_jmpbuf jmp_buf 622 | 623 | #else 624 | /* default handling with long jumps */ 625 | #define LUAI_THROW(L,c) longjmp((c)->b, 1) 626 | #define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } 627 | #define luai_jmpbuf jmp_buf 628 | 629 | #endif 630 | 631 | 632 | /* 633 | @@ LUA_MAXCAPTURES is the maximum number of captures that a pattern 634 | @* can do during pattern-matching. 635 | ** CHANGE it if you need more captures. This limit is arbitrary. 636 | */ 637 | #define LUA_MAXCAPTURES 32 638 | 639 | 640 | /* 641 | @@ lua_tmpnam is the function that the OS library uses to create a 642 | @* temporary name. 643 | @@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. 644 | ** CHANGE them if you have an alternative to tmpnam (which is considered 645 | ** insecure) or if you want the original tmpnam anyway. By default, Lua 646 | ** uses tmpnam except when POSIX is available, where it uses mkstemp. 647 | */ 648 | #if defined(loslib_c) || defined(luaall_c) 649 | 650 | #if defined(LUA_USE_MKSTEMP) 651 | #include 652 | #define LUA_TMPNAMBUFSIZE 32 653 | #define lua_tmpnam(b,e) { \ 654 | strcpy(b, "/tmp/lua_XXXXXX"); \ 655 | e = mkstemp(b); \ 656 | if (e != -1) close(e); \ 657 | e = (e == -1); } 658 | 659 | #else 660 | #define LUA_TMPNAMBUFSIZE L_tmpnam 661 | #define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } 662 | #endif 663 | 664 | #endif 665 | 666 | 667 | /* 668 | @@ lua_popen spawns a new process connected to the current one through 669 | @* the file streams. 670 | ** CHANGE it if you have a way to implement it in your system. 671 | */ 672 | #if defined(LUA_USE_POPEN) 673 | 674 | #define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) 675 | #define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) 676 | 677 | #elif defined(LUA_WIN) 678 | 679 | #define lua_popen(L,c,m) ((void)L, _popen(c,m)) 680 | #define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) 681 | 682 | #else 683 | 684 | #define lua_popen(L,c,m) ((void)((void)c, m), \ 685 | luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) 686 | #define lua_pclose(L,file) ((void)((void)L, file), 0) 687 | 688 | #endif 689 | 690 | /* 691 | @@ LUA_DL_* define which dynamic-library system Lua should use. 692 | ** CHANGE here if Lua has problems choosing the appropriate 693 | ** dynamic-library system for your platform (either Windows' DLL, Mac's 694 | ** dyld, or Unix's dlopen). If your system is some kind of Unix, there 695 | ** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for 696 | ** it. To use dlopen you also need to adapt the src/Makefile (probably 697 | ** adding -ldl to the linker options), so Lua does not select it 698 | ** automatically. (When you change the makefile to add -ldl, you must 699 | ** also add -DLUA_USE_DLOPEN.) 700 | ** If you do not want any kind of dynamic library, undefine all these 701 | ** options. 702 | ** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. 703 | */ 704 | #if defined(LUA_USE_DLOPEN) 705 | #define LUA_DL_DLOPEN 706 | #endif 707 | 708 | #if defined(LUA_WIN) 709 | #define LUA_DL_DLL 710 | #endif 711 | 712 | 713 | /* 714 | @@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State 715 | @* (the data goes just *before* the lua_State pointer). 716 | ** CHANGE (define) this if you really need that. This value must be 717 | ** a multiple of the maximum alignment required for your machine. 718 | */ 719 | #define LUAI_EXTRASPACE 0 720 | 721 | 722 | /* 723 | @@ luai_userstate* allow user-specific actions on threads. 724 | ** CHANGE them if you defined LUAI_EXTRASPACE and need to do something 725 | ** extra when a thread is created/deleted/resumed/yielded. 726 | */ 727 | #define luai_userstateopen(L) ((void)L) 728 | #define luai_userstateclose(L) ((void)L) 729 | #define luai_userstatethread(L,L1) ((void)L) 730 | #define luai_userstatefree(L) ((void)L) 731 | #define luai_userstateresume(L,n) ((void)L) 732 | #define luai_userstateyield(L,n) ((void)L) 733 | 734 | 735 | /* 736 | @@ LUA_INTFRMLEN is the length modifier for integer conversions 737 | @* in 'string.format'. 738 | @@ LUA_INTFRM_T is the integer type correspoding to the previous length 739 | @* modifier. 740 | ** CHANGE them if your system supports long long or does not support long. 741 | */ 742 | 743 | #if defined(LUA_USELONGLONG) 744 | 745 | #define LUA_INTFRMLEN "ll" 746 | #define LUA_INTFRM_T long long 747 | 748 | #else 749 | 750 | #define LUA_INTFRMLEN "l" 751 | #define LUA_INTFRM_T long 752 | 753 | #endif 754 | 755 | 756 | 757 | /* =================================================================== */ 758 | 759 | /* 760 | ** Local configuration. You can use this space to add your redefinitions 761 | ** without modifying the main part of the file. 762 | */ 763 | 764 | 765 | 766 | #endif 767 | 768 | --------------------------------------------------------------------------------