aboutsummaryrefslogtreecommitdiffstats
path: root/source/types.hpp
blob: aedc0d39ccb231d133b30d335e7fd825d7fdc3a8 (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
// sprit-forth: A portable subroutine-threaded Forth.
// Copyright (C) 2024  Clyne Sullivan <clyne@bitgloo.com>
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Library General Public License as published by
// the Free Software Foundation; either version 2 of the License, or (at your
// option) any later version.
//
// This library 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 Library General Public License for
// more details.
//
// You should have received a copy of the GNU Library General Public License
// along with this library; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.

#ifndef TYPES_HPP
#define TYPES_HPP

#include <array>
#include <cstddef>
#include <cstdint>
#include <memory>

using Cell = intptr_t;   /** Type of a dictionary's cell. */
using Addr = uintptr_t;  /** Type of a dictionary address. */
using Func = void (*)(); /** Words are built of these types of functions. */
using FuncList = Func const *; /** Words are defined as a list of Func. */

// Cells, Addrs, and Funcs must all be the same size in bytes since the
// dictionary stores all of these types of values.

static_assert(sizeof(Cell) == sizeof(Addr));
static_assert(sizeof(Cell) == sizeof(Func));

/**
 * Wraps the given functions so that a function pointer list can be created
 * and used for a word's definition.
 */
template<auto... funcs>
constexpr auto WordWrap = []() noexcept {
    constexpr static auto wrapper = +[] { (funcs(), ...); };
    return &wrapper;
}();

/**
 * @struct Word
 * @brief Structure of a word's definition.
 * A word has a name, a body (list of functions), a link to the next word
 * definition, and an immediate indicator. This structure is matched when
 * words are defined in the dictionary by ":" and ";".
 */
struct Word {
    FuncList list;        /** The word's body/definition. */
    const char *name;     /** Null-terminated string of word's name. */
    Word *link = nullptr; /** Link to next word in definition chain. */
    Cell imm = 0;         /** If non-zero, word is "immediate". */

    constexpr Word(const char *n, FuncList l):
        list(l), name(n) {}

    constexpr Word& markImmediate() noexcept {
        imm = -1;
        return *this;
    }

    constexpr bool immediate() const noexcept {
        return imm;
    }
};

// Words are built in the dictionary by the user using ":". These assertions
// ensure that the structures created by ":" match the actual structure of a
// Word exactly.

static_assert(offsetof(Word, list) == 0);
static_assert(offsetof(Word, name) == 1 * sizeof(Cell));
static_assert(offsetof(Word, link) == 2 * sizeof(Cell));
static_assert(offsetof(Word, imm)  == 3 * sizeof(Cell));
static_assert(sizeof(Word)         == 4 * sizeof(Cell));

enum class Error : int {
    none = 1,
    push,
    pop,
    rpush,
    rpop,
    noword
};

#endif // TYPES_HPP