This commit is contained in:
Dominic Grimm 2022-12-23 17:16:29 +01:00
parent 4e8c187050
commit bd9b51be9a
No known key found for this signature in database
GPG key ID: 6F294212DEAAC530
8 changed files with 142 additions and 85 deletions

View file

@ -76,11 +76,11 @@ typedef struct HYDROFORTH__SCAN_NEXT_WORD_RESULT
extern HYDROFORTH__SCAN_NEXT_WORD_RESULT hydroforth__scan_next_word(HYDROFORTH__INTERPRETER *interpreter); extern HYDROFORTH__SCAN_NEXT_WORD_RESULT hydroforth__scan_next_word(HYDROFORTH__INTERPRETER *interpreter);
extern bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter); extern void hydroforth__parse(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter);
extern bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter); extern void hydroforth__run_call_stack(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter);
extern bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter); extern void hydroforth__run(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter);
typedef struct __HYDROFORTH typedef struct __HYDROFORTH
{ {
@ -90,15 +90,16 @@ typedef struct __HYDROFORTH
bool (*is_space)(char c); bool (*is_space)(char c);
HYDROFORTH__SCAN_NEXT_WORD_RESULT(*scan_next_word) HYDROFORTH__SCAN_NEXT_WORD_RESULT(*scan_next_word)
(HYDROFORTH__INTERPRETER *interpreter); (HYDROFORTH__INTERPRETER *interpreter);
bool (*parse)(HYDROFORTH__INTERPRETER *interpreter); void (*parse)(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter);
bool (*run_call_stack)(HYDROFORTH__INTERPRETER *interpreter); void (*run_call_stack)(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter);
bool (*run)(HYDROFORTH__INTERPRETER *interpreter); void (*run)(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter);
} __HYDROFORTH; } __HYDROFORTH;
static const __HYDROFORTH hydroforth = { static const __HYDROFORTH hydroforth = {
.result = { .result = {
.add_backtrace = hydroforth__result__add_backtrace, .add_backtrace = hydroforth__result__add_backtrace,
.get_error_message = hydroforth__result__get_error_message, .get_error_message = hydroforth__result__get_error_message,
.unwrap = hydroforth__result__unwrap,
}, },
.number = { .number = {
.is_digit = hydroforth__number__is_digit, .is_digit = hydroforth__number__is_digit,

View file

@ -3,20 +3,20 @@
extern bool hydroforth__number__is_digit(char c); extern bool hydroforth__number__is_digit(char c);
extern void hydroforth__number__convert_hex_digit(HYDROFORTH__RESULT *const result, char c, unsigned char *const val); extern unsigned char hydroforth__number__convert_hex_digit(HYDROFORTH__RESULT *const result, char c);
extern void hydroforth__number__parse_number_hex(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len, int *const val); extern int hydroforth__number__parse_number_hex(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len);
extern void hydroforth__number__parse_number(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len, int *const val); extern int hydroforth__number__parse_number(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len);
extern unsigned char hydroforth__number__count_digits(int n); extern unsigned char hydroforth__number__count_digits(int n);
typedef struct __HYDROFORTH__NUMBER typedef struct __HYDROFORTH__NUMBER
{ {
bool (*is_digit)(char c); bool (*is_digit)(char c);
void (*convert_hex_digit)(HYDROFORTH__RESULT *const result, char c, unsigned char *const val); unsigned char (*convert_hex_digit)(HYDROFORTH__RESULT *const result, char c);
void (*parse_number_hex)(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len, int *const val); int (*parse_number_hex)(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len);
void (*parse_number)(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len, int *const val); int (*parse_number)(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len);
unsigned char (*count_digits)(int n); unsigned char (*count_digits)(int n);
} __HYDROFORTH__NUMBER; } __HYDROFORTH__NUMBER;

View file

@ -3,10 +3,15 @@
typedef enum HYDROFORTH__RESULT__ERROR typedef enum HYDROFORTH__RESULT__ERROR
{ {
OK, OK = 0,
ERR_UNKNOWN, ERR_UNKNOWN,
ERR_INVALID_HEX_CHAR, ERR_INVALID_HEX_CHAR,
ERR_UNKNOWN_SINGLE_CHAR_WORD,
ERR_UNKNOWN_WORD,
ERR_UNTERMINATED_WORD_DEFINITION,
ERR_WORD_NAME_CANT_BE_NUMBER,
} HYDROFORTH__RESULT__ERROR; } HYDROFORTH__RESULT__ERROR;
typedef HYDROFORTH__RESULT__ERROR HYDROFORTH__ERROR; typedef HYDROFORTH__RESULT__ERROR HYDROFORTH__ERROR;
@ -14,8 +19,8 @@ typedef HYDROFORTH__RESULT__ERROR HYDROFORTH__ERROR;
typedef struct HYDROFORTH__RESULT__RESULT typedef struct HYDROFORTH__RESULT__RESULT
{ {
HYDROFORTH__ERROR error; HYDROFORTH__ERROR error;
char **const backtrace; const char **backtrace;
unsigned backtrace_len; unsigned short backtrace_len;
} HYDROFORTH__RESULT__RESULT; } HYDROFORTH__RESULT__RESULT;
typedef HYDROFORTH__RESULT__RESULT HYDROFORTH__RESULT; typedef HYDROFORTH__RESULT__RESULT HYDROFORTH__RESULT;
@ -30,11 +35,14 @@ extern const char *hydroforth__result__get_error_message(HYDROFORTH__ERROR error
#define hydroforth__add_func_backtrace(result) hydroforth__result__add_backtrace(result, __func__); #define hydroforth__add_func_backtrace(result) hydroforth__result__add_backtrace(result, __func__);
extern int hydroforth__result__unwrap(HYDROFORTH__RESULT *const result, int code);
typedef struct __HYDROFORTH__RESULT typedef struct __HYDROFORTH__RESULT
{ {
void (*add_backtrace)(HYDROFORTH__RESULT *const result, const char *const s); void (*add_backtrace)(HYDROFORTH__RESULT *const result, const char *const s);
void (*set)(HYDROFORTH__RESULT *const result, HYDROFORTH__ERROR error, 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); const char *(*get_error_message)(HYDROFORTH__ERROR error);
int (*unwrap)(HYDROFORTH__RESULT *const result, int code);
} __HYDROFORTH__RESULT; } __HYDROFORTH__RESULT;
#endif #endif

View file

@ -1,6 +1,5 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <malloc.h>
#include <string.h> #include <string.h>
#include "hydroforth/hydroforth.h" #include "hydroforth/hydroforth.h"
@ -43,7 +42,7 @@ HYDROFORTH__SCAN_NEXT_WORD_RESULT hydroforth__scan_next_word(HYDROFORTH__INTERPR
}; };
} }
bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter) void hydroforth__parse(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter)
{ {
// const unsigned long start = interpreter->pos; // const unsigned long start = interpreter->pos;
// unsigned char len = 0; // unsigned char len = 0;
@ -96,13 +95,17 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter)
} while (hydroforth__is_space(interpreter->src[interpreter->pos]) || interpreter->src[interpreter->pos] == '\n'); } while (hydroforth__is_space(interpreter->src[interpreter->pos]) || interpreter->src[interpreter->pos] == '\n');
if (!interpreter->src[interpreter->pos]) if (!interpreter->src[interpreter->pos])
{ {
fputs("Unterminated word definition!\n", stderr); // fputs("Unterminated word definition!\n", stderr);
return false; // return false;
hydroforth__set_func_result(result, ERR_UNTERMINATED_WORD_DEFINITION);
return;
} }
if (hydroforth__number__is_digit(interpreter->src[interpreter->pos])) if (hydroforth__number__is_digit(interpreter->src[interpreter->pos]))
{ {
fputs("Word name cannot be a number!\n", stderr); // fputs("Word name cannot be a number!\n", stderr);
return false; // return false;
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); const HYDROFORTH__SCAN_NEXT_WORD_RESULT name_scan_res = hydroforth__scan_next_word(interpreter);
@ -122,11 +125,12 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter)
const bool next_is_digit = hydroforth__number__is_digit(interpreter->src[res.start + 1]); const bool next_is_digit = hydroforth__number__is_digit(interpreter->src[res.start + 1]);
if (next_is_digit && interpreter->src[res.start] == '-') if (next_is_digit && interpreter->src[res.start] == '-')
{ {
int n; int n = hydroforth__number__parse_number(result, interpreter->src + res.start + 1, res.len - 1);
if (!hydroforth__number__parse_number(interpreter->src + res.start + 1, res.len - 1, &n)) if (result->error)
{ {
hydroforth__add_func_backtrace(result);
fputs("Error parsing number!\n", stderr); fputs("Error parsing number!\n", stderr);
return false; return;
} }
interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){
.type = PUSH, .type = PUSH,
@ -135,11 +139,12 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter)
} }
else if (next_is_digit && interpreter->src[res.start] == '+') else if (next_is_digit && interpreter->src[res.start] == '+')
{ {
int n; int n = hydroforth__number__parse_number(result, interpreter->src + res.start + 1, res.len - 1);
if (!hydroforth__number__parse_number(interpreter->src + res.start + 1, res.len - 1, &n)) if (result->error)
{ {
hydroforth__add_func_backtrace(result);
fputs("Error parsing number!\n", stderr); fputs("Error parsing number!\n", stderr);
return false; return;
} }
interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){
.type = PUSH, .type = PUSH,
@ -148,11 +153,12 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter)
} }
else if (hydroforth__number__is_digit(interpreter->src[res.start])) else if (hydroforth__number__is_digit(interpreter->src[res.start]))
{ {
int n; int n = hydroforth__number__parse_number(result, interpreter->src + res.start, res.len);
if (!hydroforth__number__parse_number(interpreter->src + res.start, res.len, &n)) if (result->error)
{ {
hydroforth__add_func_backtrace(result);
fputs("Error parsing number!\n", stderr); fputs("Error parsing number!\n", stderr);
return false; return;
} }
interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){ interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){
.type = PUSH, .type = PUSH,
@ -180,11 +186,9 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter)
} }
} }
} }
return true;
} }
bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter) void hydroforth__run_call_stack(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter)
{ {
for (unsigned char i = interpreter->call_stack_len; i > 0; interpreter->call_stack_len--, i--) for (unsigned char i = interpreter->call_stack_len; i > 0; interpreter->call_stack_len--, i--)
{ {
@ -219,8 +223,8 @@ bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter)
break; break;
default: default:
fprintf(stderr, "Unknown word: '%c'\n", word->data.char_word); hydroforth__set_func_result(result, ERR_UNKNOWN_SINGLE_CHAR_WORD);
return false; return;
} }
break; break;
@ -268,17 +272,15 @@ bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter)
break; break;
default: default:
fprintf(stderr, "Unknown word with hash: 0x%x\n", word->data.hash); hydroforth__set_func_result(result, ERR_UNKNOWN_WORD);
return false; return;
} }
break; break;
} }
} }
return true;
} }
bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter) void hydroforth__run(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter)
{ {
while (true) while (true)
{ {
@ -288,15 +290,19 @@ bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter)
} }
if (!interpreter->src[interpreter->pos]) if (!interpreter->src[interpreter->pos])
{ {
return true; return;
} }
if (!hydroforth__parse(interpreter)) hydroforth__parse(result, interpreter);
if (result->error)
{ {
return false; hydroforth__add_func_backtrace(result);
return;
} }
if (!hydroforth__run_call_stack(interpreter)) hydroforth__run_call_stack(result, interpreter);
if (result->error)
{ {
return false; hydroforth__add_func_backtrace(result);
return;
} }
} }
} }

