issue #98 refactor ast library to be just a library and resolve the issue with lua_lock()

pull/167/head
Dibyendu Majumdar 6 years ago
parent 0a69234b07
commit 67accd8a41

@ -429,10 +429,6 @@ target_link_libraries(testravidebug libravinojit_static)
add_executable(test_vm tests/test_vm.c)
target_link_libraries(test_vm ${LIBRAVI_NAME})
#AST test
add_executable(test_ast tests/test_ast.c)
target_link_libraries(test_ast ${LIBRAVI_NAME})
if (LLVM_JIT)
# LLVM playground
add_executable(test_llvm tests/test_llvm.cpp)
@ -448,7 +444,6 @@ if (LLVM_JIT)
endif ()
add_test(TestVM test_vm)
add_test(TestMisc test_misc)
add_test(TestAST test_ast)
install(FILES ${LUA_HEADERS}

@ -55,9 +55,5 @@ LUAI_FUNC void luaD_inctop (lua_State *L);
LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode);
LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud);
LUAI_FUNC int raviD_protected_ast_builder (lua_State *L, ZIO *z, const char *name,
const char *mode);
#endif

@ -241,8 +241,6 @@ LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
Dyndata *dyd, const char *name, int firstchar);
/** RAVI extensions **/
LUAI_FUNC int raviY_parse_to_ast(lua_State *L, ZIO *z, Mbuffer *buff,
const char *name, int firstchar);
LUAI_FUNC const char *raviY_typename(ravitype_t tt);
/* Special printf that recognises following conversions:

@ -77,7 +77,6 @@ int lua_checkmemory (lua_State *L);
/* test for lock/unlock */
#if 0
struct L_EXTRA { int lock; int *plock; };
#undef LUA_EXTRASPACE
#define LUA_EXTRASPACE sizeof(struct L_EXTRA)
@ -92,7 +91,6 @@ struct L_EXTRA { int lock; int *plock; };
lua_assert(getlock(l)->plock == getlock(l1)->plock)
#define lua_lock(l) lua_assert((*getlock(l)->plock)++ == 0)
#define lua_unlock(l) lua_assert(--(*getlock(l)->plock) == 0)
#endif
LUA_API int luaB_opentests (lua_State *L);

@ -1332,29 +1332,6 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
return status;
}
/*
**
** Builds an Abstract Syntax Tree (encapsulated in userdata type) from the given
** input buffer. This function returns 0 if all OK
* - On success a userdata object representing the tree,
* else an error message will be pushed on to the stack
**
** This is part of the new experimental (wip) implementation of new
** parser and code generator
*/
LUA_API int (ravi_build_ast_from_buffer) (lua_State *L, lua_Reader reader, void *data,
const char *chunkname, const char *mode) {
ZIO z;
int status;
lua_lock(L);
if (!chunkname) chunkname = "?";
luaZ_init(L, &z, reader, data);
status = raviD_protected_ast_builder(L, &z, chunkname, mode);
lua_unlock(L);
return status;
}
LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) {
int status;
TValue *o;

@ -760,20 +760,6 @@ LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size,
return lua_load(L, getS, &ls, name, mode);
}
/*
* Builds an Abstract Syntax Tree (encapsulated in userdata type) from the given
* input buffer. This function returns 0 if all OK
* - On success a userdata object representing the tree,
* else an error message will be pushed on to the stack
*/
LUALIB_API int raviL_build_ast_from_buffer (lua_State *L, const char *buff, size_t size,
const char *name, const char *mode) {
LoadS ls;
ls.s = buff;
ls.size = size;
return ravi_build_ast_from_buffer(L, getS, &ls, name, mode);
}
LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
return luaL_loadbuffer(L, s, strlen(s), s);
}

