From b76213ff7efde8ed3ee898ccee48bc76d15d9521 Mon Sep 17 00:00:00 2001 From: Simon Forman Date: Sat, 4 Feb 2023 13:38:28 -0800 Subject: [PATCH] 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. --- implementations/C/joy.c | 76 +++++++++++++++++++++- implementations/C/keywords.c | 122 ++++++++++++++--------------------- 2 files changed, 123 insertions(+), 75 deletions(-) diff --git a/implementations/C/joy.c b/implementations/C/joy.c index 93e417e..d49ab2d 100644 --- a/implementations/C/joy.c +++ b/implementations/C/joy.c @@ -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 newIntNode(void) { JoyList node = newJoyList; @@ -426,10 +495,13 @@ joy(JoyListPtr stack, JoyListPtr expression) char *sym; JoyTypePtr term; const struct dict_entry *interned; + JoyList e = EMPTY_LIST; + JoyListPtr ePtr = &e; + push_quote(*expression, ePtr); + expression = ePtr; while (*expression) { - term = (*expression)->head; - *expression = (*expression)->tail; + term = next_term(expression); switch (term->kind) { case joyInt: case joyTrue: diff --git a/implementations/C/keywords.c b/implementations/C/keywords.c index 9e887aa..6a5626e 100644 --- a/implementations/C/keywords.c +++ b/implementations/C/keywords.c @@ -1,6 +1,6 @@ /* 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 */ -/* Computed positions: -k'1-2' */ +/* Computed positions: -k'1' */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ @@ -35,7 +35,7 @@ #line 7 "KEYWORDS.txt" struct dict_entry; #include -/* maximum key range = 22, duplicates = 0 */ +/* maximum key range = 16, duplicates = 0 */ #ifdef __GNUC__ __inline @@ -49,45 +49,34 @@ keyword_hash (register const char *str, register size_t len) { static const unsigned char asso_values[] = { - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 15, 23, 23, 23, 2, 23, 23, - 23, 23, 13, 3, 23, 14, 23, 9, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 10, 5, 0, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 5, 0, - 23, 23, 23, 23, 23, 23, 23, 23, 0, 23, - 23, 0, 23, 23, 5, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23 + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 14, 17, 17, + 17, 17, 9, 15, 17, 10, 17, 0, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 0, 0, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17 }; - register unsigned int hval = len; - - switch (hval) - { - default: - hval += asso_values[(unsigned char)str[1]]; - /*FALLTHROUGH*/ - case 1: - hval += asso_values[(unsigned char)str[0]]; - break; - } - return hval; + return len + asso_values[(unsigned char)str[0]]; } const struct dict_entry * @@ -95,50 +84,37 @@ in_word_set (register const char *str, register size_t len) { enum { - TOTAL_KEYWORDS = 15, + TOTAL_KEYWORDS = 9, MIN_WORD_LENGTH = 1, MAX_WORD_LENGTH = 6, MIN_HASH_VALUE = 1, - MAX_HASH_VALUE = 22 + MAX_HASH_VALUE = 16 }; 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" - {"-", sub}, -#line 22 "KEYWORDS.txt" - {"branch", branch}, + {"/", div_joyfunc}, + {""}, +#line 17 "KEYWORDS.txt" + {"cmp", cmp_joyfunc}, +#line 14 "KEYWORDS.txt" + {"bool", truthy}, #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" - {"!=", neq} + {"%", mod}, +#line 11 "KEYWORDS.txt" + {"+", add} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)