]> code.bitgloo.com Git - bitgloo/alee-forth.git/commitdiff
fundamental compiling words
authorClyne Sullivan <clyne@bitgloo.com>
Sun, 19 Feb 2023 16:52:18 +0000 (11:52 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Sun, 19 Feb 2023 16:52:18 +0000 (11:52 -0500)
alee.cpp
core.fth
corewords.cpp
corewords.hpp
dictionary.hpp
parser.cpp
state.cpp

index c8dee45dec0323ea73da1337cefc1b69ed8a3b22..855afa847ee26b1fae326166e9a1c498fff46733 100644 (file)
--- a/alee.cpp
+++ b/alee.cpp
@@ -47,6 +47,10 @@ int main(int argc, char *argv[])
     State state (dict, readchar);
     Parser parser;
 
+    dict.write(Dictionary::Base, 10);
+    dict.write(Dictionary::Compiling, 0);
+    dict.write(Dictionary::Postpone, 0);
+
     std::vector args (argv + 1, argv + argc);
     for (const auto& a : args) {
         std::ifstream file (a);
index 7a6e4550b08b63001c2f9f443ba08474d457deec..24fa6dc15d2b0aa88dcf2b8262d6e492f897f9c4 100644 (file)
--- a/core.fth
+++ b/core.fth
@@ -1,72 +1,79 @@
 ( : variable create 0 , ; )
 ( : create here const ; )
 
-: 1+      1 + ;
-: 1-      1 - ;
+: 1+       1 + ;
+: 1-       1 - ;
 
-: !       2 _! ;
-: @       2 _@ ;
-: ,       here ! 2 allot ;
-: cell+   2 + ;
-: cells   2 * ;
+: !        2 _! ;
+: @        2 _@ ;
+: ,        here ! 2 allot ;
+: cell+    2 + ;
+: cells    2 * ;
 
-: c!      1 _! ;
-: c@      1 _@ ;
-: c,      here c! 1 allot ;
-: char+   1+ ;
-: chars   ;
+: over     1 pick ;
+: -rot     rot rot ;
+: nip      swap drop ;
+: tuck     swap over ;
 
-: align   here 1 & if 1 allot then ;
-: aligned dup 1 & if 1+ then ;
+: base     0 ;
+: state    2 ;
+: decimal  1 1+ base ! 1010 base ! ;
+
+: postpone 1 4 ! ; imm
+: [']      ' postpone literal ; imm
 
-( set decimal numbers )
-10 0 !
+: if       ['] _jmp0 , here 0 , ; imm
+: then     here swap ! ; imm
+: else     ['] _jmp , here 0 , here rot ! ; imm
 
-: .       0 sys ;
-: emit    1 sys ;
+: c!       1 _! ;
+: c@       1 _@ ;
+: c,       here c! 1 allot ;
+: char+    1+ ;
+: chars    ;
+
+: align   here 1 & if 1 allot then ;
+: aligned dup 1 & if 1+ then ;
 
-: over    1 pick ;
-: -rot    rot rot ;
-: nip     swap drop ;
-: tuck    swap over ;
+: .        0 sys ;
+: emit     1 sys ;
 
-: +!      swap over @ + swap ! ;
+: +!       swap over @ + swap ! ;
 
-: and     & ;
-: or      | ;
-: xor     ^ ;
-: lshift  << ;
-: rshift  >> ;
-: mod     % ;
-: 2*      2 * ;
-: 2/      2 / ;
+: and      & ;
+: or       | ;
+: xor      ^ ;
+: lshift   << ;
+: rshift   >> ;
+: mod      % ;
+: 2*       2 * ;
+: 2/       2 / ;
 
-: 2drop   drop drop ;
-: 2dup    over over ;
-: 2over   3 pick 3 pick ;
-: 2swap   rot >r rot r> ;
+: 2drop    drop drop ;
+: 2dup     over over ;
+: 2over    3 pick 3 pick ;
+: 2swap    rot >r rot r> ;
 
-: r@      r> dup >r ;
-: 2!      swap over ! cell+ ! ;
-: 2@      dup cell+ @ swap @ ;
+: r@       r> dup >r ;
+: 2!       swap over ! cell+ ! ;
+: 2@       dup cell+ @ swap @ ;
 
-: 0=      0 = ;
-: 0<      0 < ;
-: <=      2dup - 1- 0< ;
-: >       <= 0= ;
+: 0=       0 = ;
+: 0<       0 < ;
+: <=       - 1- 0< ;
+: >        <= 0= ;
 
-: cr      9 emit ;
-: bl      32 ;
-: space   bl emit ;
+: cr       9 emit ;
+: bl       32 ;
+: space    bl emit ;
 
-: state   1 ;
-: base    0 ;
-: decimal 1 2* base ! 1010 base ! ;
+: ?dup     dup if dup then ;
 
-: ?dup    dup if dup then ;
+: negate   -1 * ;
+: abs      dup 0< if negate then ;
+: min      2dup <= if drop else nip then ;
+: max      2dup <= if nip else drop then ;
 
-: negate  -1 * ;
-: abs     dup 0< if negate then ;
-: min     2dup <= if drop else nip then ;
-: max     2dup <= if nip else drop then ;
 
+: begin    here ; imm
+: do       postpone >r postpone >r here ; imm
index 3312ef19e672108363695d5025354b31d6f49ed8..9b43fcffb6f8e158e16171b56f6158aaeabdb3e2 100644 (file)
 
 Func CoreWords::get(int index)
 {
-    switch (index) {
-    case 0: return op_drop;
-    case 1: return op_dup;
-    case 2: return op_swap;
-    case 3: return op_pick;
-    case 4: return op_sys;
-    case 5: return op_add;
-    case 6: return op_sub;
-    case 7: return op_mul;
-    case 8: return op_div;
-    case 9: return op_mod;
-    case 10: return op_peek;
-    case 11: return op_poke;
-    case 12: return op_rot;
-    case 13: return op_pushr;
-    case 14: return op_popr;
-    case 15: return op_eq;
-    case 16: return op_lt;
-    case 17: return op_allot;
-    case 18: return op_and;
-    case 19: return op_or;
-    case 20: return op_xor;
-    case 21: return op_shl;
-    case 22: return op_shr;
-    case 23: return op_comment;
-    case 24: return op_colon;
-    case 25: return op_semic; // :267
-    case 26: return op_here;
-    case 27: return op_imm;
-    case 28: return op_const;
-    case 29: return op_if;
-    case 30: return op_then;
-    case 31: return op_else;
-    case 32: return op_depth;
-    case 33: return op_literal;
-    case 34: return op_jump;
-    default: return nullptr;
-    }
+    static const Func ops[WordCount] = {
+        op_drop,  op_dup,  op_swap,    op_pick,    op_sys,
+        op_add,   op_sub,  op_mul,     op_div,     op_mod,
+        op_peek,  op_poke, op_rot,     op_pushr,   op_popr,
+        op_eq,    op_lt,   op_allot,   op_and,     op_or,
+        op_xor,   op_shl,  op_shr,     op_comment, op_colon,
+        op_semic, op_here, op_imm,     op_const,   op_depth,
+        op_key,   op_exit, op_tick,    op_execute, op_jmp,
+        op_jmp0,  op_lit,  op_literal,
+        op_jump
+    };
+
+    return index >= 0 && index < WordCount ? ops[index] : nullptr;
 }
 
 void CoreWords::op_drop(State& state)
@@ -197,13 +172,37 @@ void CoreWords::op_colon(State& state) {
         state.pushr(state.dict.alignhere());
         state.dict.addDefinition(word);
     }
+}
 
+void CoreWords::op_tick(State& state) {
+    Word word = state.dict.input();
+    while (word.size() == 0) {
+        state.input(state);
+        word = state.dict.input();
+    }
+
+    Cell xt = 0;
+    if (auto i = CoreWords::findi(state, word); i >= 0) {
+        xt = i & ~CoreWords::Compiletime;
+    } else if (auto j = state.dict.find(word); j > 0) {
+        xt = state.dict.getexec(j) - sizeof(Cell);
+    }
+
+    state.push(xt);
+}
+
+void CoreWords::op_execute(State& state) {
+    state.execute(state.pop());
+}
+
+void CoreWords::op_exit(State& state) {
+    state.ip = state.popr();
 }
 
 void CoreWords::op_semic(State& state) {
-    if (!state.compiling()) {
-        state.ip = state.popr();
-    } else {
+    if (state.compiling()) {
+        state.dict.add(findi("exit"));
+
         auto begin = state.popr();
 
         state.dict.write(begin,
@@ -213,7 +212,6 @@ void CoreWords::op_semic(State& state) {
         state.dict.latest = begin;
         state.compiling(false);
     }
-
 }
 
 void CoreWords::op_here(State& state) {
@@ -228,71 +226,50 @@ void CoreWords::op_imm(State& state)
 
 void CoreWords::op_const(State& state)
 {
-    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);
+    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(findi("_lit"));
+    state.dict.add(state.pop());
+    op_semic(state);
 }
 
-void CoreWords::op_literal(State& state)
+void CoreWords::op_lit(State& state)
 {
     state.push(state.beyondip());
     state.ip += sizeof(Cell);
 }
 
-void CoreWords::op_jump(State& state)
-{
-    state.pushr(state.ip + sizeof(Cell));
-    state.ip = state.beyondip() - sizeof(Cell);
-}
-
-void CoreWords::op_if(State& state)
+void CoreWords::op_literal(State& state)
 {
     if (state.compiling()) {
-        state.push(state.dict.here);
-        state.dict.add(0);
-    } else {
-        if (state.pop())
-            state.ip += sizeof(Cell);
-        else
-            state.ip = state.beyondip() - sizeof(Cell);
+        state.dict.add(findi("_lit"));
+        state.dict.add(state.pop());
     }
-
 }
 
-void CoreWords::op_then(State& state)
+void CoreWords::op_jump(State& state)
 {
-    if (state.compiling()) {
-        const auto ifaddr = state.pop();
-        if (state.dict.read(ifaddr) == 0)
-            state.dict.write(ifaddr, state.dict.here);
-    }
-
+    state.pushr(state.ip + sizeof(Cell));
+    state.ip = state.beyondip() - sizeof(Cell);
 }
 
-void CoreWords::op_else(State& state)
+void CoreWords::op_jmp(State& state)
 {
-    if (state.compiling()) {
-        const auto ifaddr = state.pop();
-        state.push(state.dict.here);
-        state.dict.add(0);
-        state.dict.write(ifaddr, state.dict.here);
-    } else {
-        state.ip = state.beyondip() - sizeof(Cell);
-    }
+    state.ip = state.beyondip() - sizeof(Cell);
+}
 
+void CoreWords::op_jmp0(State& state)
+{
+    if (state.pop())
+        state.ip += sizeof(Cell);
+    else
+        op_jmp(state);
 }
 
 void CoreWords::op_depth(State& state)
@@ -314,6 +291,26 @@ void CoreWords::op_key(State& state)
     state.push(val);
 }
 
+int CoreWords::findi(std::string_view word)
+{
+    std::size_t i;
+    int wordsi = 0;
+
+    std::string_view words (wordsarr, sizeof(wordsarr));
+
+    for (i = 0; i < words.size();) {
+        const auto end = words.find_first_of({"\0\1", 2}, i);
+
+        if (word == words.substr(i, end - i))
+            return words[end] == '\0' ? wordsi : (wordsi | Compiletime);
+
+        ++wordsi;
+        i = end + 1;
+    }
+
+    return -1;
+}
+
 int CoreWords::findi(State& state, Word word)
 {
     std::size_t i;
@@ -325,7 +322,7 @@ int CoreWords::findi(State& state, Word word)
         const auto end = words.find_first_of({"\0\1", 2}, i);
 
         if (state.dict.equal(word, words.substr(i, end - i)))
-            return words[end] == '\0' ? wordsi : (wordsi | CoreImmediate);
+            return words[end] == '\0' ? wordsi : (wordsi | Compiletime);
 
         ++wordsi;
         i = end + 1;
@@ -337,12 +334,12 @@ int CoreWords::findi(State& state, Word word)
 Func CoreWords::find(State& state, Word word)
 {
     const auto i = findi(state, word);
-    return i >= 0 ? get(i & ~CoreWords::CoreImmediate) : nullptr;
+    return i >= 0 ? get(i & ~Compiletime) : nullptr;
 }
 
 void CoreWords::run(int i, State& state)
 {
-    i &= ~CoreWords::CoreImmediate;
+    i &= ~Compiletime;
 
     if (i >= 0 && i < WordCount)
         get(i)(state);
index babb5aac5f31ea23b8585a90d06147b31b042379..76c1353a883684c11bb194766959a33ecc286a80 100644 (file)
 #include "types.hpp"
 #include "state.hpp"
 
+#include <string_view>
+
 void user_sys(State&);
 
 class CoreWords
 {
 public:
-    constexpr static std::size_t VisibleWordCount = 33;             // size
-    constexpr static auto HiddenWordLiteral = VisibleWordCount;     // index
-    constexpr static auto HiddenWordJump    = VisibleWordCount + 1; // index
-    constexpr static auto WordCount         = HiddenWordJump + 1;   // size
+    constexpr static std::size_t VisibleWordCount = 38;             // size
+    constexpr static auto HiddenWordJump    = VisibleWordCount;     // index
+    constexpr static auto WordCount         = VisibleWordCount + 1; // size
 
-    constexpr static Cell Immediate     = (1 << 5);
-    constexpr static Cell CoreImmediate = (1 << 6);
+    constexpr static Cell Immediate   = (1 << 5);
+    constexpr static Cell Compiletime = (1 << 6);
 
+    static int findi(std::string_view);
     static int findi(State&, Word);
     static Func find(State&, Word);
     static void run(int, State&);
 
 private:
+    // Ends with '\0': regular word
+    // Ends with '\1': compile-only word
     constexpr static char wordsarr[] =
         "drop\0dup\0swap\0pick\0sys\0"
         "+\0-\0*\0/\0%\0"
         "_@\0_!\0rot\0>r\0r>\0"
         "=\0<\0allot\0&\0|\0"
         "^\0<<\0>>\0(\0:\1"
-        ";\1here\0imm\0const\0"
-        "if\1then\1else\1depth\0";
+        ";\1here\0imm\0const\0depth\0"
+        "key\0exit\0'\0execute\0_jmp\0"
+        "_jmp0\0_lit\0literal\1";
 
     static Func get(int);
 
@@ -63,7 +68,7 @@ private:
     static void op_mod(State&);
     static void op_peek(State&);
     static void op_poke(State&);
-    static void op_rot(State&);
+    static void op_rot(State&);   // : rot >r swap r> swap ;
     static void op_pushr(State&);
     static void op_popr(State&);
     static void op_eq(State&);
@@ -80,14 +85,16 @@ private:
     static void op_here(State&);
     static void op_imm(State&);
     static void op_const(State&);
-    static void op_literal(State&);
+    static void op_lit(State&);
     static void op_jump(State&);
-    static void op_if(State&);
-    static void op_then(State&);
-    static void op_else(State&);
     static void op_depth(State&);
     static void op_key(State&);
-    static void op_word(State&);
+    static void op_exit(State&);
+    static void op_tick(State&);
+    static void op_execute(State&);
+    static void op_jmp(State&);
+    static void op_jmp0(State&);
+    static void op_literal(State&); // : literal ['] _lit , , ; imm
 };
 
 #endif // ALEEFORTH_COREWORDS_HPP
index 90234ba161872150e60538e0d9788fb20ca429e1..e30858c5c2082fce09f10070eeddb319c7da2cd3 100644 (file)
@@ -29,10 +29,11 @@ class Dictionary
 {
 public:
     constexpr static Addr Base       = 0;
-    constexpr static Addr Compiling  = Base + sizeof(Cell);
-    constexpr static Addr Input      = Compiling + sizeof(Cell); // len data...
+    constexpr static Addr Compiling  = sizeof(Cell);
+    constexpr static Addr Postpone   = sizeof(Cell) * 2;
+    constexpr static Addr Input      = sizeof(Cell) * 3; // len data...
     constexpr static Addr InputCells = 80; // bytes!
-    constexpr static Addr Begin      = Input + sizeof(Cell) + InputCells;
+    constexpr static Addr Begin      = sizeof(Cell) * 4 + InputCells;
 
     Addr here = Begin;
     Addr latest = Begin;
index b44547fbf96220f0c8f883e8dcbae304eb8c1b88..b78390c0d5e99e9f0207e82c9749fcf84e39cbd9 100644 (file)
@@ -22,6 +22,8 @@
 #include <cctype>
 #include <cstdlib>
 
+#include <iostream>
+
 ParseStatus Parser::parse(State& state, std::string_view& str)
 {
     auto addr = Dictionary::Input;
@@ -50,25 +52,42 @@ ParseStatus Parser::parseSource(State& state)
 
 ParseStatus Parser::parseWord(State& state, Word word)
 {
+    // TODO unify core-word and defined-word parsing/execution.
+
     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);
+        auto p = state.dict.read(Dictionary::Postpone);
+        auto imm = (i & CoreWords::Compiletime);
+
+        if (state.compiling() || p) {
+            if (p || !imm) {
+                state.dict.add(i & ~CoreWords::Compiletime);
+
+                if (p)
+                    state.dict.write(Dictionary::Postpone, 0);
+            } else if (imm) {
+                CoreWords::run(i & ~CoreWords::Compiletime, state);
+            }
+        } else {
+            if (state.dict.equal(word, ":"))
+                state.compiling(true);
 
-        if (!state.compiling() || (i & CoreWords::CoreImmediate))
-            CoreWords::run(i & ~CoreWords::CoreImmediate, state);
+            CoreWords::run(i & ~CoreWords::Compiletime, state);
+        }
     } else if (auto j = state.dict.find(word); j > 0) {
         auto e = state.dict.getexec(j);
+        auto p = state.dict.read(Dictionary::Postpone);
 
-        if (state.compiling()) {
-            if (state.dict.read(j) & CoreWords::Immediate) {
-                state.compiling(false);
-                state.execute(e);
-                state.compiling(true);
-            } else {
+        if (state.compiling() || p) {
+            auto imm = state.dict.read(j) & CoreWords::Immediate;
+
+            if (p || !imm) {
                 state.dict.add(CoreWords::HiddenWordJump);
                 state.dict.add(e);
+
+                if (p)
+                    state.dict.write(Dictionary::Postpone, 0);
+            } else if (imm) {
+                state.execute(e);
             }
         } else {
             state.execute(e);
@@ -85,12 +104,13 @@ ParseStatus Parser::parseWord(State& state, Word word)
 
         if (std::distance(buf, p) == word.size()) {
             if (state.compiling()) {
-                state.dict.add(CoreWords::HiddenWordLiteral);
+                state.dict.add(CoreWords::findi("_lit"));
                 state.dict.add(l);
             } else {
                 state.push(l);
             }
         } else {
+            std::cout << "word not found: " << buf << std::endl;
             return ParseStatus::NotAWord;
         }
     }
index 0fe0905f7935346107b4969719036597ce844528..6d056bab1826a84c4d5e2337917cb34f93e7d12e 100644 (file)
--- a/state.cpp
+++ b/state.cpp
@@ -40,13 +40,18 @@ void State::compiling(bool yes)
 
 void State::execute(Addr addr)
 {
-    pushr(0);
-    ip = addr - sizeof(Cell);
-
-    do {
-        ip += sizeof(Cell);
-        CoreWords::run(dict.read(ip), *this);
-    } while (ip);
+    if (addr < Dictionary::Begin) {
+        // Must be a core-word
+        CoreWords::run(addr, *this);
+    } else {
+        pushr(0);
+        ip = addr - sizeof(Cell);
+
+        do {
+            ip += sizeof(Cell);
+            CoreWords::run(dict.read(ip), *this);
+        } while (ip);
+    }
 }
 
 Cell State::beyondip() const