Skip to content

Instantly share code, notes, and snippets.

@dotbmp
Created October 18, 2017 05:27
Show Gist options
  • Save dotbmp/ef1518ab8bc27525a317241c9ff974b1 to your computer and use it in GitHub Desktop.
Save dotbmp/ef1518ab8bc27525a317241c9ff974b1 to your computer and use it in GitHub Desktop.
Lua binding for Odin
foreign import lua_c "lua53.lib"
// @todo: add luajit support
// @ref: https://www.lua.org/manual/5.3/manual.html#4
// @ref:
// @region luaconf.h
MAXINTEGER :: i64( 0x7fff_ffff_ffff_ffff);
MININTEGER :: i64(-0x8000_0000_0000_0000);
I_MAXSTACK :: 1000000;
EXTRASPACE :: 1500;
IDSIZE :: 60;
L_BUFFERSIZE :: 0x80 * size_of(rawptr) * size_of(Integer);
numbertointeger :: proc(n: Number, p: ^Integer) -> i32 #inline {
if (n >= cast(Number) MININTEGER) && (n < -(cast(Number) MININTEGER)) {
p^ = cast(Integer) n;
return 1;
}
return 0;
}
// @endregion
// @region lua.h
VERSION_MAJOR :: "5";
VERSION_MINOR :: "3";
VERSION_NUM :: 503;
VERSION_RELEASE :: "4";
VERSION :: "Lua " + VERSION_MAJOR + "." + VERSION_MINOR;
RELEASE :: VERSION + "." + VERSION_RELEASE;
COPYRIGHT :: RELEASE + " Copyright (C) 1994-2017 Lua.org, PUC-Rio";
AUTHORS :: "R. Ierusalimschy, L. H. de Figueiredo, W. Celes";
// @note: mark for precompiled code
SIGNATURE :: "\x1bLua"; // <esc>Lua
// @note: option for multiple returns in 'lua_pcall' and 'lua_call'
MULTRET :: -1;
REGISTRYINDEX :: -I_MAXSTACK - 1000;
upvalueindex :: proc(i: i32) -> i32 #inline do return REGISTRYINDEX - i;
// @note: thread status
OK :: 0;
YIELD :: 1;
ERRRUN :: 2;
ERRSYNTAX :: 3;
ERRMEM :: 4;
ERRGCMM :: 5;
ERRERR :: 6;
// @note: opaque type for the state of the entire lua instance
State :: rawptr;
// @note: basic types
TNONE :: -1;
TNIL :: 0;
TBOOLEAN :: 1;
TLIGHTUSERDATA :: 2;
TNUMBER :: 3;
TSTRING :: 4;
TTABLE :: 5;
TFUNCTION :: 6;
TUSERDATA :: 7;
TTHREAD :: 8;
NUMTAGS :: 9;
// @note: minimum lua stack available to a c function
MINSTACK :: 20;
// @note: predefined values in the registry
RIDX_MAINTHREAD :: 1;
RIDX_GLOBALS :: 2;
RIDX_LAST :: RIDX_GLOBALS;
// @note: lua number types
Number :: f64; // @todo: arch size
Integer :: int;
Unsigned :: uint;
// @note: type for continuation function contexts
KContext :: uint;
// @note: type for c functions registered with lua
CFunction :: #type proc(L: State) -> i32;
// @note: type for continuation functions
KFunction :: #type proc(L: State, status: int, ctx: KContext) -> i32;
// @note: type for functions that read/write blocks when loading/dumping lua chunks
Reader :: #type proc(L: State, data: rawptr, size: ^int) -> ^u8;
Writer :: #type proc(L: State, p: rawptr, sz: int, ud: rawptr) -> i32;
// @note: type for memory allocation functions
Alloc :: #type proc(ud, ptr: rawptr, osize, nsize: int) -> rawptr;
// lua_ident
// @note: state manipulation
foreign lua_c {
newstate :: proc(f: Alloc, ud: rawptr) -> State #cc_c #link_name "lua_newstate" ---;
close :: proc(L: State) #cc_c #link_name "lua_close" ---;
newthread :: proc(L: State) -> State #cc_c #link_name "lua_newthread" ---;
atpanic :: proc(L: State, panicf: CFunction) -> CFunction #cc_c #link_name "lua_atpanic" ---;
version :: proc(L: State) -> ^Number #cc_c #link_name "lua_version" ---;
}
// @note: basic stack manipulation
foreign lua_c {
absindex :: proc(L: State, idx: i32) -> i32 #cc_c #link_name "lua_absindex" ---;
gettop :: proc(L: State) -> i32 #cc_c #link_name "lua_gettop" ---;
settop :: proc(L: State, index: i32) #cc_c #link_name "lua_settop" ---;
pushvalue :: proc(L: State, index: i32) #cc_c #link_name "lua_pushvalue" ---;
rotate :: proc(L: State, idx: i32, n: i32) #cc_c #link_name "lua_rotate" ---;
copy :: proc(L: State, fromidx, toidx: i32) #cc_c #link_name "lua_copy" ---;
checkstack :: proc(L: State, n: i32) -> i32 #cc_c #link_name "lua_checkstack" ---;
xmove :: proc(from, to: State, n: i32) #cc_c #link_name "lua_xmove" ---;
}
// @note: access functions (stack -> c)
foreign lua_c {
isnumber :: proc(L: State, index: i32) -> i32 #cc_c #link_name "lua_isnumber" ---;
isstring :: proc(L: State, index: i32) -> i32 #cc_c #link_name "lua_isstring" ---;
iscfunction :: proc(L: State, index: i32) -> i32 #cc_c #link_name "lua_iscfunction" ---;
isinteger :: proc(L: State, index: i32) -> i32 #cc_c #link_name "lua_isinteger" ---;
isuserdata :: proc(L: State, index: i32) -> i32 #cc_c #link_name "lua_isuserdata" ---;
type_ :: proc(L: State, index: i32) -> i32 #cc_c #link_name "lua_type" ---;
typename :: proc(L: State, tp: i32) -> ^u8 #cc_c #link_name "lua_typename" ---;
tonumberx :: proc(L: State, index: i32, isnum: ^i32) -> Number #cc_c #link_name "lua_tonumberx" ---;
tointegerx :: proc(L: State, index: i32, isnum: ^i32) -> Integer #cc_c #link_name "lua_tointegerx" ---;
toboolean :: proc(L: State, index: i32) -> i32 #cc_c #link_name "lua_toboolean" ---;
tolstring :: proc(L: State, index: i32, len: ^int) -> ^u8 #cc_c #link_name "lua_tolstring" ---;
rawlen :: proc(L: State, index: i32) -> int #cc_c #link_name "lua_rawlen" ---;
tocfunction :: proc(L: State, index: i32) -> CFunction #cc_c #link_name "lua_tocfunction" ---;
touserdata :: proc(L: State, index: i32) -> rawptr #cc_c #link_name "lua_touserdata" ---;
tothread :: proc(L: State, index: i32) -> State #cc_c #link_name "lua_tothread" ---;
topointer :: proc(L: State, index: i32) -> rawptr #cc_c #link_name "lua_topointer" ---;
}
// @note: arithmetic and comparison operators
OPADD :: 0;
OPSUB :: 1;
OPMUL :: 2;
OPMOD :: 3;
OPPOW :: 4;
OPDIV :: 5;
OPIDIV :: 6;
OPBAND :: 7;
OPBOR :: 8;
OPBXOR :: 9;
OPSHL :: 10;
OPSHR :: 11;
OPUNM :: 12;
OPBNOT :: 13;
foreign lua_c {
arith :: proc(L: State, op: i32) #cc_c #link_name "lua_arith" ---;
}
OPEQ :: 0;
OPLE :: 1;
OPLT :: 2;
foreign lua_c {
rawequal :: proc(L: State, index1, index2: i32) -> i32 #cc_c #link_name "lua_rawequal" ---;
compare :: proc(L: State, index1, index2: i32, op: i32) -> i32 #cc_c #link_name "lua_compare" ---;
}
// @note: push functions
foreign lua_c {
pushnil :: proc(L: State) #cc_c #link_name "lua_pushnil" ---;
pushnumber :: proc(L: State, n: Number) #cc_c #link_name "lua_pushnumber" ---;
pushinteger :: proc(L: State, n: Integer) #cc_c #link_name "lua_pushinteger" ---;
pushlstring :: proc(L: State, s: ^u8, len: int) -> ^u8 #cc_c #link_name "lua_pushlstring" ---;
pushstring :: proc(L: State, s: ^u8) -> ^u8 #cc_c #link_name "lua_pushstring" ---;
pushvfstring :: proc(L: State, fmt: ^u8, #c_vararg args: ...any) -> ^u8 #cc_c #link_name "lua_pushvfstring" ---;
pushfstring :: proc(L: State, fmt: ^u8, #c_vararg args: ...any) -> ^u8 #cc_c #link_name "lua_pushfstring" ---;
pushcclosure :: proc(L: State, fn: CFunction, n: i32) #cc_c #link_name "lua_pushcclosure" ---;
pushboolean :: proc(L: State, b: i32) #cc_c #link_name "lua_pushboolean" ---;
pushlightuserdata :: proc(L: State, p: rawptr) #cc_c #link_name "lua_pushlightuserdata" ---;
pushthread :: proc(L: State) -> i32 #cc_c #link_name "lua_pushthread" ---;
}
// @note: get functions (lua -> stack)
foreign lua_c {
getfield :: proc(L: State, index: i32, k: ^u8) -> i32 #cc_c #link_name "lua_getfield" ---;
gettable :: proc(L: State, index: i32) -> i32 #cc_c #link_name "lua_gettable" ---;
getglobal :: proc(L: State, name: ^u8) -> i32 #cc_c #link_name "lua_getglobal" ---;
geti :: proc(L: State, index: i32, i: Integer) -> i32 #cc_c #link_name "lua_geti" ---;
rawget :: proc(L: State, index: i32) -> i32 #cc_c #link_name "lua_rawget" ---;
rawgeti :: proc(L: State, index: i32, n: Integer) -> i32 #cc_c #link_name "lua_geti" ---;
rawgetp :: proc(L: State, index: i32, p: rawptr) -> i32 #cc_c #link_name "lua_getp" ---;
createtable :: proc(L: State, narr, nrec: i32) #cc_c #link_name "lua_createtable" ---;
newuserdata :: proc(L: State, size: int) -> rawptr #cc_c #link_name "lua_userdata" ---;
getmetatable :: proc(L: State, index: i32) -> i32 #cc_c #link_name "lua_getmetatable" ---;
getuservalue :: proc(L: State, index: i32) -> i32 #cc_c #link_name "lua_uservalue" ---;
}
// @note: set functions (stack -> lua)
foreign lua_c {
setglobal :: proc(L: State, name: ^u8) #cc_c #link_name "lua_setglobal" ---;
settable :: proc(L: State, index: i32) #cc_c #link_name "lua_settable" ---;
setfield :: proc(L: State, index: i32, k: ^u8) #cc_c #link_name "lua_setfield" ---;
seti :: proc(L: State, index: i32, n: Integer) #cc_c #link_name "lua_seti" ---;
rawset :: proc(L: State, index: i32) #cc_c #link_name "lua_rawset" ---;
rawseti :: proc(L: State, index: i32, i: Integer) #cc_c #link_name "lua_rawseti" ---;
rawsetp :: proc(L: State, index: i32, p: rawptr) #cc_c #link_name "lua_rawsetp" ---;
setmetatable :: proc(L: State, index: i32) #cc_c #link_name "lua_setmetatable" ---;
setuservalue :: proc(L: State, index: i32) #cc_c #link_name "lua_setuservalue" ---;
}
// @note: load and run lua code
foreign lua_c callk :: proc(L: State, nargs, nresults: i32, ctx: KContext, k: KFunction) #cc_c #link_name "lua_callk" ---;
call :: proc(L: State, nargs, nresults: i32) #inline do callk(L, nargs, nresults, 0, nil);
foreign lua_c pcallk :: proc(L: State, nargs, nresults: i32, msgh: i32, ctx: KContext, k: KFunction) -> i32 #cc_c #link_name "lua_pcallk" ---;
pcall :: proc(L: State, nargs, nresults: i32, msgh: i32) -> i32 #inline do return pcallk(L, nargs, nresults, msgh, 0, nil);
foreign lua_c {
load :: proc(L: State, reader: Reader, data: rawptr, chunk_name, mode: ^u8) -> i32 #cc_c #link_name "lua_load" ---;
dump :: proc(L: State, writer: Writer, data: rawptr, strip: i32) -> i32 #cc_c #link_name "lua_dump" ---;
}
// @note: coroutine functions
foreign lua_c {
yieldk :: proc(L: State, nresults: i32, ctx: KContext, k: KFunction) -> i32 #cc_c #link_name "lua_yieldk" ---;
resume :: proc(L: State, from: State, nargs: i32) -> i32 #cc_c #link_name "lua_resume" ---;
status :: proc(L: State) -> i32 #cc_c #link_name "lua_status" ---;
isyieldable :: proc(L: State, index: i32) -> i32 #cc_c #link_name "lua_isyieldable" ---;
yield_ :: proc(L: State, nresults: i32) -> i32 #cc_c #link_name "lua_yield" ---;
}
// @note: garbage collection options
GCSTOP :: 0;
GCRESTART :: 1;
GCCOLLECT :: 2;
GCCOUNT :: 3;
GCCOUNTB :: 4;
GCSTEP :: 5;
GCSETPAUSE :: 6;
GCSETSTEPMUL :: 7;
GCISRUNNING :: 9;
foreign lua_c gc :: proc(L: State, what, data: i32) -> i32 #cc_c #link_name "lua_gc" ---;
// @note: miscellaneous functions
foreign lua_c {
error :: proc(L: State) -> i32 #cc_c #link_name "lua_error" ---;
next :: proc(L: State, index: i32) -> i32 #cc_c #link_name "lua_next" ---;
concat :: proc(L: State, n: int) #cc_c #link_name "lua_concat" ---;
len_ :: proc(L: State, index: i32) #cc_c #link_name "lua_len" ---;
stringtonumber :: proc(L: State, s: ^u8) -> int #cc_c #link_name "lua_stringtonumber" ---;
getallocf :: proc(L: State, ud: ^rawptr) -> Alloc #cc_c #link_name "lua_getallocf" ---;
setallocf :: proc(L: State, f: Alloc, ud: rawptr) #cc_c #link_name "lua_setallocf" ---;
}
// @note: some useful macros
getextraspace :: proc(L: State) -> rawptr #inline do return (cast(^u8) L) - EXTRASPACE;
tonumber :: proc(L: State, index: i32) -> Number #inline do return tonumberx(L, index, nil);
tointeger :: proc(L: State, index: i32) -> Integer #inline do return tointegerx(L, index, nil);
pop :: proc(L: State, n: i32) #inline do settop(L, -n - 1);
newtable :: proc(L: State) #inline do createtable(L, 0, 0);
register :: proc(L: State, name: ^u8, f: CFunction) #inline {
pushcfunction(L, f);
setglobal(L, name);
}
pushcfunction :: proc(L: State, f: CFunction) #inline do pushcclosure(L, f, 0);
isfunction :: proc(L: State, index: i32) -> i32 #inline do return i32( type_(L, index) == TFUNCTION );
istable :: proc(L: State, index: i32) -> i32 #inline do return i32( type_(L, index) == TTABLE );
islightuserdata :: proc(L: State, index: i32) -> i32 #inline do return i32( type_(L, index) == TLIGHTUSERDATA );
isnil :: proc(L: State, index: i32) -> i32 #inline do return i32( type_(L, index) == TNIL );
isboolean :: proc(L: State, index: i32) -> i32 #inline do return i32( type_(L, index) == TBOOLEAN );
isthread :: proc(L: State, index: i32) -> i32 #inline do return i32( type_(L, index) == TTHREAD );
isnone :: proc(L: State, index: i32) -> i32 #inline do return i32( type_(L, index) == TNONE );
isnoneornil :: proc(L: State, index: i32) -> i32 #inline do return i32( type_(L, index) == 0 );
pushliteral :: proc(L: State, s: ^u8) -> ^u8 #inline do return pushstring(L, s);
pushglobaltable :: proc(L: State) #inline do rawgeti(L, REGISTRYINDEX, RIDX_GLOBALS);
tostring :: proc(L: State, index: i32) -> ^u8 #inline do return tolstring(L, index, nil);
insert :: proc(L: State, index: i32) #inline do rotate(L, index, 1);
remove :: proc(L: State, index: i32) #inline {
rotate(L, index, -1);
pop(L, 1);
}
replace :: proc(L: State, index: i32) #inline {
copy(L, -1, index);
pop(L, 1);
}
// @note: unsigned conversions
pushunsigned :: proc(L: State, n: Unsigned) #inline do pushinteger(L, cast(Integer) n);
tounsignedx :: proc(L: State, index: i32, isnum: ^i32) -> Unsigned #inline do return cast(Unsigned) tointegerx(L, index, isnum);
tounsigned :: proc(L: State, index: i32) -> Unsigned #inline do return tounsignedx(L, index, nil);
// @note: debug api
// @note: event codes
HOOKCALL :: 0;
HOOKCOUNT :: 1;
HOOKLINE :: 2;
HOOKRET :: 3;
HOOKTAILCALL :: 4;
// @note: event masks
MASKCALL :: 1 << HOOKCALL;
MASKCOUNT :: 1 << HOOKRET;
MASKLINE :: 1 << HOOKLINE;
MASKRET :: 1 << HOOKCOUNT;
// @note: activation record
Debug :: struct #packed {
event: i32,
name: ^u8,
namewhat: ^u8,
what: ^u8,
source: ^u8,
currentline: i32,
linedefined: i32,
lastlinedefined: i32,
nups: u8,
nparams: u8,
isvararg: u8,
istailcall: u8,
short_src: [IDSIZE]u8,
// private part
}
// @note: functions to be called by the debugger in specific events
Hook :: #type proc(L: State, ar: ^Debug);
// @note: debug functions
foreign lua_c {
getstack :: proc(L: State, level: i32, ar: ^Debug) -> i32 #cc_c #link_name "lua_getstack" ---;
getinfo :: proc(L: State, what: ^u8, ar: ^Debug) -> i32 #cc_c #link_name "lua_getinfo" ---;
getlocal :: proc(L: State, ar: ^Debug, n: i32) -> ^u8 #cc_c #link_name "lua_getlocal" ---;
setlocal :: proc(L: State, ar: ^Debug, n: i32) -> ^u8 #cc_c #link_name "lua_setlocal" ---;
getupvalue :: proc(L: State, funcindex: i32, n: i32) -> ^u8 #cc_c #link_name "lua_getupvalue" ---;
setupvalue :: proc(L: State, funcindex: i32, n: i32) -> ^u8 #cc_c #link_name "lua_setupvalue" ---;
upvalueid :: proc(L: State, funcindex: i32, n: i32) -> rawptr #cc_c #link_name "lua_upvalueid" ---;
upvaluejoin :: proc(L: State, funcindex1: i32, n1: i32, funcindex2: i32, n2: i32) #cc_c #link_name "lua_upvaluejoin" ---;
sethook :: proc(L: State, f: Hook, mask: i32, count: i32) #cc_c #link_name "lua_sethook" ---;
gethook :: proc(L: State) -> Hook #cc_c #link_name "lua_gethook" ---;
gethookmask :: proc(L: State) -> i32 #cc_c #link_name "lua_gethookmask" ---;
gethookcount :: proc(L: State) -> i32 #cc_c #link_name "lua_gethookcount" ---;
}
// @endregion
// @region lualib.h
VERSUFFIX :: "_" + VERSION_MAJOR + "_" + VERSION_MINOR;
foreign lua_c {
open_base :: proc(L: State) -> i32 #cc_c #link_name "luaopen_base" ---;
open_coroutine :: proc(L: State) -> i32 #cc_c #link_name "luaopen_coroutine" ---;
open_table :: proc(L: State) -> i32 #cc_c #link_name "luaopen_table" ---;
open_io :: proc(L: State) -> i32 #cc_c #link_name "luaopen_io" ---;
open_os :: proc(L: State) -> i32 #cc_c #link_name "luaopen_os" ---;
open_string :: proc(L: State) -> i32 #cc_c #link_name "luaopen_string" ---;
open_utf8 :: proc(L: State) -> i32 #cc_c #link_name "luaopen_utf8" ---;
open_bit32 :: proc(L: State) -> i32 #cc_c #link_name "luaopen_bit32" ---;
open_math :: proc(L: State) -> i32 #cc_c #link_name "luaopen_math" ---;
open_debug :: proc(L: State) -> i32 #cc_c #link_name "luaopen_debug" ---;
open_package :: proc(L: State) -> i32 #cc_c #link_name "luaopen_package" ---;
}
// @note: open all previous libraries
foreign lua_c L_openlibs :: proc(L: State) #cc_c #link_name "luaL_openlibs" ---;
assert :: proc(x: $X) #inline do (cast(^int) int(0))^;
// @endregion
// @region: lauxlib.h
// @note: extra error code for 'luaL_loadfilex'
ERRFILE :: ERRERR + 1;
// @note: registry keys for loaded modules and headers
LOADED_TABLE :: "_LOADED";
PRELOAD_TABLE :: "_PRELOAD";
L_Reg :: struct #packed {
name: ^u8,
func: CFunction,
}
L_NUMSIZES :: size_of(Integer) * 16 + size_of(Number);
foreign lua_c L_checkversion_ :: proc(L: State, ver: Number, sz: int) #cc_c #link_name "luaL_checkversion_" ---;
L_checkversion :: proc(L: State) #inline do L_checkversion_(L, VERSION_NUM, L_NUMSIZES);
foreign lua_c {
L_getmetafield :: proc(L: State, obj: i32, e: ^u8) -> i32 #cc_c #link_name "luaL_getmetaversion" ---;
L_callmeta :: proc(L: State, obj: i32, e: ^u8) -> i32 #cc_c #link_name "luaL_callmeta" ---;
L_argerror :: proc(L: State, arg: i32, extramsg: ^u8) -> i32 #cc_c #link_name "luaL_argerror" ---;
L_tolstring :: proc(L: State, idx: i32, len: ^int) -> ^u8 #cc_c #link_name "luaL_tolstring" ---;
L_checklstring :: proc(L: State, arg: i32, l: ^int) -> ^u8 #cc_c #link_name "luaL_checklstring" ---;
L_optlstring :: proc(L: State, arg: i32, def: ^u8, l: ^int) -> ^u8 #cc_c #link_name "luaL_optlstring" ---;
L_checknumber :: proc(L: State, arg: i32) -> Number #cc_c #link_name "luaL_checknumber" ---;
L_optnumber :: proc(L: State, arg: i32, def: Number) -> Number #cc_c #link_name "luaL_optnumber" ---;
L_checkinterger :: proc(L: State, arg: i32) -> Integer #cc_c #link_name "luaL_checkinteger" ---;
L_optinteger :: proc(L: State, arg: i32, def: Integer) -> Integer #cc_c #link_name "luaL_optinteger" ---;
L_checkstack :: proc(L: State, sz: i32, msg: ^u8) #cc_c #link_name "luaL_checkstack" ---;
L_checktype :: proc(L: State, arg: i32, t: i32) #cc_c #link_name "luaL_checktype" ---;
L_checkany :: proc(L: State, arg: i32) #cc_c #link_name "luaL_checkany" ---;
L_newmetatable :: proc(L: State, tname: ^u8) -> i32 #cc_c #link_name "luaL_newmetatable" ---;
L_setmetatable :: proc(L: State, tname: ^u8) #cc_c #link_name "luaL_setmetatable" ---;
L_testudata :: proc(L: State, ud: i32, tname: ^u8) -> rawptr #cc_c #link_name "luaL_testudata" ---;
L_checkudata :: proc(L: State, ud: i32, tname: ^u8) -> rawptr #cc_c #link_name "luaL_checkudata" ---;
L_where :: proc(L: State, lvl: i32) #cc_c #link_name "luaL_where" ---;
L_error :: proc(L: State, ud: i32, tname: ^u8) -> i32 #cc_c #link_name "luaL_error" ---;
L_checkoption :: proc(L: State, arg: i32, def: ^u8, lst: ^^u8) -> i32 #cc_c #link_name "luaL_checkoption" ---;
L_fileresult :: proc(L: State, stat: i32, fname: ^u8) -> i32 #cc_c #link_name "luaL_fileresult" ---;
L_execresult :: proc(L: State, stat: i32) -> i32 #cc_c #link_name "luaL_execresult" ---;
}
// @note: predefined references
REFNIL :: -1;
NOREF :: -2;
foreign lua_c {
L_ref :: proc(L: State, t: i32) -> i32 #cc_c #link_name "luaL_ref" ---;
L_unref :: proc(L: State, t: i32, ref: i32) #cc_c #link_name "luaL_unref" ---;
L_loadfilex :: proc(L: State, filename: ^u8, mode: ^u8) -> i32 #cc_c #link_name "luaL_loadfilex" ---;
}
L_loadfile :: proc(L: State, filename: ^u8) -> i32 #inline do return L_loadfilex(L, filename, nil);
foreign lua_c {
L_loadbufferx :: proc(L: State, buff: ^u8, sz: int, name: ^u8, mode: ^u8) -> i32 #cc_c #link_name "luaL_loadbufferx" ---;
L_loadstring :: proc(L: State, s: ^u8) -> i32 #cc_c #link_name "luaL_loadstring" ---;
L_newstate :: proc() -> State #cc_c #link_name "luaL_newstate" ---;
L_len :: proc(L: State, idx: i32) -> Integer #cc_c #link_name "luaL_len" ---;
L_gsub :: proc(L: State, idx: i32, fname: ^u8) -> ^u8 #cc_c #link_name "luaL_gsub" ---;
L_setfuncs :: proc(L: State, l: ^L_Reg, nup: i32) #cc_c #link_name "luaL_setfuncs" ---;
L_getsubtable :: proc(L: State, idx: i32, fname: ^u8) -> i32 #cc_c #link_name "luaL_getsubtable" ---;
L_traceback :: proc(L, L1: State, msg: ^u8, level: i32) #cc_c #link_name "luaL_traceback" ---;
L_requiref :: proc(L: State, modname: ^u8, openf: CFunction, glb: i32) #cc_c #link_name "luaL_requiref" ---;
}
// @note: some useful macros
L_newlibtable :: proc(L: State, l: []L_Reg) #inline do createtable(L, 0, i32(len(l) / size_of(L_Reg) - 1));
L_newlib :: proc(L: State, l: []L_Reg) #inline {
L_checkversion(L);
L_newlibtable(L, l);
L_setfuncs(L, &l[0], 0);
}
L_argcheck :: proc(L: State, cond: i32, arg: i32, extramsg: ^u8) #inline do if !bool(cond) do L_argerror(L, arg, extramsg);
L_checkstring :: proc(L: State, arg: i32) -> ^u8 #inline do return L_checklstring(L, arg, nil);
L_optstring :: proc(L: State, arg: i32, d: ^u8) -> ^u8 #inline do return L_optlstring(L, arg, d, nil);
L_typename :: proc(L: State, index: i32) -> ^u8 #inline do return typename(L, type_(L, index));
L_dofile :: proc(L: State, filename: ^u8) -> i32 #inline do return i32(bool(L_loadfile(L, filename)) || bool(pcall(L, 0, MULTRET, 0)));
L_dostring :: proc(L: State, str: ^u8) -> i32 #inline do return i32(bool(L_loadstring(L, str)) || bool(pcall(L, 0, MULTRET, 0)));
L_getmetatable :: proc(L: State, tname: ^u8) -> i32 #inline do return getfield(L, REGISTRYINDEX, tname);
L_opt :: proc(L: State, func: proc(State, i32) -> i32, arg: i32, dflt: i32) -> i32 #inline do return bool(isnoneornil(L, arg)) ? dflt : func(L, arg); // @note: implemeneted correctly?
L_loadbuffer :: proc(L: State, buff: ^u8, sz: int, name: ^u8) -> i32 #inline do return L_loadbufferx(L, buff, sz, name, nil);
// @note: generic buffer manipulation
L_Buffer :: struct #packed {
b: ^u8,
size: int,
n: int,
L: State,
initb: [L_BUFFERSIZE]u8,
}
L_addchar :: proc(B: ^L_Buffer, c: u8) #inline {
if B.n >= B.size do L_prepbuffsize(B, 1);
(B.b + B.n)^ = c;
B.n += 1;
}
L_addsize :: proc(B: ^L_Buffer, n: int) #inline do B.n += n;
foreign lua_c {
L_buffinit :: proc(L: State, B: ^L_Buffer) #cc_c #link_name "luaL_buffinit" ---;
L_prepbuffsize :: proc(B: ^L_Buffer, sz: int) -> ^u8 #cc_c #link_name "luaL_prepbuffsize" ---;
L_addlstring :: proc(B: ^L_Buffer, s: ^u8, l: int) #cc_c #link_name "luaL_addlstring" ---;
L_addstring :: proc(B: ^L_Buffer, s: ^u8) #cc_c #link_name "luaL_addstring" ---;
L_addvalue :: proc(B: ^L_Buffer) #cc_c #link_name "luaL_addvalue" ---;
L_pushresult :: proc(B: ^L_Buffer) #cc_c #link_name "luaL_pushresult" ---;
L_pushresultsize :: proc(B: ^L_Buffer, sz: int) #cc_c #link_name "luaL_pushresultsize" ---;
L_buffinitsize :: proc(L: State, B: ^L_Buffer, sz: int) -> ^u8 #cc_c #link_name "luaL_buffinitsize" ---;
}
L_prepbuffer :: proc(B: ^L_Buffer) -> ^u8 #inline do return L_prepbuffsize(B, L_BUFFERSIZE);
// @note: file handles for IO library
FILEHANDLE :: "FILE*";
L_Stream :: struct #packed {
f: rawptr, // @note: FILE *
closef: CFunction,
}
// @todo: port -> abstraction layer for basic report of messages and errors
// @endregion
@dotbmp
Copy link
Author

dotbmp commented Oct 18, 2017

needs static lua lib of version 5.3.4 (x64)

can test with something like:

import "core:fmt.odin"
import "lua.odin"

main :: proc() {
    L := lua.L_newstate();
    lua.L_openlibs(L);

    lua_string := `io.write("LUA WOOOOOOORKS")` "\x00";

    if lua.L_dostring(L, &lua_string[0]) == lua.OK do
        fmt.println("done!");
    else do fmt.println("failed!");
}

fair warning: the binding is probably super sketchy and some stuff is probably broken, I haven't really tested much of it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment