aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2023-02-24 08:50:28 -0500
committerClyne Sullivan <clyne@bitgloo.com>2023-02-24 08:50:28 -0500
commitdac0553eb5a4bd7b8b6ce408c18bd4d2779e094f (patch)
tree724997dd683bfa6adef88e47ca4446f869374dcd
parent81b2fa5d3c270a377504eb5002f0168fc02fd2ff (diff)
remove ParseStatus; reduce stack usage
-rw-r--r--Makefile2
-rw-r--r--alee.cpp42
-rw-r--r--dictionary.cpp57
-rw-r--r--parser.cpp30
-rw-r--r--parser.hpp10
-rw-r--r--types.cpp29
-rw-r--r--types.hpp11
7 files changed, 77 insertions, 104 deletions
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<Addr>(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 <cctype>
#include <cstdlib>
-#include <iostream>
-
-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<Addr>(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 <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/>.
- */
-
-#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 <cstdint>
-#include <string_view>
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