From 4be1cc576767187259394869d18cb159ee294f91 Mon Sep 17 00:00:00 2001 From: Simon Forman Date: Thu, 2 Feb 2023 16:58:44 -0800 Subject: [PATCH] Use gperf to save memory. We check terms to see if they're in the wordlist, if they are we reuse the string from the wordlist instead of allocating a new one. (I've always wanted to use Gperf so I'm pretty stoked about this!) --- implementations/C/KEYWORDS.txt | 2 + implementations/C/Makefile | 4 +- implementations/C/joy.c | 89 +++++++++++++++------------------- implementations/C/keywords.c | 2 +- implementations/C/keywords.h | 3 ++ 5 files changed, 47 insertions(+), 53 deletions(-) create mode 100644 implementations/C/keywords.h diff --git a/implementations/C/KEYWORDS.txt b/implementations/C/KEYWORDS.txt index 1c7c7fc..8e4d2c3 100644 --- a/implementations/C/KEYWORDS.txt +++ b/implementations/C/KEYWORDS.txt @@ -1,3 +1,5 @@ +%compare-strncmp +%% != "%" * diff --git a/implementations/C/Makefile b/implementations/C/Makefile index cce0acb..35ba6e1 100644 --- a/implementations/C/Makefile +++ b/implementations/C/Makefile @@ -9,6 +9,8 @@ GPERF_OPTS = --readonly-tables --enum --includes --global-table joy: ${OBJS} $(STATIC_GCLIB) -keywords.c: KEYWORDS.txt +keywords.c: KEYWORDS.txt keywords.h gperf --output-file=$@ --hash-function-name=keyword_hash $(GPERF_OPTS) KEYWORDS.txt +# keywords.c doesn't strictly depend on keywords.h, but I want make to +# remake if keywords.h is touched. diff --git a/implementations/C/joy.c b/implementations/C/joy.c index 62a8b82..f28a558 100644 --- a/implementations/C/joy.c +++ b/implementations/C/joy.c @@ -1,55 +1,20 @@ /* - Copyright © 2023 Simon Forman +Copyright © 2023 Simon Forman - This file is part of Thun +This file is part of Thun - Thun is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. +Thun is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. - Thun is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. +Thun is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with Thun. If not see . - - -████████╗██╗ ██╗██╗ ██╗███╗ ██╗ -╚══██╔══╝██║ ██║██║ ██║████╗ ██║ - ██║ ███████║██║ ██║██╔██╗ ██║ - ██║ ██╔══██║██║ ██║██║╚██╗██║ - ██║ ██║ ██║╚██████╔╝██║ ╚████║ - ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══╝ - -This program implements an interpreter for a dialect of Joy. - -Joy is a programming language created by Manfred von Thun that is easy to -use and understand and has many other nice properties. This Python -package implements an interpreter for a dialect of Joy that attempts to -stay very close to the spirit of Joy but does not precisely match the -behaviour of the original version(s) written in C. The main difference -between Thun and the originals, other than being written in Python, is -that it works by the “Continuation-Passing Style”. - -Here is an example of Joy code: - - - [ [[abs] ii <=] - [ - [<>] [pop !-] || - ] && - ] - [[ !-] [[++]] [[--]] ifte dip] - [[pop !-] [--] [++] ifte ] - ifte - -This function accepts two integers on the stack and increments or -decrements one of them such that the new pair of numbers is the next -coordinate pair in a square spiral (like the kind used to construct an -Ulam Spiral). +You should have received a copy of the GNU General Public License +along with Thun. If not see . */ #include @@ -60,6 +25,8 @@ Ulam Spiral). #include #include +# include "keywords.h" + const char *BLANKS = " \t"; const char *FALSE = "false"; @@ -92,6 +59,9 @@ struct list_node { } JoyList; +#define EMPTY_LIST (struct list_node*)NULL + + void* reallocate_function (void *ptr, __attribute__((unused)) size_t old_size, size_t new_size) { return GC_REALLOC(ptr, new_size); @@ -184,12 +154,20 @@ make_non_list_node(char *text, size_t size) { struct list_node *node; char *sym; + const char *interned; + + node = GC_malloc(sizeof(struct list_node)); + + interned = in_word_set(text, size); + if (interned) { + node->head.kind = joySymbol; + node->head.value.symbol = (char *)interned; + return node; + } sym = GC_malloc(size + 1); /* one more for the zero, right? */ strncat(sym, text, size); - node = GC_malloc(sizeof(struct list_node)); - if (!strncmp(sym, FALSE, 6)) { /* I know it's wrong to hardcode the length here. Sorry. */ /* If head was a pointer we could reuse Boolean singletons... */ node->head.kind = joyFalse; @@ -225,14 +203,23 @@ make_list_node(struct list_node *el) return node; } -#define EMPTY_LIST (struct list_node*)NULL /* -Extract terms from the text until a closing bracket is found. +██████╗ █████╗ ██████╗ ███████╗███████╗██████╗ +██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔════╝██╔══██╗ +██████╔╝███████║██████╔╝███████╗█████╗ ██████╔╝ +██╔═══╝ ██╔══██║██╔══██╗╚════██║██╔══╝ ██╔══██╗ +██║ ██║ ██║██║ ██║███████║███████╗██║ ██║ +╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝ */ + + struct list_node* parse_list(char **text) { +/* +Extract terms from the text until a closing bracket is found. +*/ char *rest; ptrdiff_t diff; struct list_node *result = NULL; diff --git a/implementations/C/keywords.c b/implementations/C/keywords.c index 614aba1..5373008 100644 --- a/implementations/C/keywords.c +++ b/implementations/C/keywords.c @@ -144,7 +144,7 @@ in_word_set (register const char *str, register size_t len) { register const char *s = wordlist[key]; - if (*str == *s && !strcmp (str + 1, s + 1)) + if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') return s; } } diff --git a/implementations/C/keywords.h b/implementations/C/keywords.h new file mode 100644 index 0000000..7fbb7ac --- /dev/null +++ b/implementations/C/keywords.h @@ -0,0 +1,3 @@ + +const char * +in_word_set (register const char *str, register size_t len);