You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
alee-forth/libalee/corewords.hpp

199 lines
5.6 KiB
C++

//
/// @file corewords.hpp
/// @brief Manages the fundamental word-set and its execution.
//
// Alee Forth: A portable and concise Forth implementation in modern C++.
// Copyright (C) 2023 Clyne Sullivan <clyne@bitgloo.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#ifndef ALEEFORTH_COREWORDS_HPP
#define ALEEFORTH_COREWORDS_HPP
#include "config.hpp"
#include "dictionary.hpp"
#include "types.hpp"
#include <algorithm>
class State;
/**
* To be implemented by the user, this function is called when the `sys` word
* is executed.
* @param state Current execution state object.
*/
void user_sys(State& state);
/**
* @class CoreWords
* @brief Provides the fundamental word-set and manages its execution.
*/
class CoreWords
{
public:
/**
* Searches for the token/index of the given word if it is part of the
* fundamental word-set.
* @param state Current execution state object.
* @param word Word (stored in state's dictionary memory) to look up.
* @return The token/index of the word or -1 if not found.
*/
static Cell findi(State& state, Word word);
/**
* Looks up the token/index of the given fundamental word.
* Primarily used for compile-time lookup.
* @param word The word to look up.
* @return The token/index of the word or -1 if not found.
*/
consteval static Cell token(const char *word) {
return findi(word, strlen(word));
}
/**
* Executes the given execution token using the given state.
* @param token Any valid execution token (word, fundamental, constant...).
* @param state The state object to execute with.
*/
static void run(Cell token, State& state);
/**
* String lookup table for the fundamental word-set.
* This also determines the opcode (index) of these words.
*/
constexpr static char wordsarr[] =
"_lit\0drop\0dup\0swap\0pick\0sys\0"
"+\0-\0m*\0_/\0_%\0"
"_@\0_!\0>r\0r>\0=\0"
"<\0&\0|\0^\0"
"<<\0>>\0:\0_'\0execute\0"
"exit\0;\0_jmp0\0_jmp\0"
"depth\0_rdepth\0_in\0_ev\0find\0"
"_uma\0u<\0um/mod\0_nx\0";
/**
* Count of total fundamental words.
*/
constexpr static Cell WordCount = [] {
return std::count(wordsarr, wordsarr + sizeof(wordsarr), '\0'); }();
private:
/**
* Generic implementation of findi(). Private; use public implementations.
* @param it Beginning iterator of the word to search for.
* @param size Size of the searched-for word i.e. end == it + size.
* @return The token/index of the word or -1 if not found.
*/
template<typename Iter>
LIBALEE_SECTION
constexpr static Cell findi(Iter it, std::size_t size)
{
const char *ptr = CoreWords::wordsarr;
for (Cell wordsi = 0; wordsi < WordCount; ++wordsi) {
std::size_t wordsize = strlen(ptr);
if (wordsize == size && Dictionary::equal(ptr, ptr + wordsize, it))
return wordsi;
ptr += wordsize + 1;
}
return -1;
}
public:
static void word_lit(State&);
static void word_drop(State&);
static void word_dup(State&);
static void word_swap(State&);
static void word_pick(State&);
static void word_sys(State&);
static void word_add(State&);
static void word_sub(State&);
static void word_mul(State&);
static void word_div(State&);
static void word_mod(State&);
static void word_peek(State&);
static void word_poke(State&);
static void word_rpush(State&);
static void word_rpop(State&);
static void word_eq(State&);
static void word_lt(State&);
static void word_and(State&);
static void word_or(State&);
static void word_xor(State&);
static void word_shl(State&);
static void word_shr(State&);
static void word_colon(State&);
static void word_tick(State&);
static void word_execute(State&);
static void word_exit(State&);
static void word_semic(State&);
static void word_jmp0(State&);
static void word_jmp(State&);
static void word_depth(State&);
static void word_rdepth(State&);
static void word_in(State&);
static void word_ev(State&);
static void word_find(State&);
static void word_uma(State&);
static void word_ult(State&);
static void word_ummod(State&);
constexpr static void (*wordstbl[])(State&) = {
word_lit,
word_drop,
word_dup,
word_swap,
word_pick,
word_sys,
word_add,
word_sub,
word_mul,
word_div,
word_mod,
word_peek,
word_poke,
word_rpush,
word_rpop,
word_eq,
word_lt,
word_and,
word_or,
word_xor,
word_shl,
word_shr,
word_colon,
word_tick,
word_execute,
word_exit,
word_semic,
word_jmp0,
word_jmp,
word_depth,
word_rdepth,
word_in,
word_ev,
word_find,
word_uma,
word_ult,
word_ummod
};
};
#endif // ALEEFORTH_COREWORDS_HPP