Update
This commit is contained in:
parent
4e8c187050
commit
bd9b51be9a
8 changed files with 142 additions and 85 deletions
|
@ -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 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
|
||||
{
|
||||
|
@ -90,15 +90,16 @@ typedef struct __HYDROFORTH
|
|||
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);
|
||||
void (*parse)(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter);
|
||||
void (*run_call_stack)(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter);
|
||||
void (*run)(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter);
|
||||
} __HYDROFORTH;
|
||||
|
||||
static const __HYDROFORTH hydroforth = {
|
||||
.result = {
|
||||
.add_backtrace = hydroforth__result__add_backtrace,
|
||||
.get_error_message = hydroforth__result__get_error_message,
|
||||
.unwrap = hydroforth__result__unwrap,
|
||||
},
|
||||
.number = {
|
||||
.is_digit = hydroforth__number__is_digit,
|
||||
|
|
|
@ -3,20 +3,20 @@
|
|||
|
||||
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);
|
||||
|
||||
typedef struct __HYDROFORTH__NUMBER
|
||||
{
|
||||
bool (*is_digit)(char c);
|
||||
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 (*convert_hex_digit)(HYDROFORTH__RESULT *const result, char c);
|
||||
int (*parse_number_hex)(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len);
|
||||
int (*parse_number)(HYDROFORTH__RESULT *const result, const char *const start, unsigned char len);
|
||||
unsigned char (*count_digits)(int n);
|
||||
} __HYDROFORTH__NUMBER;
|
||||
|
||||
|
|
|
@ -3,10 +3,15 @@
|
|||
|
||||
typedef enum HYDROFORTH__RESULT__ERROR
|
||||
{
|
||||
OK,
|
||||
OK = 0,
|
||||
|
||||
ERR_UNKNOWN,
|
||||
|
||||
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;
|
||||
|
||||
typedef HYDROFORTH__RESULT__ERROR HYDROFORTH__ERROR;
|
||||
|
@ -14,8 +19,8 @@ typedef HYDROFORTH__RESULT__ERROR HYDROFORTH__ERROR;
|
|||
typedef struct HYDROFORTH__RESULT__RESULT
|
||||
{
|
||||
HYDROFORTH__ERROR error;
|
||||
char **const backtrace;
|
||||
unsigned backtrace_len;
|
||||
const char **backtrace;
|
||||
unsigned short backtrace_len;
|
||||
} HYDROFORTH__RESULT__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__);
|
||||
|
||||
extern int hydroforth__result__unwrap(HYDROFORTH__RESULT *const result, int code);
|
||||
|
||||
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);
|
||||
int (*unwrap)(HYDROFORTH__RESULT *const result, int code);
|
||||
} __HYDROFORTH__RESULT;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <string.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;
|
||||
// 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');
|
||||
if (!interpreter->src[interpreter->pos])
|
||||
{
|
||||
fputs("Unterminated word definition!\n", stderr);
|
||||
return false;
|
||||
// fputs("Unterminated word definition!\n", stderr);
|
||||
// return false;
|
||||
hydroforth__set_func_result(result, ERR_UNTERMINATED_WORD_DEFINITION);
|
||||
return;
|
||||
}
|
||||
if (hydroforth__number__is_digit(interpreter->src[interpreter->pos]))
|
||||
{
|
||||
fputs("Word name cannot be a number!\n", stderr);
|
||||
return false;
|
||||
// fputs("Word name cannot be a number!\n", stderr);
|
||||
// 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);
|
||||
|
||||
|
@ -122,11 +125,12 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter)
|
|||
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 + res.start + 1, res.len - 1, &n))
|
||||
int n = hydroforth__number__parse_number(result, interpreter->src + res.start + 1, res.len - 1);
|
||||
if (result->error)
|
||||
{
|
||||
hydroforth__add_func_backtrace(result);
|
||||
fputs("Error parsing number!\n", stderr);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){
|
||||
.type = PUSH,
|
||||
|
@ -135,11 +139,12 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter)
|
|||
}
|
||||
else if (next_is_digit && interpreter->src[res.start] == '+')
|
||||
{
|
||||
int n;
|
||||
if (!hydroforth__number__parse_number(interpreter->src + res.start + 1, res.len - 1, &n))
|
||||
int n = hydroforth__number__parse_number(result, interpreter->src + res.start + 1, res.len - 1);
|
||||
if (result->error)
|
||||
{
|
||||
hydroforth__add_func_backtrace(result);
|
||||
fputs("Error parsing number!\n", stderr);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){
|
||||
.type = PUSH,
|
||||
|
@ -148,11 +153,12 @@ bool hydroforth__parse(HYDROFORTH__INTERPRETER *interpreter)
|
|||
}
|
||||
else if (hydroforth__number__is_digit(interpreter->src[res.start]))
|
||||
{
|
||||
int n;
|
||||
if (!hydroforth__number__parse_number(interpreter->src + res.start, res.len, &n))
|
||||
int n = hydroforth__number__parse_number(result, interpreter->src + res.start, res.len);
|
||||
if (result->error)
|
||||
{
|
||||
hydroforth__add_func_backtrace(result);
|
||||
fputs("Error parsing number!\n", stderr);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
interpreter->call_stack[interpreter->call_stack_len++] = (HYDROFORTH__WORD){
|
||||
.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--)
|
||||
{
|
||||
|
@ -219,8 +223,8 @@ bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter)
|
|||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown word: '%c'\n", word->data.char_word);
|
||||
return false;
|
||||
hydroforth__set_func_result(result, ERR_UNKNOWN_SINGLE_CHAR_WORD);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -268,17 +272,15 @@ bool hydroforth__run_call_stack(HYDROFORTH__INTERPRETER *interpreter)
|
|||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown word with hash: 0x%x\n", word->data.hash);
|
||||
return false;
|
||||
hydroforth__set_func_result(result, ERR_UNKNOWN_WORD);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter)
|
||||
void hydroforth__run(HYDROFORTH__RESULT *const result, HYDROFORTH__INTERPRETER *interpreter)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
|
@ -288,15 +290,19 @@ bool hydroforth__run(HYDROFORTH__INTERPRETER *interpreter)
|
|||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "hydroforth/hydroforth.h"
|
||||
|
||||
|
@ -9,11 +8,11 @@ bool hydroforth__number__is_digit(char c)
|
|||
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))
|
||||
{
|
||||
*val = c - '0';
|
||||
return c - '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -21,33 +20,27 @@ void hydroforth__number__convert_hex_digit(HYDROFORTH__RESULT *const result, cha
|
|||
{
|
||||
case 'A':
|
||||
case 'a':
|
||||
*val = 0xa;
|
||||
break;
|
||||
return 0xa;
|
||||
|
||||
case 'B':
|
||||
case 'b':
|
||||
*val = 0xb;
|
||||
break;
|
||||
return 0xb;
|
||||
|
||||
case 'C':
|
||||
case 'c':
|
||||
*val = 0xc;
|
||||
break;
|
||||
return 0xc;
|
||||
|
||||
case 'D':
|
||||
case 'd':
|
||||
*val = 0xd;
|
||||
break;
|
||||
return 0xd;
|
||||
|
||||
case 'E':
|
||||
case 'e':
|
||||
*val = 0xe;
|
||||
break;
|
||||
return 0xe;
|
||||
|
||||
case 'F':
|
||||
case 'f':
|
||||
*val = 0xf;
|
||||
break;
|
||||
return 0xf;
|
||||
|
||||
default:
|
||||
// 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++)
|
||||
{
|
||||
unsigned char 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)
|
||||
unsigned char m = hydroforth__number__convert_hex_digit(result, start[i]);
|
||||
if (result->error)
|
||||
{
|
||||
hydroforth__add_func_backtrace(result);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
n *= 16;
|
||||
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')
|
||||
{
|
||||
|
@ -90,25 +78,29 @@ void hydroforth__number__parse_number(HYDROFORTH__RESULT *const result, const ch
|
|||
{
|
||||
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);
|
||||
}
|
||||
break;
|
||||
return n;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
break;
|
||||
return n;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*val = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -119,7 +111,7 @@ void hydroforth__number__parse_number(HYDROFORTH__RESULT *const result, const ch
|
|||
n *= 10;
|
||||
n += start[i] - '0';
|
||||
}
|
||||
*val = n;
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#include <malloc.h>
|
||||
|
||||
#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 = realloc(result->backtrace, sizeof(char *) * (result->backtrace_len + 1));
|
||||
result->backtrace[result->backtrace_len++] = s;
|
||||
}
|
||||
|
||||
|
@ -11,3 +13,46 @@ void hydroforth__result__set(HYDROFORTH__RESULT *const result, HYDROFORTH__ERROR
|
|||
result->error = error;
|
||||
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;
|
||||
}
|
||||
|
|
11
src/main.c
11
src/main.c
|
@ -2,6 +2,9 @@
|
|||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define UNW_LOCAL_ONLY
|
||||
#include <libunwind.h>
|
||||
|
||||
#include "hydroforth/hydroforth.h"
|
||||
|
||||
struct ReadSrcResult
|
||||
|
@ -74,11 +77,13 @@ int main(int argc, char *argv[])
|
|||
.word_keys_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);
|
||||
if (!run_res)
|
||||
if (result.error)
|
||||
{
|
||||
return 1;
|
||||
hydroforth__add_func_backtrace(&result);
|
||||
return hydroforth.result.unwrap(&result, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
2
test.fth
2
test.fth
|
@ -1,2 +1,2 @@
|
|||
: test 42 ;
|
||||
\ : test 42 ;
|
||||
40 2 + debug
|
||||
|
|
Loading…
Reference in a new issue