diff --git a/README.md b/README.md index b59c463..bf8bf9d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The goal of portability extends down to microcontroller targets with kilobytes o System-specific functionality is obtained through a `sys` Forth word. This word calls a user-supplied C++ function that implements the necessary (or any additional) functionality. -# Forth compatibility +## Forth compatibility Alee implements a large majority of the "core" and "core extension" [word sets](https://forth-standard.org/standard/core). Implementation is tracked in `compat.txt`, with missing words listed below. Fundamental words are built into Alee (written in C++); the rest of the implementation is in `core.fth` and `core-ext.fth`. @@ -41,3 +41,5 @@ The `msp430` target builds Alee for the [MSP430G2553](https://www.ti.com/product Configurable constants and types are defined either in the Makefile or in `types.hpp`. + text data bss dec hex filename + 8528 8 252 8788 2254 alee-msp430 diff --git a/alee-msp430.cpp b/alee-msp430.cpp index 4116118..3121dc1 100644 --- a/alee-msp430.cpp +++ b/alee-msp430.cpp @@ -17,9 +17,9 @@ */ #include "alee.hpp" +#include "libalee/ctype.hpp" #include "splitmemdict.hpp" -#include #include #include "core.fth.h" @@ -149,10 +149,10 @@ void user_sys(State& state) break; case 2: { auto addr = state.pop(); - *((uint8_t *)addr) = state.pop(); } + *reinterpret_cast(addr) = state.pop(); } break; case 3: - state.push(*((uint8_t *)state.pop())); + state.push(*reinterpret_cast(state.pop())); break; default: break; diff --git a/libalee/corewords.cpp b/libalee/corewords.cpp index 1d705f4..ced3973 100644 --- a/libalee/corewords.cpp +++ b/libalee/corewords.cpp @@ -214,22 +214,22 @@ execute: state.ip += sizeof(Cell); } -template -int findi(Comp comp) +template +int findi(Iter it, int size) { - std::size_t i = 0; + auto ptr = CoreWords::wordsarr; int wordsi = 0; - while (i < sizeof(CoreWords::wordsarr)) { - auto end = i; - while (CoreWords::wordsarr[end]) + while (ptr < CoreWords::wordsarr + sizeof(CoreWords::wordsarr)) { + auto end = ptr; + while (*end) ++end; - if (comp(CoreWords::wordsarr + i, end - i)) + if (end - ptr == size && Dictionary::equal(ptr, end, it)) return wordsi; ++wordsi; - i = end + 1; + ptr = end + 1; } return -1; @@ -237,13 +237,11 @@ int findi(Comp comp) int CoreWords::findi(const char *word) { - return ::findi([word](auto b, auto e) { - return !std::strncmp(word, b, e); }); + return ::findi(word, strlen(word)); } int CoreWords::findi(State& state, Word word) { - return ::findi([state, word](auto b, auto e) { - return state.dict.equal(word, b, e); }); + return ::findi(word.begin(&state.dict), word.size()); } diff --git a/libalee/ctype.cpp b/libalee/ctype.cpp new file mode 100644 index 0000000..a0c8dc1 --- /dev/null +++ b/libalee/ctype.cpp @@ -0,0 +1,52 @@ +/** + * 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 isspace(char c) { + return isspace(static_cast(c)); +} + +bool isdigit(uint8_t c) { + return c >= '0' && c <= '9'; +} + +bool isdigit(char c) { + return isdigit(static_cast(c)); +} + +bool isalpha(uint8_t c) { + return isupper(c) || (c >= 'a' && c <= 'z'); +} + +bool isalpha(char c) { + return isalpha(static_cast(c)); +} + +bool isupper(uint8_t c) { + return c >= 'A' && c <= 'Z'; +} + +bool isupper(char c) { + return isupper(static_cast(c)); +} + diff --git a/libalee/ctype.hpp b/libalee/ctype.hpp new file mode 100644 index 0000000..d1a1d0b --- /dev/null +++ b/libalee/ctype.hpp @@ -0,0 +1,37 @@ +/** + * 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 . + */ + +#ifndef ALEEFORTH_CTYPE_HPP +#define ALEEFORTH_CTYPE_HPP + +#include + +bool isspace(uint8_t); +bool isspace(char); + +bool isdigit(uint8_t); +bool isdigit(char); + +bool isalpha(uint8_t); +bool isalpha(char); + +bool isupper(uint8_t); +bool isupper(char); + +#endif // ALEEFORTH_CTYPE_HPP + diff --git a/libalee/dictionary.cpp b/libalee/dictionary.cpp index 8b617a9..81b5c64 100644 --- a/libalee/dictionary.cpp +++ b/libalee/dictionary.cpp @@ -16,9 +16,9 @@ * along with this program. If not, see . */ +#include "ctype.hpp" #include "dictionary.hpp" -#include #include void Dictionary::initialize() @@ -68,9 +68,8 @@ void Dictionary::addDefinition(Word word) noexcept Addr Dictionary::find(Word word) noexcept { - Addr lt = latest(), oldlt; - do { - oldlt = lt; + Addr lt = latest(); + for (;;) { const auto l = static_cast(read(lt)); const Addr len = l & 0x1F; const Word lw { @@ -80,9 +79,11 @@ Addr Dictionary::find(Word word) noexcept if (equal(word, lw)) return lt; + else if (lt == Begin) + break; else lt -= l >> 6; - } while (lt != oldlt); + } return 0; } @@ -124,29 +125,21 @@ Word Dictionary::input() noexcept return word; } -#include - bool Dictionary::equal(Word word, const char *str, unsigned len) const noexcept { - if (word.size() != len) - return false; - - return std::equal(word.begin(this), word.end(this), str, - [](auto wc, auto oc) { - return wc == oc || - (isalpha(wc) && isalpha(oc) && (wc | 32) == (oc | 32)); - }); + return word.size() == len && + equal(word.begin(this), word.end(this), str); } bool Dictionary::equal(Word word, Word other) const noexcept { - if (word.size() != other.size()) - return false; - - return std::equal(word.begin(this), word.end(this), other.begin(this), - [](auto wc, auto oc) { - return wc == oc || - (isalpha(wc) && isalpha(oc) && (wc | 32) == (oc | 32)); - }); + 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)); } diff --git a/libalee/dictionary.hpp b/libalee/dictionary.hpp index 0a2e4d3..53172d2 100644 --- a/libalee/dictionary.hpp +++ b/libalee/dictionary.hpp @@ -21,6 +21,7 @@ #include "types.hpp" +#include #include #include @@ -74,7 +75,15 @@ public: bool equal(Word, const char *, unsigned) const noexcept; bool equal(Word, Word) const noexcept; + template + static bool equal(Iter1 b1, Iter1 e1, Iter2 b2) { + return std::equal(b1, e1, b2, eqchars); + } + virtual ~Dictionary() = default; + +private: + static bool eqchars(char c1, char c2); }; #endif // ALEEFORTH_DICTIONARY_HPP diff --git a/libalee/parser.cpp b/libalee/parser.cpp index bcef963..3b14224 100644 --- a/libalee/parser.cpp +++ b/libalee/parser.cpp @@ -17,9 +17,9 @@ */ #include "corewords.hpp" +#include "ctype.hpp" #include "parser.hpp" -#include #include int Parser::parse(State& state, const char *str)