isolate foci code

main
Clyne 4 weeks ago
parent 1d3ef290df
commit 2a45736130
Signed by: clyne
GPG Key ID: 3267C8EBF3F9AFC7

@ -1,2 +1,6 @@
CC := gcc
CFLAGS := -O3 -ggdb -g3 -Wall -Wextra
all:
gcc -O3 -ggdb -g3 main.c -o main -Wall -Wextra #-flto
$(CC) $(CFLAGS) -c foci.c
$(CC) $(CFLAGS) main.c foci.o -o main

168
foci.c

@ -0,0 +1,168 @@
#include "foci.h"
#include <stdio.h> // puts
#include <stdlib.h> // strtol
#include <string.h> // strncmp
#define END_OF(arr) ((arr) + (sizeof((arr)) / sizeof(*(arr))))
static intptr_t dstack[32];
static intptr_t **rstack[32];
static intptr_t dict[8192] = {
0, 10
};
#define state dict[0]
#define base dict[1]
#define begin dict[2]
static intptr_t *here = &begin;
static struct word_t *latest;
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; }
void fexit(void) { if (rp < END_OF(rstack)) { pp = *rp++; NEXT; } }
NAKED void compname(void)
{
static int ch;
STASH;
for (;;) {
extern int getchar(void);
ch = getchar();
if (ch <= 0x20)
break;
*(unsigned char *)here += 1;
((char *)here)[*(unsigned char *)here] = ch;
}
here = (intptr_t *)((intptr_t)here + *(unsigned char *)here);
RESTORE;
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; }
N(rot, "rot", &w_swap) { tmp = sp[0]; sp[0] = sp[2]; sp[2] = sp[1];
sp[1] = tmp; NEXT; }
N(peek, "@", &w_rot) { *sp = *(intptr_t *)*sp; NEXT; }
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; }
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(comp, "]", &w_intr) { state = -1; NEXT; }
N(comma, ",", &w_comp) { *here++ = *sp++; NEXT; }
W(cell, "cell", &w_comma) LIT(sizeof(*sp)), END
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(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
W(inc, "1+", &w_dec) LIT(1), add, END
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
I(semic, ";", &w_colon) LIT(fexit), comma, LIT(&latest), poke, intr, END
I(literal, "literal", &w_semic) LIT(push), comma, comma, END
#define LATEST &w_literal
void call(void *ptr)
{
pp = ptr;
((void (*)())*pp)();
}
void parse_word(const char *buf, const char *s)
{
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;
}
tmp = saved_tmp;
sp = saved_sp;
rp = saved_rp;
pp = saved_pp;
if (l == 0) {
char *end;
long n = strtol(buf, &end, base);
if (*end == '\0') {
if (state) {
*here++ = (intptr_t)push;
*here++ = n;
} else {
*--sp = n;
}
} else {
puts("word not found");
}
} else {
if (state && !(l->attr & ATTR_IMMEDIATE)) {
if (!(l->attr & ATTR_NATIVE)) {
*here++ = (intptr_t)enter;
*here++ = (intptr_t)l->body;
} else {
*here++ = (intptr_t)l->body[0];
}
} else {
call(l->body);
}
}
saved_tmp = tmp;
saved_sp = sp;
saved_rp = rp;
saved_pp = pp;
}
void init(void)
{
saved_tmp = 0;
saved_sp = END_OF(dstack);
saved_rp = END_OF(rstack);
saved_pp = 0;
latest = LATEST;
}
int depth(void)
{
return END_OF(dstack) - saved_sp;
}
int compiling(void)
{
return state;
}
void define(struct word_t *w)
{
w->prev = latest;
latest = w;
}

