rgbmatrixscreen/teensy/lua.cpp

230 lines
5.9 KiB
C++

#include "log.h"
#include "lua.hpp"
#include <cstdint>
#include "luamatrix.h"
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "lua-alloc.h"
/*These three are needed for stubs because something for some god awful reason wants them. Can't find the source of them and they're easier to fix this way*/
int _kill(pid_t pid, int sig) {return 0;}
int _getpid() {return 1;}
int _gettimeofday(struct timeval *tv, struct timezone *tz) {return -1;}
int _open(const char *pathname, int flags) {return -1;}
ssize_t _write(int fd, const void *buf, size_t count) {return -1;}
}
char l_prog_buff[MAX_PRGMSIZE] = "function main()\n"
" local leds = led_data()\n"
" local white = 255 * 65536 + 255 * 256 + 255\n"
" while true do\n"
" for i = 1, 450 do\n"
" leds[i] = white\n"
" end\n"
" end\n"
"end\n";
/* "function main()\n"
" local leds = led_data()\n"
" print \"Hello World\"\n"
" while true do\n"
" \n"
" for g = 0, 255, 5 do\n"
" leds[1] = 255 * 65536 + g * 256\n"
" end\n"
" for r = 255, 0, -5 do\n"
" leds[1] = r * 65536 + 255 * 256\n"
" end\n"
" for b = 0, 255, 5 do\n"
" leds[1] = 255 * 256 + b\n"
" end\n"
" for g = 255, 0, -5 do\n"
" leds[1] = g * 256 + 255\n"
" end\n"
" for r = 0, 255, 5 do\n"
" leds[1] = r * 65536 + 255\n"
" end\n"
" for b = 255, 0, -5 do\n"
" leds[1] = 255 * 65536 + b\n"
" end\n"
" end\n"
"end\n"; */
lua_State *L, *t1;
// predeclarations
void l_start(const char *prgm);
void l_initthread();
extern char __llalloc_sbrk_start[];
static void l_dumpmem() {
uint8_t byte = 0;
LogOut.print("\t\t");
for (int i = 0; i < LL_ARENA_SIZE; i++) {
byte = __llalloc_sbrk_start[i];
LogOut.print(byte, HEX);
}
LogOut.println();
}
static void l_memstats() {
struct mallinfo c= ll_mallinfo();
char buff[64];
sprintf(buff, "->mallinfo: t:%d f:%d u:%d", c.arena, c.fordblks, c.uordblks);
debug_log(buff);
}
// I want to replace this with an arena allocator so that i can get better memory performance in the future
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
l_memstats();
//"\t->alloc called: 12345678 12345678 12345 12345";
char buff[64];
sprintf(buff, "\t->alloc called: %08X %08X %05d %05d", (size_t) ud, (size_t) ptr, osize, nsize);
debug_log(buff);
(void)ud; (void)osize; /* not used */
if (nsize == 0) {
ll_free(ptr);
return NULL;
}
else
return ll_realloc(ptr, nsize);
}
void l_yield(lua_State *L, lua_Debug *ar) {
lua_yield(L, 0);
}
static int l_sethook(lua_State *L) {
lua_sethook(L, &l_yield, LUA_MASKCOUNT, 100);
return 0;
}
int full_run(lua_State *L, lua_State *t) {
if (t == NULL)
return -1; // If thread has been cancled don't run!
int rc = lua_resume(t, L, 0);
// TODO this is the all important part where i handle errors, the main function exiting, and make sure yielding went properly
char buff[24];
if (rc == 0) {
// Should this be output log?
debug_log("User supplied function exited successfully. Restarting thread");
l_initthread();
} else if (rc == LUA_ERRRUN) {
output_log("Runtime error: ");
output_log(lua_tostring(t1, -1));
output_log("Halting lua runtime");
t1 = NULL;
} else if (rc != LUA_YIELD) {
sprintf(buff, "rc = %d", rc);
output_log("Unknown error: ");
output_log(buff);
output_log(lua_tostring(t1, -1));
output_log("Halting lua runtime");
t1 = NULL;
}
return rc;
}
// This code blatantly stolen and borrowed from lbaselib.c luaB_print
static int l_print (lua_State *L) {
int n = lua_gettop(L); /* number of arguments */
int i;
lua_getglobal(L, "tostring");
for (i=1; i<=n; i++) {
const char *s;
size_t l;
lua_pushvalue(L, -1); /* function to be called */
lua_pushvalue(L, i); /* value to print */
lua_call(L, 1, 1);
s = lua_tolstring(L, -1, &l); /* get result */
if (s == NULL)
return luaL_error(L,
LUA_QL("tostring") " must return a string to " LUA_QL("print"));
//if (i>1) luai_writestring("\t", 1);
output_log(s);
lua_pop(L, 1); /* pop result */
}
//luai_writeline();
return 0;
}
static const luaL_Reg loadedlibs[] = {
{"_G", luaopen_base},
// {LUA_LOADLIBNAME, luaopen_package},
{LUA_COLIBNAME, luaopen_coroutine},
{LUA_TABLIBNAME, luaopen_table},
{LUA_STRLIBNAME, luaopen_string},
{LUA_BITLIBNAME, luaopen_bit32},
{LUA_MATHLIBNAME, luaopen_math},
{LUA_DBLIBNAME, luaopen_debug},
{NULL, NULL}
};
void l_openlibs(lua_State *L) {
const luaL_Reg *lib;
/* call open functions from 'loadedlibs' and set results to global table */
for (lib = loadedlibs; lib->func; lib++) {
luaL_requiref(L, lib->name, lib->func, 1);
lua_pop(L, 1); /* remove lib */
}
}
// INIT AND FRAME CODE.
void l_init() {
l_start(l_prog_buff);
//l_dumpmem();
}
void l_initthread() {
// Create the coroutine
t1 = lua_newthread(L);
l_sethook(t1);
lua_getglobal(t1, "main");
}
void l_stop() {
if (L != NULL)
lua_close(L);
t1 = NULL;
}
void l_start(const char *prgm) {
ll_clean_arena();
t1 = NULL;
L = lua_newstate(l_alloc, 0);
debug_log("Importing libraries");
l_openlibs(L);
luaopen_matrixpanel(L);
lua_pushcfunction(L, l_print);
lua_setglobal(L, "print");
debug_log("Libraries imported");
debug_log("Loading program");
int e = luaL_dostring(L, prgm);
if (e) {
output_log("error evaling lua code: ");
output_log(lua_tostring(L, -1));
}
l_initthread();
}
void l_frame() {
full_run(L, t1);
}