]> code.bitgloo.com Git - clyne/foci.git/commitdiff
interpret entirely in foci
authorClyne Sullivan <clyne@bitgloo.com>
Mon, 27 Jan 2025 01:33:20 +0000 (20:33 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Mon, 27 Jan 2025 01:33:20 +0000 (20:33 -0500)
foci.c
foci.h
main.c

diff --git a/foci.c b/foci.c
index 6168b35e8ed8625467ce431133d233ae212d8df4..60c4fcac6d2e63e88e9a616a0d8216707418efa8 100644 (file)
--- a/foci.c
+++ b/foci.c
@@ -28,11 +28,10 @@ static intptr_t dict[1000] = {
 #define LATEST dict[2]
 #define begin  dict[3]
 static intptr_t *here = &begin;
+static char *in;
 
-static intptr_t     saved_tmp;
 static intptr_t *   saved_sp;
 static intptr_t *** saved_rp;
-static intptr_t **  saved_pp;
 
 NAKED void enter(void) { *--rp = ++pp; pp = (intptr_t **)*pp; goto *(*pp); }
 NAKED void  push(void) { *--sp = (intptr_t)*++pp; NEXT; }
@@ -40,22 +39,21 @@ NAKED void  push(void) { *--sp = (intptr_t)*++pp; NEXT; }
 
 NAKED void compname(void)
 {
-    static int ch;
-
     STASH;
     *(unsigned char *)here = 0;
-    for (;;) {
-        ch = foci_getchar();
 
-        if (ch <= 0x20)
+    for (; *in <= ' '; in++) {
+        if (*in == '\0')
             break;
+    }
 
+    for (; *in > ' '; in++) {
         *(unsigned char *)here += 1;
-        ((char *)here)[*(unsigned char *)here] = ch;
+        ((char *)here)[*(unsigned char *)here] = *in;
     }
+
     RESTORE;
     *--sp = *(unsigned char *)here;
-
     NEXT;
 }
 
@@ -71,6 +69,9 @@ int compare(const char *a, const char *b, int l)
 
 const struct word_t *lookup_p(const char *s, int len)
 {
+    if (len < 1)
+        return 0;
+
     for (const struct word_t *l = (const struct word_t *)LATEST; l; l = l->prev) {
         if (len == (l->attr & ATTR_LEN) && !compare(s, l->name, len))
             return l;
@@ -147,19 +148,25 @@ W(hex,     "hex",    &w_decimal) LIT(16), LIT(&BASE), poke, END
 N(dot,    ".",      &w_hex) ;
 #define LATEST_INIT &w_dot
 
-void call(void *ptr)
+void enter_forth(void *ptr)
 {
+    STASH;
+    sp = saved_sp;
+    rp = saved_rp;
     pp = ptr;
+
     ((void (*)())*pp)();
+
+    saved_sp = sp;
+    saved_rp = rp;
+    RESTORE;
 }
 
-NAKED
-void dot()
+__attribute__((noinline))
+static void dotimpl(intptr_t n)
 {
     static char dotbuf[16];
 
-    STASH;
-    intptr_t n = *sp;
     char *s = dotbuf + sizeof(dotbuf);
     int neg = n < 0;
     if (neg) n *= -1;
@@ -172,7 +179,13 @@ void dot()
     while (*s)
         foci_putchar(*s++);
     foci_putchar(' ');
+}
 
+NAKED
+void dot()
+{
+    STASH;
+    dotimpl(*sp);
     RESTORE;
     ++sp;
     NEXT;
@@ -201,24 +214,19 @@ intptr_t parse_number(const char *s, const char **endp, int b)
     return neg ? n * -1 : n;
 }
 
-void parse_word(const char *buf, const char *s)
+static void parse_word(const char *start, const char *end)
 {
-    const struct word_t *l = lookup_p(buf, s - buf);
-
-    tmp = saved_tmp;
-    sp = saved_sp;
-    rp = saved_rp;
-    pp = saved_pp;
+    const struct word_t *l = lookup_p(start, end - start);
 
     if (l == 0) {
-        const char *end;
-        intptr_t n = parse_number(buf, &end, BASE);
-        if (*end == '\0') {
+        const char *nend;
+        intptr_t n = parse_number(start, &nend, BASE);
+        if (nend == end) {
             if (state) {
                 *here++ = (intptr_t)push;
                 *here++ = n;
             } else {
-                *--sp = n;
+                *--saved_sp = n;
             }
         } else {
             const char *err = "word not found";
@@ -234,22 +242,35 @@ void parse_word(const char *buf, const char *s)
                 *here++ = (intptr_t)l->body[0];
             }
         } else {
-            call(l->body);
+            enter_forth(l->body);
         }
     }
+}
 
-    saved_tmp = tmp;
-    saved_sp = sp;
-    saved_rp = rp;
-    saved_pp = pp;
+void interpret(void)
+{
+    static char buf[128];
+    char *s = buf - 1;
+
+    do *++s = foci_getchar();
+    while (*s && *s != '\n' && *s != '\r');
+    *s = '\0';
+
+    char *start = buf;
+    for (in = buf; in <= s; in++) {
+        if (*in <= ' ') {
+            if (start != in)
+                parse_word(start, in);
+
+            start = in + 1;
+        }
+    }
 }
 
 void init(void)
 {
-    saved_tmp = 0;
     saved_sp = END_OF(dstack);
     saved_rp = END_OF(rstack);
-    saved_pp = 0;
 
     LATEST = (intptr_t)LATEST_INIT;
 }
diff --git a/foci.h b/foci.h
index 3f745a55196fb6eda4a73124ff74f0fa8f13efa7..c61e302ed22469bdb8c62dc39f0d0e5bd96884a2 100644 (file)
--- a/foci.h
+++ b/foci.h
@@ -85,7 +85,7 @@ extern int  foci_getchar(void);
 void init(void);
 int depth(void);
 int compiling(void);
-void parse_word(const char *buf, const char *s);
+void interpret(void);
 void define(struct word_t *w);
 
 void fexit(void); // internal use only
diff --git a/main.c b/main.c
index 66dcce359efa10c9b6b675d8928e339ac9b8c158..4429d2d7ee10fcf7fb7d0047ca72bbe01221a421 100644 (file)
--- a/main.c
+++ b/main.c
@@ -33,30 +33,11 @@ int foci_getchar(void)
 
 int main()
 {
-    char buf[128];
-
     init();
 
     for (;;) {
-        char c;
-        do c = getchar();
-        while (!isgraph(c));
-
-        char *s = buf;
-        do {
-            *s++ = c;
-            c = getchar();
-        } while (isgraph(c));
-        bool eol = c == '\n' || c == '\r';
-        *s = '\0';
-
-        if (strcmp(buf, "bye") == 0)
-            break;
-
-        parse_word(buf, s);
-
-        if (eol)
-            printf(compiling() ? "compiled <%d>\n" : "ok <%d>\n", depth());
+        interpret();
+        printf(compiling() ? "compiled <%d>\n" : "ok <%d>\n", depth());
     }
 
     return 0;