#include #include #include #include #include "hydroforth/hydroforth.h" unsigned hydroforth__hash_string(const char *const key, unsigned char len) { unsigned char i = 0; unsigned 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; } inline bool hydroforth__is_space(char c) { return c == ' ' || c == '\t'; } HYDROFORTH__SCAN_NEXT_WORD_RESULT hydroforth__scan_next_word(HYDROFORTH__INTERPRETER *interpreter) { const unsigned long start = interpreter->pos; unsigned char len = 0; while (!hydroforth__is_space(interpreter->src[interpreter->pos]) && interpreter->src[interpreter->pos] != '\n' && interpreter->src[interpreter->pos]) { len++; interpreter->pos++; } return (HYDROFORTH__SCAN_NEXT_WORD_RESULT){ .start = start, .len = len, }; } void hydroforth__add_word_to_word_definition(HYDROFORTH__WORD_DEFINITION *word_def, HYDROFORTH__WORD word) { word_def->words = realloc(word_def->words, sizeof(HYDROFORTH__WORD) * (word_def->words_len + 1)); word_def->words[word_def->words_len++] = word; } void hydroforth__parse(HYDROFORTH__RESULT *result, HYDROFORTH__INTERPRETER *interpreter, HYDROFORTH__WORD_DEFINITION *word_def) { const HYDROFORTH__SCAN_NEXT_WORD_RESULT res = hydroforth__scan_next_word(interpreter); if (res.len == 1) { if (hydroforth__number__is_digit(interpreter->src[res.start])) { int n = interpreter->src[res.start] - '0'; if (word_def == NULL) { interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ .type = PUSH, .data = {.number = n}, }; } else { hydroforth__add_word_to_word_definition(word_def, (HYDROFORTH__WORD){ .type = PUSH, .data = {.number = n}, }); } } else { switch (interpreter->src[res.start]) { case '\\': do { interpreter->pos++; } while (interpreter->src[interpreter->pos] != '\n' && interpreter->src[interpreter->pos]); break; case '(': while (true) { interpreter->pos++; if (interpreter->src[interpreter->pos] == ')' && (hydroforth__is_space(interpreter->src[interpreter->pos + 1]) || interpreter->src[interpreter->pos + 1] == '\n' || interpreter->src[interpreter->pos + 1] == '\0') || interpreter->src[interpreter->pos] == '\n' || interpreter->src[interpreter->pos] == '\0') { break; } } case ':': { if (word_def != NULL) { hydroforth__set_func_result(result, ERR_WORD_DEF_INSIDE_WORD_DEF); return; } printf("WORD DEFINITION\n"); do { interpreter->pos++; } while (hydroforth__is_space(interpreter->src[interpreter->pos]) || interpreter->src[interpreter->pos] == '\n'); if (!interpreter->src[interpreter->pos]) { hydroforth__set_func_result(result, ERR_UNTERMINATED_WORD_DEFINITION); return; } if (hydroforth__number__is_digit(interpreter->src[interpreter->pos])) { hydroforth__set_func_result(result, ERR_WORD_NAME_CANT_BE_NUMBER); return; } const HYDROFORTH__SCAN_NEXT_WORD_RESULT name_scan_res = hydroforth__scan_next_word(interpreter); for (unsigned char i = 0; i < name_scan_res.len; i++) { putchar(interpreter->src[name_scan_res.start + i]); } putchar('\n'); if (name_scan_res.len == 1) { } else { unsigned hash = hydroforth__hash_string(interpreter->src + name_scan_res.start, name_scan_res.len); printf("HASH: 0x%x\n", hash); interpreter->word_definitions[interpreter->word_definitions_len] = (HYDROFORTH__WORD_DEFINITION){ .words = malloc(0), .words_len = 0, }; interpreter->word_keys[interpreter->word_keys_len++] = (HYDROFORTH__WORD_DEFINITION_WORD_KEY){ .hash = hash, .key = {.word_definition_index = interpreter->word_definitions_len++}, }; } break; } default: if (word_def == NULL) { interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ .type = CHAR_WORD, .data = {.char_word = interpreter->src[res.start]}, }; } else { hydroforth__add_word_to_word_definition(word_def, (HYDROFORTH__WORD){ .type = CHAR_WORD, .data = {.char_word = interpreter->src[res.start]}, }); } break; } } } else { const bool next_is_digit = hydroforth__number__is_digit(interpreter->src[res.start + 1]); if (next_is_digit && interpreter->src[res.start] == '-') { int n = hydroforth__number__parse_number(result, interpreter->src + res.start + 1, res.len - 1); if (result->error) { hydroforth__add_func_backtrace(result); return; } if (word_def == NULL) { interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ .type = PUSH, .data = {.number = -n}, }; } else { hydroforth__add_word_to_word_definition(word_def, (HYDROFORTH__WORD){ .type = PUSH, .data = {.number = -n}, }); } } else if (next_is_digit && interpreter->src[res.start] == '+') { int n = hydroforth__number__parse_number(result, interpreter->src + res.start + 1, res.len - 1); if (result->error) { hydroforth__add_func_backtrace(result); return; } if (word_def == NULL) { interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ .type = PUSH, .data = {.number = n}, }; } else { hydroforth__add_word_to_word_definition(word_def, (HYDROFORTH__WORD){ .type = PUSH, .data = {.number = n}, }); } } else if (hydroforth__number__is_digit(interpreter->src[res.start])) { int n = hydroforth__number__parse_number(result, interpreter->src + res.start, res.len); if (result->error) { hydroforth__add_func_backtrace(result); return; } if (word_def == NULL) { interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ .type = PUSH, .data = {.number = n}, }; } else { hydroforth__add_word_to_word_definition(word_def, (HYDROFORTH__WORD){ .type = PUSH, .data = {.number = n}, }); } } else { const unsigned hash = hydroforth__hash_string(interpreter->src + res.start, res.len); switch (hash) { case 0x4078cde9: // -- do { interpreter->pos++; } while (interpreter->src[interpreter->pos] != '\n' && interpreter->src[interpreter->pos]); break; default: if (word_def == NULL) { interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ .type = WORD, .data = {.hash = hash}, }; } else { hydroforth__add_word_to_word_definition(word_def, (HYDROFORTH__WORD){ .type = WORD, .data = {.hash = hash}, }); } break; } } } } void hydroforth__run_call_stack(HYDROFORTH__RESULT *result, HYDROFORTH__INTERPRETER *interpreter) { for (unsigned char i = interpreter->call_stack_len; i > 0; interpreter->call_stack_len--, i--) { 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 '-': interpreter->stack[interpreter->stack_len - 2] -= interpreter->stack[interpreter->stack_len - 1]; interpreter->stack_len--; break; case '+': interpreter->stack[interpreter->stack_len - 2] += interpreter->stack[interpreter->stack_len - 1]; interpreter->stack_len--; break; case '*': interpreter->stack[interpreter->stack_len - 2] *= interpreter->stack[interpreter->stack_len - 1]; interpreter->stack_len--; break; case '/': interpreter->stack[interpreter->stack_len - 2] /= interpreter->stack[interpreter->stack_len - 1]; interpreter->stack_len--; break; default: hydroforth__set_func_result(result, ERR_UNKNOWN_SINGLE_CHAR_WORD); return; } break; case WORD: printf("HASH: 0x%x\n", word->data.hash); switch (word->data.hash) { case 0xaddd94c: // debug const unsigned char left_width = hydroforth__number__count_digits(interpreter->stack_len); unsigned char right_width = 0; for (unsigned char i = 0; i < interpreter->stack_len; i++) { const unsigned char tmp = hydroforth__number__count_digits(interpreter->stack[i]); if (tmp > right_width) { right_width = tmp; } } for (unsigned char i = 0; i < (2 + left_width + 3 + right_width + 2); i++) { putchar('-'); } putchar('\n'); for (unsigned char i = interpreter->stack_len - 1; i != 0xff; i--) { printf("| "); const unsigned char left_index_width = left_width - hydroforth__number__count_digits(i); for (unsigned char j = 0; j < left_index_width; j++) { putchar(' '); } printf("%u | ", i); const unsigned char right_index_width = right_width - hydroforth__number__count_digits(interpreter->stack[i]); for (unsigned char j = 0; j < right_index_width; j++) { putchar(' '); } printf("%i |\n", interpreter->stack[i]); } for (unsigned char i = 0; i < (2 + left_width + 3 + right_width + 2); i++) { putchar('-'); } putchar('\n'); break; default: hydroforth__set_func_result(result, ERR_UNKNOWN_WORD); return; } break; } } } void hydroforth__run(HYDROFORTH__RESULT *result, HYDROFORTH__INTERPRETER *interpreter) { while (true) { while (hydroforth__is_space(interpreter->src[interpreter->pos]) || interpreter->src[interpreter->pos] == '\n') { interpreter->pos++; } if (!interpreter->src[interpreter->pos]) { return; } hydroforth__parse(result, interpreter, NULL); if (result->error) { hydroforth__add_func_backtrace(result); return; } hydroforth__run_call_stack(result, interpreter); if (result->error) { hydroforth__add_func_backtrace(result); return; } } }