first draft of import builtin function
This commit is contained in:
@@ -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;
|
|
||||||
@@ -12,7 +12,7 @@ fun copy(L) {
|
|||||||
return L2;
|
return L2;
|
||||||
}
|
}
|
||||||
|
|
||||||
fun bubble_sort(L, less) {
|
fun bubbleSort(L, less) {
|
||||||
if less == none:
|
if less == none:
|
||||||
fun less(a, b) return a < b;
|
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]));
|
print(bubbleSort([3, 2, 1, 6, 0-2]));
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
PUSHSTR "Hello, world!\n";
|
|
||||||
PUSHVAR "print";
|
|
||||||
CALL 1, 1;
|
|
||||||
POP 1;
|
|
||||||
RETURN 0;
|
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
|
||||||
|
a = 1;
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
|
||||||
|
vars, err = import("examples/imported.noja");
|
||||||
|
print("vars=[", vars, "]\n");
|
||||||
|
print("err=[", err, "]\n");
|
||||||
+1
-1
@@ -34,4 +34,4 @@ w = pop(stack);
|
|||||||
assert(x == 3);
|
assert(x == 3);
|
||||||
assert(y == 2);
|
assert(y == 2);
|
||||||
assert(z == 1);
|
assert(z == 1);
|
||||||
assert(w == none);
|
assert(w == none);
|
||||||
|
|||||||
+131
-3
@@ -37,9 +37,8 @@
|
|||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "../utils/utf8.h"
|
#include "../utils/utf8.h"
|
||||||
#include "../objects/objects.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)
|
static int bin_print(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error)
|
||||||
{
|
{
|
||||||
(void) runtime;
|
(void) runtime;
|
||||||
@@ -52,6 +51,134 @@ static int bin_print(Runtime *runtime, Object **argv, unsigned int argc, Object
|
|||||||
return 0;
|
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)
|
static int bin_type(Runtime *runtime, Object **argv, unsigned int argc, Object **rets, unsigned int maxretc, Error *error)
|
||||||
{
|
{
|
||||||
assert(argc == 1);
|
assert(argc == 1);
|
||||||
@@ -412,6 +539,7 @@ StaticMapSlot bins_basic[] = {
|
|||||||
// { "files", SM_SMAP, .as_smap = bins_files, },
|
// { "files", SM_SMAP, .as_smap = bins_files, },
|
||||||
// { "net", SM_SMAP, .as_smap = bins_net, },
|
// { "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 },
|
{ "newBuffer", SM_FUNCT, .as_funct = bin_newBuffer, .argc = 1 },
|
||||||
{ "sliceBuffer", SM_FUNCT, .as_funct = bin_sliceBuffer, .argc = 3 },
|
{ "sliceBuffer", SM_FUNCT, .as_funct = bin_sliceBuffer, .argc = 3 },
|
||||||
{ "bufferToString", SM_FUNCT, .as_funct = bin_bufferToString, .argc = 1 },
|
{ "bufferToString", SM_FUNCT, .as_funct = bin_bufferToString, .argc = 1 },
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ static const InstrInfo instr_table[] = {
|
|||||||
[OPCODE_PUSHNNETYP] = {"PUSHNNETYP", 0, NULL},
|
[OPCODE_PUSHNNETYP] = {"PUSHNNETYP", 0, NULL},
|
||||||
[OPCODE_RETURN] = {"RETURN", 1, (OperandType[]) {OPTP_INT}},
|
[OPCODE_RETURN] = {"RETURN", 1, (OperandType[]) {OPTP_INT}},
|
||||||
[OPCODE_ERROR] = {"ERROR", 1, (OperandType[]) {OPTP_STRING}},
|
[OPCODE_ERROR] = {"ERROR", 1, (OperandType[]) {OPTP_STRING}},
|
||||||
|
[OPCODE_EXIT] = {"EXIT", 0, NULL},
|
||||||
[OPCODE_JUMPIFNOTANDPOP] = {"JUMPIFNOTANDPOP", 1, (OperandType[]) {OPTP_IDX}},
|
[OPCODE_JUMPIFNOTANDPOP] = {"JUMPIFNOTANDPOP", 1, (OperandType[]) {OPTP_IDX}},
|
||||||
[OPCODE_JUMPIFANDPOP] = {"JUMPIFANDPOP", 1, (OperandType[]) {OPTP_IDX}},
|
[OPCODE_JUMPIFANDPOP] = {"JUMPIFANDPOP", 1, (OperandType[]) {OPTP_IDX}},
|
||||||
[OPCODE_JUMP] = {"JUMP", 1, (OperandType[]) {OPTP_IDX}},
|
[OPCODE_JUMP] = {"JUMP", 1, (OperandType[]) {OPTP_IDX}},
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ typedef enum {
|
|||||||
OPCODE_PUSHNNETYP,
|
OPCODE_PUSHNNETYP,
|
||||||
OPCODE_RETURN,
|
OPCODE_RETURN,
|
||||||
OPCODE_ERROR,
|
OPCODE_ERROR,
|
||||||
|
OPCODE_EXIT,
|
||||||
OPCODE_JUMPIFANDPOP,
|
OPCODE_JUMPIFANDPOP,
|
||||||
OPCODE_JUMPIFNOTANDPOP,
|
OPCODE_JUMPIFNOTANDPOP,
|
||||||
OPCODE_JUMP,
|
OPCODE_JUMP,
|
||||||
|
|||||||
@@ -84,6 +84,12 @@ static void emitInstr_RETURN(CodegenContext *ctx,
|
|||||||
CodegenContext_EmitInstr(ctx, OPCODE_RETURN, opv, 1, off, len);
|
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,
|
static void emitInstr_JUMP(CodegenContext *ctx,
|
||||||
Label *op0,
|
Label *op0,
|
||||||
int off, int len)
|
int off, int len)
|
||||||
@@ -850,7 +856,7 @@ Executable *codegen(AST *ast, BPAlloc *alloc, Error *error)
|
|||||||
CodegenContext_SetJumpDest(ctx, &env);
|
CodegenContext_SetJumpDest(ctx, &env);
|
||||||
|
|
||||||
emitInstrForNode(ctx, ast->root, NULL);
|
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);
|
assert(error->occurred == false);
|
||||||
|
|
||||||
return CodegenContext_MakeExecutableAndFree(ctx, ast->src);
|
return CodegenContext_MakeExecutableAndFree(ctx, ast->src);
|
||||||
|
|||||||
@@ -1671,6 +1671,7 @@ static Node *parse_expression_2(Context *ctx, Node *left_expr, int min_prec, _Bo
|
|||||||
if(right_expr == NULL)
|
if(right_expr == NULL)
|
||||||
return 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)
|
if(ctx->token->kind == ',' && allow_toplev_tuples == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
return Runtime_New2(stack_size, heap, 1, callback_userp, callback_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Runtime_Free(Runtime *runtime)
|
void Runtime_Free(Runtime *runtime)
|
||||||
{
|
{
|
||||||
if(runtime->free_heap)
|
if(runtime->free_heap)
|
||||||
@@ -1192,6 +1193,18 @@ static _Bool step(Runtime *runtime, Error *error)
|
|||||||
return 1;
|
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:
|
case OPCODE_RETURN:
|
||||||
{
|
{
|
||||||
assert(opc == 1);
|
assert(opc == 1);
|
||||||
@@ -1316,7 +1329,11 @@ static _Bool collect(Runtime *runtime, Error *error)
|
|||||||
return Heap_StopCollection(runtime->heap);
|
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(runtime != NULL);
|
||||||
assert(error != NULL);
|
assert(error != NULL);
|
||||||
|
|||||||
Reference in New Issue
Block a user