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.
199 lines
5.6 KiB
C++
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
|
|
|