aboutsummaryrefslogtreecommitdiffstats
path: root/foci.h
blob: c61e302ed22469bdb8c62dc39f0d0e5bd96884a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// 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 *name##_body[]; \
    const 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); \
    const 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;
    const struct word_t *prev;
    unsigned char attr;
    char name[];
} __attribute__ ((packed));

#ifdef FOCI_ARM
// ARM Cortex-M:
register intptr_t *   sp  asm("r0"); // pointer to stack cells
register intptr_t *** rp  asm("r1"); // stack of pp
register intptr_t **  pp  asm("r2"); // pointer to ip
register intptr_t     tmp asm("r8");
#define STASH             asm("push {r0-r2,r8}")
#define RESTORE           asm("pop {r0-r2,r8}")
#endif // FOCI_ARM

#ifdef FOCI_X86_64
// 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")
#endif // FOCI_X86_64

extern void foci_putchar(int);
extern int  foci_getchar(void);

void init(void);
int depth(void);
int compiling(void);
void interpret(void);
void define(struct word_t *w);

void fexit(void); // internal use only

#endif // FOCI_H