language

Some fools attempt at an interpreted language
Log | Files | Refs

commit 0fa648a0db80ed4c9ee179239de9e2133715ccf5
parent 5f6e185e5748f10edd0198cd1e638664b38a05c9
Author: Paul Longtine <paullongtine@gmail.com>
Date:   Thu Mar 24 17:33:15 2016

Refreshed test cases, made the testing bed better, got everything working again, along with function calls.

Diffstat:
 src/vm/inc/ns.h                        |  4 +--
 src/vm/inc/pc.h                        |  8 +++--
 src/vm/inc/stk.h                       |  2 +-
 src/vm/src/ins_def.c                   | 31 ++++++++++++++++-----
 src/vm/src/main.c                      |  2 +-
 src/vm/src/ns.c                        | 20 +++++++++-----
 src/vm/src/pc.c                        | 47 ++++++++++++++++++++++++--------
 src/vm/src/proc.c                      |  2 +-
 src/vm/src/rt.c                        | 51 +-----------------------------------
 src/vm/src/stk.c                       | 46 ++++++++++++++++++--------------
 src/vm/src/var.c                       | 11 ++++----
 src/vm/tests/bytecodes/funtest         | Bin 0 -> 45 bytes
 src/vm/tests/cases/pc/Makefile         |  2 +-
 src/vm/tests/cases/pc/expected_output  | 10 ++++---
 src/vm/tests/cases/pc/test.c           | 19 ++++++++++---
 src/vm/tests/cases/stk/expected_output | 18 ++++++++++++-
 src/vm/tests/cases/stk/test.c          | 27 ++++++++++++++++---
 src/vm/tests/run.sh                    |  6 ++--
 src/vm/tests/tools/test.sh             | 22 ++++++++++-----
 19 files changed, 202 insertions(+), 126 deletions(-)

