move to folders, more cleaning and fixes

This commit is contained in:
2021-11-13 17:35:20 +01:00
parent 68ddeb3e17
commit cf1a0cd99b
18 changed files with 106 additions and 69 deletions
+12
View File
@@ -0,0 +1,12 @@
/**
* Forth built-ins
*
* Created on 2021/11/13.
*/
#ifndef FORTH_FH_BUILTINS_H
#define FORTH_FH_BUILTINS_H
enum fh_error register_builtin_words(struct fh_thread_s *fh);
#endif //FORTH_FH_BUILTINS_H
+19
View File
@@ -0,0 +1,19 @@
/**
* Runtime configuration
*
* Created on 2021/11/13.
*/
#ifndef FORTH_FH_CONFIG_H
#define FORTH_FH_CONFIG_H
#define CONTROL_STACK_DEPTH 1024
#define DATA_STACK_DEPTH 1024
#define RETURN_STACK_DEPTH 1024
#define MAX_NAME_LEN 32
#define DICT_SIZE 1024
#define COMPILED_BUFFER_SIZE (1024*1024)
#define HEAP_SIZE (1024*1024)
#define MAXLINE 65535
#endif //FORTH_FH_CONFIG_H
+31
View File
@@ -0,0 +1,31 @@
/**
* Forth errors
*
* Created on 2021/11/13.
*/
#ifndef FORTH_FH_ERROR_H
#define FORTH_FH_ERROR_H
/** Error codes */
enum fh_error {
FH_OK = 0,
FH_ERR_CS_OVERFLOW,
FH_ERR_DS_OVERFLOW,
FH_ERR_RS_OVERFLOW,
FH_ERR_CS_UNDERFLOW,
FH_ERR_DS_UNDERFLOW,
FH_ERR_RS_UNDERFLOW,
FH_ERR_HEAP_FULL,
FH_ERR_DICT_FULL,
FH_ERR_COMPILE_FULL,
FH_ERR_NAME_TOO_LONG,
FH_ERR_INVALID_STATE,
FH_ERR_INTERNAL,
FH_ERR_UNKNOWN_WORD,
FH_ERR_MAX,
};
const char *fherr_name(enum fh_error e);
#endif //FORTH_FH_ERROR_H
+20
View File
@@ -0,0 +1,20 @@
/**
* Global state
*
* Created on 2021/11/13.
*/
#ifndef FORTH_FH_GLOBALS_H
#define FORTH_FH_GLOBALS_H
/** Forth runtime global state */
struct fh_global_s {
/** Verbose logging enabled */
bool verbose;
/** Interactive mode (i.e. not started with a file argument) */
bool interactive;
};
extern struct fh_global_s fh_globals;
#endif //FORTH_FH_GLOBALS_H
+27
View File
@@ -0,0 +1,27 @@
/**
* Forth heap and compile memory
*
* Created on 2021/11/13.
*/
#ifndef FORTH_FH_MEM_H
#define FORTH_FH_MEM_H
enum fh_error fh_heap_reserve(
struct fh_thread_s *fh,
size_t len,
uint32_t *addr
);
void fh_heap_write(struct fh_thread_s *fh, uint32_t addr, const void *src, uint32_t len);
enum fh_error fh_heap_put(struct fh_thread_s *fh, const void *src, uint32_t len);
void fh_heap_copy_from_compile(struct fh_thread_s *fh, uint32_t addr, uint32_t srcaddr, uint32_t len);
enum fh_error fh_compile_reserve(
struct fh_thread_s *fh,
size_t len,
uint32_t *addr
);
void fh_compile_write(struct fh_thread_s *fh, uint32_t addr, const void *src, uint32_t len);
enum fh_error fh_compile_put(struct fh_thread_s *fh, const void *src, uint32_t len);
#endif //FORTH_FH_MEM_H
+24
View File
@@ -0,0 +1,24 @@
/**
* Forth printing
*
* Created on 2021/11/13.
*/
#ifndef FORTH_FH_PRINT_H
#define FORTH_FH_PRINT_H
/* for printing */
#include <stdlib.h>
#include <stdio.h>
#include "fh_globals.h"
/* logging */
#define LOG(format, ...) do { if(fh_globals.verbose) { fprintf(stderr, format "\n", ##__VA_ARGS__); } } while (0)
#define LOGI(format, ...) fprintf(stderr, "\x1b[32m" format "\x1b[m\n", ##__VA_ARGS__)
#define LOGE(format, ...) fprintf(stderr, "\x1b[31;1m" format "\x1b[m\n", ##__VA_ARGS__)
/* Forth standard output. XXX should be stdout, but then colors get mangled if logging is used */
#define FHPRINT(format, ...) fprintf(stderr, "\x1b[33;1m" format "\x1b[m", ##__VA_ARGS__)
#define FHPRINT_SVC(format, ...) fprintf(stderr, "" format "", ##__VA_ARGS__)
#endif //FORTH_FH_PRINT_H
+175
View File
@@ -0,0 +1,175 @@
/**
* Forth runtime internals
*
* Created on 2021/11/13.
*/
#ifndef FORTH_FH_RUNTIME_H
#define FORTH_FH_RUNTIME_H
#include <stdint.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "fh_config.h"
struct fh_word_s;
struct fh_instruction_s;
struct fh_thread_s;
/** Word handler typedef */
typedef enum fh_error (*word_exec_t)(struct fh_thread_s *fh);
/** Bytecode instruction type marker */
enum fb_instruction_kind {
/* Data = word pointer (dict index) */
FH_INSTR_WORD,
/* Data = numeric value to push onto the data stack */
FH_INSTR_NUMBER,
};
/** Bytecode word indices that are not in the dict, have special effect */
enum compiler_word {
/** End of a user defined word, pop address and jump back */
CPLWORD_ENDWORD = DICT_SIZE + 1,
/** This is the `s"` instruction, the length (u32) and string data immediately follow */
CPLWORD_ALLOCSTR,
/** This is the `."` instruction, same format as above. */
CPLWORD_TYPESTR,
};
/** One instruction in bytecode */
struct fh_instruction_s {
/** What is the meaning of data? */
enum fb_instruction_kind kind;
/** Data word */
uint32_t data;
};
static inline void instr_init(struct fh_instruction_s *instr, enum fb_instruction_kind kind, uint32_t data)
{
instr->kind = kind;
instr->data = data;
}
#define INSTR_SIZE (sizeof(struct fh_instruction_s))
_Static_assert(sizeof(struct fh_instruction_s) % 4 == 0, "Instruction struct is aligned");
/** Forth runtime major state */
enum fh_state {
FH_STATE_INTERPRET = 0,
FH_STATE_COMPILE,
FH_STATE_SHUTDOWN,
FH_STATE_MAX,
};
/** Forth runtime minor state */
enum fh_substate {
FH_SUBSTATE_NONE = 0,
FH_SUBSTATE_COLONNAME,
FH_SUBSTATE_SQUOTE,
FH_SUBSTATE_DOTQUOTE,
FH_SUBSTATE_PARENCOMMENT,
FH_SUBSTATE_LINECOMMENT,
FH_SUBSTATE_MAX,
};
/** Word struct as they are stored in the dictionary */
struct fh_word_s {
/** Word name */
char name[MAX_NAME_LEN];
/**
* Handler function.
* Builtin functions use pre-defined native handlers.
* User words use a shared handler that executes compiled
* bytecode at 'start' address of the compile-memory area.
*/
word_exec_t handler;
/** Indicates that this is a built-in instruction and not a word call */
bool builtin;
/** Indicates that this instruction should always be treated as interpreted,
* in practice this is only used for `;` */
bool immediate;
/** Start address in case of user words */
uint32_t start;
};
/**
* Forth runtime instance - state variables and memory areas.
*
* Some memory areas, such as the dict or heap, could be moved
* to a shared pointer if multi-threading and synchronization is added.
*/
struct fh_thread_s {
/** Control stack */
uint32_t control_stack[CONTROL_STACK_DEPTH];
size_t control_stack_top;
size_t control_stack_hwm;
/** Data stack */
uint32_t data_stack[DATA_STACK_DEPTH];
size_t data_stack_top;
size_t data_stack_hwm;
/** Return stack */
uint32_t return_stack[RETURN_STACK_DEPTH];
size_t return_stack_top;
size_t return_stack_hwm;
/** Data heap */
uint8_t heap[HEAP_SIZE];
size_t heap_top;
/** Compile buffer, used for both word data and literals */
uint8_t compile[COMPILED_BUFFER_SIZE];
size_t compile_top;
/** Pointer into the compile buffer for execution */
uint32_t execptr;
/** Word dict */
struct fh_word_s dict[DICT_SIZE];
uint32_t dict_top;
/** Forth state */
enum fh_state state;
/** Forth sub-state */
enum fh_substate substate;
/** Word currently being executed - a pointer is placed here
* before calling the handler */
struct fh_word_s *exec_word;
};
enum fh_error fh_add_word(const struct fh_word_s *w, struct fh_thread_s *fh);
void fh_setstate(struct fh_thread_s *fh, enum fh_state state, enum fh_substate substate);
void fh_setsubstate(struct fh_thread_s *fh, enum fh_substate substate);
enum fh_error w_user_word(struct fh_thread_s *fh);
/* if the return address is this, we should drop back to interactive mode */
#define MAGICADDR_INTERACTIVE 0xFFFFFFFFULL
/** Get a value rounded up to multiple of word size */
#define WORDALIGNED(var) (((var) + 3) & ~3)
_Static_assert(WORDALIGNED(0) == 0, "word align");
_Static_assert(WORDALIGNED(1) == 4, "word align");
_Static_assert(WORDALIGNED(2) == 4, "word align");
_Static_assert(WORDALIGNED(3) == 4, "word align");
_Static_assert(WORDALIGNED(4) == 4, "word align");
_Static_assert(WORDALIGNED(5) == 8, "word align");
_Static_assert(WORDALIGNED(1023) == 1024, "word align");
_Static_assert(WORDALIGNED(1024) == 1024, "word align");
#define TRY(x) \
do { \
if (FH_OK != (rv = (x))) return rv; \
} while (0)
#endif //FORTH_FH_RUNTIME_H
+17
View File
@@ -0,0 +1,17 @@
/**
* Forth stack operations
*
* Created on 2021/11/13.
*/
#ifndef FORTH_FH_STACK_H
#define FORTH_FH_STACK_H
enum fh_error ds_pop(struct fh_thread_s *fh, uint32_t *out);
enum fh_error rs_pop(struct fh_thread_s *fh, uint32_t *out);
enum fh_error cs_pop(struct fh_thread_s *fh, uint32_t *out);
enum fh_error ds_push(struct fh_thread_s *fh, uint32_t in);
enum fh_error rs_push(struct fh_thread_s *fh, uint32_t in);
enum fh_error cs_push(struct fh_thread_s *fh, uint32_t in);
#endif //FORTH_FH_STACK_H
+21
View File
@@ -0,0 +1,21 @@
/**
* Forth main entry-point
*
* Created on 2021/11/13.
*/
#ifndef FORTH_H
#define FORTH_H
#include <stdint.h>
#include <stdbool.h>
#include "fh_config.h"
#include "fh_error.h"
struct fh_thread_s;
enum fh_error fh_init(struct fh_thread_s *fh);
enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf);
#endif //FORTH_H