commit bd666939dab1c914ac7cfaf2dcba9d2c74047b8f parent 6fa3e5edebab3a6535e664aba447ae1dad7c77fe Author: Paul Longtine <paullongtine@gmail.com> Date: Tue May 3 22:32:59 2016 Work on fancy scoping required for getting objects to play nice. Compiler needs to be updated to reflect these changes Diffstat: doc/SPECIFICATION | 14 ++--- src/lc/bytecode.py | 4 +- src/vm/inc/ins_def.h | 5 +-- src/vm/inc/ins_mdata.h | 10 ++-- src/vm/inc/proc.h | 6 ++- src/vm/inc/rt.h | 16 +++--- src/vm/src/ins_def.c | 94 ++++++++++-------------------------- src/vm/src/proc.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/vm/src/rt.c | 23 ++++++++- 9 files changed, 213 insertions(+), 90 deletions(-)
diff --git a/doc/SPECIFICATION b/doc/SPECIFICATION @@ -281,16 +281,16 @@ to TOS ------------------------------------------------------------------------------- 8 - Generic object interface. Expects object on TOS ------------------------------------------------------------------------------- -80 GETN N<name> - Returns variable assosiated with name in object TBI +80 GETN N<name> - Returns variable assosiated with name in object -81 SETN N<name> - Sets the variable assosiated with name in object TBI +81 SETN N<name> - Sets the variable assosiated with name in object Object on TOS, Variable on TOS1 -82 CALLM N<name> - Calls method in object TBI +82 CALLM N<name> - Calls method in object -83 INDEXO - Index an object, uses arguement stack TBI +83 INDEXO - Index an object, uses arguement stack -84 MODO S<OP> - Modify an object based on op. [+, -, *, /, %, ^ .. etc] TBI +84 MODO S<OP> - Modify an object based on op. [+, -, *, /, %, ^ .. etc] ------------------------------------------------------------------------------- F - Functions/classes ------------------------------------------------------------------------------- @@ -300,9 +300,11 @@ FF DEFUN N<ref> S<type> D<args> - Un-funs everything. no, no- it defines a FE DECLASS N<ref> D<args> - Defines a class. +FD DENS S<ref> - Specifies a namespace scope + F2 ENDCLASS - End of class block -F1 NEW N<ref> - Instantiates class +F1 NEW S<scope> N<ref> - Instantiates class F0 RETURN - Returns from function ------------------------------------------------------------------------------- diff --git a/src/lc/bytecode.py b/src/lc/bytecode.py @@ -66,7 +66,6 @@ class NewClass(): OP_NEW, self.label.action(), OP_DEC, - self.toset.action(s=True), 0x06, self.toset.action(), OP_STV, @@ -82,8 +81,8 @@ class VariableNew(): def action(self): return([ OP_DEC, - self.label.action(s=True), self.typed.action(), + self.label.action(s=True), self.label.action() ]) @@ -148,6 +147,7 @@ class FunctionCall(): return([ self.arguements.action(), OP_CALL, + self.label.action(s=True) self.label.action() ]) diff --git a/src/vm/inc/ins_def.h b/src/vm/inc/ins_def.h @@ -98,9 +98,7 @@ void _ins_def_IFDO (rt_t*, bc_cont*); void _ins_def_ELSE (rt_t*, bc_cont*); void _ins_def_DONE (rt_t*, bc_cont*); void _ins_def_CALL (rt_t*, bc_cont*); -/* HELPER FUNCTIONS */ -void _ins_def_function_call(rt_t*, var_data_func*); -/* END HELPER FUNCTIONS */ + void _ins_def_GETN (rt_t*, bc_cont*); void _ins_def_SETN (rt_t*, bc_cont*); void _ins_def_CALLM (rt_t*, bc_cont*); @@ -110,6 +108,7 @@ void _ins_def_MODO (rt_t*, bc_cont*); void _ins_def_RETURN (rt_t*, bc_cont*); void _ins_def_NEW (rt_t*, bc_cont*); void _ins_def_ENDCLASS (rt_t*, bc_cont*); +void _ins_def_DENS (rt_t*, bc_cont*); void _ins_def_DECLASS (rt_t*, bc_cont*); void _ins_def_DEFUN (rt_t*, bc_cont*); diff --git a/src/vm/inc/ins_mdata.h b/src/vm/inc/ins_mdata.h @@ -34,7 +34,7 @@ /* DUP */ INS_MDATA[0x12] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ /* ROT_THREE */ INS_MDATA[0x13] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ \ -/* DEC */ INS_MDATA[0x20] = encode(3, A_BYTE, A_BYTE, A_NAME); \ +/* DEC */ INS_MDATA[0x20] = encode(2, A_BYTE, A_NAME, A_BYTE); \ /* LOV */ INS_MDATA[0x21] = encode(2, A_BYTE, A_NAME, A_BYTE); \ /* STV */ INS_MDATA[0x22] = encode(2, A_BYTE, A_NAME, A_BYTE); \ /* CTV */ INS_MDATA[0x23] = encode(3, A_BYTE, A_NAME, A_DYNC); \ @@ -80,7 +80,7 @@ /* IFDO */ INS_MDATA[0x72] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ /* ELSE */ INS_MDATA[0x73] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ /* DONE */ INS_MDATA[0x7E] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ -/* CALL */ INS_MDATA[0x7F] = encode(1, A_ADDR, A_BYTE, A_BYTE); \ +/* CALL */ INS_MDATA[0x7F] = encode(2, A_BYTE, A_NAME, A_BYTE); \ \ /* GETN */ INS_MDATA[0x80] = encode(1, A_NAME, A_BYTE, A_BYTE); \ /* SETN */ INS_MDATA[0x81] = encode(1, A_NAME, A_BYTE, A_BYTE); \ @@ -90,6 +90,8 @@ \ /* RETURN */ INS_MDATA[0xF0] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ /* NEW */ INS_MDATA[0xF1] = encode(1, A_NAME, A_BYTE, A_BYTE); \ +/* ENDCLASS */ INS_MDATA[0xF2] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ +/* DENS */ INS_MDATA[0xFD] = encode(1, A_BYTE, A_BYTE, A_BYTE); \ /* DECLASS */ INS_MDATA[0xFE] = encode(2, A_NAME, A_DYNC, A_BYTE); \ /* DEFUN */ INS_MDATA[0xFF] = encode(3, A_NAME, A_BYTE, A_DYNC); @@ -162,7 +164,7 @@ /* IFDO */ INS_ADATA[0x72] = encode(0, BTOI, BTOI, BTOI); \ /* ELSE */ INS_ADATA[0x73] = encode(0, BTOI, BTOI, BTOI); \ /* DONE */ INS_ADATA[0x7E] = encode(0, BTOI, BTOI, BTOI); \ -/* CALL */ INS_ADATA[0x7F] = encode(1, BTOI, BTOI, BTOI); \ +/* CALL */ INS_ADATA[0x7F] = encode(2, BTOI, BTOI, BTOI); \ \ /* GETN */ INS_ADATA[0x80] = encode(1, BTOI, BTOI, BTOI); \ /* SETN */ INS_ADATA[0x81] = encode(1, BTOI, BTOI, BTOI); \ @@ -172,6 +174,8 @@ \ /* RETURN */ INS_ADATA[0xF0] = encode(0, BTOI, BTOI, BTOI); \ /* NEW */ INS_ADATA[0xF1] = encode(1, BTOI, BTOI, BTOI); \ +/* ENDCLASS */ INS_MDATA[0xF2] = encode(0, BTOI, BTOI, BTOI); \ +/* DENS */ INS_ADATA[0xFD] = encode(1, BTOI, BTOI, BTOI); \ /* DECLASS */ INS_ADATA[0xFE] = encode(2, BTOI, DTOL, BTOI); \ /* DEFUN */ INS_ADATA[0xFF] = encode(3, BTOI, BTOT, DTOL); diff --git a/src/vm/inc/proc.h b/src/vm/inc/proc.h @@ -24,6 +24,8 @@ rt_t* proc_init(char*); */ void proc_run(rt_t*); +void proc_run_to_return(rt_t*); + /* Calls runtime context elements to free memory and terminate * rt_t* - Runtime context */ @@ -57,4 +59,8 @@ void proc_setvar(rt_t*, int, ns_addr, var_cont*); */ var_cont* proc_getvar(rt_t*, int, ns_addr); +void proc_function_call(rt_t*, int, ns_addr); + +void proc_function_call_handle(rt_t*, var_data_func*); + #endif //PROC_H diff --git a/src/vm/inc/rt.h b/src/vm/inc/rt.h @@ -10,6 +10,7 @@ #include "bc.h" #include "stk.h" #include "var.h" +#include "object.h" #include "ns.h" #include "pc.h" #include "helper.h" @@ -25,12 +26,13 @@ * [1] Function calls implement this stack to load variables as arguements. */ typedef struct rt_t { - int db; - pc_t* pc; - stk_t* stack; - stk_t* argstk; - ns_t* vars; - ns_ctx* varctx; + int db; + pc_t* pc; + stk_t* stack; + stk_t* argstk; + ns_t* vars; + ns_ctx* varctx; + ns_t* names; } rt_t; /* Creates new runtime context. @@ -39,6 +41,8 @@ typedef struct rt_t { */ rt_t* rt_ctx_new(char*, stk_t*); +void rt_ns_del(void*); + /* Destroys runtime context. */ void rt_ctx_del(rt_t*); diff --git a/src/vm/src/ins_def.c b/src/vm/src/ins_def.c @@ -170,8 +170,8 @@ void _ins_def_ROT_THREE(rt_t* ctx, bc_cont* line) void _ins_def_DEC (rt_t* ctx, bc_cont* line) { - int scope = var_data_get_G_INT(line->varg[0]); - int type = var_data_get_G_INT(line->varg[1]); + int type = var_data_get_G_INT(line->varg[0]); + int scope = var_data_get_G_INT(line->varg[1]); int name = var_data_get_G_INT(line->varg[2]); proc_decvar(ctx, type, scope, name); @@ -207,8 +207,9 @@ void _ins_def_STV (rt_t* ctx, bc_cont* line) } void _ins_def_CTV (rt_t* ctx, bc_cont* line) { - int scope = var_data_get_G_INT(line->varg[0]); - int name = var_data_get_G_INT(line->varg[1]); + int name = var_data_get_G_INT(line->varg[0]); + + int scope = var_data_get_G_INT(line->varg[1]); var_cont* new = var_data_cpy(line->varg[2]); @@ -542,45 +543,11 @@ void _ins_def_DONE (rt_t* ctx, bc_cont* line) } void _ins_def_CALL (rt_t* ctx, bc_cont* line) { - int name = var_data_get_G_INT(line->varg[0]); - - // Get the function's variable container - var_cont* var = proc_getvar(ctx, 1, name); - var_data_func* func = var_data_get_FUNC(var); + int scope = var_data_get_G_INT(line->varg[0]); + int name = var_data_get_G_INT(line->varg[1]); // Call the function - _ins_def_function_call(ctx, func); -} - -void _ins_def_function_call(rt_t* ctx, var_data_func* func) -{ - // Push a new namespace of specified size - ns_push(ctx->vars, func->size); - // Declare the return value - ns_dec(ctx->vars, func->type, 0, 0); - - // Throw in the arguements on the arguement stack into the new namespace - int offset = 1; - int i; - for (i = 0; i < func->paramlen; i++) - { - // Pop the arguement stack - var_cont* arg = stk_pop(ctx->argstk); - - // Is the arguement of the right type? - ASSERT(arg->type == func->param[i], "Invalid function call\n"); - - // Declare the name in the new namespace and pass the arguements - ns_dec(ctx->vars, arg->type, 0, i+offset); - ns_set(ctx->vars, 0, i+offset, arg); - } - - // Push new stack levels for the stack and the arguement stack - stk_newlevel(&ctx->stack); - stk_newlevel(&ctx->argstk); - - // Branch to functions body - pc_branch(ctx->pc, func->loc); + proc_function_call(ctx, scope, name); } void _ins_def_GETN (rt_t* ctx, bc_cont* line) @@ -632,33 +599,11 @@ void _ins_def_CALLM (rt_t* ctx, bc_cont* line) // Set current namespace to objects namespace ctx->vars = object->names; // Call the function - _ins_def_function_call(ctx, func); + proc_function_call_handle(ctx, func); + // Update the program counter pc_update(ctx->pc); - // Run code here so we can pop the namespace context - int n; - for (n = 0; pc_safe(ctx->pc); pc_update(ctx->pc)) - { - if (ctx->db) - { - printf("[%i]:\t", ctx->pc->address); - bc_print_op(ctx->pc->line); - printf("\n"); - } - - INS_DEF[ctx->pc->line->op](ctx, ctx->pc->line); - - // Break when the function returns - if (ctx->pc->line->op == 0x7F) - n++; - else if (ctx->pc->line->op == 0xF0) - { - if (n > 0) - n--; - else - break; - } - } + proc_run_to_return(ctx); // Pop the namespace context ctx->vars = ns_ctx_pop(ctx->varctx); } @@ -748,6 +693,23 @@ void _ins_def_ENDCLASS (rt_t* ctx, bc_cont* line) pc_return(ctx->pc); pc_inc(ctx->pc, 1); } +void _ins_def_DENS (rt_t* ctx, bc_cont* line) +{ + int name = var_data_get_G_INT(line->varg[0]); + + ns_t* ns = ns_init(0xFF); + + var_data_object* namespace = var_data_alloc_OBJECT(rt_ns_del); + namespace->ref = (void*)ns; + + var_cont* ns_var = var_new(OBJECT); + var_set(ns_var, namespace, OBJECT); + + ns_dec(ctx->names, OBJECT, 1, name); + ns_set(ctx->names, 1, name, ns_var); + + ctx->vars = ns; +} void _ins_def_DECLASS (rt_t* ctx, bc_cont* line) { int name = var_data_get_G_INT(line->varg[0]); diff --git a/src/vm/src/proc.c b/src/vm/src/proc.c @@ -47,6 +47,35 @@ void proc_run(rt_t* ctx) } } +void proc_run_to_return(rt_t* ctx) +{ + N_ASSERT(ctx, "proc_run\n"); + + int n; + for (n = 0; pc_safe(ctx->pc); pc_update(ctx->pc)) + { + if (ctx->db) + { + printf("[%i]:\t", ctx->pc->address); + bc_print_op(ctx->pc->line); + printf("\n"); + } + + INS_DEF[ctx->pc->line->op](ctx, ctx->pc->line); + + // Break when the function returns + if (ctx->pc->line->op == 0x7F) + n++; + else if (ctx->pc->line->op == 0xF0) + { + if (n > 0) + n--; + else + break; + } + } +} + /* Calls runtime context elements to free memory and terminate * rt_t* - Runtime context */ @@ -67,7 +96,14 @@ void proc_clean(rt_t* ctx) void proc_decvar(rt_t* ctx, b_type type, int scope, ns_addr name) { N_ASSERT(ctx, "proc_decvar\n"); - ns_dec(ctx->vars, type, scope, name); + + int x = (scope & 0xFE) >> 1; + int s = (scope & 0x01); + + if (x == 0) + { + ns_dec(ctx->vars, type, s, name); + } } /* Set a variable subroutine @@ -81,7 +117,21 @@ void proc_decvar(rt_t* ctx, b_type type, int scope, ns_addr name) void proc_setvar(rt_t* ctx, int scope, ns_addr name, var_cont* var) { N_ASSERT(ctx, "proc_setvar\n"); - ns_set(ctx->vars, scope, name, var); + + int x = (scope & 0xFE) >> 1; + int s = (scope & 0x01); + + if (x == 0) + { + ns_set(ctx->vars, s, name, var); + } else + { + var_cont* ns_var = ns_get(ctx->names, 1, x); + var_data_object* var_d = var_data_get_OBJECT(ns_var); + ns_t* ns = (ns_t*) var_d->ref; + + ns_set(ns, s, name, var); + } } /* Get a variable subroutine @@ -94,8 +144,83 @@ var_cont* proc_getvar(rt_t* ctx, int scope, ns_addr name) N_ASSERT(ctx, "proc_getvar\n"); var_cont* rv; - rv = ns_get(ctx->vars, scope, name); + int x = (scope & 0xFE) >> 1; + int s = (scope & 0x01); + + if (x == 0) + { + rv = ns_get(ctx->vars, scope, name); + } else + { + var_cont* ns_var = ns_get(ctx->names, 1, x); + var_data_object* var_d = var_data_get_OBJECT(ns_var); + ns_t* ns = (ns_t*) var_d->ref; + + rv = ns_get(ns, s, name); + } + return rv; } +void proc_function_call(rt_t* ctx, int scope, ns_addr name) +{ + N_ASSERT(ctx, "proc_function_call\n"); + + int x = (scope & 0xFE) >> 1; + + var_cont* var = proc_getvar(ctx, scope, name); + + if (x != 0) + { + ns_ctx_push(ctx->varctx, ctx->vars); + var_cont* ns_var = ns_get(ctx->names, 1, x); + var_data_object* var_d = var_data_get_OBJECT(ns_var); + ns_t* ns = (ns_t*) var_d->ref; + + ctx->vars = ns; + } + + var_data_func* func = var_data_get_FUNC(var); + + proc_function_call_handle(ctx, func); + + proc_run_to_return(ctx); + + if (x != 0) + { + ctx->vars = ns_ctx_pop(ctx->varctx); + } +} + +void proc_function_call_handle(rt_t* ctx, var_data_func* func) +{ + // Push a new namespace of specified size + ns_push(ctx->vars, func->size); + // Declare the return value + ns_dec(ctx->vars, func->type, 0, 0); + + // Throw in the arguements on the arguement stack into the new namespace + int offset = 1; + int i; + for (i = 0; i < func->paramlen; i++) + { + // Pop the arguement stack + var_cont* arg = stk_pop(ctx->argstk); + + // Is the arguement of the right type? + ASSERT(arg->type == func->param[i], "Invalid function call\n"); + + // Declare the name in the new namespace and pass the arguements + ns_dec(ctx->vars, arg->type, 0, i+offset); + ns_set(ctx->vars, 0, i+offset, arg); + } + + // Push new stack levels for the stack and the arguement stack + stk_newlevel(&ctx->stack); + stk_newlevel(&ctx->argstk); + + // Branch to functions body + pc_branch(ctx->pc, func->loc); +} + diff --git a/src/vm/src/rt.c b/src/vm/src/rt.c @@ -6,6 +6,7 @@ #include "stk.h" #include "var.h" #include "ns.h" +#include "object.h" #include "pc.h" #include "helper.h" @@ -25,12 +26,28 @@ rt_t* rt_ctx_new(char* fname, stk_t* args) ctx->pc = pc_new(fname); ctx->stack = stk_new(); ctx->argstk = args; - ctx->vars = ns_init(1024); + ctx->vars = ns_init(0xFF); ctx->varctx = ns_ctx_init(); + ctx->names = ns_init(0x7F); + + var_data_object* namespace = var_data_alloc_OBJECT(rt_ns_del); + namespace->ref = (void*)ctx->vars; + + var_cont* ns_var = var_new(OBJECT); + var_set(ns_var, namespace, OBJECT); + + ns_dec(ctx->names, OBJECT, 1, 1); + ns_set(ctx->names, 1, 1, ns_var); return ctx; } +void rt_ns_del(void* ns) +{ + ns_t* namespace = (ns_t*)ns; + ns_del(namespace); +} + /* Destroys runtime context. This can be *very* slow. */ void rt_ctx_del(rt_t* ctx) @@ -51,4 +68,8 @@ void rt_ctx_del(rt_t* ctx) N_ASSERT(ctx->varctx, "rt_ctx_del\n"); ns_ctx_del(ctx->varctx); + + N_ASSERT(ctx->names, "rt_ctx_del\n"); + ns_del(ctx->names); + }