From fb40b11fb0ce3e3cb170bc9d6659a7e98151951c Mon Sep 17 00:00:00 2001 From: Simon Forman Date: Fri, 3 Feb 2023 08:13:57 -0800 Subject: [PATCH] Can haz function pointers in my worldist. --- implementations/C/KEYWORDS.txt | 48 +++++----- implementations/C/Makefile | 15 ++- implementations/C/joy.c | 58 +++++------- implementations/C/joy.h | 75 +++++++++++++++ implementations/C/keywords.c | 163 +++++++++++++++++---------------- implementations/C/keywords.h | 3 - 6 files changed, 215 insertions(+), 147 deletions(-) create mode 100644 implementations/C/joy.h delete mode 100644 implementations/C/keywords.h diff --git a/implementations/C/KEYWORDS.txt b/implementations/C/KEYWORDS.txt index 8e4d2c3..50e2cf1 100644 --- a/implementations/C/KEYWORDS.txt +++ b/implementations/C/KEYWORDS.txt @@ -1,29 +1,23 @@ %compare-strncmp +%readonly-tables +%struct-type +%{ +#include "joy.h" +%} +struct dict_entry; %% -!= -"%" -* -+ -- -/ -< -<= -<> -= -> ->= -bool -branch -clear -concat -cons -dip -dup -first -i -loop -pop -rest -stack -swaack -swap +!=, neq +"%", mod +*, mul ++, add +-, sub +/, div_joyfunc +<, lt +<=, le +<>, neq +=, eq +>, gt +>=, ge +bool, truthy +branch, branch +clear, clear diff --git a/implementations/C/Makefile b/implementations/C/Makefile index 2a135db..6f3a6fc 100644 --- a/implementations/C/Makefile +++ b/implementations/C/Makefile @@ -1,19 +1,24 @@ OBJS=joy.o keywords.o STATIC_GCLIB=/usr/local/lib/libgc.a /usr/local/lib/libgmp.a + CFLAGS = -ansi -Wall -Wextra -Werror -pedantic -Wstrict-overflow -fno-strict-aliasing -pedantic-errors -I/usr/local/include + #COPTS=-I/usr/local/include # $(STATIC_GCLIB) -GPERF_OPTS = --readonly-tables --enum --includes --global-table +GPERF_OPTS = --readonly-tables --enum --includes +#--global-table joy: ${OBJS} $(STATIC_GCLIB) -keywords.c: KEYWORDS.txt keywords.h - gperf --output-file=$@ --hash-function-name=keyword_hash $(GPERF_OPTS) KEYWORDS.txt +# Gperf doesn't add anything to '{""}' unused entries in the worlist. +# This causes "warning: missing field 'func' initializer [-Wmissing-field-initializers]" +# But we can turn off that warning for this here: +keywords.o: CFLAGS+=-Wno-missing-field-initializers -# keywords.c doesn't strictly depend on keywords.h, but I want make to -# remake if keywords.h is touched. +keywords.c: KEYWORDS.txt + gperf --output-file=$@ --hash-function-name=keyword_hash $(GPERF_OPTS) KEYWORDS.txt clean: rm -vf *.o diff --git a/implementations/C/joy.c b/implementations/C/joy.c index fa227bc..0912b2b 100644 --- a/implementations/C/joy.c +++ b/implementations/C/joy.c @@ -25,7 +25,7 @@ along with Thun. If not see . #include #include -#include "keywords.h" +#include "joy.h" const char *BLANKS = " \t"; @@ -33,37 +33,12 @@ const char *FALSE = "false"; const char *TRUE = "true"; -enum JoyTypeType { - joySymbol, - joyTrue, - joyFalse, - joyInt, - joyList -}; - -typedef struct list_node* JoyList; - -typedef struct { - enum JoyTypeType kind; - union { - int boolean; - mpz_t i; - JoyList el; - char *symbol; - } value; -} JoyType; - - -struct list_node { - JoyType head; /* Should this be a pointer? */ - JoyList tail; -}; - -#define EMPTY_LIST (JoyList)NULL - - - +/* +void +dup(JoyList *stack, JoyList *expression) { +} +*/ void* @@ -157,14 +132,14 @@ make_non_list_node(char *text, size_t size) { struct list_node *node; char *sym; - const char *interned; + const struct dict_entry *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; + node->head.value.symbol = interned->name; return node; } @@ -340,6 +315,23 @@ text_to_expression(char *text) return result; } + +void add(JoyList *stack, JoyList *expression) {stack = expression;} +void branch(JoyList *stack, JoyList *expression) {stack = expression;} +void clear(JoyList *stack, JoyList *expression) {stack = expression;} +void div_joyfunc(JoyList *stack, JoyList *expression) {stack = expression;} +void eq(JoyList *stack, JoyList *expression) {stack = expression;} +void ge(JoyList *stack, JoyList *expression) {stack = expression;} +void gt(JoyList *stack, JoyList *expression) {stack = expression;} +void le(JoyList *stack, JoyList *expression) {stack = expression;} +void lt(JoyList *stack, JoyList *expression) {stack = expression;} +void mod(JoyList *stack, JoyList *expression) {stack = expression;} +void mul(JoyList *stack, JoyList *expression) {stack = expression;} +void neq(JoyList *stack, JoyList *expression) {stack = expression;} +void sub(JoyList *stack, JoyList *expression) {stack = expression;} +void truthy(JoyList *stack, JoyList *expression) {stack = expression;} + + int main(void) { diff --git a/implementations/C/joy.h b/implementations/C/joy.h new file mode 100644 index 0000000..c05ada1 --- /dev/null +++ b/implementations/C/joy.h @@ -0,0 +1,75 @@ +/* +Copyright © 2023 Simon Forman + +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 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 . + +*/ +#include + + +enum JoyTypeType { + joySymbol, + joyTrue, + joyFalse, + joyInt, + joyList +}; + +typedef struct list_node* JoyList; +typedef JoyList* JoyListPtr; + +typedef struct { + enum JoyTypeType kind; + union { + int boolean; + mpz_t i; + JoyList el; + char *symbol; + } value; +} JoyType; + + +struct list_node { + JoyType head; /* Should this be a pointer? */ + JoyList tail; +}; + +#define EMPTY_LIST (JoyList)NULL + + +typedef void (*JoyFunc)(struct list_node**, struct list_node**); + + +void add(JoyList *stack, JoyList *expression); +void branch(JoyList *stack, JoyList *expression); +void clear(JoyList *stack, JoyList *expression); +void div_joyfunc(JoyList *stack, JoyList *expression); +void eq(JoyList *stack, JoyList *expression); +void ge(JoyList *stack, JoyList *expression); +void gt(JoyList *stack, JoyList *expression); +void le(JoyList *stack, JoyList *expression); +void lt(JoyList *stack, JoyList *expression); +void mod(JoyList *stack, JoyList *expression); +void mul(JoyList *stack, JoyList *expression); +void neq(JoyList *stack, JoyList *expression); +void sub(JoyList *stack, JoyList *expression); +void truthy(JoyList *stack, JoyList *expression); + + +struct dict_entry { char *name; JoyFunc func; }; + +const struct dict_entry * +in_word_set (register const char *str, register size_t len); diff --git a/implementations/C/keywords.c b/implementations/C/keywords.c index 5373008..af621da 100644 --- a/implementations/C/keywords.c +++ b/implementations/C/keywords.c @@ -1,5 +1,5 @@ /* ANSI-C code produced by gperf version 3.1 */ -/* Command-line: gperf --output-file=keywords.c --hash-function-name=keyword_hash --readonly-tables --enum --includes --global-table KEYWORDS.txt */ +/* Command-line: gperf --output-file=keywords.c --hash-function-name=keyword_hash --readonly-tables --enum --includes KEYWORDS.txt */ /* Computed positions: -k'1-2' */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -29,17 +29,13 @@ #error "gperf generated tables don't work with this execution character set. Please report a bug to ." #endif -#include -enum - { - TOTAL_KEYWORDS = 27, - MIN_WORD_LENGTH = 1, - MAX_WORD_LENGTH = 6, - MIN_HASH_VALUE = 1, - MAX_HASH_VALUE = 37 - }; +#line 4 "KEYWORDS.txt" -/* maximum key range = 37, duplicates = 0 */ +#include "joy.h" +#line 7 "KEYWORDS.txt" +struct dict_entry; +#include +/* maximum key range = 22, duplicates = 0 */ #ifdef __GNUC__ __inline @@ -53,32 +49,32 @@ keyword_hash (register const char *str, register size_t len) { static const unsigned char asso_values[] = { - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 30, 38, 38, 38, 31, 38, 38, - 38, 38, 26, 21, 38, 1, 38, 3, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 10, 5, 0, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 15, 5, - 0, 15, 0, 38, 38, 25, 38, 38, 0, 38, - 38, 5, 0, 38, 10, 10, 0, 0, 38, 5, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, - 38, 38, 38, 38, 38, 38 + 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 }; register unsigned int hval = len; @@ -94,58 +90,67 @@ keyword_hash (register const char *str, register size_t len) return hval; } -static const char * const wordlist[] = - { - "", - ">", - "-", - "dup", - "/", - "", - "=", - ">=", - "pop", - "loop", - "clear", - "<", - "<>", - "", - "cons", - "stack", - "concat", - "<=", - "", - "swap", - "", - "swaack", - "+", - "", - "bool", - "", - "i", - "*", - "dip", - "rest", - "first", - "branch", - "%", - "", "", "", "", - "!=" - }; - -const char * +const struct dict_entry * in_word_set (register const char *str, register size_t len) { + enum + { + TOTAL_KEYWORDS = 15, + MIN_WORD_LENGTH = 1, + MAX_WORD_LENGTH = 6, + MIN_HASH_VALUE = 1, + MAX_HASH_VALUE = 22 + }; + + 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}, +#line 16 "KEYWORDS.txt" + {"<=", le}, + {""}, {""}, {""}, {""}, +#line 9 "KEYWORDS.txt" + {"!=", neq} + }; + if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) { register unsigned int key = keyword_hash (str, len); if (key <= MAX_HASH_VALUE) { - register const char *s = wordlist[key]; + register const char *s = wordlist[key].name; if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0') - return s; + return &wordlist[key]; } } return 0; diff --git a/implementations/C/keywords.h b/implementations/C/keywords.h deleted file mode 100644 index 7fbb7ac..0000000 --- a/implementations/C/keywords.h +++ /dev/null @@ -1,3 +0,0 @@ - -const char * -in_word_set (register const char *str, register size_t len);