/// sforth, an implementation of forth /// Copyright (C) 2024 Clyne Sullivan /// /// This program is free software: you can redistribute it and/or modify it /// under the terms of the GNU General Public License as published by the Free /// Software Foundation, either version 3 of the License, or (at your option) /// any later version. /// /// This program is distributed in the hope that it will be useful, but WITHOUT /// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or /// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for /// more details. /// /// You should have received a copy of the GNU General Public License along /// with this program. If not, see . #include "sforth/forth.hpp" #include #include #include #include #include constinit static sforth::forth<1024> forth {sforth::initialize<&forth>()}; constinit static sforth::native_word<".", [](auto) { char buf[32] = {}; auto ptr = buf + sizeof(buf); auto v = forth.pop(); *--ptr = '\0'; do { *--ptr = "0123456789abcdefghijklmnopqrstuvwxyz"[v % forth.base]; } while (v /= forth.base); std::cout << ptr << ' '; }> dot; constinit static sforth::native_word<"emit", [](auto) { std::cout << static_cast(forth.pop()); }, &dot> emit; constinit static sforth::native_word<"type", [](auto) { const unsigned u = forth.pop(); const auto caddr = reinterpret_cast(forth.pop()); std::cout << std::string_view{caddr, u}; }, &emit> type; static bool parse_stream(auto&, std::istream&, bool say_okay = false); int main(int argc, const char *argv[]) { std::span args (argv + 1, argc - 1); dot.next = std::exchange(forth.next, &type); for (auto arg : args) { if (std::ifstream file {arg}; parse_stream(forth, file)) return 0; } parse_stream(forth, std::cin, true); } bool parse_stream(auto &fth, std::istream& str, bool say_okay) { std::string line; while (str.good()) { std::getline(str, line); if (!line.empty()) { if (line == "bye") return true; for (auto& ch : line) { if (ch >= 'A' && ch <= 'Z') ch = ch - 'A' + 'a'; } try { fth.parse_line(line); } catch (sforth::error e) { std::cerr << sforth::error_string(e) << " in " << line << std::endl; continue; } } if (say_okay) std::cout << (fth.compiling ? "compiled" : "ok") << std::endl; } return false; }