]> code.bitgloo.com Git - bitgloo/alee-forth.git/commitdiff
common error enum; eval to _ev
authorClyne Sullivan <clyne@bitgloo.com>
Sat, 11 Mar 2023 12:36:11 +0000 (07:36 -0500)
committerClyne Sullivan <clyne@bitgloo.com>
Sat, 11 Mar 2023 12:36:11 +0000 (07:36 -0500)
alee-msp430.cpp
alee-standalone.cpp
alee.cpp
core.fth
libalee/corewords.cpp
libalee/corewords.hpp
libalee/parser.cpp
libalee/parser.hpp
libalee/state.cpp
libalee/state.hpp
libalee/types.hpp

index 3121dc1a64bde86120be35bab8711eb964c08ca4..ca00026f823dd419871caba5f49840d5d24e6c18 100644 (file)
@@ -66,14 +66,15 @@ int main()
 
                 serputs("\n\r");
 
-                if (auto r = Parser::parse(state, strbuf); r == 0) {
+                if (auto r = Parser::parse(state, strbuf); r == Error::none) {
                     serputs(state.compiling() ? " compiled" : " ok");
                 } else {
                     switch (r) {
-                    case Parser::UnknownWord:
+                    case Error::noword:
                         serputs("unknown word...");
                         break;
                     default:
+                        serputs("error...");
                         break;
                     }
                 }
index 3c4eb3de50f832e5a6da01a3506b2689cbc9f17a..2c971ce4bb0aa40c0ab897994a7daf1976992177 100644 (file)
@@ -79,7 +79,6 @@ static void load(State& state)
         state.dict.writebyte(i++, file.get());
 }
 
-#include <cstring>
 void user_sys(State& state)
 {
     char buf[32] = {0};
@@ -107,55 +106,41 @@ void user_sys(State& state)
         std::cout << buf << ' ';
         }
         break;