@ -0,0 +1,62 @@
#ifndef FOCI_H
#define FOCI_H
#include <stdint.h>
#define NAKED __attribute__((naked))
#define ATTR_NATIVE (1 << 7)
#define ATTR_IMMEDIATE (1 << 6)
#define ATTR_LEN (0x3F)
#define WORD(name, tname, prev, attr) \
extern const void *name##_body[]; \
struct word_t w_##name = { \
name##_body, prev, attr + sizeof(tname) - 1, tname \
}; \
const void *name##_body[] = {
#define LIT(x) push, (void *)(x)
#define FTH(w) enter, (w##_body)
#define END fexit, };
#define NATIVE(name, tname, prev, attr) \
extern const void *name##_body[]; \
NAKED void name(void); \
struct word_t w_##name = { \
name##_body, prev, \
(attr | ATTR_NATIVE) + sizeof(tname) - 1, tname \
}; \
const void *name##_body[] = { name, fexit }; \
NAKED void name(void)
#define W(name, tname, prev) WORD(name, tname, prev, 0)
#define I(name, tname, prev) WORD(name, tname, prev, ATTR_IMMEDIATE)
#define N(name, tname, prev) NATIVE(name, tname, prev, 0)
#define C(name, tname, prev) NATIVE(name, tname, prev, ATTR_IMMEDIATE)
#define STASH asm("push %r12; push %r13; push %r14; push %r15")
#define RESTORE asm("pop %r15; pop %r14; pop %r13; pop %r12")
#define NEXT { goto *(*++pp); }
struct word_t
{
const void **body;
struct word_t *prev;
unsigned char attr;
char name[];
} __attribute__ ((packed));
register intptr_t tmp asm("r12");
register intptr_t * sp asm("r13"); // pointer to stack cells
register intptr_t *** rp asm("r14"); // stack of pp
register intptr_t ** pp asm("r15"); // pointer to ip
void init(void);
int depth(void);
int compiling(void);
void parse_word(const char *buf, const char *s);
void define(struct word_t *w);
void fexit(void); // internal use only
#endif // FOCI_H

190
main.c

