handle input within dictionary

llvm
Clyne 2 years ago
parent a506b65bdd
commit e45926fa2a

@ -28,10 +28,23 @@ static bool okay = false;
static void parseLine(Parser&, State&, std::string_view); static void parseLine(Parser&, State&, std::string_view);
static void parseFile(Parser&, State&, std::istream&); 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[]) int main(int argc, char *argv[])
{ {
MemDict dict; MemDict dict;
State state (dict); State state (dict, readchar);
Parser parser; Parser parser;
std::vector args (argv + 1, argv + argc); std::vector args (argv + 1, argv + argc);
@ -41,7 +54,6 @@ int main(int argc, char *argv[])
} }
okay = true; okay = true;
//std::cout << state.size() << ' ' << state.compiling << "> ";
parseFile(parser, state, std::cin); parseFile(parser, state, std::cin);
return 0; return 0;

@ -46,7 +46,7 @@ Func CoreWords::get(int index)
case 22: return op_shr; case 22: return op_shr;
case 23: return op_comment; case 23: return op_comment;
case 24: return op_colon; case 24: return op_colon;
case 25: return op_semic; case 25: return op_semic; // :267
case 26: return op_here; case 26: return op_here;
case 27: return op_imm; case 27: return op_imm;
case 28: return op_const; case 28: return op_const;
@ -203,13 +203,24 @@ int CoreWords::op_shr(State& state) {
} }
int CoreWords::op_comment(State& state) { int CoreWords::op_comment(State& state) {
state.pass = Pass::Comment; do {
op_key(state);
} while (state.pop() != ')');
return 0; return 0;
} }
int CoreWords::op_colon(State& state) { int CoreWords::op_colon(State& state) {
state.pass = Pass::Colon; 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.pushr(state.dict.alignhere());
state.dict.addDefinition(word);
}
return 0; return 0;
} }
@ -244,8 +255,22 @@ int CoreWords::op_imm(State& state)
int CoreWords::op_const(State& state) int CoreWords::op_const(State& state)
{ {
state.pass = Pass::Constant; 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.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;
} }
@ -309,7 +334,22 @@ int CoreWords::op_depth(State& state)
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; std::size_t i;
int wordsi = 0; int wordsi = 0;
@ -319,7 +359,7 @@ int CoreWords::findi(std::string_view str)
for (i = 0; i < words.size();) { for (i = 0; i < words.size();) {
const auto end = words.find_first_of({"\0\1", 2}, i); 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); return words[end] == '\0' ? wordsi : (wordsi | CoreImmediate);
++wordsi; ++wordsi;
@ -329,9 +369,9 @@ int CoreWords::findi(std::string_view str)
return -1; 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; return i >= 0 ? get(i & ~CoreWords::CoreImmediate) : nullptr;
} }

@ -35,8 +35,8 @@ public:
constexpr static Cell Immediate = (1 << 5); constexpr static Cell Immediate = (1 << 5);
constexpr static Cell CoreImmediate = (1 << 6); constexpr static Cell CoreImmediate = (1 << 6);
static int findi(std::string_view); static int findi(State&, Word);
static Func find(std::string_view); static Func find(State&, Word);
static void run(int, State&); static void run(int, State&);
private: private:
@ -45,7 +45,7 @@ private:
"+\0-\0*\0/\0%\0" "+\0-\0*\0/\0%\0"
"_@\0_!\0rot\0>r\0r>\0" "_@\0_!\0rot\0>r\0r>\0"
"=\0<\0allot\0&\0|\0" "=\0<\0allot\0&\0|\0"
"^\0<<\0>>\0(\0:\0" "^\0<<\0>>\0(\0:\1"
";\1here\0imm\0const\0" ";\1here\0imm\0const\0"
"if\1then\1else\1depth\0"; "if\1then\1else\1depth\0";
@ -86,6 +86,8 @@ private:
static int op_then(State&); static int op_then(State&);
static int op_else(State&); static int op_else(State&);
static int op_depth(State&); static int op_depth(State&);
static int op_key(State&);
static int op_word(State&);
}; };
#endif // ALEEFORTH_COREWORDS_HPP #endif // ALEEFORTH_COREWORDS_HPP

