language

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

commit 8bc7df5ac15066a333c4723dfca1da814729fb69
parent f4817604b815db1dd64f17dc9aee07a4ecaf4900
Author: Paul Longtine <paullongtine@gmail.com>
Date:   Tue Mar  8 17:57:35 2016

MILESTONE, folks! We got 'er to Hello World

Diffstat:
 doc/SPECIFICATION              |   4 +-
 src/vm/inc/ins_def.h           |   1 +-
 src/vm/inc/ins_mdata.h         |   6 +-
 src/vm/inc/pc.h                |   5 ++-
 src/vm/inc/var.h               |  55 ++++++++++++++++------
 src/vm/src/ins_def.c           |  42 ++++++++++++++++-
 src/vm/src/pc.c                |   9 ++++-
 src/vm/src/proc.c              |   2 +-
 src/vm/src/var.c               | 105 +++++++++++++++++++++++++++++++++++++++++-
 src/vm/tests/bytecodes/testing | Bin 14 -> 0 bytes
 10 files changed, 206 insertions(+), 23 deletions(-)

diff --git a/doc/SPECIFICATION b/doc/SPECIFICATION @@ -219,9 +219,11 @@ F0 RETURN - Returns from function ------------------------------------------------------------------------------- 00 NULL - Terminator byte -01 SYNC S<level> - Updates global namespace with global namespace cache of +01 SYNC S<level> - Updates global namespace with global namespace cache of current thread +02 PRINT - Prints whatever is on the TOS. + 0E ARGB - Builds arguement stack 0F LIBC A<ref> - Library call diff --git a/src/vm/inc/ins_def.h b/src/vm/inc/ins_def.h @@ -30,6 +30,7 @@ int ins_def_is_valid(bc_cont*); void _ins_def_NULL (rt_t*, bc_cont*); void _ins_def_SYNC (rt_t*, bc_cont*); +void _ins_def_PRINT (rt_t*, bc_cont*); void _ins_def_ARGB (rt_t*, bc_cont*); void _ins_def_LIBC (rt_t*, bc_cont*); diff --git a/src/vm/inc/ins_mdata.h b/src/vm/inc/ins_mdata.h @@ -24,7 +24,8 @@ #define INS_MDATA_DEF() \ /* NULL */ INS_MDATA[0x00] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ /* SYNC */ INS_MDATA[0x01] = encode(1, A_BYTE, A_BYTE, A_BYTE); \ -/* ARGB */ INS_MDATA[0x02] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ +/* PRINT */ INS_MDATA[0x02] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ +/* ARGB */ INS_MDATA[0x0E] = encode(0, A_BYTE, A_BYTE, A_BYTE); \ /* LIBC */ INS_MDATA[0x0F] = encode(1, A_ADDR, A_BYTE, A_BYTE); \ \ /* POP */ INS_MDATA[0x10] = encode(1, A_BYTE, A_BYTE, A_BYTE); \ @@ -95,7 +96,8 @@ #define INS_ADATA_DEF() \ /* NULL */ INS_ADATA[0x00] = encode(0, BTOI, BTOI, BTOI); \ /* SYNC */ INS_ADATA[0x01] = encode(1, BTOI, BTOI, BTOI); \ -/* ARGB */ INS_ADATA[0x02] = encode(0, BTOI, BTOI, BTOI); \ +/* PRINT */ INS_ADATA[0x01] = encode(0, BTOI, BTOI, BTOI); \ +/* ARGB */ INS_ADATA[0x0E] = encode(0, BTOI, BTOI, BTOI); \ /* LIBC */ INS_ADATA[0x0F] = encode(1, BTOI, BTOI, BTOI); \ \ /* POP */ INS_ADATA[0x10] = encode(1, BTOI, BTOI, BTOI); \ diff --git a/src/vm/inc/pc.h b/src/vm/inc/pc.h @@ -58,4 +58,9 @@ void pc_branch(pc_t*, pc_addr); */ void pc_return(pc_t*); +/* For now, a simple function that returns true if the next instruction is not + * NULL. + */ +int pc_safe(pc_t* pc); + #endif // PC_H diff --git a/src/vm/inc/var.h b/src/vm/inc/var.h @@ -13,20 +13,20 @@ typedef unsigned int bc_addr; typedef unsigned int ns_addr; typedef enum { - VOID, - ADDR, - TYPE, - PLIST, - FUNC, - OBJECT, - G_INT, - G_FLOAT, - G_CHAR, - G_STR, - S_ARRAY, - D_ARRAY, - K_ARRAY, - G_FIFO + VOID, // 0 + ADDR, // 1 + TYPE, // 2 + PLIST, // 3 + FUNC, // 4 + OBJECT, // 5 + G_INT, // 6 + G_FLOAT,// 7 + G_CHAR, // 8 + G_STR, // 9 + S_ARRAY,// A + D_ARRAY,// B + K_ARRAY,// C + G_FIFO // D } b_type; typedef struct var_cont { @@ -59,6 +59,7 @@ typedef struct var_data_char { } var_data_char; typedef struct var_data_str { + size_t size; char* v; } var_data_str; @@ -102,12 +103,36 @@ char var_data_get_G_CHAR(var_cont*); char* var_data_get_G_STR(var_cont*); b_type* var_data_get_PLIST(var_cont*); + +void* var_data_cpy_G_INT(var_data_int*); +void* var_data_cpy_G_FLOAT(var_data_float*); +void* var_data_cpy_G_CHAR(var_data_char*); +void* var_data_cpy_G_STR(var_data_str*); + +var_cont* var_data_cpy(var_cont*); + +/* Lovely little function to take bytes and turn it into an integer. + * int - sizeof(bytes) + * byte_t* - array of bytes + */ var_cont* bytes_to_int(int, byte_t*); +/* Byte to b_type. + * byte_t - value maps to enum b_type + */ var_cont* byte_to_type(byte_t); +/* Converts array of bytes of size n into parameter list + * + * int - sizeof(bytes) + * byte_t* - array of bytes + */ var_cont* raw_to_plist(int, byte_t*); - +/* Raw variable to var_cont + * + * int - sizeof(bytes) + * byte_t* - array of bytes + */ var_cont* raw_to_var(int, byte_t*); #endif // var_H diff --git a/src/vm/src/ins_def.c b/src/vm/src/ins_def.c @@ -18,7 +18,8 @@ void init_ins_def( void ) { INS_DEF[0x00] = _ins_def_NULL; INS_DEF[0x01] = _ins_def_SYNC; - INS_DEF[0x02] = _ins_def_ARGB; + INS_DEF[0x02] = _ins_def_PRINT; + INS_DEF[0x0E] = _ins_def_ARGB; INS_DEF[0x0F] = _ins_def_LIBC; INS_DEF[0x10] = _ins_def_POP; @@ -93,12 +94,27 @@ void _ins_def_NULL (rt_t* ctx, bc_cont* line) { pc_inc(ctx->pc, 1); } +void _ins_def_PRINT (rt_t* ctx, bc_cont* line) +{ + var_cont* var = stk_at(ctx->stack, 0); + + if (var->type == G_STR) + { + char* str = var_data_get_G_STR(var); + printf("%s\n", str); + } + + pc_inc(ctx->pc, 1); +} void _ins_def_SYNC (rt_t* ctx, bc_cont* line) { pc_inc(ctx->pc, 1); } void _ins_def_ARGB (rt_t* ctx, bc_cont* line) { + var_cont* var = stk_at(ctx->stack, 0); + + stk_push(&ctx->argstk, var); pc_inc(ctx->pc, 1); } void _ins_def_LIBC (rt_t* ctx, bc_cont* line) @@ -108,18 +124,39 @@ void _ins_def_LIBC (rt_t* ctx, bc_cont* line) void _ins_def_POP (rt_t* ctx, bc_cont* line) { + int n = var_data_get_G_INT(line->varg[0]); + int i = 0; + + var_cont* var; + + while (n > i) + { + i++; + + var = stk_pop(&ctx->stack); + + if (var != NULL) + var_del(var); + } + pc_inc(ctx->pc, 1); } void _ins_def_ROT (rt_t* ctx, bc_cont* line) { + stk_rot_top(&ctx->stack); + pc_inc(ctx->pc, 1); } 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); pc_inc(ctx->pc, 1); } void _ins_def_ROT_THREE(rt_t* ctx, bc_cont* line) { + stk_rot_three(&ctx->stack); pc_inc(ctx->pc, 1); } @@ -141,6 +178,7 @@ void _ins_def_LOC (rt_t* ctx, bc_cont* line) } void _ins_def_CTS (rt_t* ctx, bc_cont* line) { + stk_push(&ctx->stack, line->varg[0]); pc_inc(ctx->pc, 1); } @@ -310,7 +348,7 @@ void _ins_def_DEFUN (rt_t* ctx, bc_cont* line) int nsize; - for (nsize = 0; ctx->pc->line->next != NULL; pc_update(ctx->pc)) + for (nsize = 0; pc_safe(ctx->pc); pc_update(ctx->pc)) { pc_inc(ctx->pc, 1); if (ctx->pc->line->op == 0xF0) diff --git a/src/vm/src/pc.c b/src/vm/src/pc.c @@ -108,3 +108,12 @@ void pc_return(pc_t* pc) free(tmp); } + +/* For now, a simple function that returns true if the next instruction is not + * NULL. + */ +int pc_safe(pc_t* pc) +{ + return (pc->line->next != NULL); +} + diff --git a/src/vm/src/proc.c b/src/vm/src/proc.c @@ -32,7 +32,7 @@ void proc_run(rt_t* ctx) int n; - for (n = 0; ctx->pc->line->next != NULL; pc_update(ctx->pc)) + 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); diff --git a/src/vm/src/var.c b/src/vm/src/var.c @@ -65,6 +65,7 @@ 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->size = size; rv->v = (char*)malloc(sizeof(char)*size); return rv; @@ -239,6 +240,76 @@ b_type* var_data_get_PLIST(var_cont* var) return t->v; } +void* var_data_cpy_G_INT(var_data_int* data) +{ + var_data_int* rv = var_data_alloc_G_INT(data->v); + + return rv; +} + +void* var_data_cpy_G_FLOAT(var_data_float* data) +{ + var_data_float* rv = var_data_alloc_G_FLOAT(data->v); + + return rv; +} + +void* var_data_cpy_G_CHAR(var_data_char* data) +{ + var_data_char* rv = var_data_alloc_G_CHAR(data->v); + + return rv; +} + +void* var_data_cpy_G_STR(var_data_str* data) +{ + var_data_str* rv = var_data_alloc_G_STR(data->size); + + int i; + for (i = 0; data->size > i; i++) + { + rv->v[i] = data->v[i]; + } + + return rv; +} + +/* Reconstructs variable into seperate variable container, copies data + * var_cont* - variable to copy + * + * Returns new variable container + */ +var_cont* var_data_cpy(var_cont* var) +{ + N_ASSERT(var); + + var_cont* rv = var_new(var->type); + + if (var->type == G_INT) + { + rv->data = var_data_cpy_G_INT(var->data); + } + + if (var->type == G_FLOAT) + { + rv->data = var_data_cpy_G_FLOAT(var->data); + } + + if (var->type == G_CHAR) + { + rv->data = var_data_cpy_G_CHAR(var->data); + } + + if (var->type == G_STR) + { + rv->data = var_data_cpy_G_STR(var->data); + } + + ASSERT((rv->data != NULL), "ERROR: Could not copy type.\n"); + + return rv; +} + /* Lovely little function to take bytes and turn it into an integer. * int - sizeof(bytes) * byte_t* - array of bytes @@ -261,6 +332,9 @@ var_cont* bytes_to_int(int size, byte_t* bytes) return rv; } +/* Byte to b_type. + * byte_t - value maps to enum b_type + */ var_cont* byte_to_type(byte_t byte) { var_cont* rv = var_new(TYPE); @@ -293,6 +367,18 @@ var_cont* raw_to_plist(int n, byte_t* bytes) return rv; } +var_data_str* raw_to_str(int n, byte_t* bytes) +{ + var_data_str* data = var_data_alloc_G_STR(n); + int i; + for (i = 0; n > i; i++) + { + data->v[i] = (char)bytes[i]; + } + + return data; +} + /* Raw variable to var_cont * * int - sizeof(bytes) @@ -300,9 +386,24 @@ var_cont* raw_to_plist(int n, byte_t* bytes) */ var_cont* raw_to_var(int n, byte_t* bytes) { - var_cont* rv = var_new(VOID); + N_ASSERT(bytes); + + b_type type = (b_type)bytes[0]; + + var_cont* rv = var_new(type); + + byte_t* data = ++bytes; + + if (type == G_STR) + { + rv->data = raw_to_str(n - 1, data); + } else + { + printf("Type {%x} is not a seralizeable type\n", type); + } + + N_ASSERT(rv->data); - // TODO: implement. return rv; } diff --git a/src/vm/tests/bytecodes/testing b/src/vm/tests/bytecodes/testing Binary files differ