View file

@ -1,6 +1,5 @@
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <malloc.h>
#include "hydroforth/hydroforth.h" #include "hydroforth/hydroforth.h"
@ -9,11 +8,11 @@ bool hydroforth__number__is_digit(char c)
return '0' <= c && c <= '9'; return '0' <= c && c <= '9';
} }
void hydroforth__number__convert_hex_digit(HYDROFORTH__RESULT *const result, char c, unsigned char *const val) unsigned char hydroforth__number__convert_hex_digit(HYDROFORTH__RESULT *const result, char c)
{ {
if (hydroforth__number__is_digit(c)) if (hydroforth__number__is_digit(c))
{ {
*val = c - '0'; return c - '0';
} }
else else
{ {
@ -21,33 +20,27 @@ void hydroforth__number__convert_hex_digit(HYDROFORTH__RESULT *const result, cha
{ {
case 'A': case 'A':
case 'a': case 'a':
*val = 0xa; return 0xa;
break;
case 'B': case 'B':
case 'b': case 'b':
*val = 0xb; return 0xb;
break;
case 'C': case 'C':
case 'c': case 'c':
*val = 0xc; return 0xc;
break;
case 'D': case 'D':
case 'd': case 'd':
*val = 0xd; return 0xd;
break;
case 'E': case 'E':
case 'e': case 'e':
*val = 0xe; return 0xe;
break;
case 'F': case 'F':
case 'f': case 'f':
*val = 0xf; return 0xf;
break;
default: default:
// hydroforth__result__set(result, ERR_INVALID_HEX_CHAR, __func__); // hydroforth__result__set(result, ERR_INVALID_HEX_CHAR, __func__);
@ -57,30 +50,25 @@ void hydroforth__number__convert_hex_digit(HYDROFORTH__RESULT *const result, cha
} }
} }
void hydroforth__number__parse_number_hex(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len, int *const val) int hydroforth__number__parse_number_hex(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len)
{ {
int n; int n = 0;
for (unsigned char i = 0; i < len; i++) for (unsigned char i = 0; i < len; i++)
{ {
unsigned char m; unsigned char m = hydroforth__number__convert_hex_digit(result, start[i]);
// if (!hydroforth__number__convert_hex_digit(result, start[i], &m)) if (result->error)
// {
// return false;
// }
hydroforth__number__convert_hex_digit(result, start[i], &m);
if (result->error != OK)
{ {
hydroforth__add_func_backtrace(result); hydroforth__add_func_backtrace(result);
return; return 0;
} }
n *= 16; n *= 16;
n += m; n += m;
} }
return true; return n;
} }
void hydroforth__number__parse_number(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len, int *const val) int hydroforth__number__parse_number(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len)
{ {
if (start[0] == '0') if (start[0] == '0')
{ {
@ -90,25 +78,29 @@ void hydroforth__number__parse_number(HYDROFORTH__RESULT *const result, const ch
{ {
case 'X': case 'X':
case 'x': case 'x':
hydroforth__number__parse_number_hex(result, start + 2, len - 2, val); {
if (result->error != OK) int n = hydroforth__number__parse_number_hex(result, start + 2, len - 2);
if (result->error)
{ {
hydroforth__add_func_backtrace(result); hydroforth__add_func_backtrace(result);
} }
break; return n;
}
default: default:
hydroforth__number__parse_number(result, start + 1, len - 1, val); {
if (result->error != OK) int n = hydroforth__number__parse_number(result, start + 1, len - 1);
if (result->error)
{ {
hydroforth__add_func_backtrace(result); hydroforth__add_func_backtrace(result);
} }
break; return n;
}
} }
} }
else else
{ {
*val = 0; return 0;
} }
} }
else else
@ -119,7 +111,7 @@ void hydroforth__number__parse_number(HYDROFORTH__RESULT *const result, const ch
n *= 10; n *= 10;
n += start[i] - '0'; n += start[i] - '0';
} }
*val = n; return n;
} }
} }

