From dac0553eb5a4bd7b8b6ce408c18bd4d2779e094f Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Fri, 24 Feb 2023 08:50:28 -0500 Subject: [PATCH] remove ParseStatus; reduce stack usage --- Makefile | 2 +- alee.cpp | 42 +++++++++++++++++++++---------------- dictionary.cpp | 57 ++++++++++++++++++++++++++------------------------ parser.cpp | 30 +++++++++++++------------- parser.hpp | 10 +++++---- types.cpp | 29 ------------------------- types.hpp | 11 ++-------- 7 files changed, 77 insertions(+), 104 deletions(-) delete mode 100644 types.cpp diff --git a/Makefile b/Makefile index 4307ca0..65dc791 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ CXXFLAGS += -std=c++17 -g3 -ggdb -O0 \ -Wall -Wextra -pedantic -Wno-vla -Werror -CXXFILES := corewords.cpp dictionary.cpp parser.cpp state.cpp types.cpp +CXXFILES := corewords.cpp dictionary.cpp parser.cpp state.cpp OBJFILES := $(subst .cpp,.o,$(CXXFILES)) LIBFILE := libalee.a EXEFILE := alee diff --git a/alee.cpp b/alee.cpp index 6c2c135..41610e4 100644 --- a/alee.cpp +++ b/alee.cpp @@ -25,23 +25,10 @@ static bool okay = false; +static void readchar(State& state); static void parseLine(Parser&, State&, std::string_view); static void parseFile(Parser&, State&, std::istream&); -static void readchar(State& state) -{ - auto len = state.dict.read(Dictionary::Input); - Addr addr = Dictionary::Input + sizeof(Cell) + - Dictionary::InputCells - len - 1; - - for (Addr i = 0; i < len; ++i, ++addr) - state.dict.writebyte(addr, state.dict.readbyte(addr + 1)); - - auto c = std::cin.get(); - state.dict.writebyte(addr, c ? c : ' '); - state.dict.write(Dictionary::Input, len + 1); -} - int main(int argc, char *argv[]) { MemDict dict; @@ -65,6 +52,20 @@ int main(int argc, char *argv[]) return 0; } +static void readchar(State& state) +{ + auto len = state.dict.read(Dictionary::Input); + Addr addr = Dictionary::Input + sizeof(Cell) + + Dictionary::InputCells - len - 1; + + for (Addr i = 0; i < len; ++i, ++addr) + state.dict.writebyte(addr, state.dict.readbyte(addr + 1)); + + auto c = std::cin.get(); + state.dict.writebyte(addr, c ? c : ' '); + state.dict.write(Dictionary::Input, len + 1); +} + static void save(State& state) { std::ofstream file ("alee.dat", std::ios::binary); @@ -106,13 +107,17 @@ void user_sys(State& state) void parseLine(Parser& parser, State& state, std::string_view line) { - auto r = parser.parse(state, line); - - if (r == ParseStatus::Finished) { + if (auto r = parser.parse(state, line); r == 0) { if (okay) std::cout << (state.compiling() ? "compiled" : "ok") << std::endl; } else { - std::cout << to_string(r) << ": " << line << std::endl; + switch (r) { + case Parser::UnknownWord: + std::cout << "word not found in: " << line << std::endl; + break; + default: + break; + } } } @@ -123,6 +128,7 @@ void parseFile(Parser& parser, State& state, std::istream& file) std::getline(file, line); if (line == "bye") exit(0); + parseLine(parser, state, line); } } diff --git a/dictionary.cpp b/dictionary.cpp index 1ac2839..cf04cb4 100644 --- a/dictionary.cpp +++ b/dictionary.cpp @@ -50,8 +50,8 @@ Addr Dictionary::alignhere() void Dictionary::addDefinition(Word word) { add(word.size()); - for (unsigned i = 0; i < word.size(); ++i) - writebyte(allot(1), readbyte(word.start + i)); + for (auto w = word.start; w != word.end; ++w) + writebyte(allot(1), readbyte(w)); alignhere(); } @@ -85,29 +85,27 @@ Addr Dictionary::getexec(Addr addr) 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)) { - if (wordstart != wordend) { - Word word {wordstart, wordend}; - writebyte(Dictionary::Input, cnt - 1); - return word; - } else { + auto len = read(Dictionary::Input); + if (len != 0) { + Addr wordstart = Dictionary::Input + sizeof(Cell) + Dictionary::InputCells + - len; + Addr wordend = wordstart; + + while (len) { + auto b = readbyte(wordend); + + if (isspace(b)) { + if (wordstart != wordend) { + writebyte(Dictionary::Input, len - 1); + return {wordstart, wordend}; + } + ++wordstart; } - } - ++wordend; - --cnt; + ++wordend; + --len; + } } return {}; @@ -115,12 +113,14 @@ Word Dictionary::input() bool Dictionary::equal(Word word, std::string_view sv) const { - if (sv.size() != static_cast(word.end - word.start)) + if (word.size() != sv.size()) return false; - for (unsigned i = 0; i < sv.size(); ++i) { - if (sv[i] != readbyte(word.start + i)) + for (auto w = word.start; w != word.end; ++w) { + if (readbyte(w) != sv.front()) return false; + + sv = sv.substr(1); } return true; @@ -131,9 +131,12 @@ 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)) + auto w = word.start, o = other.start; + while (w != word.end) { + if (readbyte(w) != readbyte(o)) return false; + + ++w, ++o; } return true; diff --git a/parser.cpp b/parser.cpp index 0883230..01dbb90 100644 --- a/parser.cpp +++ b/parser.cpp @@ -22,9 +22,7 @@ #include #include -#include - -ParseStatus Parser::parse(State& state, std::string_view& str) +int Parser::parse(State& state, std::string_view& str) { auto addr = Dictionary::Input; state.dict.write(addr, str.size() + 1); @@ -37,20 +35,20 @@ ParseStatus Parser::parse(State& state, std::string_view& str) return parseSource(state); } -ParseStatus Parser::parseSource(State& state) +int Parser::parseSource(State& state) { auto word = state.dict.input(); while (word.size() > 0) { - if (auto ret = parseWord(state, word); ret != ParseStatus::Finished) + if (auto ret = parseWord(state, word); ret) return ret; word = state.dict.input(); } - return ParseStatus::Finished; + return 0; } -ParseStatus Parser::parseWord(State& state, Word word) +int Parser::parseWord(State& state, Word word) { int ins, imm; @@ -79,21 +77,22 @@ ParseStatus Parser::parseWord(State& state, Word word) state.execute(ins); } - return ParseStatus::Finished; + return 0; } -ParseStatus Parser::parseNumber(State& state, Word word) +int Parser::parseNumber(State& state, Word word) { - char buf[word.size() + 1]; - for (unsigned i = 0; i < word.size(); ++i) + char buf[MaxCellNumberChars + 1]; + unsigned i; + for (i = 0; i < std::min(MaxCellNumberChars, word.size()); ++i) buf[i] = state.dict.readbyte(word.start + i); - buf[word.size()] = '\0'; + buf[i] = '\0'; char *p; const auto base = state.dict.read(0); const Cell l = std::strtol(buf, &p, base); - if (std::distance(buf, p) == word.size()) { + if (static_cast(std::distance(buf, p)) == word.size()) { if (state.compiling()) { state.dict.add(CoreWords::findi("_lit")); state.dict.add(l); @@ -101,10 +100,9 @@ ParseStatus Parser::parseNumber(State& state, Word word) state.push(l); } - return ParseStatus::Finished; + return 0; } else { - std::cout << "word not found: " << buf << std::endl; - return ParseStatus::NotAWord; + return UnknownWord; } } diff --git a/parser.hpp b/parser.hpp index ccd5647..8a322e2 100644 --- a/parser.hpp +++ b/parser.hpp @@ -26,12 +26,14 @@ class Parser { public: - ParseStatus parse(State&, std::string_view&); + constexpr static int UnknownWord = -1; + + int parse(State&, std::string_view&); private: - ParseStatus parseSource(State&); - ParseStatus parseWord(State&, Word); - ParseStatus parseNumber(State&, Word); + int parseSource(State&); + int parseWord(State&, Word); + int parseNumber(State&, Word); }; #endif // ALEEFORTH_PARSER_HPP diff --git a/types.cpp b/types.cpp deleted file mode 100644 index 6afe7e5..0000000 --- a/types.cpp +++ /dev/null @@ -1,29 +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 "types.hpp" - -std::string_view to_string(ParseStatus ps) -{ - switch (ps) { - case ParseStatus::Finished: return "Finished"; - case ParseStatus::NotAWord: return "Not a word"; - default: return "???"; - } -} - diff --git a/types.hpp b/types.hpp index d4f1882..b6391ba 100644 --- a/types.hpp +++ b/types.hpp @@ -20,7 +20,6 @@ #define ALEEFORTH_TYPES_HPP #include -#include struct State; @@ -28,6 +27,8 @@ using Addr = uint16_t; using Cell = int16_t; using Func = void (*)(State&); +constexpr unsigned int MaxCellNumberChars = 6; // -32768 + struct Word { Addr start = 0; @@ -38,13 +39,5 @@ struct Word } }; -enum class ParseStatus -{ - Finished, - NotAWord -}; - -std::string_view to_string(ParseStatus); - #endif // ALEEFORTH_TYPES_HPP