Can haz function pointers in my worldist.
This commit is contained in:
parent
cd98e01efc
commit
fb40b11fb0
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
const char *
|
||||
in_word_set (register const char *str, register size_t len);
|
||||
Loading…
Reference in New Issue