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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
/**
* Alee Forth: A portable and concise Forth implementation in modern C++.
* Copyright (C) 2023 Clyne Sullivan <clyne@bitgloo.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef ALEEFORTH_DICTIONARY_HPP
#define ALEEFORTH_DICTIONARY_HPP
#include "config.hpp"
#include "types.hpp"
#include "ctype.hpp"
#include <algorithm>
#include <cstddef>
#include <cstdint>
/**
* Dictionary entry format:
* - 1 information byte
* bits 0..4: Length of name (L)
* bit 5: Immediate?
* bits 6..15: Distance to next entry (negative)
* - L bytes of name
* - 0+ bytes for address alignment
* - 0+ bytes of entry's data...
*/
struct Dictionary
{
/**
* The beginning of the dictionary is used for "internal" variables.
*/
constexpr static Addr Base = 0;
constexpr static Addr Here = sizeof(Cell);
constexpr static Addr Latest = sizeof(Cell) * 2;
constexpr static Addr Compiling = sizeof(Cell) * 3;
constexpr static Addr CompToken = sizeof(Cell) * 4;
constexpr static Addr Source = sizeof(Cell) * 5;
constexpr static Addr SourceLen = sizeof(Cell) * 6;
constexpr static Addr Input = sizeof(Cell) * 7; // len data...
constexpr static Addr InputCells = 80; // bytes!
constexpr static Addr Begin = sizeof(Cell) * 8 + InputCells;
constexpr static Cell Immediate = (1 << 5);
/**
* Dictionary data can be stored on any read-write interface.
* You must create a dictionary class that inherits Dictionary and
* implement these functions. See `memdict.hpp` for a simple block-of-
* memory implementation.
*/
virtual Cell read(Addr) const noexcept = 0;
virtual void write(Addr, Cell) noexcept = 0;
virtual uint8_t readbyte(Addr) const noexcept = 0;
virtual void writebyte(Addr, uint8_t) noexcept = 0;
virtual unsigned long int capacity() const noexcept = 0;
/**
* Does initial dictionary setup, required before use for execution.
*/
void initialize();
LIBALEE_SECTION
Addr here() const noexcept { return read(Here); }
LIBALEE_SECTION
void here(Addr l) noexcept { write(Here, l); }
LIBALEE_SECTION
Addr latest() const noexcept { return read(Latest); }
LIBALEE_SECTION
void latest(Addr l) noexcept { write(Latest, l); }
// Aligns the given address.
static Addr aligned(Addr);
// Aligns `here`.
Addr alignhere() noexcept;
// Advances `here` by the given number of bytes.
Addr allot(Cell) noexcept;
// Stores value to `here`, then adds sizeof(Cell) to `here`.
void add(Cell) noexcept;
/**
* Uses add() to store a new definition entry starting at `here`.
* The entry does not become active until a semicolon is executed.
*/
void addDefinition(Word) noexcept;
/**
* Searches the dictionary for an entry for the given word.
* Returns zero if not found.
*/
Addr find(Word) noexcept;
/**
* Given the address of a dictionary entry, produces the execution token
* for that entry.
*/
Addr getexec(Addr) noexcept;
/**
* Reads the next word from the input buffer.
* Returns an empty word if the buffer is empty or entirely read.
*/
Word input() noexcept;
bool hasInput() const noexcept;
/**
* Checks if this dictionary's word is equivalent to the given string/size.
*/
bool equal(Word, const char *, unsigned) const noexcept;
/**
* Checks if two words in this dictionary's word are equivalent.
*/
bool equal(Word, Word) const noexcept;
// Used for case-insensitive comparison between two iterators.
template<typename Iter1, typename Iter2>
LIBALEE_SECTION
constexpr static bool equal(Iter1 b1, Iter1 e1, Iter2 b2) {
return std::equal(b1, e1, b2, eqchars);
}
virtual ~Dictionary() {};
private:
// Case-insensitive comparison.
LIBALEE_SECTION
constexpr static bool eqchars(char c1, char c2) {
if (isalpha(static_cast<uint8_t>(c1)))
c1 |= 32;
if (isalpha(static_cast<uint8_t>(c2)))
c2 |= 32;
return c1 == c2;
}
};
#endif // ALEEFORTH_DICTIONARY_HPP
|