language

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

commit 96353f2df124558ab919e495af73436f3ef2ce3c
parent 6720d6ea90c80e4f32c7356251be8985e3266a9b
Author: Paul Longtine <paullongtine@gmail.com>
Date:   Sat Jan 23 21:56:20 2016

More implementation of var.h and ns.h

Diffstat:
 doc/SPECIFICATION                |  29 ++++++-
 src/vm/inc/helper.h              |  20 +++++-
 src/vm/inc/ns.h                  |  26 ++++--
 src/vm/inc/var.h                 |  39 ++++++++-
 src/vm/src/ns.c                  |  79 ++++++++++++------
 src/vm/src/var.c                 | 176 +++++++++++++++++++++++++++++++++++++++-
 src/vm/tests/bc/test             | Bin 0 -> 11264 bytes
 src/vm/tests/ns/expected_output  |   3 +-
 src/vm/tests/ns/test.c           |  18 ++++-
 src/vm/tests/stk/expected_output |   8 +-
 src/vm/tests/stk/test            | Bin 0 -> 11520 bytes
 src/vm/tests/stk/test.c          |  13 +--
 src/vm/tests/var/Makefile        |  24 +++++-
 src/vm/tests/var/expected_output |   2 +-
 src/vm/tests/var/test.c          |  24 +++++-
 15 files changed, 413 insertions(+), 48 deletions(-)

