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 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);
@ -41,7 +54,6 @@ int main(int argc, char *argv[])
}
okay = true;
//std::cout << state.size() << ' ' << state.compiling << "> ";
parseFile(parser, state, std::cin);
return 0;

@ -46,7 +46,7 @@ Func CoreWords::get(int index)
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;
@ -203,13 +203,24 @@ int CoreWords::op_shr(State& state) {
}
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;
}
@ -244,8 +255,22 @@ int CoreWords::op_imm(State& state)
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;
}
@ -309,7 +334,22 @@ int CoreWords::op_depth(State& state)
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;
@ -319,7 +359,7 @@ int CoreWords::findi(std::string_view str)
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;
@ -329,9 +369,9 @@ int CoreWords::findi(std::string_view str)
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;
}

@ -35,8 +35,8 @@ public:
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:
@ -45,7 +45,7 @@ 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";
@ -86,6 +86,8 @@ private:
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

@ -18,6 +18,8 @@
#include "dictionary.hpp"
#include <cctype>
Addr Dictionary::allot(Cell amount)
{
Addr old = here;
@ -38,11 +40,11 @@ Addr Dictionary::alignhere()
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)
@ -60,7 +62,7 @@ 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;
@ -68,10 +70,14 @@ Addr Dictionary::find(std::string_view str)
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;
@ -83,6 +89,62 @@ Addr Dictionary::find(std::string_view str)
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;
}

@ -28,9 +28,15 @@
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;
@ -43,8 +49,8 @@ public:
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:

@ -20,89 +20,99 @@
#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;
//}

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

@ -36,10 +36,11 @@ class State
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);

@ -28,12 +28,14 @@ using Addr = uint16_t;
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

Loading…
Cancel
Save