@ -18,6 +18,8 @@
#include "dictionary.hpp" #include "dictionary.hpp"
#include <cctype>
Addr Dictionary::allot(Cell amount) Addr Dictionary::allot(Cell amount)
{ {
Addr old = here; Addr old = here;
@ -38,11 +40,11 @@ Addr Dictionary::alignhere()
return here; return here;
} }
void Dictionary::addDefinition(std::string_view str) void Dictionary::addDefinition(Word word)
{ {
add(str.size()); add(word.size());
for (char c : str) for (unsigned i = 0; i < word.size(); ++i)
add(c); writebyte(allot(1), readbyte(word.start + i));
} }
bool Dictionary::issame(Addr addr, std::string_view str, std::size_t n) bool Dictionary::issame(Addr addr, std::string_view str, std::size_t n)
@ -60,7 +62,7 @@ bool Dictionary::issame(Addr addr, std::string_view str, std::size_t n)
return true; return true;
} }
Addr Dictionary::find(std::string_view str) Addr Dictionary::find(Word word)
{ {
if (latest == 0) if (latest == 0)
return 0; return 0;
@ -68,10 +70,14 @@ Addr Dictionary::find(std::string_view str)
Addr lt = latest, oldlt; Addr lt = latest, oldlt;
do { do {
oldlt = lt; oldlt = lt;
const auto l = read(lt); const Cell l = read(lt);
const auto len = l & 0x1F; const Addr len = l & 0x1F;
const Word lw {
if (issame(lt + sizeof(Cell), str, len)) static_cast<Addr>(lt + sizeof(Cell)),
static_cast<Addr>(lt + sizeof(Cell) + len)
};
if (equal(word, lw))
return lt; return lt;
else else
lt -= l >> 6; lt -= l >> 6;
@ -83,6 +89,62 @@ Addr Dictionary::find(std::string_view str)
Addr Dictionary::getexec(Addr addr) Addr Dictionary::getexec(Addr addr)
{ {
const auto len = read(addr) & 0x1F; 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;
} }

@ -28,9 +28,15 @@
class Dictionary class Dictionary
{ {
public: public:
constexpr static Addr Base = 0 * sizeof(Cell); constexpr static Addr Base = 0;
constexpr static Addr Compiling = 1 * sizeof(Cell); constexpr static Addr Compiling = Base + sizeof(Cell);
constexpr static Addr Begin = 2 * 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 here = Begin;
Addr latest = Begin; Addr latest = Begin;
@ -43,8 +49,8 @@ public:
Addr alignhere(); Addr alignhere();
Addr allot(Cell); Addr allot(Cell);
void add(Cell); void add(Cell);
void addDefinition(std::string_view); void addDefinition(Word);
Addr find(std::string_view); Addr find(Word);
Addr getexec(Addr); Addr getexec(Addr);
private: private:

@ -20,47 +20,47 @@
#include "executor.hpp" #include "executor.hpp"
#include "parser.hpp" #include "parser.hpp"
#include <cctype>
#include <cstdlib> #include <cstdlib>
ParseStatus Parser::parse(State& state, std::string_view& str) ParseStatus Parser::parse(State& state, std::string_view& str)
{ {
const auto end = str.find_first_of(" \t\n\r"); auto addr = Dictionary::Input;
const auto sub = str.substr(0, end); state.dict.write(addr, str.size() + 1);
if (sub.empty())
return ParseStatus::Finished;
if (state.pass != Pass::None) { addr += sizeof(Cell) + Dictionary::InputCells - str.size() - 1;
switch (state.pass) { for (char c : str)
case Pass::Comment: state.dict.writebyte(addr++, c);
if (str.front() == ')') state.dict.writebyte(addr, '\0');
state.pass = Pass::None;
str = str.substr(1); return parseSource(state);
break;
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;
} }
} else {
if (auto i = CoreWords::findi(sub); i >= 0) { ParseStatus Parser::parseSource(State& state)
if (state.compiling()) {
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); state.dict.add(i & ~CoreWords::CoreImmediate);
} else if (state.dict.equal(word, ":")) {
state.compiling(true);
}
if (!state.compiling() || (i & CoreWords::CoreImmediate)) if (!state.compiling() || (i & CoreWords::CoreImmediate))
CoreWords::run(i & ~CoreWords::CoreImmediate, state); CoreWords::run(i & ~CoreWords::CoreImmediate, state);
} else if (auto j = state.dict.find(sub); j > 0) { } else if (auto j = state.dict.find(word); j > 0) {
auto e = state.dict.getexec(j); auto e = state.dict.getexec(j);
if (state.compiling()) { if (state.compiling()) {
@ -76,11 +76,15 @@ ParseStatus Parser::parse(State& state, std::string_view& str)
Executor::fullexec(state, e); Executor::fullexec(state, e);
} }
} else { } else {
char buf[word.size()];
for (unsigned i = 0; i < word.size(); ++i)
buf[i] = state.dict.readbyte(word.start + i);
char *p; char *p;
const auto base = state.dict.read(0); const auto base = state.dict.read(0);
const auto l = static_cast<Cell>(std::strtol(sub.data(), &p, base)); const auto l = static_cast<Cell>(std::strtol(buf, &p, base));
if (p != sub.data()) { if (p != buf) {
if (state.compiling()) { if (state.compiling()) {
state.dict.add(CoreWords::HiddenWordLiteral); state.dict.add(CoreWords::HiddenWordLiteral);
state.dict.add(l); state.dict.add(l);
@ -92,17 +96,23 @@ ParseStatus Parser::parse(State& state, std::string_view& str)
} }
} }
if (end == std::string_view::npos)
return ParseStatus::Finished; return ParseStatus::Finished;
} }
const auto next = str.find_first_not_of(" \t\n\r", end); //case Pass::Colon:
// state.pass = Pass::None;
if (next == std::string_view::npos) { // state.compiling(true);
return ParseStatus::Finished; // state.dict.addDefinition(sub);
} else { // break;
str = str.substr(next); //case Pass::Constant:
return ParseStatus::Continue; // 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;
//}

@ -27,6 +27,10 @@ class Parser
{ {
public: public:
ParseStatus parse(State&, std::string_view&); ParseStatus parse(State&, std::string_view&);
private:
ParseStatus parseSource(State&);
ParseStatus parseWord(State&, Word);
}; };
#endif // ALEEFORTH_PARSER_HPP #endif // ALEEFORTH_PARSER_HPP

@ -36,10 +36,11 @@ class State
public: public:
Addr ip = 0; Addr ip = 0;
Pass pass = Pass::None;
Dictionary& dict; 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; bool compiling() const;
void compiling(bool); void compiling(bool);

@ -28,12 +28,14 @@ using Addr = uint16_t;
using Cell = int16_t; using Cell = int16_t;
using Func = int (*)(State&); using Func = int (*)(State&);
enum class Pass struct Word
{ {
None, Addr start = 0;
Comment, Addr end = 0;
Colon,
Constant unsigned size() const noexcept {
return end - start;
}
}; };
enum class ParseStatus enum class ParseStatus

Loading…
Cancel
Save