diff --git a/libalee/corewords.cpp b/libalee/corewords.cpp index e9b9f47..62b0322 100644 --- a/libalee/corewords.cpp +++ b/libalee/corewords.cpp @@ -19,22 +19,22 @@ #include "corewords.hpp" #include "parser.hpp" -#include #include void find(State& state, Word word) { + Cell tok = 0; + Cell imm = 0; + if (auto j = state.dict.find(word); j > 0) { - state.push(state.dict.getexec(j)); - auto imm = state.dict.read(j) & Dictionary::Immediate; - state.push(imm ? 1 : -1); - } else if (auto i = CoreWords::findi(state, word); i >= 0) { - state.push(i); - state.push(i == CoreWords::Semicolon ? 1 : -1); - } else { - state.push(0); - state.push(0); + tok = state.dict.getexec(j); + imm = (state.dict.read(j) & Dictionary::Immediate) ? 1 : -1; + } else if (tok = CoreWords::findi(state, word); tok >= 0) { + imm = (tok == CoreWords::Semicolon) ? 1 : -1; } + + state.push(tok); + state.push(imm); } void CoreWords::run(Cell ins, State& state) @@ -248,35 +248,8 @@ execute: ip += sizeof(Cell); } -template -Cell findi(Iter it, std::size_t size) -{ - auto ptr = CoreWords::wordsarr; - Cell wordsi = 0; - - while (ptr < CoreWords::wordsarr + sizeof(CoreWords::wordsarr)) { - auto end = ptr; - while (*end) - ++end; - - std::size_t wordsize = end - ptr; - if (wordsize == size && Dictionary::equal(ptr, end, it)) - return wordsi; - - ++wordsi; - ptr = end + 1; - } - - return -1; -} - -Cell CoreWords::findi(const char *word) -{ - return ::findi(word, strlen(word)); -} - Cell CoreWords::findi(State& state, Word word) { - return ::findi(word.begin(&state.dict), word.size()); + return findi(word.begin(&state.dict), word.size()); } diff --git a/libalee/corewords.hpp b/libalee/corewords.hpp index d4d7ef2..25f6a6e 100644 --- a/libalee/corewords.hpp +++ b/libalee/corewords.hpp @@ -22,6 +22,8 @@ #include "types.hpp" #include "state.hpp" +#include + /** * To be implemented by the user, this function is called when the `sys` word * is executed. @@ -38,8 +40,10 @@ public: * Finds execution token that corresponds to the given word. * Returns -1 if not found. */ - static Cell findi(const char *); static Cell findi(State&, Word); + consteval static Cell findi(const char *word) { + return findi(word, std::strlen(word)); + } /** * Executes the given CoreWord execution token using the given state. @@ -55,6 +59,24 @@ public: "exit\0;\0_jmp0\0_jmp\0" "depth\0_rdepth\0_in\0_ev\0find\0" "_uma\0u<\0um/mod\0"; + +private: + template + constexpr static Cell findi(Iter it, std::size_t size) + { + const char *ptr = CoreWords::wordsarr; + + for (Cell wordsi = 0; wordsi < WordCount; ++wordsi) { + std::size_t wordsize = std::strlen(ptr); + + if (wordsize == size && Dictionary::equal(ptr, ptr + wordsize, it)) + return wordsi; + + ptr += wordsize + 1; + } + + return -1; + } }; #endif // ALEEFORTH_COREWORDS_HPP diff --git a/libalee/ctype.cpp b/libalee/ctype.cpp deleted file mode 100644 index 547cd11..0000000 --- a/libalee/ctype.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/** - * 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 "ctype.hpp" - -bool isspace(uint8_t c) { - return c == ' ' || c == '\t' || c == '\r' || c == '\n'; -} - -bool isdigit(uint8_t c) { - return c >= '0' && c <= '9'; -} - -bool isalpha(uint8_t c) { - return isupper(c) || (c >= 'a' && c <= 'z'); -} - -bool isupper(uint8_t c) { - return c >= 'A' && c <= 'Z'; -} - diff --git a/libalee/ctype.hpp b/libalee/ctype.hpp index 5842dfb..878c747 100644 --- a/libalee/ctype.hpp +++ b/libalee/ctype.hpp @@ -25,10 +25,21 @@ #include -bool isspace(uint8_t); -bool isdigit(uint8_t); -bool isalpha(uint8_t); -bool isupper(uint8_t); +constexpr inline bool isspace(uint8_t c) { + return c == ' ' || c == '\t' || c == '\r' || c == '\n'; +} + +constexpr inline bool isdigit(uint8_t c) { + return c >= '0' && c <= '9'; +} + +constexpr inline bool isupper(uint8_t c) { + return c >= 'A' && c <= 'Z'; +} + +constexpr inline bool isalpha(uint8_t c) { + return isupper(c) || (c >= 'a' && c <= 'z'); +} #endif // ALEEFORTH_CTYPE_HPP diff --git a/libalee/dictionary.cpp b/libalee/dictionary.cpp index 64c0ac2..0d225e0 100644 --- a/libalee/dictionary.cpp +++ b/libalee/dictionary.cpp @@ -16,7 +16,6 @@ * along with this program. If not, see . */ -#include "ctype.hpp" #include "dictionary.hpp" #include @@ -49,15 +48,9 @@ void Dictionary::add(Cell value) noexcept write(allot(sizeof(Cell)), value); } -Addr Dictionary::aligned(Addr addr) const noexcept +Addr Dictionary::aligned(Addr addr) { - Addr unaligned = addr & (sizeof(Cell) - sizeof(uint8_t)); - if (unaligned) { - addr += sizeof(Cell); - addr -= unaligned; - } - - return addr; + return (addr + (sizeof(Cell) - 1)) & ~(sizeof(Cell) - 1); } Addr Dictionary::alignhere() noexcept @@ -71,11 +64,12 @@ void Dictionary::addDefinition(Word word) noexcept Cell wsize = word.size(); add(wsize); + auto addr = allot(wsize); auto it = word.begin(this); const auto end = word.end(this); while (it != end) - writebyte(allot(1), *it++); + writebyte(addr++, *it++); alignhere(); } @@ -83,6 +77,7 @@ void Dictionary::addDefinition(Word word) noexcept Addr Dictionary::find(Word word) noexcept { Addr lt = latest(); + for (;;) { const Addr l = read(lt); const Addr len = l & 0x1F; @@ -159,19 +154,11 @@ Word Dictionary::input() noexcept bool Dictionary::equal(Word word, const char *str, unsigned len) const noexcept { - return word.size() == len && - equal(word.begin(this), word.end(this), str); + return word.size() == len && equal(word.begin(this), word.end(this), str); } bool Dictionary::equal(Word word, Word other) const noexcept { - return word.size() == other.size() && - equal(word.begin(this), word.end(this), other.begin(this)); -} - -bool Dictionary::eqchars(char c1, char c2) -{ - return c1 == c2 || - (isalpha(c1) && isalpha(c2) && (c1 | 32) == (c2 | 32)); + return word.size() == other.size() && equal(word.begin(this), word.end(this), other.begin(this)); } diff --git a/libalee/dictionary.hpp b/libalee/dictionary.hpp index 14366a5..b43ea2e 100644 --- a/libalee/dictionary.hpp +++ b/libalee/dictionary.hpp @@ -19,6 +19,7 @@ #ifndef ALEEFORTH_DICTIONARY_HPP #define ALEEFORTH_DICTIONARY_HPP +#include "ctype.hpp" #include "types.hpp" #include @@ -78,7 +79,7 @@ public: void latest(Addr l) noexcept { write(Latest, l); } // Aligns the given address. - Addr aligned(Addr) const noexcept; + static Addr aligned(Addr); // Aligns `here`. Addr alignhere() noexcept; // Advances `here` by the given number of bytes. @@ -123,7 +124,7 @@ public: // Used for case-insensitive comparison between two iterators. template - static bool equal(Iter1 b1, Iter1 e1, Iter2 b2) { + constexpr static bool equal(Iter1 b1, Iter1 e1, Iter2 b2) { return std::equal(b1, e1, b2, eqchars); } @@ -131,7 +132,15 @@ public: private: // Case-insensitive comparison. - static bool eqchars(char c1, char c2); + constexpr static bool eqchars(char c1, char c2) { + if (isalpha(static_cast(c1))) + c1 |= 32; + if (isalpha(static_cast(c2))) + c2 |= 32; + + return c1 == c2; + } + }; #endif // ALEEFORTH_DICTIONARY_HPP diff --git a/libalee/parser.cpp b/libalee/parser.cpp index da7ae0b..16281d3 100644 --- a/libalee/parser.cpp +++ b/libalee/parser.cpp @@ -111,12 +111,12 @@ Error Parser::parseNumber(State& state, Word word) auto ins = CoreWords::findi("_lit"); const Cell maxlit = Dictionary::Begin - CoreWords::WordCount; - if (value >= 0 && value < maxlit) { - state.dict.add(value + CoreWords::WordCount); - } else { + if (value >= 0 && value < maxlit) + value += CoreWords::WordCount; + else state.dict.add(ins); - state.dict.add(value); - } + + state.dict.add(value); } else { state.push(value); }