aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--README1
-rwxr-xr-xbuild.sh2
-rw-r--r--sorth.c95
4 files changed, 99 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..204d390
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/sorth
diff --git a/README b/README
new file mode 100644
index 0000000..cc4270e
--- /dev/null
+++ b/README
@@ -0,0 +1 @@
+bad forth in <100 lines of C
diff --git a/build.sh b/build.sh
new file mode 100755
index 0000000..f9c52b1
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,2 @@
+#!/bin/sh
+gcc -o sorth sorth.c -g3 -O0
diff --git a/sorth.c b/sorth.c
new file mode 100644
index 0000000..82cfb3a
--- /dev/null
+++ b/sorth.c
@@ -0,0 +1,95 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+long stack[1024] = {0};
+size_t stack_ptr = 0;
+bool strict = false;
+
+static void panic(const char *msg) {
+ fprintf(stderr, "%s\n", msg);
+ exit(EXIT_FAILURE);
+}
+
+static bool is(const char *s1, const char *s2) {
+ return strcmp(s1, s2) == 0;
+}
+
+static long pop(void) {
+ if (stack_ptr == 0)
+ panic("stack undeflow");
+ return stack[--stack_ptr];
+}
+
+static void push(long v) {
+ if (stack_ptr >= sizeof(stack) / sizeof(stack[0]))
+ panic("stack overflow");
+ stack[stack_ptr++] = v;
+}
+
+#define OP(X) } else if (strcmp(s, X) == 0) {
+static void exec(const char *s) {
+ if (s[0] >= '0' && s[0] <= '9') {
+ push(atol(s));
+ OP("drop")
+ pop();
+ OP("dup")
+ const long a = pop();
+ push(a); push(a);
+ OP("swap")
+ const long a = pop();
+ const long b = pop();
+ push(a); push(b);
+ OP("over")
+ const long a = pop();
+ const long b = pop();
+ push(a); push(b); push(a);
+ OP("rot")
+ const long a = pop();
+ const long b = pop();
+ const long c = pop();
+ push(b); push(a); push(c);
+ OP("+")
+ push(pop() + pop());
+ OP("-")
+ const long a = pop();
+ push(pop() - a);
+ OP("*")
+ push(pop() * pop());
+ OP("/")
+ const long a = pop();
+ push(pop() / a);
+ OP("%")
+ const long a = pop();
+ push(pop() % a);
+ OP(".s")
+ printf("\x1b[94m<%zu> ", stack_ptr);
+ for (size_t i = 0; i < stack_ptr; i++)
+ printf("%ld ", stack[i]);
+ printf("\x1b[0m\n");
+ OP(".")
+ printf("\x1b[94m%ld\x1b[0m\n", pop());
+ } else {
+ fprintf(stderr, "unrecognized word '%s'\n", s);
+ if (strict)
+ exit(EXIT_FAILURE);
+ }
+}
+
+int main(int argc, char **argv) {
+ char line[1024] = {0};
+ const char *delim = " \t\n\v\r";
+
+ if (argc > 1 && argv[1][0] == '-' && strchr(argv[1], 's'))
+ strict = true;
+
+ while (fgets(line, sizeof(line) - 1, stdin)) {
+ char *tok = strtok(line, delim);
+ while (tok != NULL) {
+ exec(tok);
+ tok = strtok(NULL, delim);
+ }
+ }
+ return 0;
+}