|
|
|
/// sforth, an implementation of forth
|
|
|
|
/// Copyright (C) 2024 Clyne Sullivan <clyne@bitgloo.com>
|
|
|
|
///
|
|
|
|
/// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#include "sforth/forth.hpp"
|
|
|
|
|
|
|
|
#include <array>
|
|
|
|
#include <fstream>
|
|
|
|
#include <iostream>
|
|
|
|
#include <span>
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
static std::array<sforth::cell, 1024> dict;
|
|
|
|
static auto fth = new (dict.data()) sforth::forth;
|
|
|
|
|
|
|
|
static bool parse_stream(sforth::forth *, std::istream&, bool say_okay = false);
|
|
|
|
|
|
|
|
int main(int argc, const char *argv[])
|
|
|
|
{
|
|
|
|
std::span args (argv + 1, argc - 1);
|
|
|
|
|
|
|
|
sforth::initialize<&fth>(dict.end());
|
|
|
|
fth->add(".", [](auto) {
|
|
|
|
char buf[32] = {};
|
|
|
|
std::to_chars(buf, buf + sizeof(buf), fth->pop(), fth->base);
|
|
|
|
std::cout << buf << ' ';
|
|
|
|
});
|
|
|
|
fth->add("emit", [](auto) { std::cout << static_cast<char>(fth->pop()); });
|
|
|
|
fth->add("dictsize", [](auto) { fth->push(dict.size() * sizeof(sforth::cell)); });
|
|
|
|
|
|
|
|
for (auto arg : args) {
|
|
|
|
if (std::ifstream file {arg}; parse_stream(fth, file))
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
parse_stream(fth, std::cin, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool parse_stream(sforth::forth *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;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|