From cf190433cba21a61a9f42367c39862198a2eb761 Mon Sep 17 00:00:00 2001
From: Clyne Sullivan <clyne@bitgloo.com>
Date: Sat, 25 Jan 2025 07:50:34 -0500
Subject: tick and execute

---
 foci.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 53 insertions(+), 15 deletions(-)

(limited to 'foci.c')

diff --git a/foci.c b/foci.c
index d957c57..edf964f 100644
--- a/foci.c
+++ b/foci.c
@@ -17,7 +17,6 @@
 #include "foci.h"
 
 #include <stdlib.h> // strtol
-#include <string.h> // strncmp
 
 #define END_OF(arr) ((arr) + (sizeof((arr)) / sizeof(*(arr))))
 
@@ -46,6 +45,7 @@ NAKED void compname(void)
     static int ch;
 
     STASH;
+    *(unsigned char *)here = 0;
     for (;;) {
         ch = foci_getchar();
 
@@ -55,12 +55,41 @@ NAKED void compname(void)
         *(unsigned char *)here += 1;
         ((char *)here)[*(unsigned char *)here] = ch;
     }
-    here = (intptr_t *)((intptr_t)here + *(unsigned char *)here);
     RESTORE;
+    *--sp = *(unsigned char *)here;
 
     NEXT;
 }
 
+int compare(const char *a, const char *b, int l)
+{
+    for (; l--; a++, b++) {
+        if (*a != *b)
+            return 1;
+    }
+
+    return 0;
+}
+
+NAKED
+void lookup()
+{
+    static struct word_t *l;
+
+    STASH;
+    for (l = latest; l; l = l->prev) {
+        if (*(char *)here == (l->attr & ATTR_LEN) &&
+            !compare((char *)((intptr_t)here + 1), l->name, *(char *)here))
+        {
+            break;
+        }
+    }
+    RESTORE;
+
+    *--sp = (intptr_t)l;
+    NEXT;
+}
+
 N(dup,    "dup",    0)        { --sp; sp[0] = sp[1]; NEXT; }
 N(drop,   "drop",   &w_dup)   { ++sp; NEXT; }
 N(swap,   "swap",   &w_drop)  { tmp = sp[0]; sp[0] = sp[1]; sp[1] = tmp; NEXT; }
@@ -71,14 +100,16 @@ N(poke,   "!",      &w_peek)  { *(intptr_t *)sp[0] = sp[1]; sp += 2; NEXT; }
 N(cpeek,  "c@",     &w_poke)  { *sp = *(char *)*sp; NEXT; }
 N(cpoke,  "c!",     &w_cpeek) { *(char *)sp[0] = (char)sp[1]; sp += 2; NEXT; }
 N(add,    "+",      &w_cpoke) { sp[1] += sp[0]; ++sp; NEXT; }
-N(sub,    "-",      &w_add)   { sp[1] -= sp[0]; ++sp; NEXT; }
+W(addto,  "+!",     &w_add)   dup, peek, rot, add, swap, poke, END
+N(sub,    "-",      &w_addto) { sp[1] -= sp[0]; ++sp; NEXT; }
 N(mul,    "*",      &w_sub)   { sp[1] *= sp[0]; ++sp; NEXT; }
 N(ndiv,   "/",      &w_mul)   { sp[1] /= sp[0]; ++sp; NEXT; }
 N(mod,    "mod",    &w_ndiv)  { sp[1] %= sp[0]; ++sp; NEXT; }
 N(and,    "and",    &w_mod)   { sp[1] &= sp[0]; ++sp; NEXT; }
 N(or,     "or",     &w_and)   { sp[1] |= sp[0]; ++sp; NEXT; }
 N(xor,    "xor",    &w_or)    { sp[1] ^= sp[0]; ++sp; NEXT; }
-C(intr,   "[",      &w_xor)   { state = 0; NEXT; }
+N(compname, "_c",   &w_xor)   ;
+C(intr,   "[",      &w_compname) { state = 0; NEXT; }
 N(comp,   "]",      &w_intr)  { state = -1; NEXT; }
 N(comma,  ",",      &w_comp)  { *here++ = *sp++; NEXT; }
 W(cell,   "cell",   &w_comma)   LIT(sizeof(*sp)),   END
@@ -86,7 +117,8 @@ W(cellp,  "cell+",  &w_cell)    FTH(cell), add,     END
 W(cells,  "cells",  &w_cellp)   FTH(cell), mul,     END
 W(dict,   "_d",     &w_cells)   LIT(dict),          END
 W(here,   "here",   &w_dict)    LIT(&here), peek,   END
-W(latest, "latest", &w_here)    LIT(&latest), peek, END
+W(allot,  "allot",  &w_here)    LIT(&here), FTH(addto), END
+W(latest, "latest", &w_allot)   LIT(&latest), peek, END
 W(negate, "negate", &w_latest)  LIT(-1), mul, END
 W(invert, "invert", &w_negate)  LIT(-1), xor, END
 W(dec,    "1-",     &w_invert)  LIT(1), sub,  END
@@ -95,8 +127,8 @@ W(aligned, "aligned", &w_inc)   LIT(sizeof(*sp) - 1), add, LIT(~(sizeof(*sp) - 1
                                 and, END
 W(align,  "align",  &w_aligned) FTH(here), FTH(aligned), LIT(&here), poke, END
 W(colon,  ":",      &w_align)   FTH(here), LIT(0), comma, FTH(latest), comma,
-                                compname, FTH(align), dup, FTH(here), swap,
-                                poke, comp, END
+                                compname, FTH(allot), FTH(align), dup,
+                                FTH(here), swap, poke, comp, END
 I(semic,  ";",      &w_colon)   LIT(fexit), comma, LIT(&latest), poke, intr, END
 I(literal, "literal", &w_semic) LIT(push), comma, comma, END
 N(b,      "_b",     &w_literal) { ++pp; pp = (intptr_t **)*pp; NEXT; }
@@ -104,7 +136,9 @@ N(bz,     "_bz",    &w_literal) { ++pp; if (!*sp++) { pp = (intptr_t **)*pp; } N
 I(fif,    "if",     &w_b)       LIT(bz), comma, FTH(here), LIT(0), comma, END
 I(then,   "then",   &w_fif)     FTH(here), LIT(sizeof(intptr_t)), sub, swap, poke, END
 I(felse,  "else",   &w_then)    LIT(b), comma, FTH(here), LIT(0), comma, swap, FTH(then), END
-#define LATEST      &w_felse
+W(tick,   "\'",     &w_felse)   compname, drop, lookup, peek, END
+N(execute, "execute", &w_tick)  { pp = (intptr_t **)*sp++ - 1; NEXT; }
+#define LATEST      &w_execute
 
 void call(void *ptr)
 {
@@ -112,16 +146,20 @@ void call(void *ptr)
     ((void (*)())*pp)();
 }
 
-void parse_word(const char *buf, const char *s)
+struct word_t *lookup_p(const char *s, int len)
 {
-    struct word_t *l;
-    for (l = latest; l; l = l->prev) {
-        const int ln = l->attr & ATTR_LEN;
-
-        if (s - buf == ln && !strncmp(buf, l->name, ln))
-            break;
+    for (struct word_t *l = latest; l; l = l->prev) {
+        if (len == (l->attr & ATTR_LEN) && !compare(s, l->name, len))
+            return l;
     }
 
+    return 0;
+}
+
+void parse_word(const char *buf, const char *s)
+{
+    struct word_t *l = lookup_p(buf, s - buf);
+
     tmp = saved_tmp;
     sp = saved_sp;
     rp = saved_rp;
-- 
cgit v1.2.3