You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
3.5 KiB
C

// foci - minimal forth implementation
// Copyright (C) 2025 Clyne Sullivan <clyne@bitgloo.com>
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
// more details.
//
// You should have received a copy of the GNU General Public License along with
// this program. If not, see <http://www.gnu.org/licenses/>.
#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 * const name##_body[]; \
const struct word_t w_##name = { \
name##_body, prev, attr + sizeof(tname) - 1, tname \
}; \
const void * const name##_body[] = {
#define LIT(x) push, (void *)(x)
#define FTH(w) enter, (w##_body)
#define END fexit, };
#define NATIVE(name, tname, prev, attr) \
const void * const name##_body[2]; \
NAKED void name(void); \
const struct word_t w_##name = { \
name##_body, prev, \
(attr | ATTR_NATIVE) + sizeof(tname) - 1, tname \
}; \
const void * const name##_body[2] = { 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)
struct word_t
{
const void * const *body;
const struct word_t *prev;
unsigned char attr;
char name[];
} __attribute__ ((packed));
#ifdef FOCI_ARM
register intptr_t * sp asm("r4"); // pointer to stack cells
register intptr_t *** rp asm("r5"); // stack of pp
register intptr_t ** pp asm("r6"); // pointer to ip
register intptr_t tmp asm("r7");
#define STASH asm("push {r4-r7}")
#define RESTORE asm("pop {r4-r7}")
#define NEXT goto *(*++pp)
#endif // FOCI_ARM
#ifdef FOCI_X86_64
register intptr_t * sp asm("r12"); // pointer to stack cells
register intptr_t *** rp asm("r13"); // stack of pp
register intptr_t ** pp asm("r14"); // pointer to ip
register intptr_t tmp asm("r15");
#define STASH asm("push %r12; push %r13; push %r14")
#define RESTORE asm("pop %r14; pop %r13; pop %r12")
#define NEXT goto *(*++pp)
#endif // FOCI_X86_64
#ifdef FOCI_MSP430
register intptr_t * sp asm("r4"); // pointer to stack cells
register intptr_t *** rp asm("r5"); // stack of pp
register intptr_t ** pp asm("r6"); // pointer to ip
register intptr_t tmp asm("r7");
#define STASH asm("push r4\npush r5\npush r6")
#define RESTORE asm("pop r6\npop r5\npop r4")
#define NEXT asm("incd r6\nbr @r6")
#endif // FOCI_MSP430
extern const struct word_t w_immediate;
#define LATEST_INIT &w_immediate
extern void foci_putchar(int);
extern int foci_getchar(void);
void init(intptr_t *dictmem);
int foci_depth(void);
int compiling(void);
void interpret(void);
void define(const struct word_t *w);
void fexit(void); // internal use only
#endif // FOCI_H