diff --git a/.gitignore b/.gitignore index 3e1d4c8..76f7136 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,8 @@ vgcore.* *.gcov lib*.a -./*.noja \ No newline at end of file +./*.noja + +embedder + +*_n.c \ No newline at end of file diff --git a/makefile b/makefile index d0960a0..709a387 100644 --- a/makefile +++ b/makefile @@ -112,9 +112,13 @@ LIB_OBJDIR = $(OBJDIR)/$(LIB_SUBDIR) CLI_OBJDIR = $(OBJDIR)/$(CLI_SUBDIR) TST_OBJDIR = $(OBJDIR)/$(TST_SUBDIR) +LIB_NFILES = $(call rwildcard, $(LIB_SRCDIR), *.noja) LIB_CFILES = $(call rwildcard, $(LIB_SRCDIR), *.c) LIB_HFILES = $(call rwildcard, $(LIB_SRCDIR), *.h) -LIB_OFILES = $(patsubst $(LIB_SRCDIR)/%.c, $(LIB_OBJDIR)/%.o, $(LIB_CFILES)) +LIB_OFILES = $(patsubst $(LIB_SRCDIR)/%.c, $(LIB_OBJDIR)/%.o, $(LIB_CFILES)) \ + $(patsubst $(LIB_SRCDIR)/%.noja, $(LIB_OBJDIR)/%_n.o, $(LIB_NFILES)) + +$(info $(LIB_OFILES)) CLI_CFILES = $(call rwildcard, $(CLI_SRCDIR), *.c) CLI_HFILES = $(call rwildcard, $(CLI_SRCDIR), *.h) @@ -139,6 +143,12 @@ TST = $(OUTDIR)/$(TST_FNAME) all: $(LIB) $(CLI) $(TST) +embedder: misc/embedder.c + gcc $< -o $@ -Wall -Wextra + +%_n.c: %.noja embedder + ./embedder $< start_noja $@ + $(OBJDIR)/%.o: $(SRCDIR)/%.c @ mkdir -p $(@D) $(CC) $(CFLAGS) -c $^ -o $@ diff --git a/misc/bugs/bug.noja b/misc/bugs/bug.noja deleted file mode 100644 index b08d68d..0000000 --- a/misc/bugs/bug.noja +++ /dev/null @@ -1,6 +0,0 @@ -a = []; -i = 0; -while(i<100000000):{ - a[i]= "ciao mondo mmododooddododododododododododdodododododd"; - i = i+1; -} \ No newline at end of file diff --git a/misc/embedder.c b/misc/embedder.c new file mode 100644 index 0000000..93e3125 --- /dev/null +++ b/misc/embedder.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include + +// gcc embedder.c -o embedder -Wall -Wextra + +int main(int argc, char **argv) +{ + const char *variable = "__variable_name__"; + const char *input = NULL; + const char *output = "output.c"; + if (argc < 3) { + fprintf(stderr, "Usage: %s []\n", + argv[0]); + return -1; + } + + input = argv[1]; + variable = argv[2]; + if (argc > 3) + output = argv[3]; + + FILE *in_stream = fopen(input, "rb"); + if (in_stream == NULL) { + fprintf(stderr, "Error: Failed to open \"%s\"\n", input); + return -1; + } + + FILE *out_stream = fopen(output, "wb"); + if (out_stream == NULL) { + fprintf(stderr, "Error: Failed to open \"%s\"\n", output); + fclose(in_stream); + return -1; + } + + fprintf(out_stream, "const unsigned char %s[] = {\n\t", variable); + + size_t w = 0; + bool done = false; + while (!done) { + uint8_t buffer[1024]; + size_t num = fread(buffer, 1, sizeof(buffer), in_stream); + if (num < sizeof(buffer)) { + if (ferror(in_stream)) { + abort(); + } else { + assert(feof(in_stream)); + done = true; + } + } + + for (size_t i = 0; i < num; i++, w++) { + fprintf(out_stream, "%3d, ", buffer[i]); + if ((w+1) % 16 == 0) + fprintf(out_stream, "\n\t"); + } + } + + fprintf(out_stream, "\n};\n"); + + fclose(in_stream); + fclose(out_stream); + return 0; +} \ No newline at end of file diff --git a/src/lib/builtins/start.noja b/src/lib/builtins/start.noja new file mode 100644 index 0000000..d7b72d3 --- /dev/null +++ b/src/lib/builtins/start.noja @@ -0,0 +1 @@ +name = "Francesco"; \ No newline at end of file diff --git a/src/lib/noja.c b/src/lib/noja.c index 7c31291..baf2fbb 100644 --- a/src/lib/noja.c +++ b/src/lib/noja.c @@ -56,18 +56,74 @@ static _Bool interpret(Executable *exe) RuntimeError error; RuntimeError_Init(&error, runt); // Here we specify the runtime to snapshot in case of failure. - Object *bins = Object_NewStaticMap(bins_basic, bins_basic_init, runt, (Error*) &error); - - if(bins == NULL) { - assert(error.base.occurred == 1); - print_error(NULL, (Error*) &error); - RuntimeError_Free(&error); - Runtime_Free(runt); - return 0; - } + Object *native_bins = Object_NewStaticMap(bins_basic, bins_basic_init, runt, (Error*) &error); + if(native_bins == NULL) + { + assert(error.base.occurred == 1); + print_error(NULL, (Error*) &error); + RuntimeError_Free(&error); + Runtime_Free(runt); + return 0; + } - Runtime_SetBuiltins(runt, bins); + // Just to execute the prelude + Runtime_SetBuiltins(runt, native_bins); + + extern char start_noja[]; + Source *prelude = Source_FromString("", start_noja, -1, (Error*) &error); + if (prelude == NULL) { + assert(error.base.occurred == 1); + print_error(NULL, (Error*) &error); + RuntimeError_Free(&error); + Runtime_Free(runt); + return 0; + } + + CompilationErrorType errtyp; + Executable *prelude_exe = compile(prelude, (Error*) &error, &errtyp); + if(exe == NULL) { + const char *errname; + switch(errtyp) { + default: + case CompilationErrorType_INTERNAL: errname = NULL; break; + case CompilationErrorType_SYNTAX: errname = "Syntax"; break; + case CompilationErrorType_SEMANTIC: errname = "Semantic"; break; + } + print_error(errname, (Error*) &error); + RuntimeError_Free(&error); + Runtime_Free(runt); + Source_Free(prelude); + return 0; + } + + Object *rets[8]; + int retc = run(runt, (Error*) &error, prelude_exe, 0, NULL, NULL, 0, rets); + if(retc < 0) { + print_error("Runtime", (Error*) &error); + RuntimeError_Free(&error); + Runtime_Free(runt); + Source_Free(prelude); + Executable_Free(prelude_exe); + return 0; + } + Object *noja_bins = rets[0]; + + Object *all_bins = Object_NewClosure(native_bins, noja_bins, Runtime_GetHeap(runt), (Error*) &error); + if (all_bins == NULL) { + print_error(NULL, (Error*) &error); + RuntimeError_Free(&error); + Runtime_Free(runt); + Source_Free(prelude); + Executable_Free(prelude_exe); + return 0; + } + + Runtime_SetBuiltins(runt, all_bins); + + Source_Free(prelude); + Executable_Free(prelude_exe); + } Object *rets[8]; int retc = run(runt, (Error*) &error, exe, 0, NULL, NULL, 0, rets); diff --git a/src/lib/objects/o_closure.c b/src/lib/objects/o_closure.c index 3f37fc4..3ceaeff 100644 --- a/src/lib/objects/o_closure.c +++ b/src/lib/objects/o_closure.c @@ -34,9 +34,9 @@ typedef struct ClosureObject ClosureObject; struct ClosureObject { - Object base; - ClosureObject *prev; - Object *vars; + Object base; + Object *prev; + Object *vars; }; static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp); @@ -57,13 +57,7 @@ Object *Object_NewClosure(Object *parent, Object *new_map, Heap *heap, Error *er if(obj == NULL) return NULL; - if(parent != NULL && parent->type != &t_closure) - { - Error_Report(error, 0, "Object is not a Closure"); - return NULL; - } - - obj->prev = (ClosureObject*) parent; + obj->prev = parent; obj->vars = new_map; return (Object*) obj; @@ -74,18 +68,13 @@ static Object *select_(Object *self, Object *key, { ClosureObject *closure = (ClosureObject*) self; - Object *selected = NULL; - - while(closure != NULL && selected == NULL) - { - selected = Object_Select(closure->vars, key, heap, err); - - if(err->occurred) - return NULL; - - closure = closure->prev; - } + Object *selected = Object_Select(closure->vars, key, heap, err); + if(err->occurred) + return NULL; + if (selected == NULL) + selected = Object_Select(closure->prev, key, heap, err); + return selected; }