@ -1,139 +1,10 @@
#include <stdint.h>
#define NAKED __attribute__((naked))
#define END_OF(arr) ((arr) + (sizeof((arr)) / sizeof(*(arr))))
#define ATTR_NATIVE (1 << 7)
#define ATTR_IMMEDIATE (1 << 6)
#define ATTR_LEN (0x3F)
#define WORD(name, tname, prev, attr) \
extern const void *name##_body[]; \
struct word_t w_##name = { \
name##_body, prev, attr + sizeof(tname) - 1, tname \
}; \
const void *name##_body[] = {
#define LIT(x) push, (void *)(x)
#define FTH(w) enter, (w##_body)
#define END fexit, };
#define NATIVE(name, tname, prev, attr) \
extern const void *name##_body[]; \
NAKED void name(void); \
struct word_t w_##name = { \
name##_body, prev, \
(attr | ATTR_NATIVE) + sizeof(tname) - 1, tname \
}; \
const void *name##_body[] = { name, fexit }; \
NAKED void name(void)
#define W(name, tname, prev) WORD(name, tname, prev, 0)
#define I(name, tname, prev) WORD(name, tname, prev, ATTR_IMMEDIATE)
#define N(name, tname, prev) NATIVE(name, tname, prev, 0)
#define C(name, tname, prev) NATIVE(name, tname, prev, ATTR_IMMEDIATE)
#define NEXT { goto *(*++pp); }
struct word_t
{
const void **body;
struct word_t *prev;
unsigned char attr;
char name[];
} __attribute__ ((packed));
static intptr_t dstack[32];
static intptr_t **rstack[32];
static intptr_t dict[8192] = {
0, 10
};
#define state dict[0]
#define base dict[1]
#define begin dict[2]
static intptr_t *here = &begin;
static struct word_t *latest;
register intptr_t tmp asm("r12");
register intptr_t * sp asm("r13"); // pointer to stack cells
register intptr_t *** rp asm("r14"); // stack of pp
register intptr_t ** pp asm("r15"); // pointer to ip
#define STASH asm("push %r12; push %r13; push %r14; push %r15")
#define RESTORE asm("pop %r15; pop %r14; pop %r13; pop %r12")
NAKED void dot(void);
NAKED void enter(void) { *--rp = ++pp; pp = (intptr_t **)*pp; goto *(*pp); }
NAKED void push(void) { *--sp = (intptr_t)*++pp; NEXT; }
void fexit(void) { if (rp < END_OF(rstack)) { pp = *rp++; NEXT; } }
NAKED void compname(void)
{
static int ch;
STASH;
for (;;) {
extern int getchar(void);
ch = getchar();
if (ch <= 0x20)
break;
*(unsigned char *)here += 1;
((char *)here)[*(unsigned char *)here] = ch;
}
here = (intptr_t *)((intptr_t)here + *(unsigned char *)here);
RESTORE;
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; }
N(rot, "rot", &w_swap) { tmp = sp[0]; sp[0] = sp[2]; sp[2] = sp[1];
sp[1] = tmp; NEXT; }
N(peek, "@", &w_rot) { *sp = *(intptr_t *)*sp; NEXT; }
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; }
N(mul, "*", &w_sub) { sp[1] *= sp[0]; ++sp; NEXT; }
N(div, "/", &w_mul) { sp[1] /= sp[0]; ++sp; NEXT; }
N(mod, "mod", &w_div) { 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(comp, "]", &w_intr) { state = -1; NEXT; }
N(comma, ",", &w_comp) { *here++ = *sp++; NEXT; }
W(cell, "cell", &w_comma) LIT(sizeof(*sp)), END
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
N(dot, ".", &w_latest) ;
W(negate, "negate", &w_dot) LIT(-1), mul, END
W(invert, "invert", &w_negate) LIT(-1), xor, END
W(dec, "1-", &w_invert) LIT(1), sub, END
W(inc, "1+", &w_dec) LIT(1), add, END
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
I(semic, ";", &w_colon) LIT(fexit), comma, LIT(&latest), poke, intr, END
I(literal, "literal", &w_semic) LIT(push), comma, comma, END
#define LATEST &w_literal
#include "foci.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
extern long strtol(char *, char **, int);
NAKED void dot() {
N(dot, ".", 0) {
STASH;
printf("%ld ", *sp);
RESTORE;
@ -141,13 +12,12 @@ NAKED void dot() {
NEXT;
}
static void call(void *ptr);
static void init(void);
int main()
{
char buf[128];
init();
define(&w_dot);
for (;;) {
char c;
@ -164,59 +34,11 @@ int main()
if (strcmp(buf, "bye") == 0)
break;
struct word_t *l;
for (l = latest; l; l = l->prev) {
const int ln = l->attr & ATTR_LEN;
parse_word(buf, s);
if (s - buf == ln && !strncmp(buf, l->name, ln))
break;
}
if (l == 0) {
char *end;
long n = strtol(buf, &end, base);
if (*end == '\0') {
if (state) {
*here++ = (intptr_t)push;
*here++ = n;
} else {
*--sp = n;
}
} else {
puts("word not found");
}
} else {
if (state && !(l->attr & ATTR_IMMEDIATE)) {
if (!(l->attr & ATTR_NATIVE)) {
*here++ = (intptr_t)enter;
*here++ = (intptr_t)l->body;
} else {
*here++ = (intptr_t)l->body[0];
}
} else {
call(l->body);
}
}
printf(state ? "compiled <%ld>\n" : "ok <%ld>\n",
(END_OF(dstack) - sp));
printf(compiling() ? "compiled <%d>\n" : "ok <%d>\n", depth());
}
return 0;
}
void init(void)
{
sp = END_OF(dstack);
rp = END_OF(rstack);
pp = 0;
latest = LATEST;
}
void call(void *ptr)
{
pp = ptr;
((void (*)())*pp)();
}

Loading…
Cancel
Save