diff --git a/implementations/C/joy.c b/implementations/C/joy.c index 25d3bbd..802931b 100644 --- a/implementations/C/joy.c +++ b/implementations/C/joy.c @@ -1,4 +1,12 @@ /* + +████████╗██╗ ██╗██╗ ██╗███╗ ██╗ +╚══██╔══╝██║ ██║██║ ██║████╗ ██║ + ██║ ███████║██║ ██║██╔██╗ ██║ + ██║ ██╔══██║██║ ██║██║╚██╗██║ + ██║ ██║ ██║╚██████╔╝██║ ╚████║ + ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ + Copyright © 2023 Simon Forman This file is part of Thun @@ -55,6 +63,16 @@ my_callback(GC_PTR void_obj, __attribute__((unused)) GC_PTR void_environment) { } +/* +██╗ ██╗████████╗██╗██╗ ███████╗ +██║ ██║╚══██╔══╝██║██║ ██╔════╝ +██║ ██║ ██║ ██║██║ ███████╗ +██║ ██║ ██║ ██║██║ ╚════██║ +╚██████╔╝ ██║ ██║███████╗███████║ + ╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝ +*/ + + JoyList push_integer_from_str(char *str, JoyList tail) { @@ -68,51 +86,6 @@ push_integer_from_str(char *str, JoyList tail) } -/* Pre-declare so we can use it in print_node(). */ -void -print_list(JoyList el); - - -void -print_node(JoyType j) -{ - switch (j.kind) { - case joyInt: - gmp_printf("%Zd", j.value.i); - break; - case joySymbol: - printf("%s", j.value.symbol); - break; - case joyTrue: - printf("true"); - break; - case joyFalse: - printf("false"); - break; - case joyList: - printf("["); - print_list(j.value.el); - printf("]"); - break; - default: - printf("wtf"); - } -} - - -void -print_list(JoyList el) -{ - while (NULL != el) { - print_node(*(el->head)); - el = el->tail; - if (NULL != el) { - printf(" "); - } - } -} - - char * trim_leading_blanks(char *str) { @@ -161,6 +134,7 @@ make_non_list_node(char *text, size_t size) return node; } + /* Create a new list_node with a joyList head. */ JoyList make_list_node(JoyList el) @@ -173,6 +147,160 @@ make_list_node(JoyList el) } +JoyList +pop_any(JoyListPtr stack) +{ + JoyList result; + if (!(*stack)) { + printf("Not enough values on stack.\n"); + exit(1); + } + result = *stack; + *stack = (*stack)->tail; + return result; +} + + +mpz_t * +pop_int(JoyListPtr stack) +{ + JoyList node; + node = pop_any(stack); + switch (node->head->kind) { + case joyInt: + return &(node->head->value.i); + default: + printf("Not an integer.\n"); + exit(1); + } +} + + +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; +} + + +JoyList +newIntNode(void) { + JoyList node = newJoyList; + node->head = newJoyType; + node->head->kind = joyInt; + mpz_init(node->head->value.i); + GC_register_finalizer(node->head->value.i, my_callback, NULL, NULL, NULL); + return node; +} + + +void +push_thing(JoyTypePtr term, JoyListPtr stack) { + JoyList node = newJoyList; + node->head = term; + node->tail = *stack; + *stack = node; +} + + +/* +██████╗ ██████╗ ██╗███╗ ██╗████████╗███████╗██████╗ +██╔══██╗██╔══██╗██║████╗ ██║╚══██╔══╝██╔════╝██╔══██╗ +██████╔╝██████╔╝██║██╔██╗ ██║ ██║ █████╗ ██████╔╝ +██╔═══╝ ██╔══██╗██║██║╚██╗██║ ██║ ██╔══╝ ██╔══██╗ +██║ ██║ ██║██║██║ ╚████║ ██║ ███████╗██║ ██║ +╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ +*/ + + +/* Pre-declare so we can use it in print_node(). */ +void +print_list(JoyList el); + + +void +print_node(JoyType j) +{ + switch (j.kind) { + case joyInt: + gmp_printf("%Zd", j.value.i); + break; + case joySymbol: + printf("%s", j.value.symbol); + break; + case joyTrue: + printf("true"); + break; + case joyFalse: + printf("false"); + break; + case joyList: + printf("["); + print_list(j.value.el); + printf("]"); + break; + default: + printf("wtf"); + } +} + + +void +print_list(JoyList el) +{ + while (NULL != el) { + print_node(*(el->head)); + el = el->tail; + if (NULL != el) { + printf(" "); + } + } +} + + +void +print_stack(JoyList el) +{ + if (el) { + if (el->tail) { + print_stack(el->tail); + printf(" "); + } + print_node(*(el->head)); + } +} + + /* ██████╗ █████╗ ██████╗ ███████╗███████╗██████╗ ██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔════╝██╔══██╗ @@ -236,6 +364,7 @@ Extract terms from the text until a closing bracket is found. return result; } + /* Get the next node from the text, updating text to point to the rest of the, uh, text. @@ -307,78 +436,31 @@ text_to_expression(char *text) } -JoyList -pop_any(JoyListPtr stack) -{ - JoyList result; - if (!(*stack)) { - printf("Not enough values on stack.\n"); - exit(1); - } - result = *stack; - *stack = (*stack)->tail; - return result; -} - -mpz_t * -pop_int(JoyListPtr stack) -{ - JoyList node; - node = pop_any(stack); - switch (node->head->kind) { - case joyInt: - return &(node->head->value.i); - default: - printf("Not an integer.\n"); - exit(1); - } -} - - -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; -} - - /* +███████╗██╗ ██╗██████╗ ██████╗ ███████╗███████╗███████╗██╗ ██████╗ ███╗ ██╗ +██╔════╝╚██╗██╔╝██╔══██╗██╔══██╗██╔════╝██╔════╝██╔════╝██║██╔═══██╗████╗ ██║ +█████╗ ╚███╔╝ ██████╔╝██████╔╝█████╗ ███████╗███████╗██║██║ ██║██╔██╗ ██║ +██╔══╝ ██╔██╗ ██╔═══╝ ██╔══██╗██╔══╝ ╚════██║╚════██║██║██║ ██║██║╚██╗██║ +███████╗██╔╝ ██╗██║ ██║ ██║███████╗███████║███████║██║╚██████╔╝██║ ╚████║ +╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═══╝ + +As elegant as it is to model the expression as a stack, it's not very +efficient, as concatenating definitions and other quoted programs to +the expression is a common and expensive operation. + +Instead, let's keep a stack of sub-expressions, reading from them +one-by-one, and prepending new sub-expressions to the stack rather than +concatenating them. + + 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) { @@ -398,21 +480,19 @@ next_term(JoyListPtr expression) if (quote) { push_quote(quote, expression); } - print_list(*expression); - printf(" <--\n"); return term; } -JoyList -newIntNode(void) { - JoyList node = newJoyList; - node->head = newJoyType; - node->head->kind = joyInt; - mpz_init(node->head->value.i); - GC_register_finalizer(node->head->value.i, my_callback, NULL, NULL, NULL); - return node; -} +/* + ██████╗ ██████╗ ██████╗ ███████╗ ██╗ ██╗ ██████╗ ██████╗ ██████╗ ███████╗ +██╔════╝██╔═══██╗██╔══██╗██╔════╝ ██║ ██║██╔═══██╗██╔══██╗██╔══██╗██╔════╝ +██║ ██║ ██║██████╔╝█████╗ ██║ █╗ ██║██║ ██║██████╔╝██║ ██║███████╗ +██║ ██║ ██║██╔══██╗██╔══╝ ██║███╗██║██║ ██║██╔══██╗██║ ██║╚════██║ +╚██████╗╚██████╔╝██║ ██║███████╗ ╚███╔███╔╝╚██████╔╝██║ ██║██████╔╝███████║ + ╚═════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚══╝╚══╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ ╚══════╝ +*/ + #define BINARY_MATH_OP(name) \ void \ @@ -473,13 +553,14 @@ void mod(JoyListPtr stack, JoyListPtr expression) {stack = expression;} void truthy(JoyListPtr stack, JoyListPtr expression) {stack = expression;} -void -push_thing(JoyTypePtr term, JoyListPtr stack) { - JoyList node = newJoyList; - node->head = term; - node->tail = *stack; - *stack = node; -} +/* +██╗███╗ ██╗████████╗███████╗██████╗ ██████╗ ██████╗ ███████╗████████╗███████╗██████╗ +██║████╗ ██║╚══██╔══╝██╔════╝██╔══██╗██╔══██╗██╔══██╗██╔════╝╚══██╔══╝██╔════╝██╔══██╗ +██║██╔██╗ ██║ ██║ █████╗ ██████╔╝██████╔╝██████╔╝█████╗ ██║ █████╗ ██████╔╝ +██║██║╚██╗██║ ██║ ██╔══╝ ██╔══██╗██╔═══╝ ██╔══██╗██╔══╝ ██║ ██╔══╝ ██╔══██╗ +██║██║ ╚████║ ██║ ███████╗██║ ██║██║ ██║ ██║███████╗ ██║ ███████╗██║ ██║ +╚═╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ +*/ void @@ -565,7 +646,7 @@ main(void) } expression = text_to_expression(line); joy(&stack, &expression); - print_list(stack); + print_stack(stack); printf("\n"); } return 0; diff --git a/implementations/C/notes b/implementations/C/notes index f1a809a..36646a6 100644 --- a/implementations/C/notes +++ b/implementations/C/notes @@ -35,4 +35,4 @@ the comparison functions as definitions: lt [false] [false] [true] cmp neq [true] [false] [true] cmp le [false] [true] [true] cmp - ge [true] [true] [false] cmp \ No newline at end of file + ge [true] [true] [false] cmp