language

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

commit 172246477cb11a3811f76e713248dc77ddbe87a8
parent a30b4d501f2e34a522f9b9538a20945354afeb76
Author: Paul Longtine <paullongtine@gmail.com>
Date:   Mon Feb 29 21:19:44 2016

Got the thing to do the thing, now thing doing. By that I mean I have the framework to parse raw arugments into typed data done. All that's left is to implement arguement list/arguement serialization

Diffstat:
 src/vm/Makefile        |   2 +-
 src/vm/inc/bc.h        |  29 +++++++++----
 src/vm/inc/ins_adata.h |  26 +------------
 src/vm/inc/ins_mdata.h |  82 +++++++++++++++++++++++++++++++++++---
 src/vm/inc/is.h        |  16 +++++--
 src/vm/inc/rt.h        |   3 +-
 src/vm/src/bc.c        | 108 +++++++++++++++++++++++++++++++++++++++++---------
 src/vm/src/ins_adata.c |  17 +--------
 src/vm/src/is.c        |   8 +++-
 src/vm/src/main.c      |   4 +-
 src/vm/src/pc.c        |   2 +-
 11 files changed, 211 insertions(+), 86 deletions(-)

diff --git a/src/vm/Makefile b/src/vm/Makefile @@ -15,7 +15,6 @@ DEPS = $(INC_DIR)/is_mdata.h \ ns.h \ pc.h \ rt.h \ - ins_adata.h\ ins_def.h \ proc.h @@ -29,7 +28,6 @@ OBJ = $(SRC_DIR)/main.o \ $(SRC_DIR)/ns.o \ $(SRC_DIR)/pc.o \ $(SRC_DIR)/rt.o \ - $(SRC_DIR)/ins_adata.o\ $(SRC_DIR)/ins_def.o \ $(SRC_DIR)/proc.o diff --git a/src/vm/inc/bc.h b/src/vm/inc/bc.h @@ -7,6 +7,7 @@ #include <stdlib.h> #include <stdio.h> +#include "var.h" #include "fh.h" #include "helper.h" @@ -17,15 +18,27 @@ typedef unsigned short int bc_addr; typedef struct bc_cont { byte_t op; byte_t* args[3]; - void* a1; - void* a2; - void* a3; byte_t mdata; + void* targ[3]; + byte_t adata; bc_addr real_addr; struct bc_cont* next; struct bc_cont* prev; } bc_cont; +typedef struct bc_targ_int { + int i; +} bc_targ_int; + +typedef struct bc_targ_list { + int size; + b_type* i; +} bc_targ_list; + +typedef struct bc_targ_var_cont { + var_cont* i; +} bc_targ_var_cont; + #include "is.h" /* Handles allocation for new `bc_cont` instances @@ -33,11 +46,9 @@ typedef struct bc_cont { bc_cont* bc_cont_new(void); /* Pushes new bc_cont to the chain. - * bc_cont* - bytecode container - * - * -> bc_cont* - push new bytecode container on chain + * bc_cont** - bytecode container */ -bc_cont* bc_cont_push(bc_cont*); +void bc_cont_push(bc_cont**); /* Deallocates all the things, assuming the arguement is the root. * bc_cont* - bytecode container, root node (hopefully) @@ -56,6 +67,10 @@ byte_t* get_dync_arg(FILE*); * bc_cont* - bytecode container */ void process_args(bc_cont*); +void arg_to_int(void*, byte_t*); +void arg_to_addr(void*, byte_t*); +void arg_to_arglist(void*, byte_t*); +void arg_to_var(void*, byte_t*); /* Scan to +/- int in bytecode chain * bc_cont* - bytecode container [0] diff --git a/src/vm/inc/ins_adata.h b/src/vm/inc/ins_adata.h @@ -1,26 +0,0 @@ -/* `ins_adata.h` provides per-opcode arguement type data. - * Provides subroutines for individual opcodes - */ - -#ifndef INS_MDATA_H -#define INS_MDATA_H - -#include <stdlib.h> -#include <stdio.h> - -#include "bc.h" -#include "is.h" -#include "var.h" -#include "helper.h" - -void init_adata( void ); - -/* TODO: figure out how to deserialize the following: - * - * Byte to integer - * Word to address type - * Dynamic length arguement to arguement type list - * Dynamic length arguement to typed data - */ - -#endif //INS_MDATA_H diff --git a/src/vm/inc/ins_mdata.h b/src/vm/inc/ins_mdata.h @@ -1,12 +1,6 @@ #ifndef INS_MDATA_H #define INS_MDATA_H -#define A_NULL 0 -#define A_BYTE 1 -#define A_WORD 2 -#define A_DYNC 3 - - /* Macro used below. * It should be self-explainitory * i.e. encode( 3, 2, 1, 0 ) = 0b11100100 @@ -15,6 +9,11 @@ #define encode(n, a0, a1, a2) \ ( n << 6 | a0 << 4 | a1 << 2 | a2 ); +#define A_NULL 0 +#define A_BYTE 1 +#define A_WORD 2 +#define A_DYNC 3 + /* This definition is ran in `is.c` * * INS_MDATA[ <opcode> ] = encode( <number of arguements>, <type..3> ) @@ -81,4 +80,75 @@ /* DECLASS */ INS_MDATA[0xFE] = encode(2, A_WORD, A_DYNC, A_NULL); \ /* DEFUN */ INS_MDATA[0xFF] = encode(3, A_WORD, A_BYTE, A_DYNC); +#define BTOI 0 +#define WTOA 1 +#define DTOL 2 +#define DTOV 3 + +/* This definition is ran in `is.c` + * + * INS_ADATA[ <opcode> ] = encode( <number of arguements>, <type..3> ) + */ +#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); \ +/* LIBC */ INS_ADATA[0x0F] = encode(1, WTOA, BTOI, BTOI); \ + \ +/* POP */ INS_ADATA[0x10] = encode(1, BTOI, BTOI, BTOI); \ +/* ROT */ INS_ADATA[0x11] = encode(0, BTOI, BTOI, BTOI); \ +/* DUP */ INS_ADATA[0x12] = encode(0, BTOI, BTOI, BTOI); \ +/* ROT_THREE */ INS_ADATA[0x13] = encode(0, BTOI, BTOI, BTOI); \ + \ +/* DEC */ INS_ADATA[0x20] = encode(3, BTOI, BTOI, WTOA); \ +/* LOV */ INS_ADATA[0x21] = encode(2, BTOI, WTOA, BTOI); \ +/* STV */ INS_ADATA[0x22] = encode(2, BTOI, WTOA, BTOI); \ +/* LOC */ INS_ADATA[0x23] = encode(3, BTOI, WTOA, BTOI); \ +/* CTS */ INS_ADATA[0x24] = encode(1, BTOI, BTOI, BTOI); \ + \ +/* TYPEOF */ INS_ADATA[0x30] = encode(0, BTOI, BTOI, BTOI); \ +/* CAST */ INS_ADATA[0x31] = encode(1, BTOI, BTOI, BTOI); \ + \ +/* ADD */ INS_ADATA[0x40] = encode(0, BTOI, BTOI, BTOI); \ +/* SUB */ INS_ADATA[0x41] = encode(0, BTOI, BTOI, BTOI); \ +/* MULT */ INS_ADATA[0x42] = encode(0, BTOI, BTOI, BTOI); \ +/* DIV */ INS_ADATA[0x43] = encode(0, BTOI, BTOI, BTOI); \ +/* POW */ INS_ADATA[0x44] = encode(0, BTOI, BTOI, BTOI); \ +/* BRT */ INS_ADATA[0x45] = encode(0, BTOI, BTOI, BTOI); \ +/* SIN */ INS_ADATA[0x46] = encode(0, BTOI, BTOI, BTOI); \ +/* COS */ INS_ADATA[0x47] = encode(0, BTOI, BTOI, BTOI); \ +/* TAN */ INS_ADATA[0x48] = encode(0, BTOI, BTOI, BTOI); \ +/* ISIN */ INS_ADATA[0x49] = encode(0, BTOI, BTOI, BTOI); \ +/* ICOS */ INS_ADATA[0x4A] = encode(0, BTOI, BTOI, BTOI); \ +/* ITAN */ INS_ADATA[0x4B] = encode(0, BTOI, BTOI, BTOI); \ +/* MOD */ INS_ADATA[0x4C] = encode(0, BTOI, BTOI, BTOI); \ +/* OR */ INS_ADATA[0x4D] = encode(0, BTOI, BTOI, BTOI); \ +/* XOR */ INS_ADATA[0x4E] = encode(0, BTOI, BTOI, BTOI); \ +/* NAND */ INS_ADATA[0x4F] = encode(0, BTOI, BTOI, BTOI); \ + \ +/* GTHAN */ INS_ADATA[0x50] = encode(0, BTOI, BTOI, BTOI); \ +/* LTHAN */ INS_ADATA[0x51] = encode(0, BTOI, BTOI, BTOI); \ +/* EQ */ INS_ADATA[0x52] = encode(0, BTOI, BTOI, BTOI); \ +/* NOT */ INS_ADATA[0x53] = encode(0, BTOI, BTOI, BTOI); \ + \ +/* STARTL */ INS_ADATA[0x60] = encode(0, BTOI, BTOI, BTOI); \ +/* CLOOP */ INS_ADATA[0x61] = encode(0, BTOI, BTOI, BTOI); \ +/* BREAK */ INS_ADATA[0x6E] = encode(0, BTOI, BTOI, BTOI); \ +/* DONE */ INS_ADATA[0x6F] = encode(0, BTOI, BTOI, BTOI); \ + \ +/* GOTO */ INS_ADATA[0x70] = encode(1, WTOA, BTOI, BTOI); \ +/* JUMPF */ INS_ADATA[0x71] = encode(1, BTOI, BTOI, BTOI); \ +/* CALL */ INS_ADATA[0x7F] = encode(1, WTOA, BTOI, BTOI); \ + \ +/* PUSH */ INS_ADATA[0x80] = encode(0, BTOI, BTOI, BTOI); \ +/* DEL */ INS_ADATA[0x81] = encode(0, BTOI, BTOI, BTOI); \ +/* GET */ INS_ADATA[0x82] = encode(0, BTOI, BTOI, BTOI); \ +/* GETP */ INS_ADATA[0x83] = encode(1, WTOA, BTOI, BTOI); \ +/* CALLM */ INS_ADATA[0x84] = encode(1, WTOA, BTOI, BTOI); \ + \ +/* RETURN */ INS_ADATA[0xF0] = encode(0, BTOI, BTOI, BTOI); \ +/* NEW */ INS_ADATA[0xF1] = encode(1, WTOA, BTOI, BTOI); \ +/* DECLASS */ INS_ADATA[0xFE] = encode(2, WTOA, BTOI, BTOI); \ +/* DEFUN */ INS_ADATA[0xFF] = encode(3, WTOA, BTOI, BTOI); + #endif diff --git a/src/vm/inc/is.h b/src/vm/inc/is.h @@ -6,14 +6,18 @@ */ #ifndef IS_H +#define IS_H #include "ins_mdata.h" #include "bc.h" #include "fh.h" -// This array is populated by inc/is_mdata.h +// This array is populated by inc/ins_mdata.h byte_t INS_MDATA[0xFF]; +// This array is populated by inc/ins_adata.h +byte_t INS_ADATA[0xFF]; + /* Takes an opcode, fills metadata about that opcode (given that it exists) in * the `bc_cont` structure * byte_t - opcode @@ -30,10 +34,16 @@ void get_opcode(byte_t, bc_cont*); * @param[1] = 3, * @param[2] = { 01, 10, 11 } */ -void get_mdata(byte_t, int*, int*); +void unencode(byte_t, int*, int*); -/* Sets up the datastructure to quickly queue for data. +/* Sets up INS_MDATA datastructure to quickly queue for data. + * Instruction arguement type metadata */ void init_mdata(void); +/* Sets up INS_ADATA datastructure to quickly queue for data. + * Instruction arguement abstract-type metadata + */ +void init_adata(void); + #endif // IS_H diff --git a/src/vm/inc/rt.h b/src/vm/inc/rt.h @@ -21,7 +21,8 @@ * vars - `ns.h` namespace instance * gvars - `ns.h` namespace container instance * - * [0] This is the stack register used at runtime to push/pop variable containers. + * [0] This is the stack register used at runtime to push/pop variable + * containers. * [1] Function calls implement this stack to load variables as arguements. */ typedef struct rt_t { diff --git a/src/vm/src/bc.c b/src/vm/src/bc.c @@ -3,7 +3,7 @@ #include "bc.h" -#include "ins_adata.h" +#include "var.h" #include "is.h" #include "fh.h" #include "helper.h" @@ -13,22 +13,20 @@ bc_cont* bc_cont_new(void) { bc_cont *new = (bc_cont*)malloc(sizeof(bc_cont)); - ASSERT(new != NULL, "Could not allocate memory\n"); + M_ASSERT(new); new->args[0] = NULL; new->args[1] = NULL; new->args[2] = NULL; - return new; -} + new->targ[0] = NULL; + new->targ[1] = NULL; + new->targ[2] = NULL; -/* Handles allocation for new `bc_cont` instances - */ -bc_cont* bc_cont_push(bc_cont* head) -{ - head->next = bc_cont_new(); - head->next->prev = head; - return head->next; + new->next = NULL; + new->prev = NULL; + + return new; } /* Pushes new bc_cont to the chain. @@ -36,6 +34,13 @@ bc_cont* bc_cont_push(bc_cont* head) * * -> 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) @@ -43,11 +48,18 @@ void bc_cont_del(bc_cont* root) bc_cont_del(root->next); } - if (root->args[0] != NULL) free(root->args[0]); - if (root->args[1] != NULL) free(root->args[1]); - if (root->args[2] != NULL) free(root->args[2]); + if (root != NULL) + { + if (root->args[0] != NULL) free(root->args[0]); + if (root->args[1] != NULL) free(root->args[1]); + if (root->args[2] != NULL) free(root->args[2]); - free(root); + if (root->targ[0] != NULL) free(root->targ[0]); + if (root->targ[1] != NULL) free(root->targ[1]); + if (root->targ[2] != NULL) free(root->targ[2]); + + free(root); + } } /* Given a file object, and an instance of `bc_cont` with proper metadata, this @@ -58,7 +70,7 @@ void get_args(FILE* f, bc_cont* ins) int num_args, arg_types[3]; - get_mdata(ins->mdata, &num_args, arg_types); + unencode(ins->mdata, &num_args, arg_types); for (int x = 0; x < num_args; x++) { @@ -88,10 +100,64 @@ byte_t* get_dync_arg(FILE* f) { return read_until_null(f); } - + +/* Given an instruction, convert raw arguement data into typed data + * bc_cont* - bytecode container + */ void process_args(bc_cont* ins) { + int num_args, + arg_types[3]; + + unencode(ins->adata, &num_args, arg_types); + for (int x = 0; x < num_args; x++) + { + if (arg_types[x] == BTOI) + { + arg_to_int(ins->targ[x], ins->args[x]); + } else + if (arg_types[x] == WTOA) + { + arg_to_addr(ins->targ[x], ins->args[x]); + } else + if (arg_types[x] == DTOL) + { + arg_to_arglist(ins->targ[x], ins->args[x]); + } else + if (arg_types[x] == DTOV) + { + arg_to_var(ins->targ[x], ins->args[x]); + } + } +} + +void arg_to_int(void* ptr, byte_t* byte) +{ + ptr = (bc_targ_int*)malloc(sizeof(bc_targ_int)); + M_ASSERT(ptr); + + bc_targ_int* v = ptr; + + v->i = (int)byte[0]; +} + +void arg_to_addr(void* ptr, byte_t* word) +{ + ptr = (bc_targ_int*)malloc(sizeof(bc_targ_int)); + M_ASSERT(ptr); + + bc_targ_int* v = ptr; + + v->i = (int)((word[1] >> 8) | word[0]); +} + +void arg_to_arglist(void* ptr, byte_t* bytes) +{ +} + +void arg_to_var(void* ptr, byte_t* bytes) +{ } /* Scan to +/- int in bytecode chain @@ -109,10 +175,14 @@ bc_cont* bc_scan(bc_cont* ptr, int scanto) ptr = ptr->next; scanto--; } else - if (scanto < 0 && ptr->next != NULL) + if (scanto < 0 && ptr->prev != NULL) { ptr = ptr->prev; scanto++; + } else + if (ptr->next == NULL || ptr->prev == NULL) + { + scanto = 0; } } @@ -145,7 +215,7 @@ bc_cont* bc_read(char* fname) ptr->real_addr = addr; - ptr = bc_cont_push(ptr); + bc_cont_push(&ptr); addr++; } diff --git a/src/vm/src/ins_adata.c b/src/vm/src/ins_adata.c @@ -1,17 +0,0 @@ -/* `ins_adata.h` provides per-opcode arguement type data. - * Provides subroutines for individual opcodes - */ - -#include <stdlib.h> -#include <stdio.h> - -#include "ins_adata.h" - -#include "bc.h" -#include "is.h" -#include "var.h" -#include "helper.h" - -void init_adata( void ) -{ -} diff --git a/src/vm/src/is.c b/src/vm/src/is.c @@ -16,7 +16,7 @@ void get_opcode(byte_t byte, bc_cont* ins) { ins->op = byte; ins->mdata = INS_MDATA[byte]; - //ins->adata = INS_ADATA[byte]; + ins->adata = INS_ADATA[byte]; } /* Fills in metadata in @param byte_t. @@ -28,7 +28,7 @@ void get_opcode(byte_t byte, bc_cont* ins) * @param[1] = 3, * @param[2] = { 01, 10, 11 } */ -void get_mdata(byte_t byte, int* n, int* at) +void unencode(byte_t byte, int* n, int* at) { *n = (byte & (3 << 6)) >> 6; at[0] = (byte & (3 << 4)) >> 4; @@ -43,3 +43,7 @@ void init_mdata(void) INS_MDATA_DEF(); } +void init_adata(void) +{ + INS_ADATA_DEF(); +} diff --git a/src/vm/src/main.c b/src/vm/src/main.c @@ -4,7 +4,6 @@ #include "rt.h" #include "is.h" #include "ins_def.h" -#include "ins_adata.h" #include "helper.h" int main(int argc, char** argv) @@ -19,7 +18,8 @@ int main(int argc, char** argv) proc_run(runtime); // Execute runtime - proc_clean(runtime); // Once `proc_run` returns, try to clean what sort of mess it made. + proc_clean(runtime); // Once `proc_run` returns, try to clean + // what sort of mess it made. return 0; } diff --git a/src/vm/src/pc.c b/src/vm/src/pc.c @@ -29,6 +29,7 @@ void pc_del(pc_t* pc) { N_ASSERT(pc); N_ASSERT(pc->root); + bc_cont_del(pc->root); free(pc); @@ -37,7 +38,6 @@ void pc_del(pc_t* pc) void pc_update(pc_t* pc) { N_ASSERT(pc); - pc->line = bc_scan(pc->line, pc->address - pc->line->real_addr); }