move to folders, more cleaning and fixes
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user