/** * Alee Forth: A portable and concise Forth implementation in modern C++. * Copyright (C) 2023 Clyne Sullivan * * 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 . */ #include "dictionary.hpp" #include Addr Dictionary::allot(Cell amount) { Addr old = here; here += amount; return old; } void Dictionary::add(Cell value) { write(allot(sizeof(Cell)), value); } Addr Dictionary::aligned(Addr addr) const noexcept { if (addr & (sizeof(Cell) - sizeof(uint8_t))) addr = (addr + sizeof(Cell)) & ~(sizeof(Cell) - sizeof(uint8_t)); return addr; } Addr Dictionary::alignhere() { here = aligned(here); return here; } void Dictionary::addDefinition(Word word) { add(word.size()); for (unsigned i = 0; i < word.size(); ++i) writebyte(allot(1), readbyte(word.start + i)); alignhere(); } Addr Dictionary::find(Word word) { Addr lt = latest, oldlt; do { oldlt = lt; const Cell l = read(lt); const Addr len = l & 0x1F; const Word lw { static_cast(lt + sizeof(Cell)), static_cast(lt + sizeof(Cell) + len) }; if (equal(word, lw)) return lt; else lt -= l >> 6; } while (lt != oldlt); return 0; } Addr Dictionary::getexec(Addr addr) { const auto len = read(addr) & 0x1F; return aligned(addr + sizeof(Cell) + len); } Word Dictionary::input() { const auto len = read(Dictionary::Input); if (len == 0) return {}; Addr wordstart = Dictionary::Input + sizeof(Cell) + Dictionary::InputCells - len; Addr wordend = wordstart; auto cnt = len; while (cnt) { auto b = readbyte(wordend); if (isspace(b) || b == '\0') { if (wordstart != wordend) { Word word {wordstart, wordend}; writebyte(Dictionary::Input, cnt - 1); return word; } else { ++wordstart; } } ++wordend; --cnt; } return {}; } bool Dictionary::equal(Word word, std::string_view sv) const { if (sv.size() != word.end - word.start) return false; for (unsigned i = 0; i < sv.size(); ++i) { if (sv[i] != readbyte(word.start + i)) return false; } return true; } bool Dictionary::equal(Word word, Word other) const { if (word.size() != other.size()) return false; for (unsigned i = 0; i < word.size(); ++i) { if (readbyte(word.start + i) != readbyte(other.start + i)) return false; } return true; }