diff options
-rw-r--r-- | forth.c | 224 | ||||
-rw-r--r-- | optable.c | 159 | ||||
-rw-r--r-- | optable.h | 42 | ||||
-rw-r--r-- | stack.c | 40 | ||||
-rw-r--r-- | stack.h | 24 |
5 files changed, 274 insertions, 215 deletions
@@ -5,213 +5,12 @@ #include <unistd.h> #include <stdbool.h> -typedef int stackitem; - -typedef struct { - int size; - int maxsize; - stackitem* start; -} stack; - -stack* newstack() { - stack* s = malloc(sizeof(stack)); - s->size = 0; - s->maxsize = 1024; - s->start = malloc(sizeof(stackitem) * s->maxsize); - return s; -} - -stackitem pop(stack* s) { - if (s->size > 0) { - s->size = s->size - 1; - stackitem si = s->start[s->size]; - return si; - } else { - // tried to pop empty stack - return 0; - } -} - -stackitem peek(stack* s) { - if (s->size > 0) { - return s->start[s->size - 1]; - } else { - // tried to pop empty stack - return 0; - } -} - -void dump(stack* s) { - for (int i = 0; i < s->size; i++) { - printf("%d,", s->start[i]); - } - printf("\n"); -} - - -void push(stack *s, stackitem si) { -// fprintf(stderr, "pushing %d", si); - if (s->size >= s->maxsize) { - fprintf(stderr, "Error Stack Overflow"); - exit(1); - } else { - s->start[s->size] = si; - s->size = s->size + 1; - } -} - -void not(stack *s) { - int x = pop(s); - push(s, !x); -} - -void drop(stack *s) { - pop(s); -} - -void over(stack *s) { - int x = pop(s); - int y = pop(s); - push(s, y); - push(s, x); - push(s, y); -} - -void rot(stack *s) { - int x = pop(s); - int y = pop(s); - int z = pop(s); - push(s, y); - push(s, x); - push(s, z); -} - -void swap(stack *s) { - int x = pop(s); - int y = pop(s); - push(s, x); - push(s, y); -} - -void eq(stack *s) { - int x = pop(s); - int y = pop(s); - push(s, x == y); -} - -void add(stack *s) { - int x = pop(s); - int y = pop(s); - push(s, x + y); -} - -void mult(stack *s) { - int x = pop(s); - int y = pop(s); - push(s, x * y); -} - -void s_div(stack *s) { - int x = pop(s); - int y = pop(s); - push(s, y / x); -} - -void sub(stack *s) { - int x = pop(s); - int y = pop(s); - push(s, y - x); -} - -void s_dup(stack *s) { - int x = pop(s); - push(s, x); - push(s, x); -} - -typedef void (*stackop)(stack *); - -typedef struct { - char* word; - bool isscript; - union { - stackop op; - struct { - char* script; - int scriptlen; - }; - }; -} wordop; - -#define OPTABLE_MAX_SIZE 1024 -wordop optable[OPTABLE_MAX_SIZE] = { - {"+", false, add}, - {"-", false, sub}, - {"*", false, mult}, - {"/", false, s_div}, - {"dup", false, s_dup}, - {"dump", false, dump}, - {"not", false, not}, - {"=", false, eq}, - {"swap", false, swap}, - {"drop", false, drop}, - {"over", false, over}, - {"rot", false, rot}, -}; -int optablelen = 12; - -const int DEFINED_FUNC_MAX_LENGTH = 1024; -const int WORD_LEN_LIMIT = 255; - -int defineop(int starti, char *input) { - // code to be evaluated when function is called - char *funcscript = malloc(sizeof(char) * DEFINED_FUNC_MAX_LENGTH); - int funcscripti = 0; - - // name by which the function will be called - char *opcode = malloc(sizeof(char) * WORD_LEN_LIMIT); - int opcodei = 0; - - // skip ' ' and ':' - while (input[starti] == ' ' || input[starti] == ':') { - starti++; - } - - // get name - while (input[starti] != ' ' && opcodei < WORD_LEN_LIMIT) { - opcode[opcodei++] = input[starti++]; - } - opcode[opcodei] = '\0'; - - // get code - while (input[starti] != ';' && funcscripti < DEFINED_FUNC_MAX_LENGTH) { - funcscript[funcscripti++] = input[starti++]; - } - funcscript[funcscripti] = '\0'; - - // optable bounds check - if (optablelen >= OPTABLE_MAX_SIZE) { - // Error - fprintf(stderr, "Error: optable reached max size, failed to create new user defined operation"); - exit(1); - } - // add op to end of table, and increment size - optable[optablelen].word = opcode; - optable[optablelen].isscript = true; - optable[optablelen].script = funcscript; - optable[optablelen].scriptlen = funcscripti; - optablelen++; - return starti; -} - -wordop* getop(char *word) { - for (int i = 0; i < optablelen; i++) { - if (!strcmp(optable[i].word, word)) { - return &optable[i]; - } - } - return 0; -} +#ifndef STACK_H +#include "stack.h" +#endif +#ifndef OPTABLE_H +#include "optable.h" +#endif //https://stackoverflow.com/a/58585995 char isnumber(char *text) { @@ -234,7 +33,7 @@ void exec(stack *s, char *word) { } else if (!strcmp(word, "peek")) { printf("%d\n", peek(s)); return; - } + } wordop* op = getop(word); if (op) { if (op->isscript) { @@ -272,19 +71,14 @@ void eval(stack* s, int len, char* line) { if (!strcmp(word, "if")) { stackitem predicate = pop(s); if (!predicate) { - while (len > i && - !( + while (len > i && !( line[i-3] == 't' && line[i-2] == 'h' && line[i-1] == 'e' && line[i] == 'n' - )) { + )) { i++; } - // if (len < i + 3) { - // // error no 'then' before EOL - // exit(1); - // } } } else { exec(s, word); diff --git a/optable.c b/optable.c new file mode 100644 index 0000000..fe7409b --- /dev/null +++ b/optable.c @@ -0,0 +1,159 @@ +#include "optable.h" +#include <string.h> + +static void dump(stack* s); +static void not(stack *s); +static void drop(stack *s); +static void over(stack *s); +static void rot(stack *s); +static void swap(stack *s); +static void eq(stack *s); +static void add(stack *s); +static void mult(stack *s); +static void s_div(stack *s); +static void sub(stack *s); +static void dup(stack *s); + +static wordop optable[OPTABLE_MAX_SIZE] = { + {"+", false, add}, + {"-", false, sub}, + {"*", false, mult}, + {"/", false, s_div}, + {"dup", false, dup}, + {"dump", false, dump}, + {"not", false, not}, + {"=", false, eq}, + {"swap", false, swap}, + {"drop", false, drop}, + {"over", false, over}, + {"rot", false, rot}, +}; +static int optablelen = 12; + +int defineop(int starti, char *input) { + // name by which the function will be called + char *opcode = malloc(sizeof(char) * WORD_LEN_LIMIT); + int opcodei = 0; + + // code to be evaluated when function is called + char *funcscript = malloc(sizeof(char) * DEFINED_FUNC_MAX_LENGTH); + int funcscripti = 0; + + // skip ' ' and ':' + while (input[starti] == ' ' || input[starti] == ':') { + starti++; + } + + // get name + while (input[starti] != ' ' && opcodei < WORD_LEN_LIMIT) { + opcode[opcodei++] = input[starti++]; + } + opcode[opcodei] = '\0'; + + // get code + while (input[starti] != ';' && funcscripti < DEFINED_FUNC_MAX_LENGTH) { + funcscript[funcscripti++] = input[starti++]; + } + funcscript[funcscripti] = '\0'; + + // optable bounds check + if (optablelen >= OPTABLE_MAX_SIZE) { + // Error + fprintf(stderr, "Error: optable reached max size, failed to create new user defined operation"); + exit(1); + } + // add op to end of table, and increment size + optable[optablelen].word = opcode; + optable[optablelen].isscript = true; + optable[optablelen].script = funcscript; + optable[optablelen].scriptlen = funcscripti; + optablelen++; + return starti; +} + +wordop* getop(char *word) { + for (int i = 0; i < optablelen; i++) { + if (!strcmp(optable[i].word, word)) { + return &optable[i]; + } + } + return 0; +} + +/* Implementations of builtin functions */ + +static void dump(stack* s) { + for (int i = 0; i < s->size; i++) { + printf("%d,", s->start[i]); + } + printf("\n"); +} + +static void not(stack *s) { + int x = pop(s); + push(s, !x); +} + +static void drop(stack *s) { + pop(s); +} + +static void over(stack *s) { + int x = pop(s); + int y = pop(s); + push(s, y); + push(s, x); + push(s, y); +} + +static void rot(stack *s) { + int x = pop(s); + int y = pop(s); + int z = pop(s); + push(s, y); + push(s, x); + push(s, z); +} + +static void swap(stack *s) { + int x = pop(s); + int y = pop(s); + push(s, x); + push(s, y); +} + +static void eq(stack *s) { + int x = pop(s); + int y = pop(s); + push(s, x == y); +} + +static void add(stack *s) { + int x = pop(s); + int y = pop(s); + push(s, x + y); +} + +static void mult(stack *s) { + int x = pop(s); + int y = pop(s); + push(s, x * y); +} + +static void s_div(stack *s) { + int x = pop(s); + int y = pop(s); + push(s, y / x); +} + +static void sub(stack *s) { + int x = pop(s); + int y = pop(s); + push(s, y - x); +} + +static void dup(stack *s) { + int x = pop(s); + push(s, x); + push(s, x); +} diff --git a/optable.h b/optable.h new file mode 100644 index 0000000..d85ff3d --- /dev/null +++ b/optable.h @@ -0,0 +1,42 @@ +#include <stdio.h> +#include <stdbool.h> +#include "stack.h" + +#ifndef OPTABLE_H +#define OPTABLE_H + +#define OPTABLE_MAX_SIZE 1024 +#define DEFINED_FUNC_MAX_LENGTH 1024 +#define WORD_LEN_LIMIT 255 + +typedef void (*stackop)(stack *); + +typedef struct { + char* word; + bool isscript; + union { + stackop op; + struct { + char* script; + int scriptlen; + }; + }; +} wordop; + +/** + * defineop reads a function identifier, followed by the commands to run when the function + * is called, stopping when a semicolon is reached. + * Reading is done from the input string. + * + * returns new position of input index + * + */ +int defineop(int starti, char *input); + +/** + * getop returns the first wordop in the optable which is called by the word given as a parameter + * if none exist, returns 0 + */ +wordop* getop(char *word); + +#endif //OPTABLE_H @@ -0,0 +1,40 @@ +#include "stack.h" + +stack* newstack() { + stack* s = (stack*)malloc(sizeof(stack)); + s->size = 0; + s->maxsize = 1024; + s->start = (stackitem*)malloc(sizeof(stackitem) * s->maxsize); + return s; +} + +stackitem pop(stack* s) { + if (s->size > 0) { + s->size = s->size - 1; + stackitem si = s->start[s->size]; + return si; + } else { + // tried to pop empty stack + return 0; + } +} + +stackitem peek(stack* s) { + if (s->size > 0) { + return s->start[s->size - 1]; + } else { + // tried to pop empty stack + return 0; + } +} + +void push(stack *s, stackitem si) { +// fprintf(stderr, "pushing %d", si); + if (s->size >= s->maxsize) { + fprintf(stderr, "Error Stack Overflow"); + exit(1); + } else { + s->start[s->size] = si; + s->size = s->size + 1; + } +} @@ -0,0 +1,24 @@ +#include <stdlib.h> +#include <stdio.h> + +#ifndef STACK_H +#define STACK_H + +typedef int stackitem; + +typedef struct { + int size; + int maxsize; + stackitem* start; +} stack; + + +stack* newstack(); + +stackitem pop(stack* s); + +stackitem peek(stack* s); + +void push(stack *s, stackitem si); + +#endif |