aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--forth.c224
-rw-r--r--optable.c159
-rw-r--r--optable.h42
-rw-r--r--stack.c40
-rw-r--r--stack.h24
5 files changed, 274 insertions, 215 deletions
diff --git a/forth.c b/forth.c
index 80ff670..e9f7637 100644
--- a/forth.c
+++ b/forth.c
@@ -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
diff --git a/stack.c b/stack.c
new file mode 100644
index 0000000..80b8ed2
--- /dev/null
+++ b/stack.c
@@ -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;
+ }
+}
diff --git a/stack.h b/stack.h
new file mode 100644
index 0000000..16fe07b
--- /dev/null
+++ b/stack.h
@@ -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