View file

@ -1,8 +1,10 @@
#include <malloc.h>
#include "hydroforth/hydroforth.h" #include "hydroforth/hydroforth.h"
void hydroforth__result__add_backtrace(HYDROFORTH__RESULT *const result, const char *const s) void hydroforth__result__add_backtrace(HYDROFORTH__RESULT *const result, const char *const s)
{ {
realloc(result->backtrace, sizeof(char *) * (result->backtrace_len + 1)); result->backtrace = realloc(result->backtrace, sizeof(char *) * (result->backtrace_len + 1));
result->backtrace[result->backtrace_len++] = s; result->backtrace[result->backtrace_len++] = s;
} }
@ -11,3 +13,46 @@ void hydroforth__result__set(HYDROFORTH__RESULT *const result, HYDROFORTH__ERROR
result->error = error; result->error = error;
hydroforth__result__add_backtrace(result, s); hydroforth__result__add_backtrace(result, s);
} }
const char *hydroforth__result__get_error_message(HYDROFORTH__ERROR error)
{
switch (error)
{
case OK:
return "OK";
case ERR_UNKNOWN:
return "Unknown error";
case ERR_INVALID_HEX_CHAR:
return "Invalid hexadecimal char in number";
case ERR_UNKNOWN_SINGLE_CHAR_WORD:
case ERR_UNKNOWN_WORD:
return "Unknown word";
case ERR_UNTERMINATED_WORD_DEFINITION:
return "Unterminated word definition";
case ERR_WORD_NAME_CANT_BE_NUMBER:
return "Word name can't be a number";
default:
return "???";
}
}
int hydroforth__result__unwrap(HYDROFORTH__RESULT *const result, int code)
{
printf("BACKTRACE LEN: %u\n", result->backtrace_len);
puts("ERROR! Backtrace:");
printf("Error: %u -> \"%s\"\n", result->error, hydroforth__result__get_error_message(result->error));
for (unsigned short i = 0; i < result->backtrace_len; i++)
{
printf("%u: %s\n", result->backtrace_len - i - 1, result->backtrace[i]);
}
printf("EXITING with code: %u!\n", code);
free(result->backtrace);
return code;
}

View file

@ -2,6 +2,9 @@
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#define UNW_LOCAL_ONLY
#include <libunwind.h>
#include "hydroforth/hydroforth.h" #include "hydroforth/hydroforth.h"
struct ReadSrcResult struct ReadSrcResult
@ -74,11 +77,13 @@ int main(int argc, char *argv[])
.word_keys_len = 0, .word_keys_len = 0,
.word_keys_max_len = 0, .word_keys_max_len = 0,
}; };
const bool run_res = hydroforth.run(&interpreter); HYDROFORTH__RESULT result = {.error = OK, .backtrace_len = 0};
hydroforth.run(&result, &interpreter);
free(res.src); free(res.src);
if (!run_res) if (result.error)
{ {
return 1; hydroforth__add_func_backtrace(&result);
return hydroforth.result.unwrap(&result, 1);
} }
} }
else else

View file

@ -1,2 +1,2 @@
: test 42 ; \ : test 42 ;
40 2 + debug 40 2 + debug