small: CXXFLAGS += -Os
small: alee
-fast: CXXFLAGS += -O3 -march=native -mtune=native
+fast: CXXFLAGS += -O3 -march=native -mtune=native -flto
fast: alee
alee: $(LIBFILE)
: here 1 cells @ ;
: allot 1 cells +! ;
: _latest 2 cells ;
-: imm _latest @ dup @ 1 5 << | swap ! ;
+: imm _latest @ dup @ 1 6 << | swap ! ;
: state 3 cells ;
: postpone 1 4 cells ! ; imm
: _input 5 cells ;
: decimal 10 base ! ;
: hex 16 base ! ;
-: literal 0 , , ; imm
+: literal 1 , , ; imm
: ['] ' postpone literal ; imm
: [ 0 state ! ; imm
: ] 1 state ! ;
: create align here bl word count nip cell+ allot align
['] _lit , here 3 cells + , ['] exit dup , ,
- dup @ 31 & over _latest @ - 6 << or over ! _latest ! ;
+ dup @ 31 & over _latest @ - 7 << or over ! _latest ! ;
: _latword _latest @
dup @ 31 & + cell+ aligned ;
: _does> _latword 2 cells +
dict.addDefinition(word);
dict.write(addr,
(dict.read(addr) & 0x1F) |
- ((addr - dict.latest()) << 6));
+ ((addr - dict.latest()) << 7));
dict.latest(addr);
};
void tick(State& state)
if (auto j = state.dict.find(word); j > 0)
state.push(state.dict.getexec(j));
else if (auto i = CoreWords::findi(state, word); i >= 0)
- state.push(i & ~CoreWords::Immediate);
+ state.push(((i & ~CoreWords::Immediate) << 1) | 1);
else
state.push(0);
}
DoubleCell dcell;
execute:
- switch (index) {
- default:
+ if ((index & 1) == 0) {
// must be calling a defined subroutine
state.pushr(state.ip);
state.ip = index;
return;
+ } else switch ((index & 0x3E) >> 1) {
case 0: // _lit
- state.push(state.beyondip());
+ state.push((index & 0xFF00) ? (index >> 8) - 1 : state.beyondip());
break;
case 1: // drop
state.pop();
case 24: // execute
index = state.pop();
goto execute;
- break;
case 25: // exit
state.ip = state.popr();
if (state.ip == 0) {
}
break;
case 26: // semic
- state.dict.add(findi("exit"));
+ state.dict.add((findi("exit") << 1) | 1);
state.compiling(false);
break;
case 27: // _jmp0
int CoreWords::findi(const char *word)
{
- const auto size = std::strlen(word);
- std::size_t i;
+ std::size_t i = 0;
int wordsi = 0;
- for (i = 0; i < sizeof(wordsarr);) {
+ while (i < sizeof(wordsarr)) {
auto end = i;
- while (wordsarr[end] > '\1')
+ while (wordsarr[end])
++end;
- if (size == end - i && !std::strncmp(word, wordsarr + i, size))
- return wordsarr[end] == '\0' ? wordsi : (wordsi | Immediate);
+ if (!std::strcmp(word, wordsarr + i))
+ return wordsi;
++wordsi;
i = end + 1;
int CoreWords::findi(State& state, Word word)
{
- std::size_t i;
+ std::size_t i = 0;
int wordsi = 0;
- for (i = 0; i < sizeof(wordsarr);) {
+ while (i < sizeof(wordsarr)) {
auto end = i;
- while (wordsarr[end] > '\1')
+ while (wordsarr[end])
++end;
if (state.dict.equal(word, wordsarr + i, end - i))
- return wordsarr[end] == '\0' ? wordsi : (wordsi | Immediate);
+ return wordsi;
++wordsi;
i = end + 1;
public:
constexpr static std::size_t WordCount = 32;
- constexpr static Cell Immediate = (1 << 5);
+ constexpr static Cell Immediate = (1 << 6);
+
+ constexpr static int Semicolon = 26;
static int findi(const char *);
static int findi(State&, Word);
static void run(unsigned int, State&);
private:
- // Ends with '\0': regular word
- // Ends with '\1': compile-only word
constexpr static char wordsarr[] =
"_lit\0drop\0dup\0swap\0pick\0sys\0"
"+\0-\0m*\0_/\0_%\0"
"_@\0_!\0>r\0r>\0=\0"
"<\0&\0|\0^\0"
"<<\0>>\0:\0'\0execute\0"
- "exit\0;\1_jmp0\0_jmp\0"
+ "exit\0;\0_jmp0\0_jmp\0"
"depth\0_rdepth\0key\0";
};
if (equal(word, lw))
return lt;
else
- lt -= l >> 6;
+ lt -= l >> 7;
} while (lt != oldlt);
return 0;
if (ins < 0) {
return parseNumber(state, word);
} else {
- imm = ins & CoreWords::Immediate;
+ imm = ins == CoreWords::Semicolon;
ins &= ~CoreWords::Immediate;
+ ins = (ins << 1) | 1;
}
} else {
imm = state.dict.read(ins) & CoreWords::Immediate;
if (ec == std::errc() && ptr == buf + i) {
if (state.compiling()) {
- state.dict.add(CoreWords::findi("_lit"));
- state.dict.add(l);
+ auto ins = (CoreWords::findi("_lit") << 1) | 1;
+
+ if (l >= 0 && l < 0xFF) {
+ state.dict.add(ins | ((l + 1) << 8));
+ } else {
+ state.dict.add(ins);
+ state.dict.add(l);
+ }
} else {
state.push(l);
}
State::Error State::execute(Addr addr)
{
- auto stat = setjmp(jmpbuf);
- if (!stat) {
- if (addr < CoreWords::WordCount) {
- CoreWords::run(addr, *this);
- ip = 0;
- } else {
- auto ins = addr;
+ auto stat = static_cast<State::Error>(setjmp(jmpbuf));
+
+ if (stat == State::Error::none) {
+ CoreWords::run(addr, *this);
- for (;;) {
- CoreWords::run(ins, *this);
- ins = dict.read(ip);
- }
+ if (ip >= Dictionary::Begin) {
+ // longjmp will exit this loop.
+ for (;;)
+ CoreWords::run(dict.read(ip), *this);
+ } else {
+ // addr was a CoreWord, all done now.
+ ip = 0;
}
- } else {
- auto err = static_cast<State::Error>(stat);
- return err == State::Error::exit ? State::Error::none : err;
+ } else if (stat == State::Error::exit) {
+ stat = State::Error::none;
}
- return State::Error::none;
+ return stat;
}
std::size_t State::size() const noexcept
struct State
{
enum class Error : int {
- none,
+ none = 0,
push,
pop,
pushr,