-    case 5: // eval
-        {
-        auto oldip = state.ip;
-        std::jmp_buf oldjb;
-        memcpy(oldjb, state.jmpbuf, sizeof(std::jmp_buf));
-        state.ip = 0;
-        Parser::parseSource(state);
-        memcpy(state.jmpbuf, oldjb, sizeof(std::jmp_buf));
-        state.ip = oldip;
-        }
+    default:
         break;
     }
 }
 
 void parseLine(State& state, const std::string& line)
 {
-    if (auto r = Parser::parse(state, line.c_str()); r == 0) {
+    if (auto r = Parser::parse(state, line.c_str()); r == Error::none) {
         if (okay)
-            std::cout << (state.compiling() ? "compiled" : "ok") << std::endl;
+            std::cout << (state.compiling() ? " compiled" : " ok") << std::endl;
     } else {
         switch (r) {
-        case Parser::UnknownWord:
+        case Error::noword:
             std::cout << "word not found in: " << line << std::endl;
             break;
-        case static_cast<int>(State::Error::push):
+        case Error::push:
             std::cout << "stack overflow" << std::endl;
             break;
-        case static_cast<int>(State::Error::pushr):
+        case Error::pushr:
             std::cout << "return stack overflow" << std::endl;
             break;
-        case static_cast<int>(State::Error::popr):
+        case Error::popr:
             std::cout << "return stack underflow" << std::endl;
             break;
-        case static_cast<int>(State::Error::pop):
-        case static_cast<int>(State::Error::top):
-        case static_cast<int>(State::Error::pick):
+        case Error::pop:
+        case Error::top:
+        case Error::pick:
             std::cout << "stack underflow" << std::endl;
             break;
         default:
-            std::cout << "error: " << r << std::endl;
+            std::cout << "unknown error" << std::endl;
             break;
         }
 
-        while (state.size())
-            state.pop();
-        while (state.rsize())
-            state.popr();
-        state.dict.write(Dictionary::Compiling, 0);
-        state.ip = 0;
+        state.reset();
     }
 }
 
index e222363d052ff7c6264d1e9be20fe43f02d6ffca..92af96960148688a706fe7a7e4d04e511bd9cb94 100644 (file)
--- a/alee.cpp
+++ b/alee.cpp
@@ -26,7 +26,7 @@
 
 static bool okay = false;
 
-static void readchar(State& state);
+static void readchar(State&);
 static void parseLine(State&, const std::string&);
 static void parseFile(State&, std::istream&);
 
@@ -76,12 +76,10 @@ static void load(State& state)
 {
     std::ifstream file ("alee.dat", std::ios::binary);
 
-    Addr i = 0;
-    while (file.good())
-        state.dict.writebyte(i++, file.get());
+    for (Addr i = 0; file.good(); i++)
+        state.dict.writebyte(i, file.get());
 }
 
-#include <cstring>
 void user_sys(State& state)
 {
     char buf[32] = {0};
@@ -109,55 +107,41 @@ void user_sys(State& state)
         std::cout << buf << ' ';
         }
         break;
-    case 5: // eval
-        {
-        auto oldip = state.ip;
-        std::jmp_buf oldjb;
-        memcpy(oldjb, state.jmpbuf, sizeof(std::jmp_buf));
-        state.ip = 0;
-        Parser::parseSource(state);
-        memcpy(state.jmpbuf, oldjb, sizeof(std::jmp_buf));
-        state.ip = oldip;
-        }
+    default:
         break;
     }
 }
 
 void parseLine(State& state, const std::string& line)
 {
-    if (auto r = Parser::parse(state, line.c_str()); r == 0) {
+    if (auto r = Parser::parse(state, line.c_str()); r == Error::none) {
         if (okay)
-            std::cout << (state.compiling() ? "compiled" : "ok") << std::endl;
+            std::cout << (state.compiling() ? " compiled" : " ok") << std::endl;
     } else {
         switch (r) {
-        case Parser::UnknownWord:
+        case Error::noword:
             std::cout << "word not found in: " << line << std::endl;
             break;
-        case static_cast<int>(State::Error::push):
+        case Error::push:
             std::cout << "stack overflow" << std::endl;
             break;
-        case static_cast<int>(State::Error::pushr):
+        case Error::pushr:
             std::cout << "return stack overflow" << std::endl;
             break;
-        case static_cast<int>(State::Error::popr):
+        case Error::popr:
             std::cout << "return stack underflow" << std::endl;
             break;
-        case static_cast<int>(State::Error::pop):
-        case static_cast<int>(State::Error::top):
-        case static_cast<int>(State::Error::pick):
+        case Error::pop:
+        case Error::top:
+        case Error::pick:
             std::cout << "stack underflow" << std::endl;
             break;
         default:
-            std::cout << "error: " << r << std::endl;
+            std::cout << "unknown error" << std::endl;
             break;
         }
 
-        while (state.size())
-            state.pop();
-        while (state.rsize())
-            state.popr();
-        state.dict.write(Dictionary::Compiling, 0);
-        state.ip = 0;
+        state.reset();
     }
 }
 
index c23c366d6b8a0021dfd149f6c163a4b877207931..a8ccb9d3d3c359318b9942ab851152903563909a 100644 (file)
--- a/core.fth
+++ b/core.fth
 : :noname  0 , here ] ;
 
 : evaluate _source @ >r _sourceu @ >r >in @ >r
-           0 >in ! _sourceu ! _source ! 5 sys
+           0 >in ! _sourceu ! _source ! _ev
            r> >in ! r> _sourceu ! r> _source ! ;
index ced3973405d61e948a0e9989a9bcc1e5f8980b13..b8a415e81e3a6b7cb261feee288c9b797c5b28ca 100644 (file)
@@ -17,6 +17,7 @@
  */
 
 #include "corewords.hpp"
+#include "parser.hpp"
 
 #include <cstring>
 #include <utility>
@@ -171,10 +172,8 @@ execute:
         goto execute;
     case 25: // exit
         state.ip = state.popr();
