changed to by-default 64 bit session addressing & implementation of word became better with helper functions and restructuring
This commit is contained in:
parent
00e818e43b
commit
f83fd990f8
116
engine/slc.h
116
engine/slc.h
@ -5,6 +5,18 @@
|
||||
#include<string.h> // memcpy, strlen..
|
||||
#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 */
|
||||
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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user