Expression is a list-of-lists now.

That way we don't have to concatinate quotes onto it all the time.
Instead we amortize in the next_term() function.
This commit is contained in:
Simon Forman 2023-02-04 13:38:28 -08:00
parent 45865acc2f
commit b76213ff7e
2 changed files with 123 additions and 75 deletions

View File

@ -333,6 +333,75 @@ pop_int(JoyListPtr stack) {
} }
JoyList
pop_list(JoyListPtr stack)
{
JoyList node;
node = pop_any(stack);
switch (node->head->kind) {
case joyList:
return node;
default:
printf("Not a list.\n");
exit(1);
}
}
JoyList
pop_list_node(JoyListPtr stack)
{
return pop_list(stack)->head->value.el;
}
void
push_quote(JoyList el, JoyListPtr expression)
{
JoyList node;
if (!el) return;
node = newJoyList;
node->head = newJoyType;
node->head->kind = joyList;
node->head->value.el = el;
node->tail = *expression;
*expression = node;
}
/*
Return the next term from the expression and the new expression.
(item, quote), expression = expression
return item, push_quote(quote, expression)
*/
JoyTypePtr
next_term(JoyListPtr expression)
{
JoyList quote;
JoyTypePtr term;
if (!(*expression)) {
printf("Do not call next_term on an empty expression.\n");
exit(1);
}
quote = pop_list_node(expression);
if (!quote) {
printf("How did an empty list get onto the expression!?\n");
exit(1);
}
term = quote->head;
quote = quote->tail;
if (quote) {
push_quote(quote, expression);
}
print_list(*expression);
printf(" <--\n");
return term;
}
JoyList JoyList
newIntNode(void) { newIntNode(void) {
JoyList node = newJoyList; JoyList node = newJoyList;
@ -426,10 +495,13 @@ joy(JoyListPtr stack, JoyListPtr expression)
char *sym; char *sym;
JoyTypePtr term; JoyTypePtr term;
const struct dict_entry *interned; const struct dict_entry *interned;
JoyList e = EMPTY_LIST;
JoyListPtr ePtr = &e;
push_quote(*expression, ePtr);
expression = ePtr;
while (*expression) { while (*expression) {
term = (*expression)->head; term = next_term(expression);
*expression = (*expression)->tail;
switch (term->kind) { switch (term->kind) {
case joyInt: case joyInt:
case joyTrue: case joyTrue:

View File

@ -1,6 +1,6 @@
/* ANSI-C code produced by gperf version 3.1 */ /* ANSI-C code produced by gperf version 3.1 */
/* Command-line: gperf --output-file=keywords.c --readonly-tables --enum --includes --hash-function-name=keyword_hash KEYWORDS.txt */ /* Command-line: gperf --output-file=keywords.c --readonly-tables --enum --includes --hash-function-name=keyword_hash KEYWORDS.txt */
/* Computed positions: -k'1-2' */ /* Computed positions: -k'1' */
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
&& ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
@ -35,7 +35,7 @@
#line 7 "KEYWORDS.txt" #line 7 "KEYWORDS.txt"
struct dict_entry; struct dict_entry;
#include <string.h> #include <string.h>
/* maximum key range = 22, duplicates = 0 */ /* maximum key range = 16, duplicates = 0 */
#ifdef __GNUC__ #ifdef __GNUC__
__inline __inline
@ -49,45 +49,34 @@ keyword_hash (register const char *str, register size_t len)
{ {
static const unsigned char asso_values[] = static const unsigned char asso_values[] =
{ {
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 15, 23, 23, 23, 2, 23, 23, 17, 17, 17, 17, 17, 17, 17, 14, 17, 17,
23, 23, 13, 3, 23, 14, 23, 9, 23, 23, 17, 17, 9, 15, 17, 10, 17, 0, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
10, 5, 0, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 5, 0, 17, 17, 17, 17, 17, 17, 17, 17, 0, 0,
23, 23, 23, 23, 23, 23, 23, 23, 0, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 0, 23, 23, 5, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
23, 23, 23, 23, 23, 23 17, 17, 17, 17, 17, 17
}; };
register unsigned int hval = len; return len + asso_values[(unsigned char)str[0]];
switch (hval)
{
default:
hval += asso_values[(unsigned char)str[1]];
/*FALLTHROUGH*/
case 1:
hval += asso_values[(unsigned char)str[0]];
break;
}
return hval;
} }
const struct dict_entry * const struct dict_entry *
@ -95,50 +84,37 @@ in_word_set (register const char *str, register size_t len)
{ {
enum enum
{ {
TOTAL_KEYWORDS = 15, TOTAL_KEYWORDS = 9,
MIN_WORD_LENGTH = 1, MIN_WORD_LENGTH = 1,
MAX_WORD_LENGTH = 6, MAX_WORD_LENGTH = 6,
MIN_HASH_VALUE = 1, MIN_HASH_VALUE = 1,
MAX_HASH_VALUE = 22 MAX_HASH_VALUE = 16
}; };
static const struct dict_entry wordlist[] = static const struct dict_entry wordlist[] =
{ {
{""}, {""},
#line 19 "KEYWORDS.txt"
{">", gt},
{""},
#line 10 "KEYWORDS.txt"
{"%", mod},
#line 12 "KEYWORDS.txt"
{"+", add},
#line 23 "KEYWORDS.txt"
{"clear", clear},
#line 18 "KEYWORDS.txt"
{"=", eq},
#line 20 "KEYWORDS.txt"
{">=", ge},
{""},
#line 21 "KEYWORDS.txt"
{"bool", truthy},
#line 14 "KEYWORDS.txt"
{"/", div_joyfunc},
#line 15 "KEYWORDS.txt"
{"<", lt},
#line 17 "KEYWORDS.txt"
{"<>", neq},
{""},
#line 11 "KEYWORDS.txt"
{"*", mul},
#line 13 "KEYWORDS.txt" #line 13 "KEYWORDS.txt"
{"-", sub}, {"/", div_joyfunc},
#line 22 "KEYWORDS.txt" {""},
{"branch", branch}, #line 17 "KEYWORDS.txt"
{"cmp", cmp_joyfunc},
#line 14 "KEYWORDS.txt"
{"bool", truthy},
#line 16 "KEYWORDS.txt" #line 16 "KEYWORDS.txt"
{"<=", le}, {"clear", clear},
{""}, {""}, {""}, {""}, #line 15 "KEYWORDS.txt"
{"branch", branch},
{""}, {""}, {""},
#line 10 "KEYWORDS.txt"
{"*", mul},
#line 12 "KEYWORDS.txt"
{"-", sub},
{""}, {""}, {""},
#line 9 "KEYWORDS.txt" #line 9 "KEYWORDS.txt"
{"!=", neq} {"%", mod},
#line 11 "KEYWORDS.txt"
{"+", add}
}; };
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)