aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2025-01-26 20:33:20 -0500
committerClyne Sullivan <clyne@bitgloo.com>2025-01-26 20:33:20 -0500
commiteb3ea1994428e25e4866afb0ca6ad4edfce5ae8c (patch)
treead1145464172ae38398d7aa77d49a950dac27c98
parent9307097160390b384907c193aca0d6703ab63516 (diff)
interpret entirely in foci
-rw-r--r--foci.c85
-rw-r--r--foci.h2
-rw-r--r--main.c23
3 files changed, 56 insertions, 54 deletions
diff --git a/foci.c b/foci.c
index 6168b35..60c4fca 100644
--- 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 3f745a5..c61e302 100644
--- 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 66dcce3..4429d2d 100644
--- 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;