diff --git a/src/vm/inc/ns.h b/src/vm/inc/ns.h @@ -35,7 +35,7 @@ ns_cont* ns_cont_init(ns_addr); /* Cleans up memory */ void ns_del(ns_t*); -void ns_cont_del(ns_cont*); +var_cont* ns_cont_del(ns_cont*, ns_addr); /* Pushes namespace of size * ns_t* - namespace instance @@ -45,7 +45,7 @@ void ns_push(ns_t*, ns_addr); /* Pops last namespace level */ -void ns_pop(ns_t*); +var_cont* ns_pop(ns_t*); /* Declares a variable, at root or last namespace * ns_t* - Namespace instance diff --git a/src/vm/inc/pc.h b/src/vm/inc/pc.h @@ -29,7 +29,7 @@ typedef struct pc_t { pc_addr address; pc_addr_stk* stk; bc_cont* line; - bc_t program; + bc_t* bc; } pc_t; /* Initalizes program counter, returns pc_t* instance @@ -37,8 +37,6 @@ typedef struct pc_t { */ pc_t* pc_new(char*); -void pc_read(char*, pc_t*); - pc_addr_stk* pc_addr_stk_new(ns_addr); /* Frees memory assosiated with pc_t* instance @@ -66,6 +64,10 @@ void pc_branch(pc_t*, pc_addr); */ void pc_return(pc_t*); +/* Simply goto that address + */ +void pc_goto(pc_t*, pc_addr); + /* For now, a simple function that returns true if the next instruction is not * NULL. */ diff --git a/src/vm/inc/stk.h b/src/vm/inc/stk.h @@ -40,7 +40,7 @@ void stk_newlevel(stk_t**); /* Pops a stack level */ -int stk_poplevel(stk_t**); +void stk_poplevel(stk_t**); /* Scales the stack by n^2 * stk_t* - stack instance diff --git a/src/vm/src/ins_def.c b/src/vm/src/ins_def.c @@ -452,21 +452,27 @@ 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]); + var_cont* var = proc_getvar(ctx, 1, name); var_data_func* func = var_data_get_FUNC(var); ns_push(ctx->vars, func->size); + ns_dec(ctx->vars, func->type, 0, 0); + + int offset = 1; int i; for (i = 0; i < func->paramlen; i++) { var_cont* arg = stk_pop(ctx->argstk); ASSERT(arg->type == func->param[i], "Invalid function call\n"); - ns_dec(ctx->vars, 0, i, arg->type); - ns_set(ctx->vars, 0, i, arg); + ns_dec(ctx->vars, arg->type, 0, i+offset); + ns_set(ctx->vars, 0, i+offset, arg); } + stk_newlevel(&ctx->stack); + stk_newlevel(&ctx->argstk); pc_branch(ctx->pc, func->loc); } @@ -493,6 +499,15 @@ void _ins_def_CALLM (rt_t* ctx, bc_cont* line) void _ins_def_RETURN (rt_t* ctx, bc_cont* line) { + var_cont* return_value = ns_pop(ctx->vars); + + stk_poplevel(&ctx->stack); + stk_poplevel(&ctx->argstk); + + stk_push(ctx->stack, return_value); + + pc_return(ctx->pc); + pc_inc(ctx->pc, 1); } void _ins_def_NEW (rt_t* ctx, bc_cont* line) @@ -510,6 +525,8 @@ void _ins_def_DEFUN (rt_t* ctx, bc_cont* line) b_type* args = var_data_get_PLIST(line->varg[2]); size_t alen = line->sarg[2]; + var_cont* func = var_new(NAMESPACE, FUNC); + var_data_func* data = var_data_alloc_FUNC(type); data->loc = line->real_addr + 1; @@ -530,13 +547,13 @@ void _ins_def_DEFUN (rt_t* ctx, bc_cont* line) } data->end = ctx->pc->line->real_addr; - data->size = nsize; - data->type = type; + data->size = nsize + alen + 1;// How many names will this function have? + data->type = type; // Return type data->paramlen = alen; data->param = args; - proc_decvar(ctx, 1, name, FUNC); + var_set(func, data, FUNC); - var_cont* var = proc_getvar(ctx, 1, name); - var_set(var, data, FUNC); + proc_decvar(ctx, FUNC, 1, name); + proc_setvar(ctx, 1, name, func); } diff --git a/src/vm/src/main.c b/src/vm/src/main.c @@ -8,7 +8,7 @@ int main(int argc, char** argv) { - ASSERT(argc > 1, "C'mon, man! Gimme some args\n"); + ASSERT(argc > 1, "Specify a bytecode file in the first and only argument, please\n"); init_mdata(); // Initalize the instruction defs init_adata(); diff --git a/src/vm/src/ns.c b/src/vm/src/ns.c @@ -41,22 +41,28 @@ ns_t* ns_init(ns_addr size) return ns; } -/* Cleans up memory +/* Cleans up memory, returns variable with label exclude */ -void ns_cont_del(ns_cont* container) +var_cont* ns_cont_del(ns_cont* container, ns_addr exclude) { N_ASSERT(container, "ns_cont_del\n"); N_ASSERT(container->names, "ns_cont_del\n"); + var_cont* rv; + for (int i = 0; i < container->size; i++) { - if (container->names[i] != NULL) + if (container->names[i] != NULL && i != exclude) var_del(container->names[i]); + else if (i == exclude) + rv = container->names[i]; } free(container->names); free(container); + + return rv; } /* Cleans up memory @@ -67,7 +73,7 @@ void ns_del(ns_t* ns) if (ns->last != NULL) while (ns->last->next != NULL) - ns_pop(ns); + var_del(ns_pop(ns)); free(ns); } @@ -96,17 +102,19 @@ void ns_push(ns_t* ns, ns_addr size) /* Pops last namespace level */ -void ns_pop(ns_t* ns) +var_cont* ns_pop(ns_t* ns) { N_ASSERT(ns, "ns_pop\n"); + var_cont* rv; if (ns->last->next != NULL) { ns_cont* newlast = ns->last->next; - ns_cont_del(ns->last); + rv = ns_cont_del(ns->last, 0); ns->last = newlast; } + return rv; } /* Declares a variable, at root or last namespace diff --git a/src/vm/src/pc.c b/src/vm/src/pc.c @@ -20,7 +20,9 @@ pc_t* pc_new(char* fname) pc->stk = pc_addr_stk_new(0); - pc->program = bc_init(fname); + pc_branch(pc, 0); + + pc->bc = bc_init(fname); pc_update(pc); @@ -49,30 +51,32 @@ void pc_del(pc_t* pc) { N_ASSERT(pc, "pc_del\n"); N_ASSERT(pc->stk, "pc_del\n"); -// gotta actually handle this realquick + N_ASSERT(pc->bc, "pc_del\n"); + + pc_addr_stk_del(pc->stk); + bc_del(pc->bc); + free(pc); } void pc_addr_stk_del(pc_addr_stk* stk) { N_ASSERT(stk, "pc_addr_stk_del\n"); -// and this -} + N_ASSERT(stk->addresses, "pc_addr_stk_del\n"); -void pc_push(pc_t* pc, bc_cont* bytecode) -{ - N_ASSERT(pc, "pc_push\n"); + free(stk->addresses); + free(stk); } /* Updates currently reading line * - * When called, pc_t->line will reflect pc_t->heap[pc_t->address] + * When called, pc_t->line will reflect pc_t->bc[pc_t->address] */ void pc_update(pc_t* pc) { N_ASSERT(pc, "pc_update\n"); - - pc->line = pc->heap[pc->address]; + ASSERT((pc->address <= pc->bc->size), "Uhoh\n"); + pc->line = pc->bc->heap[pc->address]; } /* Increment program counter by +-addr @@ -90,6 +94,11 @@ void pc_branch(pc_t* pc, pc_addr address) { N_ASSERT(pc, "pc_branch\n"); + ASSERT(((pc->stk->ptr + 1) < pc->stk->size), "Address Stack Overflow\n"); + + pc->stk->addresses[pc->stk->ptr] = pc->address; + pc->stk->ptr = pc->stk->ptr + 1; + pc->address = address; } @@ -98,6 +107,21 @@ void pc_branch(pc_t* pc, pc_addr address) void pc_return(pc_t* pc) { N_ASSERT(pc, "pc_return\n"); + + ASSERT(((pc->stk->ptr - 1) > 0), "Address Stack Underflow\n"); + + pc->stk->ptr = pc->stk->ptr - 1; + + pc->address = pc->stk->addresses[pc->stk->ptr]; +} + +/* Simply goto that address + */ +void pc_goto(pc_t* pc, pc_addr addr) +{ + N_ASSERT(pc, "pc_goto\n"); + + pc->address = addr; } /* For now, a simple function that returns true if the next instruction is not @@ -105,6 +129,7 @@ void pc_return(pc_t* pc) */ int pc_safe(pc_t* pc) { - return 0; + int rv = (pc->address >= pc->bc->size) ? 0 : 1; + return rv; } diff --git a/src/vm/src/proc.c b/src/vm/src/proc.c @@ -34,7 +34,7 @@ void proc_run(rt_t* ctx) for (n = 0; pc_safe(ctx->pc); pc_update(ctx->pc)) { -// printf("%i - %i: %x\n", n, ctx->pc->stk->address, ctx->pc->line->op); +// printf("%i - %i: %x\n", n, ctx->pc->address, ctx->pc->line->op); INS_DEF[ctx->pc->line->op](ctx, ctx->pc->line); diff --git a/src/vm/src/rt.c b/src/vm/src/rt.c @@ -48,54 +48,3 @@ void rt_ctx_del(rt_t* ctx) N_ASSERT(ctx->pc, "rt_ctx_del\n"); pc_del(ctx->pc); } - -#ifdef THREADING - -#include <pthread.h> -rt_pool* rt_pool_init(int depth) -{ - -} - -void rt_pool_kill(rt_pool* pool) -{ - -} - -void *rt_worker_run(void* ctx) -{ - rt_worker* c; - c = (rt_worker*)ctx; - - //TODO this. - - return 0; -} - - -rt_worker* rt_worker_new(char* fname, ns_addr func, ns_cont* gs, stk_t* args) -{ - rt_worker* worker = (rt_worker*)malloc(sizeof(rt_worker)); - M_ASSERT(worker); - - pthread_create(&worker->thread_ctx, NULL, rt_worker_run, worker); - - return worker; -} - -void rt_worker_del(rt_worker* worker) -{ - N_ASSERT(worker); - N_ASSERT(worker->thread_ctx); - pthread_cancel(worker->thread_ctx); - - N_ASSERT(worker->runtime_ctx); - rt_ctx_del(worker->runtime_ctx); - - N_ASSERT(worker->pc); - pc_del(worker->pc); - - free(worker); -} - -#endif // SINGLE_THREAD diff --git a/src/vm/src/stk.c b/src/vm/src/stk.c @@ -42,13 +42,11 @@ void stk_del(stk_t* stack) { N_ASSERT(stack, "stk_del"); - while (stk_poplevel(&stack)) + while (stack->next != NULL) { - if (stack->stack != NULL) - { - stk_line_del(stack->stack); - } + stk_poplevel(&stack); } + free(stack); } @@ -70,7 +68,6 @@ void stk_line_del(stk_line* stack) free(stack); } - /* Pushes a new stack level * stk_t** - stack instances */ @@ -78,17 +75,27 @@ void stk_newlevel(stk_t** stack) { N_ASSERT(stack, "stk_newlevel\n"); + stk_t* new = stk_new(); + + new->next = *stack; + + *stack = new; } /* Pops a stack level * stk_t* - stack instance - * - * This function returns FALSE if stk_t->stack is on the last element */ -int stk_poplevel(stk_t** stack) +void stk_poplevel(stk_t** stack) { N_ASSERT(stack, "stk_poplevel\n"); - return 0; + + if ((*stack)->next != NULL) + { + stk_t* tmp = (*stack)->next; + stk_line_del((*stack)->stack); + free(*stack); + *stack = tmp; + } } /* Scales the stack by n^2 @@ -110,14 +117,10 @@ var_cont* stk_pop(stk_t* stack) { N_ASSERT(stack, "stk_pop\n"); - ASSERT(((stack->stack->ptr - 1) > 0), "Stack Underflow\n"); - - var_cont* rv = stack->stack->data[stack->stack->ptr]; + ASSERT(((stack->stack->ptr - 1) >= 0), "Stack Underflow\n"); stack->stack->ptr = stack->stack->ptr - 1; - - N_ASSERT(stack->stack->data[stack->stack->ptr], - "Found NULL value in stack, running away for obvious reasons.\n"); + var_cont* rv = stack->stack->data[stack->stack->ptr]; return rv; } @@ -136,14 +139,19 @@ void stk_push(stk_t* stack, var_cont* data) stk_scale(stack->stack); } - stack->stack->ptr = stack->stack->ptr + 1; - stack->stack->data[stack->stack->ptr] = data; + stack->stack->ptr = stack->stack->ptr + 1; } +/* Returns the data at location in the stack + * stk_line* - Stack line instance + * int - (integer + 1) < (STK_SIZE_LIMIT - stk_line->ptr) + */ var_cont* stk_at(stk_t* stack, int n) { - ASSERT(((stack->stack->ptr + n) < stack->stack->size), "Out of Bounds\n"); + n = n + 1; + + ASSERT(((stack->stack->ptr - n) >= 0), "Out of Bounds\n"); var_cont* rv = stack->stack->data[stack->stack->ptr - n]; diff --git a/src/vm/src/var.c b/src/vm/src/var.c @@ -97,12 +97,13 @@ var_cont* var_new(var_state state, b_type type) void var_del(var_cont* var) { - N_ASSERT(var, "var_del\n"); - - if (var->data != NULL) - var_data_free(var->data, var->type); + if (var != NULL) + { + if (var->data != NULL) + var_data_free(var->data, var->type); - free(var); + free(var); + } } void var_data_free(void* data, b_type type) diff --git a/src/vm/tests/bytecodes/funtest b/src/vm/tests/bytecodes/funtest Binary files differ diff --git a/src/vm/tests/cases/pc/Makefile b/src/vm/tests/cases/pc/Makefile @@ -9,12 +9,14 @@ DEPS = i$(INC_DIR)/is_mdata.h \ fh.h \ is.h \ bc.h \ + var.h \ pc.h OBJ = test.o \ $(SRC_DIR)/fh.o \ $(SRC_DIR)/is.o \ $(SRC_DIR)/bc.o \ + $(SRC_DIR)/var.o\ $(SRC_DIR)/pc.o OUT = test diff --git a/src/vm/tests/cases/pc/expected_output b/src/vm/tests/cases/pc/expected_output @@ -1,3 +1,7 @@ -OP: ff -OP: 20 -OP: f0 +Loading file 'bytecode' +ADDR: 0, OP: ff +ADDR: 1, OP: 20 +ADDR: 2, OP: f0 +ADDR: 1, OP: 20 +ADDR: 2, OP: f0 +ADDR: 2, OP: f0 diff --git a/src/vm/tests/cases/pc/test.c b/src/vm/tests/cases/pc/test.c @@ -11,17 +11,30 @@ int main(int argc, char *argv[]) init_mdata(); init_adata(); + printf("Loading file 'bytecode'\n"); pc_t* pc = pc_new("bytecode"); - while (pc->line->next != NULL) + while (pc_safe(pc)) { + printf("ADDR: %x, OP: %x\n", pc->address, pc->line->op); pc_inc(pc, 1); + pc_update(pc); + } + pc_inc(pc, -1); + pc_branch(pc, 1); + pc_update(pc); - printf("OP: %x\n", pc->line->op); - + while (pc_safe(pc)) + { + printf("ADDR: %x, OP: %x\n", pc->address, pc->line->op); + pc_inc(pc, 1); pc_update(pc); } + pc_return(pc); + pc_update(pc); + printf("ADDR: %x, OP: %x\n", pc->address, pc->line->op); + pc_del(pc); return 0; } diff --git a/src/vm/tests/cases/stk/expected_output b/src/vm/tests/cases/stk/expected_output @@ -1,5 +1,23 @@ +init: 9, 8, 7, 6 +stk_pop: 8, 7, 6, 0 +stk_rot_top: 7, 8, 6, 0 +stk_rot_top + stk_rot_three: 6, 7, 8, 0 +stk_rot_three: 8, 7, 6, 0 +-- NEW STACK LEVEL -- +init: +9, 8, 7, 6 +stk_pop: +8, 7, 6, 0 +stk_rot_top: +7, 8, 6, 0 +stk_rot_top + stk_rot_three: +6, 7, 8, 0 +stk_rot_three: +8, 7, 6, 0 +-- LEVEL 1: 8, 7, 6, 0 +-- LEVEL 0: 8, 7, 6, 0 diff --git a/src/vm/tests/cases/stk/test.c b/src/vm/tests/cases/stk/test.c @@ -14,10 +14,8 @@ void printstk(stk_t* stk) test0->type, test1->type, test2->type, test3->type); } -int main(int argc, char* argv[]) +void playstk(stk_t* new) { - stk_t* new = stk_new(); - stk_push(new, var_new(TEMPORARY, VOID)); stk_push(new, var_new(TEMPORARY, G_INT)); stk_push(new, var_new(TEMPORARY, G_FLOAT)); @@ -48,6 +46,29 @@ int main(int argc, char* argv[]) printf("stk_rot_three: \n"); printstk(new); +} + +int main(int argc, char* argv[]) +{ + stk_t* new = stk_new(); + + playstk(new); + + printf("-- NEW STACK LEVEL --\n"); + stk_newlevel(&new); + + playstk(new); + + printf("-- LEVEL 1: "); + printstk(new); + + stk_poplevel(&new); + + printf("-- LEVEL 0: "); + printstk(new); + + stk_newlevel(&new); + stk_newlevel(&new); stk_del(new); diff --git a/src/vm/tests/run.sh b/src/vm/tests/run.sh @@ -4,8 +4,8 @@ cd cases ../tools/test.sh $1 -../tools/clean.sh $1 +../tools/clean.sh $1 &> /dev/null -cd .. +cd .. &> /dev/null -rm ../src/*.o +rm ../src/*.o &> /dev/null diff --git a/src/vm/tests/tools/test.sh b/src/vm/tests/tools/test.sh @@ -1,21 +1,29 @@ #!/bin/bash -SEPARATOR="--------------------------------------------------------------------------------" - dir=$(ls) +successes=0 +total=0 for i in $dir do if [ "$1" == 'all' ] || [ "$1" == $i ]; then + total=$((total + 1)) + cd $i make - + printf "\nTESTCASE: $(basename $PWD)\n" - printf "The following differences between valid test vs. current test:" - printf "\n" - ./test bytecode | diff /dev/stdin expected_output - printf "\n$SEPARATOR\n" + if (./test | diff /dev/stdin expected_output &> /dev/null); then + printf "TESTCASE $(basename $PWD) succeeded\n" + successes=$((successes + 1)) + else + printf "TESTCASE $(basename $PWD) failed\n" + printf "$output\n" + fi + cd .. fi done + +printf "PASSING: $successes/$total\n"