Can haz function pointers in my worldist.
This commit is contained in:
parent
cd98e01efc
commit
fb40b11fb0
|
|
@ -1,29 +1,23 @@
|
||||||
%compare-strncmp
|
%compare-strncmp
|
||||||
|
%readonly-tables
|
||||||
|
%struct-type
|
||||||
|
%{
|
||||||
|
#include "joy.h"
|
||||||
|
%}
|
||||||
|
struct dict_entry;
|
||||||
%%
|
%%
|
||||||
!=
|
!=, neq
|
||||||
"%"
|
"%", mod
|
||||||
*
|
*, mul
|
||||||
+
|
+, add
|
||||||
-
|
-, sub
|
||||||
/
|
/, div_joyfunc
|
||||||
<
|
<, lt
|
||||||
<=
|
<=, le
|
||||||
<>
|
<>, neq
|
||||||
=
|
=, eq
|
||||||
>
|
>, gt
|
||||||
>=
|
>=, ge
|
||||||
bool
|
bool, truthy
|
||||||
branch
|
branch, branch
|
||||||
clear
|
clear, clear
|
||||||
concat
|
|
||||||
cons
|
|
||||||
dip
|
|
||||||
dup
|
|
||||||
first
|
|
||||||
i
|
|
||||||
loop
|
|
||||||
pop
|
|
||||||
rest
|
|
||||||
stack
|
|
||||||
swaack
|
|
||||||
swap
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,24 @@
|
||||||
OBJS=joy.o keywords.o
|
OBJS=joy.o keywords.o
|
||||||
STATIC_GCLIB=/usr/local/lib/libgc.a /usr/local/lib/libgmp.a
|
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
|
CFLAGS = -ansi -Wall -Wextra -Werror -pedantic -Wstrict-overflow -fno-strict-aliasing -pedantic-errors -I/usr/local/include
|
||||||
|
|
||||||
#COPTS=-I/usr/local/include
|
#COPTS=-I/usr/local/include
|
||||||
# $(STATIC_GCLIB)
|
# $(STATIC_GCLIB)
|
||||||
|
|
||||||
GPERF_OPTS = --readonly-tables --enum --includes --global-table
|
GPERF_OPTS = --readonly-tables --enum --includes
|
||||||
|
#--global-table
|
||||||
|
|
||||||
|
|
||||||
joy: ${OBJS} $(STATIC_GCLIB)
|
joy: ${OBJS} $(STATIC_GCLIB)
|
||||||
|
|
||||||
keywords.c: KEYWORDS.txt keywords.h
|
# Gperf doesn't add anything to '{""}' unused entries in the worlist.
|
||||||
gperf --output-file=$@ --hash-function-name=keyword_hash $(GPERF_OPTS) KEYWORDS.txt
|
# 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
|
keywords.c: KEYWORDS.txt
|
||||||
# remake if keywords.h is touched.
|
gperf --output-file=$@ --hash-function-name=keyword_hash $(GPERF_OPTS) KEYWORDS.txt
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -vf *.o
|
rm -vf *.o
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ along with Thun. If not see <http://www.gnu.org/licenses/>.
|
||||||
#include <gc.h>
|
#include <gc.h>
|
||||||
#include <gmp.h>
|
#include <gmp.h>
|
||||||
|
|
||||||
#include "keywords.h"
|
#include "joy.h"
|
||||||
|
|
||||||
|
|
||||||
const char *BLANKS = " \t";
|
const char *BLANKS = " \t";
|
||||||
|
|
@ -33,37 +33,12 @@ const char *FALSE = "false";
|
||||||
const char *TRUE = "true";
|
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*
|
void*
|
||||||
|
|
@ -157,14 +132,14 @@ make_non_list_node(char *text, size_t size)
|
||||||
{
|
{
|
||||||
struct list_node *node;
|
struct list_node *node;
|
||||||
char *sym;
|
char *sym;
|
||||||
const char *interned;
|
const struct dict_entry *interned;
|
||||||
|
|
||||||
node = GC_malloc(sizeof(struct list_node));
|
node = GC_malloc(sizeof(struct list_node));
|
||||||
|
|
||||||
interned = in_word_set(text, size);
|
interned = in_word_set(text, size);
|
||||||
if (interned) {
|
if (interned) {
|
||||||
node->head.kind = joySymbol;
|
node->head.kind = joySymbol;
|
||||||
node->head.value.symbol = (char *)interned;
|
node->head.value.symbol = interned->name;
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -340,6 +315,23 @@ text_to_expression(char *text)
|
||||||
return result;
|
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
|
int
|
||||||
main(void)
|
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 */
|
/* 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' */
|
/* Computed positions: -k'1-2' */
|
||||||
|
|
||||||
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
|
#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>."
|
#error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gperf@gnu.org>."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#line 4 "KEYWORDS.txt"
|
||||||
enum
|
|
||||||
{
|
|
||||||
TOTAL_KEYWORDS = 27,
|
|
||||||
MIN_WORD_LENGTH = 1,
|
|
||||||
MAX_WORD_LENGTH = 6,
|
|
||||||
MIN_HASH_VALUE = 1,
|
|
||||||
MAX_HASH_VALUE = 37
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 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__
|
#ifdef __GNUC__
|
||||||
__inline
|
__inline
|
||||||
|
|
@ -53,32 +49,32 @@ keyword_hash (register const char *str, register size_t len)
|
||||||
{
|
{
|
||||||
static const unsigned char asso_values[] =
|
static const unsigned char asso_values[] =
|
||||||
{
|
{
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 30, 38, 38, 38, 31, 38, 38,
|
23, 23, 23, 15, 23, 23, 23, 2, 23, 23,
|
||||||
38, 38, 26, 21, 38, 1, 38, 3, 38, 38,
|
23, 23, 13, 3, 23, 14, 23, 9, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
10, 5, 0, 38, 38, 38, 38, 38, 38, 38,
|
10, 5, 0, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 15, 5,
|
23, 23, 23, 23, 23, 23, 23, 23, 5, 0,
|
||||||
0, 15, 0, 38, 38, 25, 38, 38, 0, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 0, 23,
|
||||||
38, 5, 0, 38, 10, 10, 0, 0, 38, 5,
|
23, 0, 23, 23, 5, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38, 38, 38, 38, 38,
|
23, 23, 23, 23, 23, 23, 23, 23, 23, 23,
|
||||||
38, 38, 38, 38, 38, 38
|
23, 23, 23, 23, 23, 23
|
||||||
};
|
};
|
||||||
register unsigned int hval = len;
|
register unsigned int hval = len;
|
||||||
|
|
||||||
|
|
@ -94,58 +90,67 @@ keyword_hash (register const char *str, register size_t len)
|
||||||
return hval;
|
return hval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char * const wordlist[] =
|
const struct dict_entry *
|
||||||
{
|
|
||||||
"",
|
|
||||||
">",
|
|
||||||
"-",
|
|
||||||
"dup",
|
|
||||||
"/",
|
|
||||||
"",
|
|
||||||
"=",
|
|
||||||
">=",
|
|
||||||
"pop",
|
|
||||||
"loop",
|
|
||||||
"clear",
|
|
||||||
"<",
|
|
||||||
"<>",
|
|
||||||
"",
|
|
||||||
"cons",
|
|
||||||
"stack",
|
|
||||||
"concat",
|
|
||||||
"<=",
|
|
||||||
"",
|
|
||||||
"swap",
|
|
||||||
"",
|
|
||||||
"swaack",
|
|
||||||
"+",
|
|
||||||
"",
|
|
||||||
"bool",
|
|
||||||
"",
|
|
||||||
"i",
|
|
||||||
"*",
|
|
||||||
"dip",
|
|
||||||
"rest",
|
|
||||||
"first",
|
|
||||||
"branch",
|
|
||||||
"%",
|
|
||||||
"", "", "", "",
|
|
||||||
"!="
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *
|
|
||||||
in_word_set (register const char *str, register size_t len)
|
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)
|
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
||||||
{
|
{
|
||||||
register unsigned int key = keyword_hash (str, len);
|
register unsigned int key = keyword_hash (str, len);
|
||||||
|
|
||||||
if (key <= MAX_HASH_VALUE)
|
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')
|
if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
|
||||||
return s;
|
return &wordlist[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
const char *
|
|
||||||
in_word_set (register const char *str, register size_t len);
|
|
||||||
Loading…
Reference in New Issue