Trying to build a forth runtime in C
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
forth/src/fh_builtins.c

189 lines
3.9 KiB

3 years ago
#include <string.h>
#include <stdbool.h>
3 years ago
#include "fh_runtime.h"
#include "fh_config.h"
#include "fh_error.h"
#include "fh_print.h"
3 years ago
#include "fh_builtins.h"
#include "fh_stack.h"
#include "fh_mem.h"
static enum fh_error w_add(struct fh_thread_s *fh)
{
enum fh_error rv;
uint32_t a = 0, b = 0;
TRY(ds_pop(fh, &a));
TRY(ds_pop(fh, &b));
TRY(ds_push(fh, a + b));
return FH_OK;
}
static enum fh_error w_sub(struct fh_thread_s *fh)
{
enum fh_error rv;
uint32_t a = 0, b = 0;
TRY(ds_pop(fh, &a));
TRY(ds_pop(fh, &b));
TRY(ds_push(fh, a - b));
return FH_OK;
}
static enum fh_error w_mul(struct fh_thread_s *fh)
{
enum fh_error rv;
uint32_t a = 0, b = 0;
TRY(ds_pop(fh, &a));
TRY(ds_pop(fh, &b));
TRY(ds_push(fh, a * b));
return FH_OK;
}
static enum fh_error w_colon(struct fh_thread_s *fh)
{
if (fh->state != FH_STATE_INTERPRET) {
return FH_ERR_INVALID_STATE;
}
fh_setstate(fh, FH_STATE_COMPILE, FH_SUBSTATE_COLONNAME);
if (fh->dict_top >= DICT_SIZE) {
return FH_ERR_DICT_FULL;
}
fh->dict[fh->dict_top].start = fh->compile_top;
fh->dict[fh->dict_top].handler = w_user_word;
return FH_OK;
}
static enum fh_error w_semicolon(struct fh_thread_s *fh)
{
enum fh_error rv;
struct fh_instruction_s instr;
if (fh->state != FH_STATE_COMPILE) {
return FH_ERR_INVALID_STATE;
}
instr.kind = FH_INSTR_WORD;
instr.data = CPLWORD_ENDWORD;
TRY(fh_compile_put(fh, &instr, INSTR_SIZE));
/* Return to interpret state */
fh_setstate(fh, FH_STATE_INTERPRET, 0);
fh->dict_top++;
return FH_OK;
}
static enum fh_error w_dot(struct fh_thread_s *fh)
{
enum fh_error rv;
uint32_t a = 0;
TRY(ds_pop(fh, &a));
FHPRINT("%d ", (int32_t) a);
return FH_OK;
}
static enum fh_error w_type(struct fh_thread_s *fh)
{
enum fh_error rv;
uint32_t count = 0, addr = 0;
TRY(ds_pop(fh, &count));
TRY(ds_pop(fh, &addr));
FHPRINT("%.*s", count, &fh->heap[addr]);
return FH_OK;
}
static enum fh_error w_cr(struct fh_thread_s *fh)
{
(void) fh;
FHPRINT("\n");
return FH_OK;
}
static enum fh_error w_space(struct fh_thread_s *fh)
{
(void) fh;
FHPRINT(" ");
return FH_OK;
}
static enum fh_error w_s_quote(struct fh_thread_s *fh)
{
fh_setsubstate(fh, FH_SUBSTATE_SQUOTE);
return FH_OK;
}
static enum fh_error w_dot_quote(struct fh_thread_s *fh)
{
fh_setsubstate(fh, FH_SUBSTATE_DOTQUOTE);
return FH_OK;
}
static enum fh_error w_backslash(struct fh_thread_s *fh)
{
fh_setsubstate(fh, FH_SUBSTATE_LINECOMMENT);
return FH_OK;
}
static enum fh_error w_paren(struct fh_thread_s *fh)
{
fh_setsubstate(fh, FH_SUBSTATE_PARENCOMMENT);
return FH_OK;
}
static enum fh_error w_bye(struct fh_thread_s *fh)
{
LOG("state=SHUTDOWN");
fh_setstate(fh, FH_STATE_SHUTDOWN, 0);
return FH_OK;
}
/** Add pointers to built-in word handlers to a runtime struct */
enum fh_error register_builtin_words(struct fh_thread_s *fh)
{
struct name_and_handler {
const char *name;
word_exec_t handler;
bool immediate;
};
const struct name_and_handler builtins[] = {
{"s\"", w_s_quote, 1},
{".\"", w_dot_quote, 1},
/* Compiler control words */
{"bye", w_bye, 0},
/* Basic arithmetics */
{"+", w_add, 0},
{"-", w_sub, 0},
{"*", w_mul, 0},
/* Control words */
{":", w_colon, 0},
{";", w_semicolon, 1},
{".", w_dot, 0},
{"type", w_type, 0},
{"cr", w_cr, 0},
{"space", w_space, 0},
{"\\", w_backslash, 0}, // line comment
{"(", w_paren, 0}, // enclosed comment
{ /* end marker */ }
};
// foreach
struct fh_word_s w;
const struct name_and_handler *p = builtins;
enum fh_error rv;
while (p->handler) {
strcpy(w.name, p->name);
w.handler = p->handler;
w.builtin = 1;
w.immediate = p->immediate;
rv = fh_add_word(&w, fh);
if (rv != FH_OK) {
return rv;
}
p++;
}
return FH_OK;
}