@ -355,24 +355,6 @@ static int luaB_load (lua_State *L) {
return load_aux(L, status, env);
}
static int raviB_build_ast(lua_State *L) {
int status;
size_t l;
const char *s = lua_tolstring(L, 1, &l);
const char *mode = luaL_optstring(L, 3, "bt");
int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
if (s != NULL) { /* loading a string? */
const char *chunkname = luaL_optstring(L, 2, s);
status = raviL_build_ast_from_buffer(L, s, l, chunkname, mode);
}
else { /* loading from a reader function */
const char *chunkname = luaL_optstring(L, 2, "=(load)");
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_settop(L, RESERVEDSLOT); /* create reserved slot */
status = ravi_build_ast_from_buffer(L, generic_reader, NULL, chunkname, mode);
}
return status == 0 ? 1 : 0;
}
/* }====================================================== */
@ -483,8 +465,6 @@ static const luaL_Reg base_funcs[] = {
{"ipairs", luaB_ipairs},
{"loadfile", luaB_loadfile},
{"load", luaB_load},
/* Entrypoint for new AST */
{"build_ast", raviB_build_ast},
#if defined(LUA_COMPAT_LOADSTRING)
{"loadstring", luaB_load},
#endif

@ -886,30 +886,4 @@ int luaD_protectedparser (lua_State *L, ZIO *z, const char *name,
return status;
}
static int ravi_f_parser (lua_State *L, void *ud) {
LClosure *cl;
struct SParser *p = cast(struct SParser *, ud);
int c = zgetc(p->z); /* read first character */
checkmode(L, p->mode, "text");
return raviY_parse_to_ast(L, p->z, &p->buff, p->name, c);
}
int raviD_protected_ast_builder (lua_State *L, ZIO *z, const char *name,
const char *mode) {
struct SParser p;
int status;
L->nny++; /* cannot yield during parsing */
p.z = z; p.name = name; p.mode = mode;
p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
p.dyd.label.arr = NULL; p.dyd.label.size = 0;
luaZ_initbuffer(L, &p.buff);
status = luaD_pcall(L, ravi_f_parser, &p, savestack(L, L->top), L->errfunc);
luaZ_freebuffer(L, &p.buff);
luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
L->nny--;
return status;
}

@ -21,6 +21,7 @@
#include "lstate.h"
#include "lstring.h"
#include "ltable.h"
#include "lzio.h"
#include "ravi_ast.h"
#include "lauxlib.h"
@ -2411,7 +2412,7 @@ static void print_ast_container(struct ast_container *container) {
** syntax tree.
** On failure push an error message.
*/
int raviY_parse_to_ast(lua_State *L, ZIO *z, Mbuffer *buff,
static int parse_to_ast(lua_State *L, ZIO *z, Mbuffer *buff,
const char *name, int firstchar) {
StkId cvalue = L->top; /* where ast_container will be */
struct ast_container *container = new_ast_container(L);
@ -2427,17 +2428,167 @@ int raviY_parse_to_ast(lua_State *L, ZIO *z, Mbuffer *buff,
luaX_setinput(L, &lexstate, z, src, firstchar);
struct parser_state parser_state;
parser_state_init(&parser_state, &lexstate, container);
lua_lock(L); // Workaround for ZIO (used by lexer) which assumes lua_lock()
parse_chunk(&parser_state);
lua_unlock(L);
L->top--; /* remove source name */
assert(cvalue == L->top - 1);
print_ast_container(container);
return 0; /* OK */
}
/*
** Execute a protected parser.
*/
struct SParser { /* data to 'f_parser' */
ZIO *z;
Mbuffer buff; /* dynamic structure used by the scanner */
Dyndata dyd; /* dynamic structures used by the parser */
const char *mode;
const char *name;
};
static void checkmode(lua_State *L, const char *mode, const char *x) {
if (mode && strchr(mode, x[0]) == NULL) {
luaO_pushfstring(L,
"attempt to load a %s chunk (mode is '%s')", x, mode);
luaD_throw(L, LUA_ERRSYNTAX);
}
}
static int ravi_f_parser(lua_State *L, void *ud) {
LClosure *cl;
struct SParser *p = cast(struct SParser *, ud);
lua_lock(L); // Workaroud for zgetc() which assumes lua_lock()
int c = zgetc(p->z); /* read first character */
lua_unlock(L);
checkmode(L, p->mode, "text");
return parse_to_ast(L, p->z, &p->buff, p->name, c);
}
static int protected_ast_builder(lua_State *L, ZIO *z, const char *name,
const char *mode) {
struct SParser p;
int status;
L->nny++; /* cannot yield during parsing */
p.z = z; p.name = name; p.mode = mode;
p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0;
p.dyd.gt.arr = NULL; p.dyd.gt.size = 0;
p.dyd.label.arr = NULL; p.dyd.label.size = 0;
luaZ_initbuffer(L, &p.buff);
status = luaD_pcall(L, ravi_f_parser, &p, savestack(L, L->top), L->errfunc);
luaZ_freebuffer(L, &p.buff);
luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size);
luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size);
luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size);
L->nny--;
return status;
}
/*
**
** Builds an Abstract Syntax Tree (encapsulated in userdata type) from the given
** input buffer. This function returns 0 if all OK
* - On success a userdata object representing the tree,
* else an error message will be pushed on to the stack
**
** This is part of the new experimental (wip) implementation of new
** parser and code generator
*/
static int build_ast_from_reader(lua_State *L, lua_Reader reader, void *data,
const char *chunkname, const char *mode) {
ZIO z;
int status;
if (!chunkname) chunkname = "?";
luaZ_init(L, &z, reader, data);
status = protected_ast_builder(L, &z, chunkname, mode);
return status;
}
/*
** reserved slot, above all arguments, to hold a copy of the returned
** string to avoid it being collected while parsed. 'load' has four
** optional arguments (chunk, source name, mode, and environment).
*/
#define RESERVEDSLOT 5
/*
** Reader for generic 'load' function: 'lua_load' uses the
** stack for internal stuff, so the reader cannot change the
** stack top. Instead, it keeps its resulting string in a
** reserved slot inside the stack.
*/
static const char *generic_reader(lua_State *L, void *ud, size_t *size) {
(void)(ud); /* not used */
luaL_checkstack(L, 2, "too many nested functions");
lua_pushvalue(L, 1); /* get function */
lua_call(L, 0, 1); /* call it */
if (lua_isnil(L, -1)) {
lua_pop(L, 1); /* pop result */
*size = 0;
return NULL;
}
else if (!lua_isstring(L, -1))
luaL_error(L, "reader function must return a string");
lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */
return lua_tolstring(L, RESERVEDSLOT, size);
}
typedef struct LoadS {
const char *s;
size_t size;
} LoadS;
static const char *getS(lua_State *L, void *ud, size_t *size) {
LoadS *ls = (LoadS *)ud;
(void)L; /* not used */
if (ls->size == 0) return NULL;
*size = ls->size;
ls->size = 0;
return ls->s;
}
/*
* Builds an Abstract Syntax Tree (encapsulated in userdata type) from the given
* input buffer. This function returns 0 if all OK
* - On success a userdata object representing the tree,
* else an error message will be pushed on to the stack
*/
static int build_ast_from_buffer(lua_State *L, const char *buff, size_t size,
const char *name, const char *mode) {
LoadS ls;
ls.s = buff;
ls.size = size;
return build_ast_from_reader(L, getS, &ls, name, mode);
}
static int build_ast(lua_State *L) {
int status;
size_t l;
const char *s = lua_tolstring(L, 1, &l);
const char *mode = luaL_optstring(L, 3, "bt");
int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */
if (s != NULL) { /* loading a string? */
const char *chunkname = luaL_optstring(L, 2, s);
status = build_ast_from_buffer(L, s, l, chunkname, mode);
}
else { /* loading from a reader function */
const char *chunkname = luaL_optstring(L, 2, "=(load)");
luaL_checktype(L, 1, LUA_TFUNCTION);
lua_settop(L, RESERVEDSLOT); /* create reserved slot */
status = build_ast_from_reader(L, generic_reader, NULL, chunkname, mode);
}
return status == 0 ? 1 : 0;
}
static const luaL_Reg container_methods[] = {
{ NULL, NULL } };
static const luaL_Reg astlib[] = {
/* Entrypoint for new AST */
{ "parse", build_ast },
{ NULL, NULL } };
LUAMOD_API int raviopen_ast_library(lua_State *L) {
@ -2451,5 +2602,4 @@ LUAMOD_API int raviopen_ast_library(lua_State *L) {
luaL_newlib(L, astlib);
return 1;
return 0;
}
Loading…
Cancel
Save