diff --git a/examples/bubble_sort.njbc b/examples/bubble_sort.njbc deleted file mode 100644 index 2317ae9..0000000 --- a/examples/bubble_sort.njbc +++ /dev/null @@ -1,174 +0,0 @@ - PUSHFUN copy, 1; - ASS "copy"; - POP 1; - JUMP copy_end; - -copy: - ASS "L"; - POP 1; - PUSHLST 0; - ASS "L2"; - POP 1; - PUSHINT 0; - ASS "i"; - POP 1; - -loop_start: - PUSHVAR "i"; - PUSHVAR "L"; - PUSHVAR "count"; - CALL 1, 1; - LSS; - JUMPIFNOTANDPOP loop_end; - PUSHVAR "L"; - PUSHVAR "i"; - SELECT; - PUSHVAR "L2"; - PUSHVAR "i"; - INSERT2; - POP 1; - PUSHVAR "i"; - PUSHINT 1; - ADD; - ASS "i"; - POP 1; - JUMP loop_start; -loop_end: - PUSHVAR "L2"; - RETURN 1; - RETURN 0; - -copy_end: - PUSHFUN bubble_sort, 2; - ASS "bubble_sort"; - POP 1; - JUMP bubble_sort_end; - -bubble_sort: - ASS "less"; - POP 1; - ASS "L"; - POP 1; - PUSHVAR "less"; - PUSHNNE; - EQL; - JUMPIFNOTANDPOP default_less_cb_end; - PUSHFUN default_less_cb, 2; - ASS "less"; - POP 1; - JUMP default_less_cb_end; - -default_less_cb: - ASS "b"; - POP 1; - ASS "a"; - POP 1; - PUSHVAR "a"; - PUSHVAR "b"; - LSS; - RETURN 1; - RETURN 0; - -default_less_cb_end: - PUSHVAR "L"; - PUSHVAR "copy"; - CALL 1, 1; - ASS "L"; - POP 1; - -outer_loop_start: - PUSHFLS; - ASS "swapped"; - POP 1; - PUSHINT 0; - ASS "i"; - POP 1; - -inner_loop_start: - PUSHVAR "i"; - PUSHVAR "L"; - PUSHVAR "count"; - CALL 1, 1; - PUSHINT 1; - SUB; - LSS; - PUSHVAR "swapped"; - NOT; - AND; - JUMPIFNOTANDPOP outer_loop_end; - PUSHVAR "L"; - PUSHVAR "i"; - SELECT; - PUSHVAR "L"; - PUSHVAR "i"; - PUSHINT 1; - ADD; - SELECT; - PUSHVAR "less"; - CALL 2, 1; - JUMPIFNOTANDPOP if_branch_end; - PUSHTRU; - ASS "swapped"; - POP 1; - PUSHVAR "L"; - PUSHVAR "i"; - PUSHINT 1; - ADD; - SELECT; - ASS "tmp"; - POP 1; - PUSHVAR "L"; - PUSHVAR "i"; - SELECT; - PUSHVAR "L"; - PUSHVAR "i"; - PUSHINT 1; - ADD; - INSERT2; - POP 1; - PUSHVAR "tmp"; - PUSHVAR "L"; - PUSHVAR "i"; - INSERT2; - POP 1; - -if_branch_end: - PUSHVAR "i"; - PUSHINT 1; - ADD; - ASS "i"; - POP 1; - JUMP inner_loop_start; - -outer_loop_end: - PUSHVAR "swapped"; - JUMPIFANDPOP outer_loop_start; - PUSHVAR "L"; - RETURN 1; - RETURN 0; - -bubble_sort_end: - PUSHLST 5; - PUSHINT 0; - PUSHINT 3; - INSERT; - PUSHINT 1; - PUSHINT 2; - INSERT; - PUSHINT 2; - PUSHINT 1; - INSERT; - PUSHINT 3; - PUSHINT 6; - INSERT; - PUSHINT 4; - PUSHINT 0; - PUSHINT 2; - SUB; - INSERT; - PUSHVAR "bubble_sort"; - CALL 1, 1; - PUSHVAR "print"; - CALL 1, 1; - POP 1; - RETURN 0; diff --git a/examples/bubble_sort.noja b/examples/bubble_sort.noja index 909be0f..00eb3a0 100644 --- a/examples/bubble_sort.noja +++ b/examples/bubble_sort.noja @@ -12,7 +12,7 @@ fun copy(L) { return L2; } -fun bubble_sort(L, less) { +fun bubbleSort(L, less) { if less == none: fun less(a, b) return a < b; @@ -37,4 +37,4 @@ fun bubble_sort(L, less) { } -print(bubble_sort([3, 2, 1, 6, 0-2])); \ No newline at end of file +print(bubbleSort([3, 2, 1, 6, 0-2])); \ No newline at end of file diff --git a/examples/hello-world.njbc b/examples/hello-world.njbc deleted file mode 100644 index f37fe92..0000000 --- a/examples/hello-world.njbc +++ /dev/null @@ -1,5 +0,0 @@ -PUSHSTR "Hello, world!\n"; -PUSHVAR "print"; -CALL 1, 1; -POP 1; -RETURN 0; diff --git a/examples/imported.noja b/examples/imported.noja new file mode 100644 index 0000000..3c654e9 --- /dev/null +++ b/examples/imported.noja @@ -0,0 +1,2 @@ + +a = 1; \ No newline at end of file diff --git a/examples/importer.noja b/examples/importer.noja new file mode 100644 index 0000000..7f0045d --- /dev/null +++ b/examples/importer.noja @@ -0,0 +1,4 @@ + +vars, err = import("examples/imported.noja"); +print("vars=[", vars, "]\n"); +print("err=[", err, "]\n"); diff --git a/examples/stack.noja b/examples/stack.noja index c1f6b6c..d44bc43 100644 --- a/examples/stack.noja +++ b/examples/stack.noja @@ -34,4 +34,4 @@ w = pop(stack); assert(x == 3); assert(y == 2); assert(z == 1); -assert(w == none); \ No newline at end of file +assert(w == none); diff --git a/src/lib/builtins/basic.c b/src/lib/builtins/basic.c index f766f3b..c7a5161 100644 --- a/src/lib/builtins/basic.c +++ b/src/lib/builtins/basic.c @@ -37,9 +37,8 @@ #include "files.h" #include "../utils/utf8.h" #include "../objects/objects.h" - - - +#include "../compiler/compile.h" +#include "../runtime/runtime.h" static int bin_print(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) { (void) runtime; @@ -52,6 +51,134 @@ static int bin_print(Runtime *runtime, Object **argv, unsigned int argc, Object return 0; } +static int bin_import(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) +{ + assert(argc == 1); + Heap *heap = Runtime_GetHeap(runtime); + assert(heap != NULL); + + Object *o_path = argv[0]; + const char *path; + size_t path_len; + { + if(!Object_IsString(o_path)) + { + Error_Report(error, 0, "Argument #%d is not a string", 1); + return -1; + } + + int n; + path = Object_ToString(o_path, &n, Runtime_GetHeap(runtime), error); + if (path == NULL) + return -1; + + assert(n >= 0); + path_len = (size_t) n; + } + + Error sub_error; + Error_Init(&sub_error); + Source *src = Source_FromFile(path, &sub_error); + if(src == NULL) { + + if(maxretc == 0) + return 0; + + Object *o_none = Object_NewNone(heap, error); + if(o_none == NULL) + return -1; + + if(maxretc == 1) { + rets[0] = o_none; + return 1; + } + Object *o_err = Object_FromString(sub_error.message, -1, heap, error); + if(o_err == NULL) + return -1; + Error_Free(&sub_error); + + rets[0] = o_none; + rets[1] = o_err; + return 2; + } + + CompilationErrorType errtyp; + Executable *exe = compile(src, &sub_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; + } + (void) errname; + + { + if(maxretc == 0) + return 0; + + Object *o_none = Object_NewNone(heap, error); + if(o_none == NULL) + return -1; + + if(maxretc == 1) { + rets[0] = o_none; + return 1; + } + Object *o_err = Object_FromString(sub_error.message, -1, heap, error); + if(o_err == NULL) + return -1; + Error_Free(&sub_error); + + rets[0] = o_none; + rets[1] = o_err; + return 2; + } + } + + { + Object *sub_rets[8]; + int sub_maxretc = sizeof(sub_rets)/sizeof(sub_rets[0]); + int retc = run(runtime, &sub_error, exe, 0, NULL, NULL, 0, sub_rets, sub_maxretc); + if(retc < 0) + { + const char *errname = "Runtime"; + // Snapshot? + (void) errname; + { + if(maxretc == 0) + return 0; + + Object *o_none = Object_NewNone(heap, error); + if(o_none == NULL) + return -1; + + if(maxretc == 1) { + rets[0] = o_none; + return 1; + } + + Object *o_err = Object_FromString(sub_error.message, -1, heap, error); + if(o_err == NULL) + return -1; + Error_Free(&sub_error); + + rets[0] = o_none; + rets[1] = o_err; + return 2; + } + } + assert(retc == 1); + + if(maxretc == 0) + return 0; + rets[0] = sub_rets[0]; + return 1; + } + return 0; +} + static int bin_type(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error) { assert(argc == 1); @@ -412,6 +539,7 @@ StaticMapSlot bins_basic[] = { // { "files", SM_SMAP, .as_smap = bins_files, }, // { "net", SM_SMAP, .as_smap = bins_net, }, + { "import", SM_FUNCT, .as_funct = bin_import, .argc = 1, }, { "newBuffer", SM_FUNCT, .as_funct = bin_newBuffer, .argc = 1 }, { "sliceBuffer", SM_FUNCT, .as_funct = bin_sliceBuffer, .argc = 3 }, { "bufferToString", SM_FUNCT, .as_funct = bin_bufferToString, .argc = 1 }, diff --git a/src/lib/common/executable.c b/src/lib/common/executable.c index 517abed..2586a0e 100644 --- a/src/lib/common/executable.c +++ b/src/lib/common/executable.c @@ -105,6 +105,7 @@ static const InstrInfo instr_table[] = { [OPCODE_PUSHNNETYP] = {"PUSHNNETYP", 0, NULL}, [OPCODE_RETURN] = {"RETURN", 1, (OperandType[]) {OPTP_INT}}, [OPCODE_ERROR] = {"ERROR", 1, (OperandType[]) {OPTP_STRING}}, + [OPCODE_EXIT] = {"EXIT", 0, NULL}, [OPCODE_JUMPIFNOTANDPOP] = {"JUMPIFNOTANDPOP", 1, (OperandType[]) {OPTP_IDX}}, [OPCODE_JUMPIFANDPOP] = {"JUMPIFANDPOP", 1, (OperandType[]) {OPTP_IDX}}, [OPCODE_JUMP] = {"JUMP", 1, (OperandType[]) {OPTP_IDX}}, diff --git a/src/lib/common/executable.h b/src/lib/common/executable.h index 73a2148..28f5c46 100644 --- a/src/lib/common/executable.h +++ b/src/lib/common/executable.h @@ -90,6 +90,7 @@ typedef enum { OPCODE_PUSHNNETYP, OPCODE_RETURN, OPCODE_ERROR, + OPCODE_EXIT, OPCODE_JUMPIFANDPOP, OPCODE_JUMPIFNOTANDPOP, OPCODE_JUMP, diff --git a/src/lib/compiler/codegen.c b/src/lib/compiler/codegen.c index db7b3ef..292033a 100644 --- a/src/lib/compiler/codegen.c +++ b/src/lib/compiler/codegen.c @@ -84,6 +84,12 @@ static void emitInstr_RETURN(CodegenContext *ctx, CodegenContext_EmitInstr(ctx, OPCODE_RETURN, opv, 1, off, len); } +static void emitInstr_EXIT(CodegenContext *ctx, + int off, int len) +{ + CodegenContext_EmitInstr(ctx, OPCODE_EXIT, NULL, 0, off, len); +} + static void emitInstr_JUMP(CodegenContext *ctx, Label *op0, int off, int len) @@ -850,7 +856,7 @@ Executable *codegen(AST *ast, BPAlloc *alloc, Error *error) CodegenContext_SetJumpDest(ctx, &env); emitInstrForNode(ctx, ast->root, NULL); - emitInstr_RETURN(ctx, 0, Source_GetSize(ast->src), 0); + emitInstr_EXIT(ctx, Source_GetSize(ast->src), 0); assert(error->occurred == false); return CodegenContext_MakeExecutableAndFree(ctx, ast->src); diff --git a/src/lib/compiler/parse.c b/src/lib/compiler/parse.c index a3b3efb..45bd649 100644 --- a/src/lib/compiler/parse.c +++ b/src/lib/compiler/parse.c @@ -1671,6 +1671,7 @@ static Node *parse_expression_2(Context *ctx, Node *left_expr, int min_prec, _Bo if(right_expr == NULL) return NULL; +#warning "Should this break also trigger when the token is a = and allow_assignments is false?" if(ctx->token->kind == ',' && allow_toplev_tuples == 0) break; } diff --git a/src/lib/runtime/runtime.c b/src/lib/runtime/runtime.c index 39b9c20..c133860 100644 --- a/src/lib/runtime/runtime.c +++ b/src/lib/runtime/runtime.c @@ -123,6 +123,7 @@ Runtime *Runtime_New(int stack_size, int heap_size, void *callback_userp, _Bool return Runtime_New2(stack_size, heap, 1, callback_userp, callback_addr); } + void Runtime_Free(Runtime *runtime) { if(runtime->free_heap) @@ -1192,6 +1193,18 @@ static _Bool step(Runtime *runtime, Error *error) return 1; } + case OPCODE_EXIT: + { + assert(opc == 0); + + Object *vars = runtime->frame->locals; + assert(vars != NULL); + + if(!Runtime_Push(runtime, error, vars)) + return 0; + return 0; + } + case OPCODE_RETURN: { assert(opc == 1); @@ -1316,7 +1329,11 @@ static _Bool collect(Runtime *runtime, Error *error) return Heap_StopCollection(runtime->heap); } -int run(Runtime *runtime, Error *error, Executable *exe, int index, Object *closure, Object **argv, int argc, Object **rets, int maxretc) +int run(Runtime *runtime, Error *error, + Executable *exe, int index, + Object *closure, + Object **argv, int argc, + Object **rets, int maxretc) { assert(runtime != NULL); assert(error != NULL);