From 4e8c1870500c2a757addf3f75a70adae79ef9a14 Mon Sep 17 00:00:00 2001 From: Dominic Grimm Date: Fri, 23 Dec 2022 15:02:29 +0100 Subject: [PATCH] Update --- include/hydroforth/hydroforth.h | 18 +++++ include/hydroforth/number.h | 17 ++--- include/hydroforth/result.h | 40 +++++++++++ src/hydroforth/hydroforth.c | 121 +++++++++++++++++++++++++------- src/hydroforth/number.c | 60 ++++++++++++---- src/hydroforth/result.c | 13 ++++ src/main.c | 12 ++-- test.fth | 1 + 8 files changed, 228 insertions(+), 54 deletions(-) create mode 100644 include/hydroforth/result.h create mode 100644 src/hydroforth/result.c diff --git a/include/hydroforth/hydroforth.h b/include/hydroforth/hydroforth.h index f5fc772..1201029 100644 --- a/include/hydroforth/hydroforth.h +++ b/include/hydroforth/hydroforth.h @@ -3,6 +3,7 @@ #include +#include "result.h" #include "number.h" extern unsigned int hydroforth__hash_string(const char *const key, unsigned char len); @@ -67,6 +68,14 @@ typedef struct HYDROFORTH__INTERPRETER unsigned char stack_len; } HYDROFORTH__INTERPRETER; +typedef struct HYDROFORTH__SCAN_NEXT_WORD_RESULT +{ + unsigned long start; + unsigned char len; +} HYDROFORTH__SCAN_NEXT_WORD_RESULT; + +extern HYDROFORTH__SCAN_NEXT_WORD_RESULT hydroforth__scan_next_word(HYDROFORTH__INTERPRETER *interpreter); + extern bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter); extern bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter); @@ -75,23 +84,32 @@ extern bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter); typedef struct __HYDROFORTH { + __HYDROFORTH__RESULT result; __HYDROFORTH__NUMBER number; unsigned int (*hash_string)(const char *const key, unsigned char len); bool (*is_space)(char c); + HYDROFORTH__SCAN_NEXT_WORD_RESULT(*scan_next_word) + (HYDROFORTH__INTERPRETER *interpreter); bool (*parse)(HYDROFORTH__INTERPRETER *interpreter); bool (*run_call_stack)(HYDROFORTH__INTERPRETER *interpreter); bool (*run)(HYDROFORTH__INTERPRETER *interpreter); } __HYDROFORTH; static const __HYDROFORTH hydroforth = { + .result = { + .add_backtrace = hydroforth__result__add_backtrace, + .get_error_message = hydroforth__result__get_error_message, + }, .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, + .count_digits = hydroforth__number__count_digits, }, .hash_string = hydroforth__hash_string, .is_space = hydroforth__is_space, + .scan_next_word = hydroforth__scan_next_word, .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 bb92bbc..cb8773e 100644 --- a/include/hydroforth/number.h +++ b/include/hydroforth/number.h @@ -1,22 +1,23 @@ #ifndef __HYDROFORTH__NUMBER_H__ #define __HYDROFORTH__NUMBER_H__ -#include - extern bool hydroforth__number__is_digit(char c); -extern bool hydroforth__number__convert_hex_digit(char c, unsigned char *const val); +extern void hydroforth__number__convert_hex_digit(HYDROFORTH__RESULT *const result, char c, unsigned char *const val); -extern bool hydroforth__number__parse_number_hex(const char *const start, unsigned char len, int *const val); +extern void hydroforth__number__parse_number_hex(HYDROFORTH__RESULT *const result, 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); +extern void hydroforth__number__parse_number(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len, int *const val); + +extern unsigned char hydroforth__number__count_digits(int n); 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); + void (*convert_hex_digit)(HYDROFORTH__RESULT *const result, char c, unsigned char *const val); + void (*parse_number_hex)(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len, int *const val); + void (*parse_number)(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len, int *const val); + unsigned char (*count_digits)(int n); } __HYDROFORTH__NUMBER; #endif diff --git a/include/hydroforth/result.h b/include/hydroforth/result.h new file mode 100644 index 0000000..0d0adf6 --- /dev/null +++ b/include/hydroforth/result.h @@ -0,0 +1,40 @@ +#ifndef __HYDROFORTH__RESULT_H__ +#define __HYDROFORTH__RESULT_H__ + +typedef enum HYDROFORTH__RESULT__ERROR +{ + OK, + + ERR_UNKNOWN, + ERR_INVALID_HEX_CHAR, +} HYDROFORTH__RESULT__ERROR; + +typedef HYDROFORTH__RESULT__ERROR HYDROFORTH__ERROR; + +typedef struct HYDROFORTH__RESULT__RESULT +{ + HYDROFORTH__ERROR error; + char **const backtrace; + unsigned backtrace_len; +} HYDROFORTH__RESULT__RESULT; + +typedef HYDROFORTH__RESULT__RESULT HYDROFORTH__RESULT; + +extern void hydroforth__result__add_backtrace(HYDROFORTH__RESULT *const result, const char *const s); + +extern void hydroforth__result__set(HYDROFORTH__RESULT *const result, HYDROFORTH__ERROR error, const char *const s); + +extern const char *hydroforth__result__get_error_message(HYDROFORTH__ERROR error); + +#define hydroforth__set_func_result(result, error) hydroforth__result__set(result, error, __func__); + +#define hydroforth__add_func_backtrace(result) hydroforth__result__add_backtrace(result, __func__); + +typedef struct __HYDROFORTH__RESULT +{ + void (*add_backtrace)(HYDROFORTH__RESULT *const result, const char *const s); + void (*set)(HYDROFORTH__RESULT *const result, HYDROFORTH__ERROR error, const char *const s); + const char *(*get_error_message)(HYDROFORTH__ERROR error); +} __HYDROFORTH__RESULT; + +#endif diff --git a/src/hydroforth/hydroforth.c b/src/hydroforth/hydroforth.c index 7ec2fc0..2cde17c 100644 --- a/src/hydroforth/hydroforth.c +++ b/src/hydroforth/hydroforth.c @@ -27,7 +27,7 @@ inline bool hydroforth__is_space(char c) return c == ' ' || c == '\t'; } -bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter) +HYDROFORTH__SCAN_NEXT_WORD_RESULT hydroforth__scan_next_word(HYDROFORTH__INTERPRETER *interpreter) { const unsigned long start = interpreter->pos; unsigned char len = 0; @@ -36,18 +36,35 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter) len++; interpreter->pos++; } - if (len == 1) + + return (HYDROFORTH__SCAN_NEXT_WORD_RESULT){ + .start = start, + .len = len, + }; +} + +bool hydroforth__parse(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++; + // } + const HYDROFORTH__SCAN_NEXT_WORD_RESULT res = hydroforth__scan_next_word(interpreter); + if (res.len == 1) { - if (hydroforth__number__is_digit(interpreter->src[start])) + if (hydroforth__number__is_digit(interpreter->src[res.start])) { interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ .type = PUSH, - .data = {.number = interpreter->src[start] - '0'}, + .data = {.number = interpreter->src[res.start] - '0'}, }; } else { - switch (interpreter->src[start]) + switch (interpreter->src[res.start]) { case '\\': do @@ -71,10 +88,30 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter) } } + case ':': + 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]) + { + fputs("Unterminated word definition!\n", stderr); + return false; + } + if (hydroforth__number__is_digit(interpreter->src[interpreter->pos])) + { + fputs("Word name cannot be a number!\n", stderr); + return false; + } + const HYDROFORTH__SCAN_NEXT_WORD_RESULT name_scan_res = hydroforth__scan_next_word(interpreter); + + break; + default: interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ .type = CHAR_WORD, - .data = {.char_word = interpreter->src[start]}, + .data = {.char_word = interpreter->src[res.start]}, }; break; } @@ -82,13 +119,13 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter) } else { - const bool next_is_digit = hydroforth__number__is_digit(interpreter->src[start + 1]); - if (next_is_digit && interpreter->src[start] == '-') + const bool next_is_digit = hydroforth__number__is_digit(interpreter->src[res.start + 1]); + if (next_is_digit && interpreter->src[res.start] == '-') { int n; - if (!hydroforth__number__parse_number(interpreter->src + start + 1, len - 1, &n)) + if (!hydroforth__number__parse_number(interpreter->src + res.start + 1, res.len - 1, &n)) { - fputs("Error parsing number!", stderr); + fputs("Error parsing number!\n", stderr); return false; } interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ @@ -96,12 +133,12 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter) .data = {.number = -n}, }; } - else if (next_is_digit && interpreter->src[start] == '+') + else if (next_is_digit && interpreter->src[res.start] == '+') { int n; - if (!hydroforth__number__parse_number(interpreter->src + start + 1, len - 1, &n)) + if (!hydroforth__number__parse_number(interpreter->src + res.start + 1, res.len - 1, &n)) { - fputs("Error parsing number!", stderr); + fputs("Error parsing number!\n", stderr); return false; } interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ @@ -109,12 +146,12 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter) .data = {.number = n}, }; } - else if (hydroforth__number__is_digit(interpreter->src[start])) + else if (hydroforth__number__is_digit(interpreter->src[res.start])) { int n; - if (!hydroforth__number__parse_number(interpreter->src + start, len, &n)) + if (!hydroforth__number__parse_number(interpreter->src + res.start, res.len, &n)) { - fputs("Error parsing number!", stderr); + fputs("Error parsing number!\n", stderr); return false; } interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ @@ -124,7 +161,7 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter) } else { - const unsigned int hash = hydroforth__hash_string(interpreter->src + start, len); + const unsigned int hash = hydroforth__hash_string(interpreter->src + res.start, res.len); switch (hash) { case 0x4078cde9: // -- @@ -161,10 +198,6 @@ bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter) case CHAR_WORD: switch (word->data.char_word) { - case ':': - printf("WORD DEFINITION\n"); - break; - case '-': interpreter->stack[interpreter->stack_len - 2] -= interpreter->stack[interpreter->stack_len - 1]; interpreter->stack_len--; @@ -186,7 +219,8 @@ bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter) break; default: - break; + fprintf(stderr, "Unknown word: '%c'\n", word->data.char_word); + return false; } break; @@ -195,10 +229,47 @@ bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter) 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: - break; + fprintf(stderr, "Unknown word with hash: 0x%x\n", word->data.hash); + return false; } break; } @@ -215,10 +286,6 @@ bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter) { interpreter->pos++; } - if (interpreter->src[interpreter->pos] == '\0') - { - return true; - } if (!interpreter->src[interpreter->pos]) { return true; diff --git a/src/hydroforth/number.c b/src/hydroforth/number.c index 18ae41d..8ce0d41 100644 --- a/src/hydroforth/number.c +++ b/src/hydroforth/number.c @@ -1,14 +1,15 @@ #include #include +#include -#include "hydroforth/number.h" +#include "hydroforth/hydroforth.h" bool hydroforth__number__is_digit(char c) { return '0' <= c && c <= '9'; } -bool hydroforth__number__convert_hex_digit(char c, unsigned char *const val) +void hydroforth__number__convert_hex_digit(HYDROFORTH__RESULT *const result, char c, unsigned char *const val) { if (hydroforth__number__is_digit(c)) { @@ -49,22 +50,28 @@ bool hydroforth__number__convert_hex_digit(char c, unsigned char *const val) break; default: - return false; + // hydroforth__result__set(result, ERR_INVALID_HEX_CHAR, __func__); + hydroforth__set_func_result(result, ERR_INVALID_HEX_CHAR); + break; } } - - return true; } -bool hydroforth__number__parse_number_hex(const char *const start, unsigned char len, int *const val) +void hydroforth__number__parse_number_hex(HYDROFORTH__RESULT *const result, 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)) + // if (!hydroforth__number__convert_hex_digit(result, start[i], &m)) + // { + // return false; + // } + hydroforth__number__convert_hex_digit(result, start[i], &m); + if (result->error != OK) { - return false; + hydroforth__add_func_backtrace(result); + return; } n *= 16; n += m; @@ -73,7 +80,7 @@ bool hydroforth__number__parse_number_hex(const char *const start, unsigned char return true; } -bool hydroforth__number__parse_number(const char *const start, unsigned char len, int *const val) +void hydroforth__number__parse_number(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len, int *const val) { if (start[0] == '0') { @@ -83,16 +90,25 @@ bool hydroforth__number__parse_number(const char *const start, unsigned char len { case 'X': case 'x': - return hydroforth__number__parse_number_hex(start + 2, len - 2, val); + hydroforth__number__parse_number_hex(result, start + 2, len - 2, val); + if (result->error != OK) + { + hydroforth__add_func_backtrace(result); + } + break; default: - return hydroforth__number__parse_number(start + 1, len - 1, val); + hydroforth__number__parse_number(result, start + 1, len - 1, val); + if (result->error != OK) + { + hydroforth__add_func_backtrace(result); + } + break; } } else { *val = 0; - return true; } } else @@ -104,6 +120,24 @@ bool hydroforth__number__parse_number(const char *const start, unsigned char len n += start[i] - '0'; } *val = n; - return true; + } +} + +unsigned char hydroforth__number__count_digits(int n) +{ + if (n == 0) + { + return 1; + } + else + { + unsigned char res = 0; + while (n != 0) + { + n /= 10; + res++; + } + + return res; } } diff --git a/src/hydroforth/result.c b/src/hydroforth/result.c new file mode 100644 index 0000000..fc702f4 --- /dev/null +++ b/src/hydroforth/result.c @@ -0,0 +1,13 @@ +#include "hydroforth/hydroforth.h" + +void hydroforth__result__add_backtrace(HYDROFORTH__RESULT *const result, const char *const s) +{ + realloc(result->backtrace, sizeof(char *) * (result->backtrace_len + 1)); + result->backtrace[result->backtrace_len++] = s; +} + +void hydroforth__result__set(HYDROFORTH__RESULT *const result, HYDROFORTH__ERROR error, const char *const s) +{ + result->error = error; + hydroforth__result__add_backtrace(result, s); +} diff --git a/src/main.c b/src/main.c index fb34790..3f5759c 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ struct ReadSrcResult read_src(FILE *fp) { if (fseek(fp, 0L, SEEK_END) != 0) { - fputs("Error seeking to file end!", stderr); + fputs("Error seeking to file end!\n", stderr); return (struct ReadSrcResult){ .success = false, }; @@ -22,7 +22,7 @@ struct ReadSrcResult read_src(FILE *fp) const long bufsize = ftell(fp); if (bufsize == -1) { - fputs("Error getting file size!", stderr); + fputs("Error getting file size!\n", stderr); return (struct ReadSrcResult){ .success = false, }; @@ -30,7 +30,7 @@ struct ReadSrcResult read_src(FILE *fp) char *const src = malloc(sizeof(char) * bufsize); if (fseek(fp, 0L, SEEK_SET) != 0) { - fputs("Error rewinding file to start!", stderr); + fputs("Error rewinding file to start!\n", stderr); return (struct ReadSrcResult){ .success = false, }; @@ -38,7 +38,7 @@ struct ReadSrcResult read_src(FILE *fp) fread(src, sizeof(char), bufsize, fp); if (ferror(fp) != 0) { - fputs("Error reading file!", stderr); + fputs("Error reading file!\n", stderr); return (struct ReadSrcResult){ .success = false, }; @@ -54,13 +54,13 @@ int main(int argc, char *argv[]) { if (argc < 2) { - fputs("No source file specified!", stderr); + fputs("No source file specified!\n", stderr); return 1; } FILE *fp = fopen(argv[1], "rb"); if (fp == NULL) { - fputs("Error opening file!", stderr); + fputs("Error opening file!\n", stderr); return 1; } const struct ReadSrcResult res = read_src(fp); diff --git a/test.fth b/test.fth index 40e2dbf..08597e0 100644 --- a/test.fth +++ b/test.fth @@ -1 +1,2 @@ +: test 42 ; 40 2 + debug