/// 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<2048> forth {sforth::initialize<&forth>()}; constinit static sforth::native_word<".", [](auto) { char buf[32] = {}; auto ptr = buf + sizeof(buf); auto v = forth.pop(); bool neg = v < 0; if (neg) v = -v; *--ptr = '\0'; do { *--ptr = "0123456789abcdefghijklmnopqrstuvwxyz"[v % forth.base]; } while (v /= forth.base); if (neg) *--ptr = '-'; 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()) { for (auto& ch : line) { if (ch >= 'a' && ch <= 'z') ch = ch - 'a' + 'A'; } if (line == "BYE") return true; 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; }