Can haz function pointers in my worldist.

This commit is contained in:
Simon Forman 2023-02-03 08:13:57 -08:00
parent cd98e01efc
commit fb40b11fb0
6 changed files with 215 additions and 147 deletions

View File

@ -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

View File

@ -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

View File

@ -25,7 +25,7 @@ along with Thun. If not see <http://www.gnu.org/licenses/>.
#include <gc.h>
#include <gmp.h>
#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)
{

75
implementations/C/joy.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <gmp.h>
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);

View File

@ -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 <bug-gperf@gnu.org>."
#endif
#include <string.h>
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 <string.h>
/* 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;

View File

@ -1,3 +0,0 @@
const char *
in_word_set (register const char *str, register size_t len);