-        if (state.ip == 0) {
-            std::longjmp(state.jmpbuf,
-                static_cast<int>(State::Error::exit));
-        }
+        if (state.ip == 0)
+            std::longjmp(state.jmpbuf, static_cast<int>(Error::exit));
         break;
     case 26: // semic
         {
@@ -206,6 +205,14 @@ execute:
     case 31: // _in
         state.input(state);
         break;
+    case 32: // _ex
+        {
+        const auto st = state.save();
+        state.ip = 0;
+        Parser::parseSource(state);
+        state.load(st);
+        }
+        break;
     default:
         state.push(index - WordCount);
         break;
index 70cbb304fe867d8cd94bf10bd1d1bec4f57581a2..33f4fc573c256ad405d3a5e7ec6ce0fd11e187ef 100644 (file)
@@ -27,7 +27,7 @@ void user_sys(State&);
 class CoreWords
 {
 public:
-    constexpr static std::size_t WordCount = 32;
+    constexpr static std::size_t WordCount = 33;
 
     constexpr static Cell Immediate = (1 << 5);
 
@@ -44,7 +44,7 @@ public:
         "<\0&\0|\0^\0"
         "<<\0>>\0:\0_'\0execute\0"
         "exit\0;\0_jmp0\0_jmp\0"
-        "depth\0_rdepth\0_in\0";
+        "depth\0_rdepth\0_in\0_ev\0";
 };
 
 #endif // ALEEFORTH_COREWORDS_HPP
index 3b1422418c461998665e8ae8eae302c593ca93c7..39695c44b4a0aa434bb5c554da06a8a42bcddf03 100644 (file)
@@ -22,7 +22,7 @@
 
 #include <cstring>
 
-int Parser::parse(State& state, const char *str)
+Error Parser::parse(State& state, const char *str)
 {
     auto addr = Dictionary::Input;
     state.dict.write(addr, 0);
@@ -38,20 +38,20 @@ int Parser::parse(State& state, const char *str)
     return parseSource(state);
 }
 
-int Parser::parseSource(State& state)
+Error Parser::parseSource(State& state)
 {
     auto word = state.dict.input();
     while (word.size() > 0) {
-        if (auto ret = parseWord(state, word); ret)
+        if (auto ret = parseWord(state, word); ret != Error::none)
             return ret;
 
         word = state.dict.input();
     }
 
-    return 0;
+    return Error::none;
 }
 
-int Parser::parseWord(State& state, Word word)
+Error Parser::parseWord(State& state, Word word)
 {
     int ins, imm;
 
@@ -71,13 +71,13 @@ int Parser::parseWord(State& state, Word word)
 
     if (state.compiling() && !imm)
         state.dict.add(ins);
-    else if (auto stat = state.execute(ins); stat != State::Error::none)
-        return static_cast<int>(stat);
+    else if (auto stat = state.execute(ins); stat != Error::none)
+        return stat;
 
-    return 0;
+    return Error::none;
 }
 
-int Parser::parseNumber(State& state, Word word)
+Error Parser::parseNumber(State& state, Word word)
 {
     const auto base = state.dict.read(Dictionary::Base);
     DoubleCell result = 0;
@@ -97,7 +97,7 @@ int Parser::parseNumber(State& state, Word word)
             result *= base;
             result += 10 + (c > 'a' ? c - 'a' : c - 'A');
         } else {
-            return UnknownWord;
+            return Error::noword;
         }
 
         if (++i < word.wend)
@@ -121,6 +121,6 @@ int Parser::parseNumber(State& state, Word word)
         state.push(value);
     }
 
-    return 0;
+    return Error::none;
 }
 
