It turns out the error machinery was working...
So I was memset'ing the hash table and string table /after/ setting up the left- and right-bracket tokens! So then when I tried to print the token list and ht_lookup() dutifully set the error code when it couldn't find the strings in the hash table, the system properly quit printing and halted. D'oh! That was a subtle one. Obvious in hindsight.
This commit is contained in:
parent
0a9cdba456
commit
0af1a9f7b5
|
|
@ -17,6 +17,39 @@
|
||||||
//
|
//
|
||||||
#include <uvm/syscalls.h>
|
#include <uvm/syscalls.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
/*
|
||||||
|
███████╗██████╗ ██████╗ ██████╗ ██████╗
|
||||||
|
██╔════╝██╔══██╗██╔══██╗██╔═══██╗██╔══██╗
|
||||||
|
█████╗ ██████╔╝██████╔╝██║ ██║██████╔╝
|
||||||
|
██╔══╝ ██╔══██╗██╔══██╗██║ ██║██╔══██╗
|
||||||
|
███████╗██║ ██║██║ ██║╚██████╔╝██║ ██║
|
||||||
|
╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝
|
||||||
|
|
||||||
|
██╗ ██╗ █████╗ ███╗ ██╗██████╗ ██╗ ██╗███╗ ██╗ ██████╗
|
||||||
|
██║ ██║██╔══██╗████╗ ██║██╔══██╗██║ ██║████╗ ██║██╔════╝
|
||||||
|
███████║███████║██╔██╗ ██║██║ ██║██║ ██║██╔██╗ ██║██║ ███╗
|
||||||
|
██╔══██║██╔══██║██║╚██╗██║██║ ██║██║ ██║██║╚██╗██║██║ ██║
|
||||||
|
██║ ██║██║ ██║██║ ╚████║██████╔╝███████╗██║██║ ╚████║╚██████╔╝
|
||||||
|
╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝╚═════╝ ╚══════╝╚═╝╚═╝ ╚═══╝ ╚═════╝
|
||||||
|
|
||||||
|
No setjmp/longjmp, so let's have a global error value and check it after ops.
|
||||||
|
*/
|
||||||
|
|
||||||
|
u64 error = 0;
|
||||||
|
|
||||||
|
#define NO_ERROR 0
|
||||||
|
#define UNKNOWN_WORD_ERROR 1
|
||||||
|
#define MISSING_CLOSING_BRACKET 2
|
||||||
|
#define CONS_HEAP_OOM 3
|
||||||
|
#define STRING_HEAP_OOM 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
char *error_messages[3] = {
|
||||||
|
"",
|
||||||
|
"Unknown word",
|
||||||
|
"Missing closing bracket"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
██████╗ ██████╗ ███╗ ██╗███████╗ ██╗ ██╗███████╗ █████╗ ██████╗
|
██████╗ ██████╗ ███╗ ██╗███████╗ ██╗ ██╗███████╗ █████╗ ██████╗
|
||||||
|
|
@ -76,9 +109,10 @@ u32 empty_list = 0;
|
||||||
u32
|
u32
|
||||||
cons(u32 head, u32 tail)
|
cons(u32 head, u32 tail)
|
||||||
{
|
{
|
||||||
if (free >= HEAP_SIZE)
|
if (free >= HEAP_SIZE) {
|
||||||
|
error = CONS_HEAP_OOM;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
heads[free] = head;
|
heads[free] = head;
|
||||||
tails[free] = tail;
|
tails[free] = tail;
|
||||||
u32 cell = JOY_VALUE(joyList, free);
|
u32 cell = JOY_VALUE(joyList, free);
|
||||||
|
|
@ -120,8 +154,10 @@ char*
|
||||||
allocate_string(char *buffer, u32 offset, u32 length)
|
allocate_string(char *buffer, u32 offset, u32 length)
|
||||||
{
|
{
|
||||||
u64 end = string_heap_top + length + 1;
|
u64 end = string_heap_top + length + 1;
|
||||||
if (end >= STRING_HEAP_SIZE)
|
if (end >= STRING_HEAP_SIZE) {
|
||||||
|
error = STRING_HEAP_OOM;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
memcpy(string_heap + string_heap_top, buffer + offset, length);
|
memcpy(string_heap + string_heap_top, buffer + offset, length);
|
||||||
string_heap[end] = '\0';
|
string_heap[end] = '\0';
|
||||||
u32 new_string = string_heap_top;
|
u32 new_string = string_heap_top;
|
||||||
|
|
@ -131,18 +167,6 @@ allocate_string(char *buffer, u32 offset, u32 length)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
// No setjmp/longjmp, so let's have a global error value and check it after ops.
|
|
||||||
u64 error;
|
|
||||||
|
|
||||||
#define NO_ERROR 0
|
|
||||||
#define UNKNOWN_WORD_ERROR 1
|
|
||||||
#define MISSING_CLOSING_BRACKET 2
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
██████╗ ██████╗ ██╗███╗ ██╗████████╗███████╗██████╗
|
██████╗ ██████╗ ██╗███╗ ██╗████████╗███████╗██████╗
|
||||||
██╔══██╗██╔══██╗██║████╗ ██║╚══██╔══╝██╔════╝██╔══██╗
|
██╔══██╗██╔══██╗██║████╗ ██║╚══██╔══╝██╔════╝██╔══██╗
|
||||||
|
|
@ -349,6 +373,13 @@ convert_integer(char *str, u32 index, u32 length)
|
||||||
╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝╚═╝╚══════╝╚══════╝╚═╝ ╚═╝
|
╚═╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═══╝╚═╝╚══════╝╚══════╝╚═╝ ╚═╝
|
||||||
Tokenizer
|
Tokenizer
|
||||||
|
|
||||||
|
For now this works, but there are a few improvements to be made: the
|
||||||
|
tokenizer is recursive but it could be made iterative if it builds the
|
||||||
|
expression in reverse, and then the parser should relink the tokens into
|
||||||
|
the expression in-place (currently it makes one copy of the list.) Once
|
||||||
|
that's done the tokenizer and the parser can be integrated into one pass,
|
||||||
|
I think.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
char* LEFT_BRACKET_symbol = "[";
|
char* LEFT_BRACKET_symbol = "[";
|
||||||
|
|
@ -386,8 +417,12 @@ tokenate(char *str, u32 index, u32 length)
|
||||||
}
|
}
|
||||||
// TODO: Use ht_insert to avoid multiple allocations of the same string!
|
// TODO: Use ht_insert to avoid multiple allocations of the same string!
|
||||||
char *token = allocate_string(str, index, length);
|
char *token = allocate_string(str, index, length);
|
||||||
if (!token)
|
if (error != NO_ERROR) {
|
||||||
return 0; // OOM
|
print_str("a. Error code: ");print_i64(error);print_endl();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//if (!token)
|
||||||
|
// return 0; // OOM
|
||||||
return JOY_VALUE(joySymbol, ht_insert(token));
|
return JOY_VALUE(joySymbol, ht_insert(token));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -422,7 +457,12 @@ tokenize0(char *str, u32 str_length, u32 index, u32 acc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// i == str_length OR str[i] is a delimiter char.
|
// i == str_length OR str[i] is a delimiter char.
|
||||||
return cons(tokenate(str, index, i - index), tokenize0(str, str_length, i, acc));
|
u32 tok = tokenate(str, index, i - index);
|
||||||
|
if (error != NO_ERROR) {
|
||||||
|
print_str("d. Error code: ");print_i64(error);print_endl();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return cons(tok, tokenize0(str, str_length, i, acc));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -468,7 +508,12 @@ text_to_expression(char *str)
|
||||||
{
|
{
|
||||||
u32 frame = empty_list;
|
u32 frame = empty_list;
|
||||||
u32 tokens = tokenize(str);
|
u32 tokens = tokenize(str);
|
||||||
//print_str("tokens: "); print_joy_list(tokens); print_endl();
|
if (error != NO_ERROR) {
|
||||||
|
print_str("Error code: ");print_i64(error);print_endl();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
print_str("tokens: "); print_joy_list(tokens); print_endl();
|
||||||
//return tokens;
|
//return tokens;
|
||||||
while (tokens) {
|
while (tokens) {
|
||||||
u32 tok = head(tokens);
|
u32 tok = head(tokens);
|
||||||
|
|
@ -497,17 +542,17 @@ text_to_expression(char *str)
|
||||||
void
|
void
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
memset(hash_table, 0, sizeof(hash_table));
|
||||||
|
memset(string_heap, 0, sizeof(string_heap));
|
||||||
|
memset(t2e_stack, 0, sizeof(t2e_stack));
|
||||||
|
error = NO_ERROR;
|
||||||
|
|
||||||
LEFT_BRACKET = JOY_VALUE(joySymbol, ht_insert(LEFT_BRACKET_symbol));
|
LEFT_BRACKET = JOY_VALUE(joySymbol, ht_insert(LEFT_BRACKET_symbol));
|
||||||
RIGHT_BRACKET = JOY_VALUE(joySymbol, ht_insert(RIGHT_BRACKET_symbol));
|
RIGHT_BRACKET = JOY_VALUE(joySymbol, ht_insert(RIGHT_BRACKET_symbol));
|
||||||
// TODO: these should be global.
|
// TODO: these should be global.
|
||||||
u32 joy_true = JOY_VALUE(joyBool, 1);
|
u32 joy_true = JOY_VALUE(joyBool, 1);
|
||||||
u32 joy_false = JOY_VALUE(joyBool, 0);
|
u32 joy_false = JOY_VALUE(joyBool, 0);
|
||||||
|
|
||||||
memset(hash_table, 0, sizeof(hash_table));
|
|
||||||
memset(string_heap, 0, sizeof(string_heap));
|
|
||||||
memset(t2e_stack, 0, sizeof(t2e_stack));
|
|
||||||
error = NO_ERROR;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
u32 stack = empty_list;
|
u32 stack = empty_list;
|
||||||
stack = push_int(23, stack);
|
stack = push_int(23, stack);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue