diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0ca8ea8 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "files.associations": { + "*.lock": "yarnlock", + ".shards.info": "yaml", + ".graphqlconfig": "json", + "stdbool.h": "c" + } +} diff --git a/CMakeLists.txt b/CMakeLists.txt index bc48ab4..7f3a5cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,17 @@ cmake_minimum_required(VERSION 3.22.1) project(hydroforth) +include(CheckIPOSupported) +check_ipo_supported(RESULT supported OUTPUT error) + file(GLOB_RECURSE SOURCES ${PROJECT_SOURCE_DIR}/src/*.c) add_executable(hydroforth ${SOURCES}) +if( supported ) + message(STATUS "IPO / LTO enabled") + set_property(TARGET hydroforth PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) +else() + message(STATUS "IPO / LTO not supported: <${error}>") +endif() + target_include_directories(hydroforth PRIVATE ${PROJECT_SOURCE_DIR}/include) diff --git a/include/hydroforth/hydroforth.h b/include/hydroforth/hydroforth.h index 6debd13..4f3edba 100644 --- a/include/hydroforth/hydroforth.h +++ b/include/hydroforth/hydroforth.h @@ -5,6 +5,8 @@ #include "number.h" +extern unsigned int hydroforth__hash_string(const char *const key, unsigned char length); + typedef enum HYDROFORTH__WORD_TYPE { PUSH, @@ -25,34 +27,69 @@ typedef struct HYDROFORTH__WORD HYDROFORTH__WORD_DATA data; } HYDROFORTH__WORD; +typedef struct HYDROFORTH__WORD_DEFINITION +{ + HYDROFORTH__WORD *words; +} HYDROFORTH__WORD_DEFINITION; + +typedef struct HYDROFORTH__WORD_DEFINITION_BASE_KEY +{ + unsigned char word_definition_index; +} HYDROFORTH__WORD_DEFINITION_BASE_KEY; + +typedef struct HYDROFORTH__WORD_DEFINITION_SINGLE_CHAR_WORD_KEY +{ + char c; + HYDROFORTH__WORD_DEFINITION_BASE_KEY key; +} HYDROFORTH__WORD_DEFINITION_SINGLE_CHAR_WORD_KEY; + +typedef struct HYDROFORTH__WORD_DEFINITION_WORD_KEY +{ + unsigned int hash; + HYDROFORTH__WORD_DEFINITION_BASE_KEY key; +} HYDROFORTH__WORD_DEFINITION_WORD_KEY; + typedef struct HYDROFORTH__INTERPRETER { char *src; unsigned long pos; + HYDROFORTH__WORD_DEFINITION_SINGLE_CHAR_WORD_KEY single_char_word_keys[32]; + unsigned char single_char_word_keys_len; + unsigned short word_keys_len; + unsigned short word_keys_max_len; + HYDROFORTH__WORD_DEFINITION_WORD_KEY *word_keys; + HYDROFORTH__WORD_DEFINITION word_definitions[256]; HYDROFORTH__WORD call_stack[256]; unsigned char call_stack_len; int stack[256]; unsigned char stack_len; } HYDROFORTH__INTERPRETER; -extern bool hydroforth__step(HYDROFORTH__INTERPRETER *interpreter); +extern bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter); + +extern bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter); extern bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter); typedef struct __HYDROFORTH { __HYDROFORTH__NUMBER number; - bool (*step)(HYDROFORTH__INTERPRETER *interpreter); + unsigned int (*hash_string)(const char *const key, unsigned char len); + bool (*parse)(HYDROFORTH__INTERPRETER *interpreter); + bool (*run_call_stack)(HYDROFORTH__INTERPRETER *interpreter); bool (*run)(HYDROFORTH__INTERPRETER *interpreter); } __HYDROFORTH; static const __HYDROFORTH hydroforth = { .number = { .is_digit = hydroforth__number__is_digit, + .convert_hex_digit = hydroforth__number__convert_hex_digit, + .parse_number_hex = hydroforth__number__parse_number_hex, .parse_number = hydroforth__number__parse_number, - .parse_number_with_sign = hydroforth__number__parse_number_with_sign, }, - .step = hydroforth__step, + .hash_string = hydroforth__hash_string, + .parse = hydroforth__parse, + .run_call_stack = hydroforth__run_call_stack, .run = hydroforth__run, }; diff --git a/include/hydroforth/number.h b/include/hydroforth/number.h index fab514a..bb92bbc 100644 --- a/include/hydroforth/number.h +++ b/include/hydroforth/number.h @@ -5,15 +5,18 @@ extern bool hydroforth__number__is_digit(char c); -extern bool hydroforth__number__parse_number(const char *const start, unsigned char len, int *const val); +extern bool hydroforth__number__convert_hex_digit(char c, unsigned char *const val); -extern bool hydroforth__number__parse_number_with_sign(const char *const start, unsigned char len, int *const val); +extern bool hydroforth__number__parse_number_hex(const char *const start, unsigned char len, int *const val); + +extern bool hydroforth__number__parse_number(const char *const start, unsigned char len, int *const val); typedef struct __HYDROFORTH__NUMBER { bool (*is_digit)(char c); + bool (*convert_hex_digit)(char c, unsigned char *const val); + bool (*parse_number_hex)(const char *const start, unsigned char len, int *const val); bool (*parse_number)(const char *const start, unsigned char len, int *const val); - bool (*parse_number_with_sign)(const char *const start, unsigned char len, int *const val); } __HYDROFORTH__NUMBER; #endif diff --git a/src/hydroforth/hydroforth.c b/src/hydroforth/hydroforth.c index ba4d05c..c72d654 100644 --- a/src/hydroforth/hydroforth.c +++ b/src/hydroforth/hydroforth.c @@ -1,9 +1,28 @@ #include #include +#include +#include #include "hydroforth/hydroforth.h" -bool hydroforth__step(HYDROFORTH__INTERPRETER *interpreter) +unsigned int hydroforth__hash_string(const char *const key, unsigned char len) +{ + unsigned char i = 0; + unsigned int hash = 0; + while (i != len) + { + hash += key[i++]; + hash += hash << 10; + hash ^= hash >> 6; + } + hash += hash << 3; + hash ^= hash >> 11; + hash += hash << 15; + + return hash; +} + +bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter) { const unsigned long start = interpreter->pos; unsigned char len = 0; @@ -12,7 +31,6 @@ bool hydroforth__step(HYDROFORTH__INTERPRETER *interpreter) len++; interpreter->pos++; } - printf("START: %lu\nLEN: %u\n", start, len); HYDROFORTH__WORD word; if (len == 1) { @@ -33,22 +51,89 @@ bool hydroforth__step(HYDROFORTH__INTERPRETER *interpreter) } else { - if ((interpreter->src[start] == '-' || interpreter->src[start] == '+') && - hydroforth__number__is_digit(interpreter->src[start + 1])) + const bool next_is_digit = hydroforth__number__is_digit(interpreter->src[start + 1]); + if (next_is_digit && interpreter->src[start] == '-') { + int n; + if (!hydroforth__number__parse_number(interpreter->src + start + 1, len - 1, &n)) + { + fputs("Error parsing number!", stderr); + return false; + } + word = (HYDROFORTH__WORD){ + .type = PUSH, + .data = {.number = -n}, + }; + } + else if (next_is_digit && interpreter->src[start] == '+') + { + int n; + if (!hydroforth__number__parse_number(interpreter->src + start + 1, len - 1, &n)) + { + fputs("Error parsing number!", stderr); + return false; + } + word = (HYDROFORTH__WORD){ + .type = PUSH, + .data = {.number = n}, + }; } else if (hydroforth__number__is_digit(interpreter->src[start])) { int n; if (!hydroforth__number__parse_number(interpreter->src + start, len, &n)) { - printf("RESULT IS FALSE!!!\nNUMBER: %i\n", n); + fputs("Error parsing number!", stderr); return false; } - printf("NUMBER: %i\n", n); + word = (HYDROFORTH__WORD){ + .type = PUSH, + .data = {.number = n}, + }; } else { + char *const s = malloc(sizeof(char) * (len + 1)); + strncpy(s, interpreter->src + start, len); + s[len] = '\0'; + word = (HYDROFORTH__WORD){ + .type = WORD, + .data = {.word = s}, + }; + } + } + + interpreter->call_stack[interpreter->call_stack_len++] = word; + + return true; +} + +bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter) +{ + printf("CALL STACK LEN: %u\n", interpreter->call_stack_len); + for (unsigned char i = interpreter->call_stack_len; i > 0; interpreter->call_stack_len--, i--) + { + printf("TYPE: %u\n", interpreter->call_stack[i - 1].type); + const HYDROFORTH__WORD *word = interpreter->call_stack + i - 1; + switch (word->type) + { + case PUSH: + interpreter->stack[interpreter->stack_len++] = word->data.number; + break; + + case CHAR_WORD: + switch (word->data.char_word) + { + case '-': + break; + + default: + break; + } + break; + + case WORD: + break; } } @@ -65,10 +150,13 @@ bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter) } if (!interpreter->src[interpreter->pos]) { - puts("END REACHED!"); return true; } - if (!hydroforth__step(interpreter)) + if (!hydroforth__parse(interpreter)) + { + return false; + } + if (!hydroforth__run_call_stack(interpreter)) { return false; } diff --git a/src/hydroforth/number.c b/src/hydroforth/number.c index 2b1cd42..18ae41d 100644 --- a/src/hydroforth/number.c +++ b/src/hydroforth/number.c @@ -8,9 +8,73 @@ bool hydroforth__number__is_digit(char c) return '0' <= c && c <= '9'; } +bool hydroforth__number__convert_hex_digit(char c, unsigned char *const val) +{ + if (hydroforth__number__is_digit(c)) + { + *val = c - '0'; + } + else + { + switch (c) + { + case 'A': + case 'a': + *val = 0xa; + break; + + case 'B': + case 'b': + *val = 0xb; + break; + + case 'C': + case 'c': + *val = 0xc; + break; + + case 'D': + case 'd': + *val = 0xd; + break; + + case 'E': + case 'e': + *val = 0xe; + break; + + case 'F': + case 'f': + *val = 0xf; + break; + + default: + return false; + } + } + + return true; +} + +bool hydroforth__number__parse_number_hex(const char *const start, unsigned char len, int *const val) +{ + int n; + for (unsigned char i = 0; i < len; i++) + { + unsigned char m; + if (!hydroforth__number__convert_hex_digit(start[i], &m)) + { + return false; + } + n *= 16; + n += m; + } + + return true; +} + bool hydroforth__number__parse_number(const char *const start, unsigned char len, int *const val) { - int num; if (start[0] == '0') { if (len > 1) @@ -19,7 +83,7 @@ bool hydroforth__number__parse_number(const char *const start, unsigned char len { case 'X': case 'x': - return false; + return hydroforth__number__parse_number_hex(start + 2, len - 2, val); default: return hydroforth__number__parse_number(start + 1, len - 1, val); @@ -43,7 +107,3 @@ bool hydroforth__number__parse_number(const char *const start, unsigned char len return true; } } - -bool hydroforth__number__parse_number_with_sign(const char *const start, unsigned char len, int *const val) -{ -} diff --git a/src/main.c b/src/main.c index 3cffd1f..28cdb37 100644 --- a/src/main.c +++ b/src/main.c @@ -71,6 +71,9 @@ int main(int argc, char *argv[]) HYDROFORTH__INTERPRETER interpreter = { .src = res.src, .pos = 0, + .single_char_word_keys_len = 0, + .word_keys_len = 0, + .word_keys_max_len = 0, }; const bool run_res = hydroforth.run(&interpreter); free(res.src);