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.

121 lines
3.6 KiB
C++

10 months ago
// sprit-forth: A portable subroutine-threaded Forth.
// Copyright (C) 2023 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>
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.
10 months ago
static_assert(sizeof(Cell) == sizeof(Addr));
static_assert(sizeof(Cell) == sizeof(Func));
/**
* @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 ";".
*/
10 months ago
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". */
10 months ago
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.
10 months ago
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));
/**
* @struct WordSet
* @brief Groups a set of pre-defined words and links them.
*/
10 months ago
template<typename... Words>
struct WordSet
{
std::array<Word, sizeof...(Words)> words;
Word *latest;
/**
* Stores the given pre-defined words into the `words` array and links
* their definitions together. The resulting `latest` value can be used
* to set the global LATEST.
*/
10 months ago
constexpr WordSet(Words... ws):
words {ws...}
{
auto it = words.begin();
while (++it != words.end())
it->link = it - 1;
latest = &*words.rbegin();
}
};
/**
* Wraps the given functions so that a function pointer list can be created
* and used for a word's definition.
*/
10 months ago
template<auto... funcs>
auto WordWrap = [] {
constexpr static Func list[1] = {
+[] { (funcs(), ...); }
};
return list;
};
10 months ago
enum class Error : int {
none = 1,
push,
pop,
rpush,
rpop
};
10 months ago
#endif // TYPES_HPP