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));
+
+ state.dict.writebyte(addr, std::cin.get());
+ state.dict.write(Dictionary::Input, len + 1);
+}
+
int main(int argc, char *argv[])
{
MemDict dict;
- State state (dict);
+ State state (dict, readchar);
Parser parser;
std::vector args (argv + 1, argv + argc);
}
okay = true;
- //std::cout << state.size() << ' ' << state.compiling << "> ";
parseFile(parser, state, std::cin);
return 0;
case 22: return op_shr;
case 23: return op_comment;
case 24: return op_colon;
- case 25: return op_semic;
+ case 25: return op_semic; // :267
case 26: return op_here;
case 27: return op_imm;
case 28: return op_const;
}
int CoreWords::op_comment(State& state) {
- state.pass = Pass::Comment;
+ do {
+ op_key(state);
+ } while (state.pop() != ')');
return 0;
}
int CoreWords::op_colon(State& state) {
- state.pass = Pass::Colon;
- state.pushr(state.dict.alignhere());
+ if (state.compiling()) {
+ Word word = state.dict.input();
+ while (word.size() == 0) {
+ state.input(state);
+ word = state.dict.input();
+ }
+
+ state.pushr(state.dict.alignhere());
+ state.dict.addDefinition(word);
+ }
+
return 0;
}
int CoreWords::op_const(State& state)
{
- state.pass = Pass::Constant;
- state.pushr(state.dict.alignhere());
+ if (state.compiling()) {
+ Word word = state.dict.input();
+ while (word.size() == 0) {
+ state.input(state);
+ word = state.dict.input();
+ }
+
+ state.pushr(state.dict.alignhere());
+ state.dict.addDefinition(word);
+ state.dict.add(CoreWords::HiddenWordLiteral);
+ state.dict.add(state.pop());
+ state.dict.add(25 | CoreImmediate);
+ op_semic(state);
+ state.compiling(false);
+ }
+
return 0;
}
return 0;
}
-int CoreWords::findi(std::string_view str)
+int CoreWords::op_key(State& state)
+{
+ auto len = state.dict.read(Dictionary::Input);
+ while (len <= 0)
+ state.input(state);
+
+ state.dict.write(Dictionary::Input, len - 1);
+ Addr addr = Dictionary::Input + sizeof(Cell) +
+ Dictionary::InputCells - len;
+ Cell val = state.dict.readbyte(addr);
+
+ state.push(val);
+ return 0;
+}
+
+int CoreWords::findi(State& state, Word word)
{
std::size_t i;
int wordsi = 0;
for (i = 0; i < words.size();) {
const auto end = words.find_first_of({"\0\1", 2}, i);
- if (words.compare(i, end - i, str) == 0)
+ if (state.dict.equal(word, words.substr(i, end - i)))
return words[end] == '\0' ? wordsi : (wordsi | CoreImmediate);
++wordsi;
return -1;
}
-Func CoreWords::find(std::string_view str)
+Func CoreWords::find(State& state, Word word)
{
- const auto i = findi(str);
+ const auto i = findi(state, word);
return i >= 0 ? get(i & ~CoreWords::CoreImmediate) : nullptr;
}
constexpr static Cell Immediate = (1 << 5);
constexpr static Cell CoreImmediate = (1 << 6);
- static int findi(std::string_view);
- static Func find(std::string_view);
+ static int findi(State&, Word);
+ static Func find(State&, Word);
static void run(int, State&);
private:
"+\0-\0*\0/\0%\0"
"_@\0_!\0rot\0>r\0r>\0"
"=\0<\0allot\0&\0|\0"
- "^\0<<\0>>\0(\0:\0"
+ "^\0<<\0>>\0(\0:\1"
";\1here\0imm\0const\0"
"if\1then\1else\1depth\0";
static int op_then(State&);
static int op_else(State&);
static int op_depth(State&);
+ static int op_key(State&);
+ static int op_word(State&);
};
#endif // ALEEFORTH_COREWORDS_HPP
#include "dictionary.hpp"
+#include <cctype>
+
Addr Dictionary::allot(Cell amount)
{
Addr old = here;
return here;
}
-void Dictionary::addDefinition(std::string_view str)
+void Dictionary::addDefinition(Word word)
{
- add(str.size());
- for (char c : str)
- add(c);
+ add(word.size());
+ for (unsigned i = 0; i < word.size(); ++i)
+ writebyte(allot(1), readbyte(word.start + i));
}
bool Dictionary::issame(Addr addr, std::string_view str, std::size_t n)
return true;
}
-Addr Dictionary::find(std::string_view str)
+Addr Dictionary::find(Word word)
{
if (latest == 0)
return 0;
Addr lt = latest, oldlt;
do {
oldlt = lt;
- const auto l = read(lt);
- const auto len = l & 0x1F;
-
- if (issame(lt + sizeof(Cell), str, len))
+ const Cell l = read(lt);
+ const Addr len = l & 0x1F;
+ const Word lw {
+ static_cast<Addr>(lt + sizeof(Cell)),
+ static_cast<Addr>(lt + sizeof(Cell) + len)
+ };
+
+ if (equal(word, lw))
return lt;
else
lt -= l >> 6;
Addr Dictionary::getexec(Addr addr)
{
const auto len = read(addr) & 0x1F;
- return addr + (1 + len) * sizeof(Cell);
+ return 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;
}
class Dictionary
{
public:
- constexpr static Addr Base = 0 * sizeof(Cell);
- constexpr static Addr Compiling = 1 * sizeof(Cell);
- constexpr static Addr Begin = 2 * sizeof(Cell);
+ constexpr static Addr Base = 0;
+ constexpr static Addr Compiling = Base + sizeof(Cell);
+ constexpr static Addr Input = Compiling + sizeof(Cell); // len data...
+ constexpr static Addr InputCells = 80; // bytes!
+ constexpr static Addr Begin = Input + sizeof(Cell) + InputCells;
+
+ Word input();
+ bool equal(Word, std::string_view) const;
+ bool equal(Word, Word) const;
Addr here = Begin;
Addr latest = Begin;
Addr alignhere();
Addr allot(Cell);
void add(Cell);
- void addDefinition(std::string_view);
- Addr find(std::string_view);
+ void addDefinition(Word);
+ Addr find(Word);
Addr getexec(Addr);
private:
#include "executor.hpp"
#include "parser.hpp"
+#include <cctype>
#include <cstdlib>
ParseStatus Parser::parse(State& state, std::string_view& str)
{
- const auto end = str.find_first_of(" \t\n\r");
- const auto sub = str.substr(0, end);
- if (sub.empty())
- return ParseStatus::Finished;
+ auto addr = Dictionary::Input;
+ state.dict.write(addr, str.size() + 1);
- if (state.pass != Pass::None) {
- switch (state.pass) {
- case Pass::Comment:
- if (str.front() == ')')
- state.pass = Pass::None;
+ addr += sizeof(Cell) + Dictionary::InputCells - str.size() - 1;
+ for (char c : str)
+ state.dict.writebyte(addr++, c);
+ state.dict.writebyte(addr, '\0');
- str = str.substr(1);
- break;
- case Pass::Colon:
- state.pass = Pass::None;
- state.compiling(true);
- state.dict.addDefinition(sub);
- break;
- case Pass::Constant:
- state.pass = Pass::None;
+ return parseSource(state);
+}
+
+ParseStatus Parser::parseSource(State& state)
+{
+ auto word = state.dict.input();
+ while (word.size() > 0) {
+ if (auto ret = parseWord(state, word); ret == ParseStatus::Error)
+ return ret;
+
+ word = state.dict.input();
+ }
+
+ return ParseStatus::Finished;
+}
+
+ParseStatus Parser::parseWord(State& state, Word word)
+{
+ if (auto i = CoreWords::findi(state, word); i >= 0) {
+ if (state.compiling()) {
+ state.dict.add(i & ~CoreWords::CoreImmediate);
+ } else if (state.dict.equal(word, ":")) {
state.compiling(true);
- state.dict.addDefinition(sub);
- state.dict.add(CoreWords::HiddenWordLiteral);
- state.dict.add(state.pop());
- state.dict.add(CoreWords::findi(";"));
- CoreWords::run(CoreWords::findi(";"), state);
- break;
- default:
- break;
}
- } else {
- if (auto i = CoreWords::findi(sub); i >= 0) {
- if (state.compiling())
- state.dict.add(i & ~CoreWords::CoreImmediate);
- if (!state.compiling() || (i & CoreWords::CoreImmediate))
- CoreWords::run(i & ~CoreWords::CoreImmediate, state);
- } else if (auto j = state.dict.find(sub); j > 0) {
- auto e = state.dict.getexec(j);
- if (state.compiling()) {
- if (state.dict.read(j) & CoreWords::Immediate) {
- state.compiling(false);
- Executor::fullexec(state, e);
- state.compiling(true);
- } else {
- state.dict.add(CoreWords::HiddenWordJump);
- state.dict.add(e);
- }
- } else {
+ if (!state.compiling() || (i & CoreWords::CoreImmediate))
+ CoreWords::run(i & ~CoreWords::CoreImmediate, state);
+ } else if (auto j = state.dict.find(word); j > 0) {
+ auto e = state.dict.getexec(j);
+
+ if (state.compiling()) {
+ if (state.dict.read(j) & CoreWords::Immediate) {
+ state.compiling(false);
Executor::fullexec(state, e);
+ state.compiling(true);
+ } else {
+ state.dict.add(CoreWords::HiddenWordJump);
+ state.dict.add(e);
}
} else {
- char *p;
- const auto base = state.dict.read(0);
- const auto l = static_cast<Cell>(std::strtol(sub.data(), &p, base));
+ Executor::fullexec(state, e);
+ }
+ } else {
+ char buf[word.size()];
+ for (unsigned i = 0; i < word.size(); ++i)
+ buf[i] = state.dict.readbyte(word.start + i);
+
+ char *p;
+ const auto base = state.dict.read(0);
+ const auto l = static_cast<Cell>(std::strtol(buf, &p, base));
- if (p != sub.data()) {
- if (state.compiling()) {
- state.dict.add(CoreWords::HiddenWordLiteral);
- state.dict.add(l);
- } else {
- state.push(l);
- }
+ if (p != buf) {
+ if (state.compiling()) {
+ state.dict.add(CoreWords::HiddenWordLiteral);
+ state.dict.add(l);
} else {
- return ParseStatus::Error;
+ state.push(l);
}
+ } else {
+ return ParseStatus::Error;
}
-
- if (end == std::string_view::npos)
- return ParseStatus::Finished;
}
- const auto next = str.find_first_not_of(" \t\n\r", end);
-
- if (next == std::string_view::npos) {
- return ParseStatus::Finished;
- } else {
- str = str.substr(next);
- return ParseStatus::Continue;
- }
+ return ParseStatus::Finished;
}
+ //case Pass::Colon:
+ // state.pass = Pass::None;
+ // state.compiling(true);
+ // state.dict.addDefinition(sub);
+ // break;
+ //case Pass::Constant:
+ // state.pass = Pass::None;
+ // state.compiling(true);
+ // state.dict.addDefinition(sub);
+ // state.dict.add(CoreWords::HiddenWordLiteral);
+ // state.dict.add(state.pop());
+ // state.dict.add(CoreWords::findi(";"));
+ // CoreWords::run(CoreWords::findi(";"), state);
+ // break;
+ //default:
+ // break;
+ //}
{
public:
ParseStatus parse(State&, std::string_view&);
+
+private:
+ ParseStatus parseSource(State&);
+ ParseStatus parseWord(State&, Word);
};
#endif // ALEEFORTH_PARSER_HPP
public:
Addr ip = 0;
- Pass pass = Pass::None;
Dictionary& dict;
+ void (*input)(State&);
- constexpr State(Dictionary& d): dict(d) {}
+ constexpr State(Dictionary& d, void (*i)(State&)):
+ dict(d), input(i) {}
bool compiling() const;
void compiling(bool);
using Cell = int16_t;
using Func = int (*)(State&);
-enum class Pass
+struct Word
{
- None,
- Comment,
- Colon,
- Constant
+ Addr start = 0;
+ Addr end = 0;
+
+ unsigned size() const noexcept {
+ return end - start;
+ }
};
enum class ParseStatus