index f2117815eac94ea651961bd55f98683921b1439f..be6f3f79a019fa4013394d8307565bbf4d8114a2 100644 (file)
 class Parser
 {
 public:
-    constexpr static int UnknownWord = -1;
-
-    static int parse(State&, const char *);
-    static int parseSource(State&);
+    static Error parse(State&, const char *);
+    static Error parseSource(State&);
 
 private:
-    static int parseWord(State&, Word);
-    static int parseNumber(State&, Word);
+    static Error parseWord(State&, Word);
+    static Error parseNumber(State&, Word);
 };
 
 #endif // ALEEFORTH_PARSER_HPP
index b3c98b1eb1e75f092d267aa7de0c8892b7043af4..bfd29d113fd6331727e2791a8729e1097f11eb7e 100644 (file)
@@ -19,6 +19,7 @@
 #include "corewords.hpp"
 #include "state.hpp"
 
+#include <cstring>
 #include <iterator>
 
 bool State::compiling() const
@@ -31,11 +32,25 @@ void State::compiling(bool yes)
     dict.write(Dictionary::Compiling, yes);
 }
 
-State::Error State::execute(Addr addr)
+std::pair<Addr, std::jmp_buf> State::save()
 {
-    auto stat = static_cast<State::Error>(setjmp(jmpbuf));
+    std::pair<Addr, std::jmp_buf> st;
+    st.first = ip;
+    std::memcpy(st.second, jmpbuf, sizeof(std::jmp_buf));
+    return st;
+}
+
+void State::load(const std::pair<Addr, std::jmp_buf>& st)
+{
+    ip = st.first;
+    std::memcpy(jmpbuf, st.second, sizeof(std::jmp_buf));
+}
+
+Error State::execute(Addr addr)
+{
+    auto stat = static_cast<Error>(setjmp(jmpbuf));
 
-    if (stat == State::Error::none) {
+    if (stat == Error::none) {
         CoreWords::run(addr, *this);
 
         if (ip >= Dictionary::Begin) {
@@ -46,13 +61,24 @@ State::Error State::execute(Addr addr)
             // addr was a CoreWord, all done now.
             ip = 0;
         }
-    } else if (stat == State::Error::exit) {
-        stat = State::Error::none;
+    } else if (stat == Error::exit) {
+        stat = Error::none;
     }
 
     return stat;
 }
 
+void State::reset()
+{
+    while (size())
+        pop();
+    while (rsize())
+        popr();
+
+    dict.write(Dictionary::Compiling, 0);
+    ip = 0;
+}
+
 std::size_t State::size() const noexcept
 {
     return std::distance(dstack, static_cast<const Cell *>(dsp));
index 648b868659bc55dca21a3b710ca4d625913c95f8..325f405f6b8b20185a7f0acfb7be3f7478bc993f 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <csetjmp>
 #include <cstddef>
+#include <tuple>
 
 constexpr unsigned DataStackSize = 16;
 constexpr unsigned ReturnStackSize = 16;
@@ -31,17 +32,6 @@ constexpr unsigned ReturnStackSize = 16;
 class State
 {
 public:
-    enum class Error : int {
-        none = 0,
-        push,
-        pop,
-        pushr,
-        popr,
-        top,
-        pick,
-        exit
-    };
-
     Addr ip = 0;
     Dictionary& dict;
     void (*input)(State&);
@@ -54,7 +44,11 @@ public:
     bool compiling() const;
     void compiling(bool);
 
+    std::pair<Addr, std::jmp_buf> save();
+    void load(const std::pair<Addr, std::jmp_buf>&);
+
     Error execute(Addr);
+    void reset();
 
     std::size_t size() const noexcept;
     std::size_t rsize() const noexcept;
index 5b577f200368e99b0ffea4909a57db07df27a04f..0a7f7ee0c1ecd6f69bea4d52de684b1f225b4a21 100644 (file)
@@ -32,6 +32,18 @@ using Func = void (*)(State&);
 
 constexpr unsigned int MaxCellNumberChars = 6; // -32768
 
+enum class Error : int {
+    none = 0,
+    push,
+    pop,
+    pushr,
+    popr,
+    top,
+    pick,
+    exit,
+    noword
+};
+
 struct Word
 {
     struct iterator;