aboutsummaryrefslogtreecommitdiffstats
path: root/forthmachine.c
diff options
context:
space:
mode:
authordan <[email protected]>2023-06-02 16:22:29 -0400
committerdan <[email protected]>2023-06-02 16:22:29 -0400
commitac8a2fd77f7661b60cf2b272090ece67f65951db (patch)
treed45442d8bcf5c40febb85fc35d02c6c4f1d3684e /forthmachine.c
parent558b0646c5580454dd35a6bdee07bcc711db134e (diff)
downloadforth-ac8a2fd77f7661b60cf2b272090ece67f65951db.tar.gz
forth-ac8a2fd77f7661b60cf2b272090ece67f65951db.tar.bz2
forth-ac8a2fd77f7661b60cf2b272090ece67f65951db.zip
refactor: always output via buffer
Diffstat (limited to 'forthmachine.c')
-rw-r--r--forthmachine.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/forthmachine.c b/forthmachine.c
new file mode 100644
index 0000000..91c77ff
--- /dev/null
+++ b/forthmachine.c
@@ -0,0 +1,66 @@
+#include "forthmachine.h"
+#include <string.h>
+#include "drhstrings.h"
+/****/
+
+forthmachine* forthmachine_new() {
+ forthmachine* fm = (forthmachine*)malloc(sizeof(forthmachine));
+ fm->ot = optable_new();
+ fm->s = stack_new();
+ fm->outputbuffer = (char*)malloc(sizeof(char) * MAX_OUTPUT_BUFFER_SIZE);
+ strcpy(fm->outputbuffer, "");
+ return fm;
+}
+
+static void op_exec(wordop* op, forthmachine* fm, char *word, int len, char* line, int* i) {
+ switch (op->optype) {
+ case script:
+ forthmachine_eval(fm, op->scriptlen, op->script);
+ break;
+ case builtin:
+ op->op(fm);
+ break;
+ case directive:
+ op->directive(fm, len, line, i);
+ break;
+ case compiled:
+ for (int j = 0; j < op->oplistlen; j++) {
+ if (op->oplist[j].isliteral) {
+ stack_push(fm->s, op->oplist[j].literal);
+ } else {
+ op_exec(op->oplist[j].wordop, fm, word, len, line, i);
+ }
+ }
+ break;
+ }
+}
+
+static void forthmachine_exec(forthmachine* fm, char *word, int len, char* line, int* i) {
+ wordop* op = optable_getop(fm->ot, word);
+ if (op) {
+ op_exec(op, fm, word, len, line, i);
+ } else if (isnumber(word)) {
+ stack_push(fm->s, atoi(word));
+ }
+}
+
+void forthmachine_eval(forthmachine* fm, int len, char* line) {
+ char word[WORD_LEN_LIMIT];
+ int wordi = 0;
+ for (int i = 0; i < len; i++) {
+ if (notdelim(line[i]) && wordi < WORD_LEN_LIMIT - 1) {
+ word[wordi++] = line[i];
+ } else { // end of word
+ if (wordi > 0) { // don't exec an empty string
+ word[wordi] = '\0';
+ forthmachine_exec(fm, word, len, line, &i);
+ }
+ // start new word
+ wordi = 0;
+ }
+ // end of input string
+ if (line[i] == '\0') {
+ return;
+ }
+ }
+}