moka/lib/module.c

130 lines
2.4 KiB
C

#include <dlfcn.h>
#include "module.h"
#include "builtins.h"
void module_init(struct module* self)
{
assert(self);
status_init(&self->status);
moka_init(&self->moka, &self->status);
register_builtins(&self->moka);
prog_init(&self->prog);
self->handle = NULL;
}
void module_free(struct module* self)
{
assert(self);
status_free(&self->status);
prog_free(&self->prog);
moka_free(&self->moka);
if (self->handle)
{
dlclose(self->handle);
self->handle = NULL;
}
}
int module_load_from_dl(struct module* self, char const* path)
{
assert(self);
assert(path);
self->handle = dlopen(path, RTLD_NOW);
if (!self->handle)
{
return EXIT_FAILURE;
}
void (*f)(struct module*) = dlsym(self->handle, "create_module");
if (!f)
{
dlclose(self->handle);
return EXIT_FAILURE;
}
f(self);
return EXIT_SUCCESS;
}
int module_load_from_file(struct module* self, char const* path)
{
assert(self);
assert(path);
struct str source;
str_init(&source);
FILE* file = fopen(path, "r+");
size_t sz;
char buf;
while ( (sz=fread(&buf, sizeof(char), 1, file)) )
{
str_push(&source, buf);
}
fclose(file);
int ret = module_load_from_str(self, source.value);
str_free(&source);
return ret;
}
int module_load_from_str(struct module* self, char const* source)
{
status_init(&self->status);
struct lexer lex;
lexer_init(&lex, source, &self->status);
struct parser parser;
parser_init(&parser, &lex);
struct node* root = parser_try_new_root(&parser);
if (!root || !status_is_ok(&self->status))
{
status_dump(&self->status);
goto free_parser;
}
struct compiler compiler;
compiler_init(&compiler, &self->status);
compiler_compile(&compiler, root, &self->prog, &self->moka);
if (!status_is_ok(&self->status))
{
status_dump(&self->status);
goto free_compiler;
}
struct exec exec;
exec_init(&exec);
exec_prog(&exec, &self->moka, &self->prog);
if (!status_is_ok(self->moka.status))
{
status_dump(self->moka.status);
}
exec_free(&exec);
free_compiler:
compiler_free(&compiler);
node_free(root);
free(root);
free_parser:
parser_free(&parser);
lexer_free(&lex);
int ret = status_is_ok(&self->status) ? EXIT_SUCCESS : EXIT_FAILURE;
return ret;
}