diff --git a/engine/slc.h b/engine/slc.h index afa9082..8442ec9 100644 --- a/engine/slc.h +++ b/engine/slc.h @@ -5,6 +5,18 @@ #include // memcpy, strlen.. #include // 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 */ enum SLC_WORDTYP { /** Still in plain text */ @@ -18,20 +30,9 @@ enum SLC_WORDTYP { }; typedef enum SLC_WORDTYP SLC_WORDTYP; -/** Gets the wordtyp from a flags field - see wordstart */ -static inline SLC_WORDTYP get_word_type(uint8_t flags) { - return (SLC_WORDTYP)(flags >> 6); -} - -// 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; +static inline int get_padding(uint8_t *ptr, int alignment) { + // return (alignment - (ptr % alignment)) % alignment; + return (ptrdiff_t)(ptr + alignment - 1) / alignment * alignment; } /** @@ -55,7 +56,9 @@ static inline uint32_t get_word_storage_offset(uint8_t high_offset, uint16_t low * #swap * #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... * 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 } * # */ -struct wordstart { - /** The ':' char - after processing it stores the flags */ +struct word { + /** Defines how to understand this word */ uint8_t flags; - /** whitespace after ':' and first char of name - after processing contains the high-offset */ - uint16_t high_offset; - /** Either remaining parts of the name - or the leading tab/space for starting variables (or newline if there's none) */ - uint8_t low_offset; - /* 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;" */ - // 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 (*/ - /* char data[]; // The "body" of the word - either text source or inline threaded code (at least 1 character) */ - /* char ender[]; // The ender-string that ends the word - always at least 1 character! */ + uint8_t reserved; // Padding to ensure alignment of vars (4byte) */ + uint16_t var_count; // can be zero + /* XXX: name is stored in symbol table only, not stored here */ + uint32_t first_var; /* uint32_t ..vars[]; // The local variables memories for the word. Like "@a @b @c". Can be empty! */ + + /* Possibly overlapping with first_var (var_count == 0) possibly using that as padding... */ + + /* EITHER: */ + /* word_body processed_body; // Where to find the body data (ptr or offset) if its not "inline_data[]" */ + + /* 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 }; typedef enum SLC_SYM_OP SLC_SYM_OP; @@ -113,7 +147,7 @@ typedef enum SLC_IO_OP SLC_IO_OP; union symptr { uint32_t *varp; - wordstart *worp; + word *worp; }; 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_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 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. */ 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); union iores { - /** Either the cmd result or the handle pointer*/ + /** Either the terminal cmd result or the handle pointer */ const char *ptr; /** The read character */ char c; @@ -237,7 +271,15 @@ static inline slc_state slc_comment_statechange_in( 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, char c, const char *prefix) { @@ -323,13 +365,17 @@ static inline void slc( &multiline_i); /* state -> def_name */ if(state == SLC_START) { - state = slc_defname_statechange( + state = slc_def_name_statechange( state, c, prefix); - } + /* state -> word_name */ if(state == SLC_START) { + state = slc_word_name_statechange( + state, + c, + prefix); } break; case SLC_COMMENT: