From 9ac937e88fb8ff129c1ada2be94f472170a59889 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Tue, 22 Apr 2014 21:51:31 -0400 Subject: [PATCH] Moved typedefs and defines to a header and removed some unneeded code in main.c --- source/slvm/main.c | 276 +++++++++++++-------------------------------- source/slvm/slvm.h | 93 +++++++++++++++ 2 files changed, 171 insertions(+), 198 deletions(-) create mode 100644 source/slvm/slvm.h diff --git a/source/slvm/main.c b/source/slvm/main.c index a8ecb72..c9f6cf3 100644 --- a/source/slvm/main.c +++ b/source/slvm/main.c @@ -5,64 +5,25 @@ #include #include -/** - This type represents a pointer to a function handler for executing a word. - For built-in words this typically points to the C function that implements - the word. For compiled words, this typically points to the docolon function. - - @param code This is a pointer to the next bytecode instruction to execute. - For built-in words this pointer is 0. - */ -typedef void (*codeword_t)(long* code); - -/** - This structure contains all of the relevant attributes of a word definition -*/ -typedef struct word_t { - /** Pointer to the next most recently defined word in the dictionary. */ - struct word_t const* link; - /** A collection of flags describing attributes of the word. */ - struct { - long f_hidden : 1; /*< Flag if this word should be hidden from the interpreter */ - long f_immed : 1; /*< flag if this word should be executed at compile time */ - long padding : 6; /*< Pads the flags to 8-bits */ - long codesize : 24; /*< The lenght of the bytecode section of the word */ - } flags; - /** Pointer to the null terminated string that holds the name of the word. */ - char const* name; - /** - * Pointer to the execution handler for this word. For words defined in C - * This points to the implementation function. For words defined in - * bytecode this will point to the docolon function. */ - codeword_t codeword; - /** - * A pointer to the list of instructions that make up this word. For words - * defined in C this will be 0u (NULL). */ - long* code; -} word_t; - -/** Execute a built-in word directly */ -#define EXEC(word) (word).codeword((word).code) +#include "slvm.h" + +/* Built-in Constants + *****************************************************************************/ +/** The argument stack */ +long ArgStack[ARG_STACK_SIZE]; /** Pointer to current position on the stack */ -static long* ArgStackPtr; +long* ArgStackPtr = ArgStack-1; /** Pointer to current instruction being executed */ -static long* CodePtr; - -/** The argument stack */ -static long ArgStack[32]; +long* CodePtr = 0; /** A state variable used to flag when the interpreter reads a line of input */ -static long Line_Read; - -/** - * This is the "inner" interpreter. This function is responsible for running - * the threaded code that make up colon defintions. - * - * @param code This is a pointer to the next instruction to be executed. - * */ -static void docolon(long* code) { +long Line_Read = 0; + +/* Built-in Constants + *****************************************************************************/ +void docolon(long* code) { word_t* word; /* We may have previously been executing a word so we should save off our * previous position */ @@ -82,74 +43,26 @@ static void docolon(long* code) { CodePtr = prev_code; } -/** A barebones stack integrity check. Check to see if we overflowed or - * underflowed the stack and bail if we did. */ -static void check_stack(void) -{ - if(ArgStackPtr < (ArgStack-1)) - { - puts("Stack Underflow!"); - //exit(1); - } - - if(ArgStackPtr > (ArgStack+30)) - { - puts("Stack Overflow!"); - //exit(1); - } -} - -/** - * Define a built-in word that executes native code */ -#define defcode(name_str,c_name,immed,hide,prev) \ - static void c_name##_code(long* code); \ - static word_t const c_name = { \ - prev, \ - { immed, hide, 0, 0 }, \ - name_str, \ - &c_name##_code, \ - 0 \ - }; \ - static void c_name##_code(long* inst_ptr) \ - -/** - * Define a built-in word representing a variable with the provided initial value */ -#define defvar(name_str,c_name,immed,hide,prev,initial) \ - static long c_name##_val = initial; \ - defcode(name_str,c_name,immed,hide,prev) { \ - ArgStackPtr++; \ - *(ArgStackPtr) = (long)&(c_name##_val); \ - } - -/** - * Define a built-in word representing a constant with the provided value */ -#define defconst(name_str,c_name,immed,hide,prev,value) \ - static long const c_name##_val = value; \ - defcode(name_str,c_name,immed,hide,prev) { \ - ArgStackPtr++; \ - *(ArgStackPtr) = c_name##_val; \ - } - /* Built-in Constants *****************************************************************************/ -defconst("VERSION", version, 0, 0, 0, 1); -defconst("EXECDEF", execdef, 0, 0, &version, (long)&docolon); -defconst("WORDSZ", wordsz, 0, 0, &execdef, sizeof(long)); +defconst("VERSION", version, 0, 0, 1); +defconst("EXECDEF", execdef, 0, &version, (long)&docolon); +defconst("WORDSZ", wordsz, 0, &execdef, sizeof(long)); /* Built-in Variables *****************************************************************************/ -defvar("state", state, 0, 0, &wordsz, 0); -defvar("here", here, 0, 0, &state, 0); -defvar("latest", latest, 0, 0, &here, 0); +defvar("state", state, 0, &wordsz, 0); +defvar("here", here, 0, &state, 0); +defvar("latest", latest, 0, &here, 0); /* Input Words *****************************************************************************/ -defcode("getc", get_char, 0, 0, &latest){ +defcode("getc", get_char, 0, &latest){ ArgStackPtr++; *(ArgStackPtr) = getc(stdin); } -defcode("ws?", is_ws, 0, 0, &get_char){ +defcode("ws?", is_ws, 0, &get_char){ char ch = *(ArgStackPtr); *(ArgStackPtr) = ((ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n')); @@ -160,7 +73,7 @@ defcode("ws?", is_ws, 0, 0, &get_char){ Line_Read = 1; } -defcode("getw", get_word, 0, 0, &is_ws){ +defcode("getw", get_word, 0, &is_ws){ static char buffer[32]; int i = 0; int wschar = 0; @@ -193,7 +106,7 @@ defcode("getw", get_word, 0, 0, &is_ws){ *(ArgStackPtr) = (long)&buffer; } -defcode("findw", find_word, 0, 0, &get_word){ +defcode("findw", find_word, 0, &get_word){ word_t const* curr = (word_t const*)latest_val; char* name = (char*)*(ArgStackPtr); while(curr) @@ -209,17 +122,17 @@ defcode("findw", find_word, 0, 0, &get_word){ /* Branching and Literal Words *****************************************************************************/ -defcode("lit", literal, 0, 0, &find_word){ +defcode("lit", literal, 0, &find_word){ ArgStackPtr++; *(ArgStackPtr) = *CodePtr; CodePtr++; } -defcode("br", branch, 0, 0, &literal){ +defcode("br", branch, 0, &literal){ CodePtr = (long*)(((long)CodePtr) + *(CodePtr)); } -defcode("0br", zbranch, 0, 0, &branch){ +defcode("0br", zbranch, 0, &branch){ if (*ArgStackPtr == 0) { CodePtr = (long*)(((long)CodePtr) + *(CodePtr)); @@ -233,19 +146,19 @@ defcode("0br", zbranch, 0, 0, &branch){ /* Compiler Words *****************************************************************************/ -defcode("ret", ret, 0, 0, &zbranch){ +defcode("ret", ret, 0, &zbranch){ CodePtr = 0; } -defcode("[", lbrack, 0, 0, &ret){ +defcode("[", lbrack, 0, &ret){ state_val = 0; } -defcode("]", rbrack, 0, 1, &lbrack){ +defcode("]", rbrack, 1, &lbrack){ state_val = 1; } -defcode("create", create, 0, 0, &rbrack){ +defcode("create", create, 0, &rbrack){ /* Copy the name string */ char* name = 0u; if (*(ArgStackPtr)) @@ -272,7 +185,7 @@ defcode("create", create, 0, 0, &rbrack){ *(ArgStackPtr) = (long)word; } -defcode(",", comma, 0, 0, &create){ +defcode(",", comma, 0, &create){ /* Get the word we are currently compiling */ word_t* word = (word_t*)latest_val; /* Put the next instruction in place of the terminating 'ret' that "here" @@ -287,40 +200,40 @@ defcode(",", comma, 0, 0, &create){ *((long*)here_val) = (long)&ret; } -defcode("hidden", hidden, 0, 1, &comma){ +defcode("hidden", hidden, 1, &comma){ ((word_t*)*(ArgStackPtr))->flags.f_hidden ^= 1; } -defcode("immediate", immediate, 0, 1, &hidden){ +defcode("immediate", immediate, 1, &hidden){ ((word_t*)*(ArgStackPtr))->flags.f_immed ^= 1; } -defcode(":", colon, 0, 0, &immediate){ +defcode(":", colon, 0, &immediate){ EXEC(get_word); EXEC(create); EXEC(rbrack); } -defcode(";", semicolon, 0, 1, &colon){ +defcode(";", semicolon, 1, &colon){ EXEC(lbrack); EXEC(hidden); ArgStackPtr--; } -defcode("'", tick, 0, 1, &semicolon){ +defcode("'", tick, 1, &semicolon){ EXEC(get_word); EXEC(find_word); } /* Interpreter Words *****************************************************************************/ -defcode("execw", exec_word, 0, 0, &tick){ +defcode("execw", exec_word, 0, &tick){ word_t* word = (word_t*)(*ArgStackPtr); ArgStackPtr--; EXEC( *(word) ); } -defcode("parsenum", parse_num, 0, 0, &exec_word){ +defcode("parsenum", parse_num, 0, &exec_word){ char* end; long num = strtol((const char *)*(ArgStackPtr), &end, 10); if(end != (char *)*(ArgStackPtr)) @@ -334,7 +247,7 @@ defcode("parsenum", parse_num, 0, 0, &exec_word){ } } -defcode("interpret", interpret, 0, 0, &parse_num){ +defcode("interpret", interpret, 0, &parse_num){ char* curr_word; /* Parse a word */ EXEC(get_word); @@ -376,7 +289,7 @@ defcode("interpret", interpret, 0, 0, &parse_num){ } } -defcode("quit", quit, 0, 0, &interpret){ +defcode("quit", quit, 0, &interpret){ int i; printf("=> "); Line_Read = 0; @@ -385,7 +298,6 @@ defcode("quit", quit, 0, 0, &interpret){ EXEC(interpret); if(Line_Read) { - check_stack(); long stacksz = ArgStackPtr - ArgStack + 1; if (stacksz > 5) printf("( ... "); @@ -405,34 +317,34 @@ defcode("quit", quit, 0, 0, &interpret){ /* Stack Manipulation Words *****************************************************************************/ -defcode("drop", drop, 0, 0, &quit){ +defcode("drop", drop, 0, &quit){ ArgStackPtr--; } -defcode("swap", swap, 0, 0, &drop){ +defcode("swap", swap, 0, &drop){ long temp = *(ArgStackPtr); *(ArgStackPtr) = *(ArgStackPtr-1); *(ArgStackPtr-1) = temp; } -defcode("dup", dup, 0, 0, &swap){ +defcode("dup", dup, 0, &swap){ ArgStackPtr++; *(ArgStackPtr) = *(ArgStackPtr-1); } -defcode("over", over, 0, 0, &dup){ +defcode("over", over, 0, &dup){ ArgStackPtr++; *(ArgStackPtr) = *(ArgStackPtr-2); } -defcode("rot", rot, 0, 0, &over){ +defcode("rot", rot, 0, &over){ long temp = *(ArgStackPtr); *(ArgStackPtr) = *(ArgStackPtr-1); *(ArgStackPtr-1) = *(ArgStackPtr-2); *(ArgStackPtr-2) = temp; } -defcode("-rot", nrot, 0, 0, &rot){ +defcode("-rot", nrot, 0, &rot){ long temp = *(ArgStackPtr-2); *(ArgStackPtr-2) = *(ArgStackPtr-1); *(ArgStackPtr-1) = *(ArgStackPtr); @@ -441,137 +353,137 @@ defcode("-rot", nrot, 0, 0, &rot){ /* Arithmetic Words *****************************************************************************/ -defcode("+", add, 0, 0, &nrot){ +defcode("+", add, 0, &nrot){ *(ArgStackPtr-1) += *(ArgStackPtr); ArgStackPtr--; } -defcode("-", sub, 0, 0, &add){ +defcode("-", sub, 0, &add){ *(ArgStackPtr-1) -= *(ArgStackPtr); ArgStackPtr--; } -defcode("*", mul, 0, 0, &sub){ +defcode("*", mul, 0, &sub){ *(ArgStackPtr-1) *= *(ArgStackPtr); ArgStackPtr--; } -defcode("/", divide, 0, 0, &mul){ +defcode("/", divide, 0, &mul){ *(ArgStackPtr-1) /= *(ArgStackPtr); ArgStackPtr--; } -defcode("%", mod, 0, 0, ÷){ +defcode("%", mod, 0, ÷){ *(ArgStackPtr-1) %= *(ArgStackPtr); ArgStackPtr--; } /* Boolean Conditional Words *****************************************************************************/ -defcode("=", equal, 0, 0, &mod){ +defcode("=", equal, 0, &mod){ *(ArgStackPtr-1) = *(ArgStackPtr-1) == *(ArgStackPtr); ArgStackPtr--; } -defcode("!=", notequal, 0, 0, &equal){ +defcode("!=", notequal, 0, &equal){ *(ArgStackPtr-1) = *(ArgStackPtr-1) != *(ArgStackPtr); ArgStackPtr--; } -defcode("<", lessthan, 0, 0, ¬equal){ +defcode("<", lessthan, 0, ¬equal){ *(ArgStackPtr-1) = *(ArgStackPtr-1) < *(ArgStackPtr); ArgStackPtr--; } -defcode(">", greaterthan, 0, 0, &lessthan){ +defcode(">", greaterthan, 0, &lessthan){ *(ArgStackPtr-1) = *(ArgStackPtr-1) > *(ArgStackPtr); ArgStackPtr--; } -defcode("<=", lessthaneq, 0, 0, &greaterthan){ +defcode("<=", lessthaneq, 0, &greaterthan){ *(ArgStackPtr-1) = *(ArgStackPtr-1) <= *(ArgStackPtr); ArgStackPtr--; } -defcode(">=", greaterthaneq, 0, 0, &lessthaneq){ +defcode(">=", greaterthaneq, 0, &lessthaneq){ *(ArgStackPtr-1) = *(ArgStackPtr-1) >= *(ArgStackPtr); ArgStackPtr--; } -defcode("and", and, 0, 0, &greaterthaneq){ +defcode("and", and, 0, &greaterthaneq){ *(ArgStackPtr-1) = *(ArgStackPtr-1) && *(ArgStackPtr); ArgStackPtr--; } -defcode("or", or, 0, 0, &and){ +defcode("or", or, 0, &and){ *(ArgStackPtr-1) = *(ArgStackPtr-1) || *(ArgStackPtr); ArgStackPtr--; } -defcode("not", not, 0, 0, &or){ +defcode("not", not, 0, &or){ *(ArgStackPtr) = !(*(ArgStackPtr)); } /* Bitwise Words *****************************************************************************/ -defcode("band", band, 0, 0, ¬){ +defcode("band", band, 0, ¬){ *(ArgStackPtr-1) = *(ArgStackPtr-1) & *(ArgStackPtr); ArgStackPtr--; } -defcode("bor", bor, 0, 0, &band){ +defcode("bor", bor, 0, &band){ *(ArgStackPtr-1) = *(ArgStackPtr-1) | *(ArgStackPtr); ArgStackPtr--; } -defcode("bxor", bxor, 0, 0, &bor){ +defcode("bxor", bxor, 0, &bor){ *(ArgStackPtr-1) = *(ArgStackPtr-1) ^ *(ArgStackPtr); ArgStackPtr--; } -defcode("bnot", bnot, 0, 0, &bxor){ +defcode("bnot", bnot, 0, &bxor){ *(ArgStackPtr) = ~(*(ArgStackPtr)); } /* Memory Manipulation Words *****************************************************************************/ -defcode("!", store, 0, 0, &bnot){ +defcode("!", store, 0, &bnot){ *((long*)*(ArgStackPtr)) = *(ArgStackPtr-1); ArgStackPtr -= 2; } -defcode("@", fetch, 0, 0, &store){ +defcode("@", fetch, 0, &store){ *(ArgStackPtr) = *((long*)*(ArgStackPtr)); } -defcode("+!", addstore, 0, 0, &fetch){ +defcode("+!", addstore, 0, &fetch){ *((long*)*(ArgStackPtr)) += *(ArgStackPtr-1); ArgStackPtr -= 2; } -defcode("-!", substore, 0, 0, &addstore){ +defcode("-!", substore, 0, &addstore){ *((long*)*(ArgStackPtr)) -= *(ArgStackPtr-1); ArgStackPtr -= 2; } -defcode("b!", bytestore, 0, 0, &substore){ +defcode("b!", bytestore, 0, &substore){ *((char*)*(ArgStackPtr)) = (char)*(ArgStackPtr-1); ArgStackPtr -= 2; } -defcode("b@", bytefetch, 0, 0, &bytestore){ +defcode("b@", bytefetch, 0, &bytestore){ *(ArgStackPtr) = *((char*)*(ArgStackPtr)); } -defcode("b@b!", bytecopy, 0, 0, &bytefetch){ +defcode("b@b!", bytecopy, 0, &bytefetch){ } -defcode("bmove", bytemove, 0, 0, &bytecopy){ +defcode("bmove", bytemove, 0, &bytecopy){ } /* Control Flow Words *****************************************************************************/ -defcode("if", _if, 0, 1, &bytemove){ +defcode("if", _if, 1, &bytemove){ // : IF IMMEDIATE // ' 0BRANCH , \ compile 0BRANCH ArgStackPtr++; @@ -587,7 +499,7 @@ defcode("if", _if, 0, 1, &bytemove){ // ; } -defcode("then", _then, 0, 1, &_if){ +defcode("then", _then, 1, &_if){ // : THEN IMMEDIATE // DUP EXEC(dup); @@ -603,7 +515,7 @@ defcode("then", _then, 0, 1, &_if){ // ; } -defcode("else", _else, 0, 1, &_then){ +defcode("else", _else, 1, &_then){ // : ELSE IMMEDIATE // ' BRANCH , \ definite branch to just over the false-part ArgStackPtr++; @@ -634,7 +546,7 @@ defcode("else", _else, 0, 1, &_then){ /* Debugging Words *****************************************************************************/ -defcode("printw", printw, 0, 0, &_else){ +defcode("printw", printw, 0, &_else){ word_t* word = (word_t*)*(ArgStackPtr); long* bytecode = word->code; ArgStackPtr--; @@ -680,7 +592,7 @@ defcode("printw", printw, 0, 0, &_else){ } } -defcode("printallw", printallw, 0, 0, &printw){ +defcode("printallw", printallw, 0, &printw){ const word_t* word = (word_t*)latest_val; while(word) { @@ -689,7 +601,7 @@ defcode("printallw", printallw, 0, 0, &printw){ } } -defcode("printdefw", printdefw, 0, 0, &printallw){ +defcode("printdefw", printdefw, 0, &printallw){ const word_t* word = (word_t*)latest_val; while(word != &printdefw) { @@ -703,43 +615,11 @@ defcode("printdefw", printdefw, 0, 0, &printallw){ /* Main *****************************************************************************/ -static void run_tests(void); - int main(int argc, char** argv) { - run_tests(); ArgStackPtr = ArgStack - 1; latest_val = (long)&printdefw; EXEC(quit); return 0; } -/* Unit Tests - *****************************************************************************/ -static char* Current_Test_Desc; - -#define TEST(desc) \ - Current_Test_Desc = desc; \ - test_setup(); \ - for(int i=0; i == 0; i++) - -#define CHECK(expr) \ - if (!(expr)) { \ - test_setup(); \ - printf(__FILE__ ":%d:0:FAIL:%s\n\t" #expr "\n", __LINE__-1, Current_Test_Desc); \ - continue; \ - } - -static void test_setup(void) -{ - ArgStackPtr = ArgStack - 1; - CodePtr = 0; - latest_val = (long)&printw; -} - -static void run_tests(void) { - TEST("Expected 0 to be 1"){ - CHECK(0 == 1); - } -} - diff --git a/source/slvm/slvm.h b/source/slvm/slvm.h new file mode 100644 index 0000000..58c8596 --- /dev/null +++ b/source/slvm/slvm.h @@ -0,0 +1,93 @@ +/** + @file slvm.h + @brief TODO: Describe this file + $Revision$ + $HeadURL$ + */ +#ifndef SLVM_H +#define SLVM_H + +/** + This type represents a pointer to a function handler for executing a word. + For built-in words this typically points to the C function that implements + the word. For compiled words, this typically points to the docolon function. + + @param code This is a pointer to the next bytecode instruction to execute. + For built-in words this pointer is 0. + */ +typedef void (*codeword_t)(long* code); + +/** + This structure contains all of the relevant attributes of a word definition +*/ +typedef struct word_t { + /** Pointer to the next most recently defined word in the dictionary. */ + struct word_t const* link; + /** A collection of flags describing attributes of the word. */ + struct { + long f_hidden : 1; /*< Flag if this word should be hidden from the interpreter */ + long f_immed : 1; /*< flag if this word should be executed at compile time */ + long padding : 6; /*< Pads the flags to 8-bits */ + long codesize : 24; /*< The lenght of the bytecode section of the word */ + } flags; + /** Pointer to the null terminated string that holds the name of the word. */ + char const* name; + /** + * Pointer to the execution handler for this word. For words defined in C + * This points to the implementation function. For words defined in + * bytecode this will point to the docolon function. */ + codeword_t codeword; + /** + * A pointer to the list of instructions that make up this word. For words + * defined in C this will be 0u (NULL). */ + long* code; +} word_t; + +/** Execute a built-in word directly */ +#define EXEC(word) (word).codeword((word).code) + +/** The maximum number of entries that can be on the argument stack */ +#ifndef ARG_STACK_SIZE +#define ARG_STACK_SIZE 32 +#endif + +/** + * Define a built-in word that executes native code */ +#define defcode(name_str,c_name,immed,prev) \ + static void c_name##_code(long* code); \ + static word_t const c_name = { \ + prev, \ + { 0, immed, 0, 0 }, \ + name_str, \ + &c_name##_code, \ + 0 \ + }; \ + static void c_name##_code(long* inst_ptr) \ + +/** + * Define a built-in word representing a variable with the provided initial value */ +#define defvar(name_str,c_name,immed,prev,initial) \ + static long c_name##_val = initial; \ + defcode(name_str,c_name,immed,prev) { \ + ArgStackPtr++; \ + *(ArgStackPtr) = (long)&(c_name##_val); \ + } + +/** + * Define a built-in word representing a constant with the provided value */ +#define defconst(name_str,c_name,immed,prev,value) \ + static long const c_name##_val = value; \ + defcode(name_str,c_name,immed,prev) { \ + ArgStackPtr++; \ + *(ArgStackPtr) = c_name##_val; \ + } + +/** + * This is the "inner" interpreter. This function is responsible for running + * the threaded code that make up colon defintions. + * + * @param code This is a pointer to the next instruction to be executed. + * */ +void docolon(long* code); + +#endif /* SLVM_H */ -- 2.52.0