commit 6e7aa81b58e74af3c25ce7cc3edb77e8264bd0fd parent eeb5d0dfd38350cd294c1448b6443eaf1fc20eb6 Author: Paul Longtine <paullongtine@gmail.com> Date: Wed Mar 23 11:18:11 2016 Broken codebase, but it compiles. In middle of moving to more efficent data structures. Diffstat: doc/SPECIFICATION | 57 +++++--------- src/vm/Makefile | 6 +-- src/vm/inc/bc.h | 24 +----- src/vm/inc/ht.h | 62 +---------------- src/vm/inc/ins_def.h | 2 +- src/vm/inc/is.h | 6 +- src/vm/inc/pc.h | 38 ++++++---- src/vm/inc/stk.h | 44 ++++++++--- src/vm/inc/var.h | 10 ++- src/vm/src/bc.c | 83 +++------------------ src/vm/src/ht.c | 161 +---------------------------------------- src/vm/src/ins_def.c | 99 ++++++++++++++----------- src/vm/src/is.c | 3 +- src/vm/src/main.c | 4 +- src/vm/src/ns.c | 2 +- src/vm/src/pc.c | 105 ++++++++++++++++---------- src/vm/src/stk.c | 163 ++++++++++++++++++++++++++++++----------- src/vm/src/var.c | 14 ++-- src/vm/src/var_ops.c | 28 +++---- src/vm/tests/bytecodes/looptest | Bin 12 -> 0 bytes src/vm/tests/bytecodes/testing | Bin 17 -> 0 bytes 21 files changed, 387 insertions(+), 524 deletions(-)
diff --git a/doc/SPECIFICATION b/doc/SPECIFICATION @@ -13,39 +13,27 @@ are deemed inferior. #TO BE DETERMINED# TYPES - Providing basic types, such as: - * integer - * float - * character - * boolean -Types are structured in memory with an integer representing types, along with a -null pointer to a space in memory containing the data. Building on top of basic -types, there will be more complex data structures built into the virtual machine -such as static Arrays, dynamic Arrays, and a hashtable implementation. Functions -and Classes have their own type, which acts as a pointer to an address within -the program space. For example, variables would be accessed in the runtime, in -code would be like so: - - var_cont* get_variable(ns_cont* namespace, int x) - { - var_cont* var = namespace->names[x]; - return var; - } - -To set variable: - - void set_variable(ns_cont* namespace, var_cont* var, int x) - { - var_cont* c_var = namespace->names[x]; - - del_var(c_var); - - var_cont* c_var = var; - } - -Both of these functions require some safeguards against hard crashes, where the -program will segfault if given incorrect values. + 0 VOID - Null, no data + 1 ADDR - Address type (bytecode) + 2 TYPE - A type type + 3 PLIST - Parameter list + 4 FUNC - Function + 5 OBJECT - Object/Class + 6 G_INT - Generic integer + 7 G_FLOAT - Generic double + 8 G_CHAR - Generic character + 9 G_STR - Generic string +10 S_ARRAY - Static array +11 D_ARRAY - Dynamic array +12 H_TABLE - Hashtable +13 G_FIFO - Stack + +Types are a structure in memory with an enumeration representing types, along +with a null pointer to a space in memory containing the data structure that +corresponds with the enumerated data type. Functions and Classes are both data- +types that behave like normal variables, although their data structure contains +references to addresses/subsets of namespaces. ________________________________________________________________________________ RUNTIME @@ -73,8 +61,9 @@ variables declared in the global scope. +---------+ |Function | -> Functions are defined with a reference, called with the same - +---------+ reference. The top elements on the stack are used as arguements - when calling a function, which must align with the parameter + +---------+ reference. A special stack called the "arguement stack", built + pre-call the are used as arguements. + When calling a function, the order must align with the parameter types. +---------------+ diff --git a/src/vm/Makefile b/src/vm/Makefile @@ -12,7 +12,6 @@ DEPS = $(INC_DIR)/is_mdata.h \ var.h \ var_ops.h \ stk.h \ - ht.h \ ns.h \ pc.h \ rt.h \ @@ -21,16 +20,15 @@ DEPS = $(INC_DIR)/is_mdata.h \ OBJ = $(SRC_DIR)/main.o \ $(SRC_DIR)/fh.o \ - $(SRC_DIR)/bc.o \ $(SRC_DIR)/is.o \ + $(SRC_DIR)/bc.o \ $(SRC_DIR)/var.o \ $(SRC_DIR)/var_ops.o \ $(SRC_DIR)/stk.o \ - $(SRC_DIR)/ht.o \ $(SRC_DIR)/ns.o \ - $(SRC_DIR)/pc.o \ $(SRC_DIR)/rt.o \ $(SRC_DIR)/ins_def.o \ + $(SRC_DIR)/pc.o \ $(SRC_DIR)/proc.o OUT = toi diff --git a/src/vm/inc/bc.h b/src/vm/inc/bc.h @@ -8,8 +8,8 @@ #include <stdio.h> #include "fh.h" -#include "helper.h" #include "var.h" +#include "helper.h" typedef unsigned int bc_addr; @@ -23,8 +23,6 @@ typedef struct bc_cont { byte_t* args[3]; var_cont* varg[3]; int sarg[3]; - struct bc_cont* next; - struct bc_cont* prev; } bc_cont; #include "is.h" @@ -33,11 +31,6 @@ typedef struct bc_cont { */ bc_cont* bc_cont_new(void); -/* Pushes new bc_cont to the chain. - * bc_cont** - bytecode container - */ -void bc_cont_push(bc_cont**); - /* Deallocates all the things, assuming the arguement is the root. * bc_cont* - bytecode container, root node (hopefully) */ @@ -57,18 +50,9 @@ byte_t* get_dync_arg(FILE*, int*); */ void process_args(bc_cont*); -/* Scan to +/- int in bytecode chain - * bc_cont* - bytecode container [0] - * int - +/- up/down [1] - * - * -> bc_cont* - Bytecode @param[0]'s location +/- @param[1] - */ -bc_cont* bc_scan(bc_cont*, int); - -/* Initiates the first pass to take a raw binary file and translate it into a - * basic datastructure - * char* -> filename +/* Gets bytecode size + * char* - filename */ -bc_cont* bc_read(char*); +size_t bc_getsize(char*); #endif // BC_H diff --git a/src/vm/inc/ht.h b/src/vm/inc/ht.h @@ -1,62 +0,0 @@ -/* `ht` Hashtable implementation - */ - -#ifndef HT_H -#define HT_H - -#include <stdio.h> -#include <stdlib.h> -#include <limits.h> -#include <string.h> - -#include "var.h" -#include "helper.h" - -typedef struct ht_entry { - char* key; - var_cont* value; - struct ht_entry *next; -} ht_entry; - -typedef struct ht_t { - int size; - ht_entry** table; -} ht_t; - -/* Creates hashtable of @param int size - */ -ht_t* ht_init(int); - -/* Creates the table of empty buckets for the hashtable - */ -ht_entry** ht_init_table(int); - -/* Destroys hashtable - */ -void ht_destroy(ht_t*); - -/* Destroys the table of buckets for the hashtable - */ -void ht_destroy_table(ht_entry**, int); - -/* Destroys an entry. - */ -void ht_destroy_entry(ht_entry*); - -/* Set a key-value pair - */ -void ht_set(ht_t*, char*, var_cont*); - -/* Get a value - */ -var_cont* ht_get(ht_t*, char*); - -/* Make a new key-value pair - */ -ht_entry* ht_newpair(char*, var_cont*); - -/* Hash a string - */ -int ht_hash(ht_t*, char*); - -#endif // HT_H diff --git a/src/vm/inc/ins_def.h b/src/vm/inc/ins_def.h @@ -17,7 +17,7 @@ #include "helper.h" // This array is populated by init_ins_def( void ); -void (*INS_DEF[0xFF])(rt_t*, bc_cont*); +void (*INS_DEF[0x100])(rt_t*, bc_cont*); /* Initializes INS_DEF with pointers to each instructions function * Populates INS_DEF diff --git a/src/vm/inc/is.h b/src/vm/inc/is.h @@ -9,14 +9,14 @@ #define IS_H #include "ins_mdata.h" -#include "bc.h" #include "fh.h" +#include "bc.h" // This array is populated by inc/ins_mdata.h -byte_t INS_MDATA[0xFF]; +byte_t INS_MDATA[0x100]; // This array is populated by inc/ins_adata.h -byte_t INS_ADATA[0xFF]; +byte_t INS_ADATA[0x100]; /* Takes an opcode, fills metadata about that opcode (given that it exists) in * the `bc_cont` structure diff --git a/src/vm/inc/pc.h b/src/vm/inc/pc.h @@ -4,45 +4,53 @@ #ifndef PC_H #define PC_H +#define PC_RETURN_DEPTH 0xFF + #include <stdlib.h> #include <stdio.h> -#include "bc.h" #include "is.h" #include "fh.h" +#include "bc.h" #include "helper.h" typedef unsigned short int pc_addr; -typedef struct pc_stk { - pc_addr address; - struct pc_stk* next; -} pc_stk; +typedef struct pc_addr_stk { + size_t size; + int ptr; + pc_addr* addresses; +} pc_addr_stk; /* pc_t structure - * - * bc_cont* root - First instruction - * bc_cont* line - Current instruction - * pc_stk* stk - Address stack */ typedef struct pc_t { - bc_cont* root; - bc_cont* line; - pc_stk* stk; + size_t size; + pc_addr address; + bc_cont* line; + pc_addr_stk* stk; + bc_cont** heap; } pc_t; /* Initalizes program counter, returns pc_t* instance * char* - filename of file containing bytecode */ pc_t* pc_new(char*); -pc_stk* pc_stk_new(ns_addr); + +void pc_read(char*, pc_t*); + +pc_addr_stk* pc_addr_stk_new(ns_addr); /* Frees memory assosiated with pc_t* instance */ void pc_del(pc_t*); -void pc_stk_del(pc_stk*); +void pc_addr_stk_del(pc_addr_stk*); + +/* Pushes instruction to heap + */ +void pc_push(pc_t*, bc_cont*); -/* Updates program counter on changes +/* Updates program counter on changes in address */ void pc_update(pc_t*); diff --git a/src/vm/inc/stk.h b/src/vm/inc/stk.h @@ -4,37 +4,63 @@ #ifndef STK_H #define STK_H +#define STACK_SIZE_LIMIT 0xFFFF +#define STACK_INIT_SIZE 0xFF + #include <stdlib.h> #include <stdio.h> #include "var.h" #include "helper.h" +typedef struct stk_line { + int ptr; + size_t size; + var_cont** data; +} stk_line; + typedef struct stk_t { struct stk_t* next; - var_cont* data; + stk_line* stack; } stk_t; /* Create a new stack instance */ stk_t* stk_new(void); +stk_line* stk_line_new(size_t); /* Delete a stack */ void stk_del(stk_t*); +void stk_line_del(stk_line*); + +/* Pushes new stack level + */ +void stk_newlevel(stk_t**); + +/* Pops a stack level + */ +int stk_poplevel(stk_t**); + +/* Scales the stack by n^2 + * stk_t* - stack instance + */ +void stk_scale(stk_line*); /* Pop the first element of the stack - * - * @param stk_t* - * stack instance pointer + * stk_t* - stack instance */ -var_cont* stk_pop(stk_t**); +var_cont* stk_pop(stk_t*); -/* Pushes @param var_cont* to the stack +/* Pushes var_cont* to the stack + * stk_t* - stack instance + * var_cont* - variable instance */ -void stk_push(stk_t**, var_cont*); +void stk_push(stk_t*, var_cont*); /* Returns the data at location in the stack + * stk_line* - Stack line instance + * int - integer < (STK_SIZE_LIMIT - stk_line->ptr) */ var_cont* stk_at(stk_t*, int); @@ -42,12 +68,12 @@ var_cont* stk_at(stk_t*, int); * i.e. [4, 3, 2, 1] -> [3, 4, 2, 1] * ^ rot_top() */ -void stk_rot_top(stk_t**); +void stk_rot_top(stk_t*); /* Rotates the top three elements of the stack * i.e. [4, 3, 2, 1] -> [2, 3, 4, 1] * ^ rot_three() */ -void stk_rot_three(stk_t**); +void stk_rot_three(stk_t*); #endif // STK_H diff --git a/src/vm/inc/var.h b/src/vm/inc/var.h @@ -13,6 +13,12 @@ typedef unsigned int bc_addr; typedef unsigned int ns_addr; typedef enum { + NAMESPACE, + CONSTANT, + TEMPORARY +} var_state; + +typedef enum { VOID, // 0 ADDR, // 1 TYPE, // 2 @@ -30,6 +36,7 @@ typedef enum { } b_type; typedef struct var_cont { + var_state state; b_type type; void* data; } var_cont; @@ -47,6 +54,7 @@ typedef struct var_data_func { bc_addr end; b_type type; ns_addr size; + size_t paramlen; b_type* param; } var_data_func; @@ -76,7 +84,7 @@ typedef struct var_data_array { /* Initialze variable with type */ -var_cont* var_new(b_type); +var_cont* var_new(var_state, b_type); void* var_data_alloc_TYPE(b_type); void* var_data_alloc_PLIST(size_t); diff --git a/src/vm/src/bc.c b/src/vm/src/bc.c @@ -27,31 +27,11 @@ bc_cont* bc_cont_new(void) new->sarg[1] = 0; new->sarg[2] = 0; - new->next = NULL; - new->prev = NULL; - return new; } -/* Pushes new bc_cont to the chain. - * bc_cont* - bytecode container - * - * -> bc_cont* - push new bytecode container on chain - */ -void bc_cont_push(bc_cont** head) -{ - (*head)->next = bc_cont_new(); - (*head)->next->prev = *head; - *head = (*head)->next; -} - void bc_cont_del(bc_cont* root) { - if (root->next != NULL) - { - bc_cont_del(root->next); - } - if (root != NULL) { if (root->args[0] != NULL) free(root->args[0]); @@ -160,71 +140,36 @@ void process_args(bc_cont* ins) } } } - -/* Scan to +/- int in bytecode chain - * bc_cont* - bytecode container [0] - * int - +/- up/down [1] - * - * -> bc_cont* - Bytecode @param[0]'s location +/- @param[1] - */ -bc_cont* bc_scan(bc_cont* ptr, int scanto) -{ - while (scanto != 0) - { - if (scanto > 0 && ptr->next != NULL) - { - ptr = ptr->next; - scanto--; - } else - if (scanto < 0 && ptr->prev != NULL) - { - ptr = ptr->prev; - scanto++; - } else - if (ptr->next == NULL || ptr->prev == NULL) - { - scanto = 0; - } - } - - return ptr; -} - -/* Initiates the first pass to take a raw binary file and translate it into a - * basic datastructure +/* Gets bytecode size + * char* - filename */ -bc_cont* bc_read(char* fname) +size_t bc_getsize(char* fname) { - FILE* f; + FILE* f; + size_t rv = 0; + size_t fsize; byte_t byte; - long fsize; - + bc_cont* ptr; + f = fopen(fname, "rb"); fsize = read_size(f); - - bc_cont *root = bc_cont_new(); - bc_cont *ptr = root; - bc_addr addr = 0; - /* Loop through file byte-by-byte */ - while (ftell(f)<fsize) + while (ftell(f) < fsize) { + ptr = bc_cont_new(); + byte = read_byte(f); get_opcode(byte, ptr); get_args(f, ptr); - process_args(ptr); - - ptr->real_addr = addr; - - bc_cont_push(&ptr); + bc_cont_del(ptr); - addr++; + rv++; } fclose(f); - return root; + return rv; } diff --git a/src/vm/src/ht.c b/src/vm/src/ht.c @@ -1,161 +0,0 @@ -#define _XOPEN_SOURCE 500 - -#include <stdio.h> -#include <stdlib.h> -#include <limits.h> -#include <string.h> - -#include "ht.h" -#include "var.h" -#include "helper.h" - -ht_t* ht_init(int size) -{ - ASSERT((size % 2) == 0, "Hashtable size must be powers of 2\n"); - - ht_t* hashtable = (ht_t*)malloc(sizeof(ht_t)); - M_ASSERT(hashtable); - - hashtable->size = size; - hashtable->table = ht_init_table(hashtable->size); - - return hashtable; -} - -ht_entry** ht_init_table(int size) -{ - ASSERT((size % 2 ) == 0, "hashtable size must be powers of 2\n"); - - ht_entry** table = (ht_entry**)malloc(sizeof(ht_entry*)*size); - M_ASSERT(table); - - for (int i = 0; i < size; i++) - { - table[i] = NULL; - } - - return table; -} - -void ht_destroy(ht_t* hashtable) -{ - ht_destroy_table(hashtable->table, hashtable->size); -} - -void ht_destroy_table(ht_entry** table, int size) -{ - for (int i = 0; i < size; i++) - { - if (table[i] != NULL){ - ht_destroy_entry(table[i]); - } - } -} - -void ht_destroy_entry(ht_entry* entry) -{ - var_del(entry->value); - - if (entry->key != NULL) - free(entry->key); - - if (entry->next != NULL) - ht_destroy_entry(entry->next); - - free(entry); -} - -void ht_set(ht_t* hashtable, char* key, var_cont* value) -{ - int bucket = 0; - ht_entry* np = NULL; - ht_entry* next = NULL; - ht_entry* last = NULL; - - bucket = ht_hash(hashtable, key); - - next = hashtable->table[ bucket ]; - - /* Get relavent key/value pair if it exists in the bucket */ - while (next != NULL && next->key != NULL && strcmp(key, next->key) > 0) - { - last = next; - next = next->next; - } - - if (next != NULL && next->key != NULL && strcmp(key, next->key) == 0) - { - var_del(next->value); - next->value = value; - } - else - { - np = ht_newpair(key, value); - - if (next == hashtable->table[bucket]) - { - np->next = next; - hashtable->table[bucket] = np; - } - else if (next == NULL) - { - last->next = np; - } - else - { - np->next = next; - last->next = np; - } - } -} - -var_cont* ht_get(ht_t* hashtable, char* key) -{ - int bucket = ht_hash(hashtable, key); - - ht_entry* pair = hashtable->table[bucket]; - while (pair != NULL && pair->key != NULL && strcmp(key, pair->key) > 0) - { - pair = pair->next; - } - - if (pair == NULL || pair->key == NULL || strcmp(key, pair->key) != 0) - { - return var_new(0); - } - else - { - return pair->value; - } -} - -ht_entry* ht_newpair(char* key, var_cont* value) -{ - ht_entry* newpair; - - newpair = malloc(sizeof(ht_entry)); - M_ASSERT(newpair); - - newpair->key = (char*)strdup(key); - M_ASSERT(newpair->key); - - newpair->value = value; - - return newpair; -} - -int ht_hash(ht_t* hashtable, char* key) -{ - unsigned long int hashval; - int i = 0; - - /* Convert our string to an integer */ - while (hashval < ULONG_MAX && i < strlen(key)) - { - hashval = hashval << 8; - hashval += key[ i ]; - i++; - } - - return hashval % hashtable->size; -} diff --git a/src/vm/src/ins_def.c b/src/vm/src/ins_def.c @@ -100,7 +100,7 @@ void _ins_def_NULL (rt_t* ctx, bc_cont* line) } void _ins_def_PRINT (rt_t* ctx, bc_cont* line) { - var_cont* var = stk_pop(&ctx->stack); + var_cont* var = stk_pop(ctx->stack); if (var->type == G_STR) { @@ -128,7 +128,7 @@ void _ins_def_ARGB (rt_t* ctx, bc_cont* line) { var_cont* var = stk_at(ctx->stack, 0); - stk_push(&ctx->argstk, var); + stk_push(ctx->argstk, var); pc_inc(ctx->pc, 1); } void _ins_def_LIBC (rt_t* ctx, bc_cont* line) @@ -144,14 +144,14 @@ void _ins_def_POP (rt_t* ctx, bc_cont* line) while (n > i) { i++; - stk_pop(&ctx->stack); + stk_pop(ctx->stack); } pc_inc(ctx->pc, 1); } void _ins_def_ROT (rt_t* ctx, bc_cont* line) { - stk_rot_top(&ctx->stack); + stk_rot_top(ctx->stack); pc_inc(ctx->pc, 1); } @@ -159,12 +159,12 @@ void _ins_def_DUP (rt_t* ctx, bc_cont* line) { var_cont* var = stk_at(ctx->stack, 0); var_cont* dup = var_data_cpy(var); - stk_push(&ctx->stack, dup); + stk_push(ctx->stack, dup); pc_inc(ctx->pc, 1); } void _ins_def_ROT_THREE(rt_t* ctx, bc_cont* line) { - stk_rot_three(&ctx->stack); + stk_rot_three(ctx->stack); pc_inc(ctx->pc, 1); } @@ -187,7 +187,7 @@ void _ins_def_LOV (rt_t* ctx, bc_cont* line) var = proc_getvar(ctx, scope, name); - stk_push(&ctx->stack, var); + stk_push(ctx->stack, var); pc_inc(ctx->pc, 1); } @@ -196,7 +196,7 @@ void _ins_def_STV (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]); - var_cont* var = stk_pop(&ctx->stack); + var_cont* var = stk_pop(ctx->stack); proc_setvar(ctx, scope, name, var); @@ -214,20 +214,20 @@ void _ins_def_CTV (rt_t* ctx, bc_cont* line) } void _ins_def_CTS (rt_t* ctx, bc_cont* line) { - stk_push(&ctx->stack, line->varg[0]); + stk_push(ctx->stack, line->varg[0]); pc_inc(ctx->pc, 1); } void _ins_def_TYPEOF (rt_t* ctx, bc_cont* line) { var_cont* var = stk_at(ctx->stack, 0); - var_cont* new = var_new(TYPE); + var_cont* new = var_new(TYPE, TEMPORARY); var_data_type* data = var_data_alloc_TYPE(var->type); var_set(new, data, TYPE); - stk_push(&ctx->stack, new); + stk_push(ctx->stack, new); pc_inc(ctx->pc, 1); } @@ -238,45 +238,45 @@ void _ins_def_CAST (rt_t* ctx, bc_cont* line) void _ins_def_ADD (rt_t* ctx, bc_cont* line) { - var_cont* A = stk_pop(&ctx->stack); - var_cont* B = stk_pop(&ctx->stack); + var_cont* A = stk_pop(ctx->stack); + var_cont* B = stk_pop(ctx->stack); var_cont* var = var_add(A, B); - stk_push(&ctx->stack, var); + stk_push(ctx->stack, var); pc_inc(ctx->pc, 1); } void _ins_def_SUB (rt_t* ctx, bc_cont* line) { - var_cont* A = stk_pop(&ctx->stack); - var_cont* B = stk_pop(&ctx->stack); + var_cont* A = stk_pop(ctx->stack); + var_cont* B = stk_pop(ctx->stack); var_cont* var = var_sub(A, B); - stk_push(&ctx->stack, var); + stk_push(ctx->stack, var); pc_inc(ctx->pc, 1); } void _ins_def_MULT (rt_t* ctx, bc_cont* line) { - var_cont* A = stk_pop(&ctx->stack); - var_cont* B = stk_pop(&ctx->stack); + var_cont* A = stk_pop(ctx->stack); + var_cont* B = stk_pop(ctx->stack); var_cont* var = var_mult(A, B); - stk_push(&ctx->stack, var); + stk_push(ctx->stack, var); pc_inc(ctx->pc, 1); } void _ins_def_DIV (rt_t* ctx, bc_cont* line) { - var_cont* A = stk_pop(&ctx->stack); - var_cont* B = stk_pop(&ctx->stack); + var_cont* A = stk_pop(ctx->stack); + var_cont* B = stk_pop(ctx->stack); var_cont* var = var_mult(A, B); - stk_push(&ctx->stack, var); + stk_push(ctx->stack, var); pc_inc(ctx->pc, 1); } @@ -331,34 +331,34 @@ void _ins_def_BNAND (rt_t* ctx, bc_cont* line) void _ins_def_GTHAN (rt_t* ctx, bc_cont* line) { - var_cont* A = stk_pop(&ctx->stack); - var_cont* B = stk_pop(&ctx->stack); + var_cont* A = stk_pop(ctx->stack); + var_cont* B = stk_pop(ctx->stack); var_cont* C = var_gthan(A, B); - stk_push(&ctx->stack, C); + stk_push(ctx->stack, C); pc_inc(ctx->pc, 1); } void _ins_def_LTHAN (rt_t* ctx, bc_cont* line) { - var_cont* A = stk_pop(&ctx->stack); - var_cont* B = stk_pop(&ctx->stack); + var_cont* A = stk_pop(ctx->stack); + var_cont* B = stk_pop(ctx->stack); var_cont* C = var_lthan(A, B); - stk_push(&ctx->stack, C); + stk_push(ctx->stack, C); pc_inc(ctx->pc, 1); } void _ins_def_EQ (rt_t* ctx, bc_cont* line) { - var_cont* A = stk_pop(&ctx->stack); - var_cont* B = stk_pop(&ctx->stack); + var_cont* A = stk_pop(ctx->stack); + var_cont* B = stk_pop(ctx->stack); var_cont* C = var_eq(A, B); - stk_push(&ctx->stack, C); + stk_push(ctx->stack, C); pc_inc(ctx->pc, 1); } @@ -377,12 +377,12 @@ void _ins_def_AND (rt_t* ctx, bc_cont* line) void _ins_def_STARTL (rt_t* ctx, bc_cont* line) { - pc_branch(ctx->pc, ctx->pc->stk->address); + pc_branch(ctx->pc, ctx->pc->address); pc_inc(ctx->pc, 1); } void _ins_def_CLOOP (rt_t* ctx, bc_cont* line) { - var_cont* var = stk_pop(&ctx->stack); + var_cont* var = stk_pop(ctx->stack); int value = var_data_get_G_INT(var); @@ -423,7 +423,7 @@ void _ins_def_JUMPF (rt_t* ctx, bc_cont* line) } void _ins_def_IFDO (rt_t* ctx, bc_cont* line) { - var_cont* var = stk_pop(&ctx->stack); + var_cont* var = stk_pop(ctx->stack); int value = var_data_get_G_INT(var); @@ -451,7 +451,23 @@ void _ins_def_DONE (rt_t* ctx, bc_cont* line) } void _ins_def_CALL (rt_t* ctx, bc_cont* line) { - pc_inc(ctx->pc, 1); + 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); + + 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); + } + + pc_branch(ctx->pc, func->loc); } void _ins_def_PUSH (rt_t* ctx, bc_cont* line) @@ -492,6 +508,7 @@ void _ins_def_DEFUN (rt_t* ctx, bc_cont* line) int name = var_data_get_G_INT(line->varg[0]); b_type type = var_data_get_TYPE(line->varg[1]); b_type* args = var_data_get_PLIST(line->varg[2]); + size_t alen = line->sarg[2]; var_data_func* data = var_data_alloc_FUNC(type); @@ -511,10 +528,12 @@ void _ins_def_DEFUN (rt_t* ctx, bc_cont* line) nsize++; } } - - data->size = nsize; - data->type = type; - data->param = args; + + data->end = ctx->pc->line->real_addr; + data->size = nsize; + data->type = type; + data->paramlen = alen; + data->param = args; proc_decvar(ctx, 1, name, FUNC); diff --git a/src/vm/src/is.c b/src/vm/src/is.c @@ -1,10 +1,9 @@ #include <stdlib.h> -#include "bc.h" #include "is.h" -#include "ins_mdata.h" #include "fh.h" +#include "bc.h" #include "ins_mdata.h" diff --git a/src/vm/src/main.c b/src/vm/src/main.c @@ -10,7 +10,7 @@ int main(int argc, char** argv) { ASSERT(argc > 1, "C'mon, man! Gimme some args\n"); - init_mdata(); // Initalize the instruction definitions + init_mdata(); // Initalize the instruction defs init_adata(); init_ins_def(); @@ -18,7 +18,7 @@ int main(int argc, char** argv) proc_run(runtime); // Execute runtime - proc_clean(runtime); // Once `proc_run` returns, try to clean + proc_clean(runtime); // Once `proc_run` returns, clean // what sort of mess it made. return 0; diff --git a/src/vm/src/ns.c b/src/vm/src/ns.c @@ -140,7 +140,7 @@ void ns_cont_dec(ns_cont* ns, b_type type, ns_addr address) SIZE_ASSERT( ns->size > address ); - ns->names[ address ] = var_new(type); + ns->names[ address ] = var_new(NAMESPACE, type); } /* Sets variable to value, at root or last namespace diff --git a/src/vm/src/pc.c b/src/vm/src/pc.c @@ -3,9 +3,9 @@ #include "pc.h" -#include "bc.h" #include "is.h" #include "fh.h" +#include "bc.h" #include "helper.h" /* Initalizes program counter, returns pc_t* instance @@ -18,25 +18,67 @@ pc_t* pc_new(char* fname) pc_t* pc = (pc_t*)malloc(sizeof(pc_t)); M_ASSERT(pc); - pc->stk = pc_stk_new(0); + pc->stk = pc_addr_stk_new(0); - pc->root = bc_read(fname); + pc->size = bc_getsize(fname); - pc->line = pc->root; + pc->heap = (bc_cont**)malloc(sizeof(bc_cont*)*pc->size); - pc->stk->address = pc->root->real_addr; + pc_read(fname, pc); + + pc_update(pc); return pc; } -pc_stk* pc_stk_new(ns_addr address) +/* Initiates the first pass to take a raw binary file and translate it into a + * basic datastructure + */ +void pc_read(char* fname, pc_t* program) +{ + FILE* f; + byte_t byte; + long fsize; + + f = fopen(fname, "rb"); + fsize = read_size(f); + + bc_cont* ptr; + bc_addr addr = 0; + + /* Loop through file byte-by-byte */ + while (ftell(f) < fsize) + { + ptr = bc_cont_new(); + + byte = read_byte(f); + + get_opcode(byte, ptr); + + get_args(f, ptr); + + process_args(ptr); + + ptr->real_addr = addr; + + pc_push(program, ptr); + + addr++; + } + + fclose(f); +} + +pc_addr_stk* pc_addr_stk_new(ns_addr address) { - pc_stk* new = (pc_stk*)malloc(sizeof(pc_stk)); + pc_addr_stk* new = (pc_addr_stk*)malloc(sizeof(pc_addr_stk)); M_ASSERT(new); - new->address = address; + new->addresses = (pc_addr*)malloc(sizeof(pc_addr)*PC_RETURN_DEPTH); + M_ASSERT(new->addresses); - new->next = NULL; + new->ptr = 0; + new->size = PC_RETURN_DEPTH; return new; } @@ -47,32 +89,30 @@ void pc_del(pc_t* pc) { N_ASSERT(pc, "pc_del\n"); N_ASSERT(pc->stk, "pc_del\n"); - N_ASSERT(pc->root, "pc_del\n"); - - bc_cont_del(pc->root); - - pc_stk_del(pc->stk); - +// gotta actually handle this realquick free(pc); } -void pc_stk_del(pc_stk* stk) +void pc_addr_stk_del(pc_addr_stk* stk) { - N_ASSERT(stk, "pc_stk_del\n"); - - if (stk->next != NULL) - { - pc_stk_del(stk->next); - } + N_ASSERT(stk, "pc_addr_stk_del\n"); +// and this +} - free(stk); +void pc_push(pc_t* pc, bc_cont* bytecode) +{ + N_ASSERT(pc, "pc_push\n"); } -/* Updates program counter on changes + +/* Updates currently reading line + * + * When called, pc_t->line will reflect pc_t->heap[pc_t->address] */ void pc_update(pc_t* pc) { N_ASSERT(pc, "pc_update\n"); - pc->line = bc_scan(pc->line, (pc->stk->address - pc->line->real_addr) ); + + pc->line = pc->heap[pc->address]; } /* Increment program counter by +-addr @@ -81,7 +121,7 @@ void pc_inc(pc_t* pc, pc_addr addr) { N_ASSERT(pc, "pc_inc\n"); - pc->stk->address = pc->stk->address + addr; + pc->address = pc->address + addr; } /* Branch to addr @@ -90,11 +130,7 @@ void pc_branch(pc_t* pc, pc_addr address) { N_ASSERT(pc, "pc_branch\n"); - pc_stk* new = pc_stk_new(address); - - new->next = pc->stk; - - pc->stk = new; + pc->address = address; } /* Return from branch @@ -102,11 +138,6 @@ void pc_branch(pc_t* pc, pc_addr address) void pc_return(pc_t* pc) { N_ASSERT(pc, "pc_return\n"); - - pc_stk* tmp = pc->stk; - pc->stk = pc->stk->next; - - free(tmp); } /* For now, a simple function that returns true if the next instruction is not @@ -114,6 +145,6 @@ void pc_return(pc_t* pc) */ int pc_safe(pc_t* pc) { - return (pc->line->next != NULL); + return 0; } diff --git a/src/vm/src/stk.c b/src/vm/src/stk.c @@ -10,81 +10,158 @@ stk_t* stk_new( void ) stk_t* new = (stk_t*)malloc(sizeof(stk_t)); M_ASSERT(new); - new->data = var_new(VOID); - new->next = NULL; + new->stack = stk_line_new(STACK_INIT_SIZE); + new->next = NULL; return new; } -void stk_del(stk_t* root) +stk_line* stk_line_new(size_t size) { - //N_ASSERT(root); + ASSERT(size > 1, "stk_line_new\n"); - var_cont* data; + stk_line* new = (stk_line*)malloc(sizeof(stk_line)); + M_ASSERT(new); + + new->data = (var_cont**)malloc(sizeof(var_cont*)*size); + M_ASSERT(new); - while ((data = stk_pop(&root)) != NULL) + int i; + for (i = 0; i < size; i++) { - if (data != NULL) + new->data[i] = NULL; + } + + new->size = size; + new->ptr = 0; + + return new; +} + +void stk_del(stk_t* stack) +{ + N_ASSERT(stack, "stk_del"); + + while (stk_poplevel(&stack)) + { + if (stack->stack != NULL) { - var_del(data); + stk_line_del(stack->stack); } } + free(stack); +} + +void stk_line_del(stk_line* stack) +{ + N_ASSERT(stack, "stk_line_del\n"); - var_del(root->data); + int i; + for (i = 0; i < stack->size; i++) + { + if (stack->data[i] != NULL) + { + if (stack->data[i]->state == TEMPORARY) + var_del(stack->data[i]); + } + } - free(root); + free(stack->data); + free(stack); } -var_cont* stk_pop(stk_t** root) + +/* Pushes a new stack level + * stk_t** - stack instances + */ +void stk_newlevel(stk_t** stack) { - if ((*root)->next == NULL) - return NULL; + N_ASSERT(stack, "stk_newlevel\n"); + +} - stk_t* new = (*root)->next; - var_cont* data = (*root)->data; +/* 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) +{ + N_ASSERT(stack, "stk_poplevel\n"); + return 0; +} - free(*root); +/* Scales the stack by n^2 + * stk_t* - stack instance + */ +void stk_scale(stk_line* stack) +{ + N_ASSERT(stack, "stk_scale\n"); - *root = new; + size_t newsize = stack->size * stack->size; - return data; + stack->data = realloc(stack->data, sizeof(var_cont*) * newsize); } -void stk_push(stk_t** root, var_cont* data) +/* Pop the first element of the stack + * stk_t* - stack instance + */ +var_cont* stk_pop(stk_t* stack) { - stk_t* new = stk_new(); - new->data = data; - new->next = *root; - *root = new; + N_ASSERT(stack, "stk_pop\n"); + + ASSERT(((stack->stack->ptr - 1) > 1), "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"); + + return stack->stack->data[stack->stack->ptr]; } -var_cont* stk_at(stk_t* root, int n) +/* Pushes var_cont* to the stack + * stk_t* - stack instance + * var_cont* - variable instance + */ +void stk_push(stk_t* stack, var_cont* data) { - n--; - if (n >= 0) - { - return stk_at(root->next, n); - } - else + N_ASSERT(stack, "stk_push\n"); + N_ASSERT(data, "stk_push\n"); + + if ((stack->stack->ptr + 1) < stack->stack->size) { - return root->data; + stk_scale(stack->stack); } + + stack->stack->ptr = stack->stack->ptr + 1; + + stack->stack->data[stack->stack->ptr] = data; +} + +var_cont* stk_at(stk_t* stack, int n) +{ + ASSERT(((stack->stack->ptr + n) < stack->stack->size), "Out of Bounds\n"); + + var_cont* rv = stack->stack->data[stack->stack->ptr + n]; + + return rv; } -void stk_rot_top(stk_t** root) +/* Rotates the top two elements of the stack + * i.e. [4, 3, 2, 1] -> [3, 4, 2, 1] + * ^ rot_top() + */ +void stk_rot_top(stk_t* stack) { - stk_t* tmp = (*root)->next; - (*root)->next = tmp->next; - tmp->next = *root; - *root = tmp; + N_ASSERT(stack, "stk_rot_top\n"); } -void stk_rot_three(stk_t** root) +/* Rotates the top three elements of the stack + * i.e. [4, 3, 2, 1] -> [2, 3, 4, 1] + * ^ rot_three() + */ +void stk_rot_three(stk_t* stack) { - stk_t* tmp2 = (*root)->next->next; - stk_t* tmp1 = (*root)->next; - (*root)->next = tmp2->next; - tmp2->next = tmp1; - tmp1->next = *root; - *root = tmp2; + N_ASSERT(stack, "stk_rot_three\n"); } diff --git a/src/vm/src/var.c b/src/vm/src/var.c @@ -81,13 +81,15 @@ void* var_data_alloc_G_STR(size_t size) return rv; } -var_cont* var_new(b_type type) +var_cont* var_new(var_state state, b_type type) { var_cont* new = (var_cont*)malloc(sizeof(var_cont)); M_ASSERT(new); new->type = type; + new->state = state; + new->data = NULL; return new; @@ -282,7 +284,7 @@ var_cont* var_data_cpy(var_cont* var) { N_ASSERT(var, "var_data_cpy\n"); - var_cont* rv = var_new(var->type); + var_cont* rv = var_new(var->state, var->type); if (var->type == G_INT) { @@ -315,7 +317,7 @@ var_cont* var_data_cpy(var_cont* var) */ var_cont* raw_to_int(int size, int start, byte_t* bytes) { - var_cont* rv = var_new(G_INT); + var_cont* rv = var_new(CONSTANT, G_INT); int i, data; @@ -335,7 +337,7 @@ var_cont* raw_to_int(int size, int start, byte_t* bytes) */ var_cont* byte_to_type(byte_t byte) { - var_cont* rv = var_new(TYPE); + var_cont* rv = var_new(CONSTANT, TYPE); var_set(rv, var_data_alloc_TYPE((b_type)byte), TYPE); @@ -349,7 +351,7 @@ var_cont* byte_to_type(byte_t byte) */ var_cont* raw_to_plist(int n, byte_t* bytes) { - var_cont* rv = var_new(PLIST); + var_cont* rv = var_new(CONSTANT, PLIST); var_set(rv, var_data_alloc_PLIST(n), PLIST); @@ -372,7 +374,7 @@ var_cont* raw_to_plist(int n, byte_t* bytes) */ var_cont* raw_to_str(int n, int offset, byte_t* bytes) { - var_cont* rv = var_new(G_STR); + var_cont* rv = var_new(CONSTANT, G_STR); var_data_str* data = var_data_alloc_G_STR(n); int i; for (i = offset; n > i; i++) diff --git a/src/vm/src/var_ops.c b/src/vm/src/var_ops.c @@ -8,7 +8,7 @@ var_cont* var_add_float(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_FLOAT); + var_cont* var = var_new(NAMESPACE, G_FLOAT); double AV = var_data_get_G_FLOAT(A); double BV = var_data_get_G_FLOAT(B); @@ -22,7 +22,7 @@ var_cont* var_add_float(var_cont* A, var_cont* B) } var_cont* var_add_int(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_INT); + var_cont* var = var_new(NAMESPACE, G_INT); int AV = var_data_get_G_INT(A); int BV = var_data_get_G_INT(B); @@ -55,7 +55,7 @@ var_cont* var_add(var_cont* A, var_cont* B) var_cont* var_sub_float(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_FLOAT); + var_cont* var = var_new(NAMESPACE, G_FLOAT); double AV = var_data_get_G_FLOAT(A); double BV = var_data_get_G_FLOAT(B); @@ -69,7 +69,7 @@ var_cont* var_sub_float(var_cont* A, var_cont* B) } var_cont* var_sub_int(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_INT); + var_cont* var = var_new(NAMESPACE, G_INT); int AV = var_data_get_G_INT(A); int BV = var_data_get_G_INT(B); @@ -102,7 +102,7 @@ var_cont* var_sub(var_cont* A, var_cont* B) var_cont* var_mult_float(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_FLOAT); + var_cont* var = var_new(NAMESPACE, G_FLOAT); double AV = var_data_get_G_FLOAT(A); double BV = var_data_get_G_FLOAT(B); @@ -116,7 +116,7 @@ var_cont* var_mult_float(var_cont* A, var_cont* B) } var_cont* var_mult_int(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_INT); + var_cont* var = var_new(NAMESPACE, G_INT); int AV = var_data_get_G_INT(A); int BV = var_data_get_G_INT(B); @@ -149,7 +149,7 @@ var_cont* var_mult(var_cont* A, var_cont* B) var_cont* var_div_float(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_FLOAT); + var_cont* var = var_new(NAMESPACE, G_FLOAT); double AV = var_data_get_G_FLOAT(A); double BV = var_data_get_G_FLOAT(B); @@ -163,7 +163,7 @@ var_cont* var_div_float(var_cont* A, var_cont* B) } var_cont* var_div_int(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_INT); + var_cont* var = var_new(NAMESPACE, G_INT); int AV = var_data_get_G_INT(A); int BV = var_data_get_G_INT(B); @@ -196,7 +196,7 @@ var_cont* var_div(var_cont* A, var_cont* B) var_cont* var_gthan_float(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_INT); + var_cont* var = var_new(NAMESPACE, G_INT); double AV = var_data_get_G_FLOAT(A); double BV = var_data_get_G_FLOAT(B); @@ -210,7 +210,7 @@ var_cont* var_gthan_float(var_cont* A, var_cont* B) } var_cont* var_gthan_int(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_INT); + var_cont* var = var_new(NAMESPACE, G_INT); int AV = var_data_get_G_INT(A); int BV = var_data_get_G_INT(B); @@ -244,7 +244,7 @@ var_cont* var_gthan(var_cont* A, var_cont* B) var_cont* var_lthan_float(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_INT); + var_cont* var = var_new(NAMESPACE, G_INT); double AV = var_data_get_G_FLOAT(A); double BV = var_data_get_G_FLOAT(B); @@ -258,7 +258,7 @@ var_cont* var_lthan_float(var_cont* A, var_cont* B) } var_cont* var_lthan_int(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_INT); + var_cont* var = var_new(NAMESPACE, G_INT); int AV = var_data_get_G_INT(A); int BV = var_data_get_G_INT(B); @@ -291,7 +291,7 @@ var_cont* var_lthan(var_cont* A, var_cont* B) var_cont* var_eq_float(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_INT); + var_cont* var = var_new(NAMESPACE, G_INT); double AV = var_data_get_G_FLOAT(A); double BV = var_data_get_G_FLOAT(B); @@ -305,7 +305,7 @@ var_cont* var_eq_float(var_cont* A, var_cont* B) } var_cont* var_eq_int(var_cont* A, var_cont* B) { - var_cont* var = var_new(G_INT); + var_cont* var = var_new(NAMESPACE, G_INT); int AV = var_data_get_G_INT(A); int BV = var_data_get_G_INT(B); diff --git a/src/vm/tests/bytecodes/looptest b/src/vm/tests/bytecodes/looptest Binary files differ diff --git a/src/vm/tests/bytecodes/testing b/src/vm/tests/bytecodes/testing Binary files differ