diff --git a/doc/SPECIFICATION b/doc/SPECIFICATION @@ -18,7 +18,34 @@ are deemed inferior. * float * character * boolean - Will be elaborated on as thoughts progress. + +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. RUNTIME diff --git a/src/vm/inc/helper.h b/src/vm/inc/helper.h @@ -11,4 +11,24 @@ exit(1); \ } +#define SIZE_ASSERT(condition) \ + if (!(condition)) \ + { \ + fprintf(stderr, "address exeeded namespace limit\n"); \ + exit(1); \ + } + +#define M_ASSERT(x) \ + if (x == NULL) \ + { \ + fprintf(stderr, "Could not allocate memory\n");\ + } + +#define N_ASSERT(x) \ + if (x == NULL) \ + { \ + fprintf(stderr, "Null Exception\n");\ + exit(1); \ + } \ + #endif // HELPER_H diff --git a/src/vm/inc/ns.h b/src/vm/inc/ns.h @@ -9,8 +9,10 @@ #include "var.h" #include "helper.h" +typedef int ns_addr; + typedef struct ns_cont { - int size; + ns_addr size; var_cont** names; struct ns_cont* next; } ns_cont; @@ -20,18 +22,18 @@ typedef struct ns_t { ns_cont* last; } ns_t; +ns_cont* ns_cont_init(ns_addr); + /* Initializes namespace of size */ -ns_t* ns_init(int); +ns_t* ns_init(ns_addr); -ns_cont* ns_cont_init(int); +void ns_cont_del(ns_cont*); /* Cleans up memory */ void ns_del(ns_t*); -void ns_cont_del(ns_cont*); - /* Pushes namespace of size */ void ns_push(ns_t*, int); @@ -40,12 +42,22 @@ void ns_push(ns_t*, int); */ void ns_pop(ns_t*); +void ns_cont_dec(ns_cont*, b_type, ns_addr); + /* Declares a variable, at root or last namespace */ -void ns_dec(ns_t*, b_type, int, int); +void ns_dec(ns_t*, b_type, int, ns_addr); + +void ns_cont_set(ns_cont*, var_cont*, ns_addr); /* Sets variable to value, at root or last namespace */ -void ns_set(ns_t*, int, int, var_cont*); +void ns_set(ns_t*, int, ns_addr, var_cont*); + +var_cont* ns_cont_get(ns_cont*, ns_addr); + +/* Gets variable from address + */ +var_cont* ns_get(ns_t*, int, ns_addr); #endif // NS_H diff --git a/src/vm/inc/var.h b/src/vm/inc/var.h @@ -14,7 +14,9 @@ typedef enum { G_INT, G_FLOAT, G_CHAR, - G_STRING, + U_CHAR, + G_STR, + U_STR, S_ARRAY, D_ARRAY, K_ARRAY, @@ -23,25 +25,54 @@ typedef enum { typedef struct var_cont { b_type type; - void* data; + void** data; } var_cont; typedef void var_data_void; typedef int var_data_int; -typedef char var_data_char; +typedef double var_data_float; +typedef char var_data_char; +/* +typedef char var_data_u_char; +*/ typedef struct var_data_str { - char* str; + var_data_char* str; } var_data_str; +/* +typedef struct var_data_u_str { + var_data_u_char* str; +} var_data_u_str; +*/ + +void** var_data_alloc_G_INT(var_data_int); +void** var_data_alloc_G_FLOAT(var_data_float); +void** var_data_alloc_G_CHAR(var_data_char); +void** var_data_alloc_G_STR(size_t); + +void** var_data_alloc(b_type); /* Initialze variable with type */ var_cont* var_new(b_type); +void var_data_free(void**, b_type); + /* Frees variable */ void var_del(var_cont*); +void var_set(var_cont*, void**, b_type); + +var_cont* var_cast_data(var_cont*, b_type); + +void var_cast(var_cont**, b_type); + +var_cont* var_cast_data_G_INT(void**, b_type); +var_cont* var_cast_data_G_FLOAT(void**, b_type); +var_cont* var_cast_data_G_CHAR(void**, b_type); +var_cont* var_cast_data_G_STR(void**, b_type); + #endif // TYPES_H diff --git a/src/vm/src/ns.c b/src/vm/src/ns.c @@ -4,24 +4,13 @@ #include "var.h" #include "helper.h" -ns_t* ns_init(int size) -{ - ns_t* ns = (ns_t*)malloc(sizeof(ns_t)); - ASSERT(ns != NULL, "Could not allocate memory\n"); - - ns->root = ns_cont_init(size); - ns->last = NULL; - - return ns; -} - -ns_cont* ns_cont_init(int size) +ns_cont* ns_cont_init(ns_addr size) { ns_cont* new = (ns_cont*)malloc(sizeof(ns_cont)); - ASSERT(new != NULL, "Could not allocate memory\n"); + M_ASSERT(new); new->names = (var_cont**)malloc(sizeof(var_cont*)*size); - ASSERT(new->names != NULL, "Could not allocate memory\n"); + M_ASSERT(new->names); new->size = size; @@ -35,12 +24,15 @@ ns_cont* ns_cont_init(int size) return new; } -void ns_del(ns_t* ns) +ns_t* ns_init(ns_addr size) { - while (ns->last->next != NULL) - ns_pop(ns); + ns_t* ns = (ns_t*)malloc(sizeof(ns_t)); + M_ASSERT(ns); - free(ns); + ns->root = ns_cont_init(size); + ns->last = NULL; + + return ns; } void ns_cont_del(ns_cont* container) @@ -56,7 +48,17 @@ void ns_cont_del(ns_cont* container) free(container); } -void ns_push(ns_t* ns, int size) +void ns_del(ns_t* ns) +{ + M_ASSERT(ns); + if (ns->last != NULL) + while (ns->last->next != NULL) + ns_pop(ns); + + free(ns); +} + +void ns_push(ns_t* ns, ns_addr size) { ns_cont* new = ns_cont_init(size); @@ -83,13 +85,44 @@ void ns_pop(ns_t* ns) } } -void ns_dec(ns_t* ns, b_type type, int scope, int name) +void ns_cont_dec(ns_cont* ns, b_type type, ns_addr address) +{ + SIZE_ASSERT( ns->size > address ); + + ns->names[ address ] = var_new(type); +} + +void ns_dec(ns_t* ns, b_type type, int scope, ns_addr address) { - return; + ns_cont* scoped_ns = scope ? ns->root : ns->last; + + ns_cont_dec(scoped_ns, type, address); } -void ns_set(ns_t* ns, int scope, int name, var_cont* data) +void ns_cont_set(ns_cont* ns, var_cont* var, ns_addr address) { - return; + SIZE_ASSERT( ns->size > address ); + + var_set(ns->names[ address ], var->data, var->type); } +void ns_set(ns_t* ns, int scope, ns_addr address, var_cont* var) +{ + ns_cont* scoped_ns = scope ? ns->root : ns->last; + + ns_cont_set(scoped_ns, var, address); +} + +var_cont* ns_cont_get(ns_cont* ns, ns_addr address) +{ + SIZE_ASSERT( ns->size > address ); + + return ns->names[ address ]; +} + +var_cont* ns_get(ns_t* ns, int scope, ns_addr address) +{ + ns_cont* scoped_ns = scope ? ns->root : ns->last; + + return ns_cont_get(scoped_ns, address); +} diff --git a/src/vm/src/var.c b/src/vm/src/var.c @@ -4,23 +4,193 @@ #include "var.h" #include "helper.h" +void** var_data_alloc_G_INT(var_data_int value) +{ + var_data_int* rv = (var_data_int*)malloc(sizeof(var_data_int)); + M_ASSERT(rv); + + *rv = value; + + return (void**)rv; +} + +void** var_data_alloc_G_FLOAT(var_data_float value) +{ + var_data_float* rv = (var_data_float*)malloc(sizeof(var_data_float)); + M_ASSERT(rv); + + *rv = value; + + return (void**)rv; +} + +void** var_data_alloc_G_CHAR(var_data_char value) +{ + var_data_char* rv = (var_data_char*)malloc(sizeof(var_data_char)); + M_ASSERT(rv); + + *rv = value; + + return (void**)rv; +} + +void** var_data_alloc_G_STR(size_t size) +{ + var_data_str* rv = (var_data_str*)malloc(sizeof(var_data_str)); + M_ASSERT(rv); + + rv->str = (var_data_char*)malloc(sizeof(var_data_char)*size); + + return (void**)rv; +} + +void** var_data_alloc(b_type type) +{ + void** rv = NULL; + + if (type == G_INT) + rv = var_data_alloc_G_INT(0); + + if (type == G_FLOAT) + rv = var_data_alloc_G_FLOAT(0.0); + + if (type == G_CHAR) + rv = var_data_alloc_G_CHAR(0); + + if (type == G_STR) + { + rv = var_data_alloc_G_STR(1); + } + + return rv; +} + var_cont* var_new(b_type type) { var_cont* new = (var_cont*)malloc(sizeof(var_cont)); - ASSERT(new != NULL, "Could not allocate memory\n"); + M_ASSERT(new); new->type = type; - new->data = NULL; + + new->data = var_data_alloc(type); + return new; } +void var_data_free(void** data, b_type type) +{ + N_ASSERT(data); + + if (type == G_INT) + free(data); + + if (type == G_FLOAT) + free(data); + + if (type == G_CHAR) + free(data); + + if (type == G_STR) + { + var_data_str* t_data = *data; + if (t_data->str != NULL) + free(t_data->str); + + free(data); + } +} + void var_del(var_cont* var) { if (var == NULL) return; if (var->data != NULL) - free(var->data); + var_data_free(var->data, var->type); free(var); } + +void var_set(var_cont* var, void** data, b_type type) +{ + if (var == NULL || data == NULL) + return; + + ASSERT(var->type == type, + "Trying to set variable of different type without cast\n"); + + if (var->data != NULL) + var_data_free(var->data, type); + + var->data = data; +} + +var_cont* var_cast_data(var_cont* var, b_type type) +{ + if (var->type == VOID) + return var_new(type); + + if (var->type == G_INT) + return var_cast_data_G_INT(var->data, type); + + if (var->type == G_FLOAT) + return var_cast_data_G_FLOAT(var->data, type); + + if (var->type == G_CHAR) + return var_cast_data_G_CHAR(var->data, type); + + if (var->type == G_STR) + return var_cast_data_G_STR(var->data, type); + + return var_new(type); +} + +void var_cast(var_cont** var, b_type type) +{ + if (var == NULL) + return; + + *var = var_cast_data(*var, type); + + (*var)->type = type; +} + +var_cont* var_cast_data_G_INT(void** data, b_type type) +{ + var_cont* new = var_new(type); + + if (data != NULL) + free(data); + + return new; +} + +var_cont* var_cast_data_G_FLOAT(void** data, b_type type) +{ + var_cont* new = var_new(type); + + if (data != NULL) + free(data); + + return new; +} + +var_cont* var_cast_data_G_CHAR(void** data, b_type type) +{ + var_cont* new = var_new(type); + + if (data != NULL) + free(data); + + return new; +} + +var_cont* var_cast_data_G_STR(void** data, b_type type) +{ + var_cont* new = var_new(type); + + if (data != NULL) + free(data); + + return new; +} diff --git a/src/vm/tests/bc/test b/src/vm/tests/bc/test Binary files differ diff --git a/src/vm/tests/ns/expected_output b/src/vm/tests/ns/expected_output @@ -0,0 +1,3 @@ +2 +5 +10 diff --git a/src/vm/tests/ns/test.c b/src/vm/tests/ns/test.c @@ -4,5 +4,23 @@ int main( void ) { + ns_t* test = ns_init(10); + + ns_push(test, 5); + + ns_push(test, 2); + + printf("%d\n", test->last->size); + + ns_pop(test); + + printf("%d\n", test->last->size); + + ns_pop(test); + + printf("%d\n", test->last->size); + + ns_del(test); + return 0; } diff --git a/src/vm/tests/stk/expected_output b/src/vm/tests/stk/expected_output @@ -1,4 +1,4 @@ -5, 4, 3, 2 -4, 3, 2, 1 -3, 4, 2, 1 -2, 3, 4, 1 +7, 5, 4, 3 +5, 4, 3, 0 +4, 5, 3, 0 +3, 4, 5, 0 diff --git a/src/vm/tests/stk/test b/src/vm/tests/stk/test Binary files differ diff --git a/src/vm/tests/stk/test.c b/src/vm/tests/stk/test.c @@ -17,13 +17,14 @@ void printstk(stk_t* stk) int main(int argc, char* argv[]) { stk_t* new = stk_new(); - new->data = var_new(0); - stk_push(&new, var_new(1)); - stk_push(&new, var_new(2)); - stk_push(&new, var_new(3)); - stk_push(&new, var_new(4)); - stk_push(&new, var_new(5)); + new->data = var_new(VOID); + + stk_push(&new, var_new(VOID)); + stk_push(&new, var_new(G_INT)); + stk_push(&new, var_new(G_FLOAT)); + stk_push(&new, var_new(G_CHAR)); + stk_push(&new, var_new(G_STR)); printstk(new); diff --git a/src/vm/tests/var/Makefile b/src/vm/tests/var/Makefile @@ -0,0 +1,24 @@ +SRC_DIR = ../../src +INC_DIR = ../../inc + +CC = gcc +CFLAGS = -std=c99 -Wall -I$(INC_DIR) + +DEPS = i$(INC_DIR)/helper.h \ + var.h \ + +OBJ = test.o \ + $(SRC_DIR)/var.o + +OUT = test + +%.o: %.c $(DEPS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(OUT): $(OBJ) + $(CC) $(CFLAGS) -o $@ $^ + +clean: + rm *.o + rm $(SRC_DIR)/*.o + rm $(OUT) diff --git a/src/vm/tests/var/expected_output b/src/vm/tests/var/expected_output @@ -0,0 +1,2 @@ +1 +1 diff --git a/src/vm/tests/var/test.c b/src/vm/tests/var/test.c @@ -0,0 +1,24 @@ +#include <stdio.h> + +#include "var.h" + +int main( void ) +{ + var_cont* test0 = var_new(VOID); + if (test0->type == VOID) + printf("1\n"); + else + printf("0\n"); + + var_cont* test1 = var_new(G_INT); + + var_set(test1, var_data_alloc_G_INT(32), G_INT); + int testing = *(test1->data); + if (testing == 32) + printf("1\n"); + else + printf("0: %d\n", testing); + + var_del(test0); + var_del(test1); +}