changed to by-default 64 bit session addressing & implementation of word became better with helper functions and restructuring

This commit is contained in:
Richard Thier 2024-09-25 23:18:30 +02:00
parent 00e818e43b
commit f83fd990f8

View File

@ -5,6 +5,18 @@
#include<string.h> // memcpy, strlen.. #include<string.h> // memcpy, strlen..
#include<stddef.h> // NULL #include<stddef.h> // NULL
// Session offset type - defaults to 64 bit, but you can override
#ifndef SLOFFS_T
#define SLOFFS_T uint64_t
#endif
union word_body {
SLOFFS_T offset;
void *ptr;
};
typedef union word_body word_body;
/** Possible word types */ /** Possible word types */
enum SLC_WORDTYP { enum SLC_WORDTYP {
/** Still in plain text */ /** Still in plain text */
@ -18,20 +30,9 @@ enum SLC_WORDTYP {
}; };
typedef enum SLC_WORDTYP SLC_WORDTYP; typedef enum SLC_WORDTYP SLC_WORDTYP;
/** Gets the wordtyp from a flags field - see wordstart */ static inline int get_padding(uint8_t *ptr, int alignment) {
static inline SLC_WORDTYP get_word_type(uint8_t flags) { // return (alignment - (ptr % alignment)) % alignment;
return (SLC_WORDTYP)(flags >> 6); return (ptrdiff_t)(ptr + alignment - 1) / alignment * alignment;
}
// TODO: probably should remove this?
/** Gets the 6-bit variable count (at most 64 vars possible per word) */
static inline uint8_t get_word_var_count(uint8_t flags) {
return (flags && 0x3F); /* 0011 1111 */
}
/** Gets the 24bit storage offset of the word: Natives contain pointers in an offseted array */
static inline uint32_t get_word_storage_offset(uint8_t high_offset, uint16_t low_offset) {
return ((uint32_t)high_offset << 16) + low_offset;
} }
/** /**
@ -55,7 +56,9 @@ static inline uint32_t get_word_storage_offset(uint8_t high_offset, uint16_t low
* #swap * #swap
* #dup * #dup
* *
* TODO: How to do this builtin to be properly changed inline? If it can be inline threaded-coded, then its fine, but is spec-case * ^^This built-in generates threaded code / text while processing in a way so that the
* to_prefix becomes prefixed with the "right" prefix and '#' exchanged with the current!
*
* ^^The above always needs starting '#builtin' at the definition and inside. That is exchanged to real prefix... * ^^The above always needs starting '#builtin' at the definition and inside. That is exchanged to real prefix...
* This is used for implementation implementing built-ins with FORTH-like code instead of native (saves native interpret. space) * This is used for implementation implementing built-ins with FORTH-like code instead of native (saves native interpret. space)
* *
@ -69,21 +72,52 @@ static inline uint32_t get_word_storage_offset(uint8_t high_offset, uint16_t low
* ) [ #parse_num #print ] { #parse_num #print } * ) [ #parse_num #print ] { #parse_num #print }
* # * #
*/ */
struct wordstart { struct word {
/** The ':' char - after processing it stores the flags */ /** Defines how to understand this word */
uint8_t flags; uint8_t flags;
/** whitespace after ':' and first char of name - after processing contains the high-offset */ uint8_t reserved; // Padding to ensure alignment of vars (4byte) */
uint16_t high_offset; uint16_t var_count; // can be zero
/** Either remaining parts of the name - or the leading tab/space for starting variables (or newline if there's none) */ /* XXX: name is stored in symbol table only, not stored here */
uint8_t low_offset; uint32_t first_var; /* uint32_t ..vars[]; // The local variables memories for the word. Like "@a @b @c". Can be empty! */
/* char ..name[]; // The REMAINS of name of the word being defined. Can be empty! */
/* char vars[]; // The local (at least 1-letter) variables of the word. Can be empty - min 4x8bit per a var, like: " @a;" */ /* Possibly overlapping with first_var (var_count == 0) possibly using that as padding... */
// TODO: process vars when doing the reader->session store
/* char newline; // there is always a newline at this point! XXX: "@a; ", "@b;\n" is how we store vars (*/ /* EITHER: */
/* char data[]; // The "body" of the word - either text source or inline threaded code (at least 1 character) */ /* word_body processed_body; // Where to find the body data (ptr or offset) if its not "inline_data[]" */
/* char ender[]; // The ender-string that ends the word - always at least 1 character! */
/* OR: */
/* uint8_t inline_data[]; // The "body" - either text src (contains "ender") or inline threaded code (zero term) */
}; };
typedef struct wordstart wordstart; typedef struct word word;
/** Gets the wordtyp from a flags field - see word */
static inline SLC_WORDTYP word_type(uint8_t flags) {
return (SLC_WORDTYP) (flags >> 6);
}
/** Gets the variable array of the given word */
static inline uint32_t *word_vars(word *w) {
return &(w->first_var);
}
/** Gets the (inline or processed - same addr) "data" of the word. */
static inline uint8_t *word_inline_data(word *w) {
uint32_t *vars = (uint32_t *)word_vars(w);
uint16_t vcnt = w->var_count;
// Might be overlapping "first_var" in case we had no vars
uint8_t *after_wars = (uint8_t *)(vars + vcnt);
int padding = get_padding(after_wars, 8);
after_wars += padding;
return after_wars; // no more wars
}
/** Gets the processed body of the word. */
static word_body word_processed_body(word *w) {
word_body *body = (word_body *)word_inline_data(w);
return *body;
}
enum SLC_SYM_OP { SLC_SYM_SET, SLC_SYM_GET, SLC_SYM_ERASE }; enum SLC_SYM_OP { SLC_SYM_SET, SLC_SYM_GET, SLC_SYM_ERASE };
typedef enum SLC_SYM_OP SLC_SYM_OP; typedef enum SLC_SYM_OP SLC_SYM_OP;
@ -113,7 +147,7 @@ typedef enum SLC_IO_OP SLC_IO_OP;
union symptr { union symptr {
uint32_t *varp; uint32_t *varp;
wordstart *worp; word *worp;
}; };
typedef union symptr symptr; typedef union symptr symptr;
@ -126,11 +160,11 @@ typedef union symptr symptr;
* SLC_SYM_GET Gets the symbol at key (the word parameter is unused). Returns NULL if there is no word for the key. * SLC_SYM_GET Gets the symbol at key (the word parameter is unused). Returns NULL if there is no word for the key.
* SLC_SYM_ERASE Erases the symbol table so it becomes empty again. Can never fail, returns NULL. * SLC_SYM_ERASE Erases the symbol table so it becomes empty again. Can never fail, returns NULL.
* *
* Rem.: On GET we return a wordstart* in case the key is to a word and a regular uint32_t* if its a variable name! * Rem.: On GET we return a word* in case the key is to a word and a regular uint32_t* if its a variable name!
* *
* @param op Defines which operation the caller wants. * @param op Defines which operation the caller wants.
* @param key The key (both for SET and GET) * @param key The key (both for SET and GET)
* @param ptr When adding a found word/variable to the symbol table, the key will point to this wordstart* or uint32_t* * @param ptr When adding a found word/variable to the symbol table, the key will point to this word* or uint32_t*
* @returns The word/var definition stored for the key, or NULL when it is not stored yet or op is SET and there was an error. * @returns The word/var definition stored for the key, or NULL when it is not stored yet or op is SET and there was an error.
*/ */
typedef symptr (*sym)(SLC_SYM_OP op, char *key, symptr ptr); typedef symptr (*sym)(SLC_SYM_OP op, char *key, symptr ptr);
@ -171,7 +205,7 @@ typedef uint32_t (*stack)(SLC_STACK_OP op, uint32_t param);
typedef uint32_t (*session)(SLC_SESSION_OP op, uint32_t i, uint32_t j); typedef uint32_t (*session)(SLC_SESSION_OP op, uint32_t i, uint32_t j);
union iores { union iores {
/** Either the cmd result or the handle pointer*/ /** Either the terminal cmd result or the handle pointer */
const char *ptr; const char *ptr;
/** The read character */ /** The read character */
char c; char c;
@ -237,7 +271,15 @@ static inline slc_state slc_comment_statechange_in(
return current_state; return current_state;
} }
static inline slc_state slc_defname_statechange( static inline slc_state slc_def_name_statechange(
slc_state current_state,
char c,
const char *prefix) {
// FIXME: Implement
return current_state;
}
static inline slc_state slc_word_name_statechange(
slc_state current_state, slc_state current_state,
char c, char c,
const char *prefix) { const char *prefix) {
@ -323,13 +365,17 @@ static inline void slc(
&multiline_i); &multiline_i);
/* state -> def_name */ /* state -> def_name */
if(state == SLC_START) { if(state == SLC_START) {
state = slc_defname_statechange( state = slc_def_name_statechange(
state, state,
c, c,
prefix); prefix);
} }
/* state -> word_name */
if(state == SLC_START) { if(state == SLC_START) {
state = slc_word_name_statechange(
state,
c,
prefix);
} }
break; break;
case SLC_COMMENT: case SLC_COMMENT: