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);