From 085fdb6a950e2440910164c1b6a41ebb3db93f2c Mon Sep 17 00:00:00 2001 From: Zander Thannhauser Date: Sat, 25 Apr 2026 16:00:10 -0400 Subject: [PATCH] exploded out the source code --- .gitignore | 2 + avl/avl.c | 596 ++++++++++++++++++++++ avl/avl.h | 186 +++++++ calculate.c | 0 calculate.h | 0 cmdln/free.c | 11 + cmdln/free.h | 5 + cmdln/print_usage.c | 9 + cmdln/print_usage.h | 3 + cmdln/process.c | 254 +++++++++ cmdln/process.h | 4 + cmdln/struct.h | 54 ++ debug.c | 4 + debug.h | 46 ++ defines/M.h | 2 + defines/N.h | 1 + defines/W.h | 1 + defines/X.h | 1 + defines/Y.h | 1 + defines/Z.h | 1 + expression/and/evaluate.c | 0 expression/and/evaluate.h | 0 expression/and/free.c | 11 + expression/and/free.h | 5 + expression/and/inheritance.c | 11 + expression/and/inheritance.h | 5 + expression/and/new.c | 27 + expression/and/new.h | 5 + expression/and/print.c | 16 + expression/and/print.h | 3 + expression/and/struct.h | 12 + expression/evaluate.c | 0 expression/evaluate.h | 0 expression/free.c | 25 + expression/free.h | 3 + expression/inc.c | 17 + expression/inc.h | 3 + expression/inheritance.h | 12 + expression/literal/evaluate.c | 0 expression/literal/evaluate.h | 0 expression/literal/free.c | 11 + expression/literal/free.h | 3 + expression/literal/inheritance.c | 11 + expression/literal/inheritance.h | 5 + expression/literal/new.c | 26 + expression/literal/new.h | 4 + expression/literal/print.c | 21 + expression/literal/print.h | 3 + expression/literal/struct.h | 10 + expression/new.c | 22 + expression/new.h | 7 + expression/not/evaluate.c | 0 expression/not/evaluate.h | 0 expression/not/free.c | 11 + expression/not/free.h | 5 + expression/not/inheritance.c | 11 + expression/not/inheritance.h | 5 + expression/not/new.c | 25 + expression/not/new.h | 4 + expression/not/print.c | 16 + expression/not/print.h | 3 + expression/not/struct.h | 10 + expression/or/evaluate.c | 0 expression/or/evaluate.h | 0 expression/or/free.c | 11 + expression/or/free.h | 5 + expression/or/inheritance.c | 11 + expression/or/inheritance.h | 5 + expression/or/new.c | 27 + expression/or/new.h | 5 + expression/or/print.c | 16 + expression/or/print.h | 3 + expression/or/struct.h | 12 + expression/print.c | 17 + expression/print.h | 5 + expression/struct.h | 12 + expression/unreachable/evaluate.c | 0 expression/unreachable/evaluate.h | 0 expression/unreachable/free.c | 11 + expression/unreachable/free.h | 3 + expression/unreachable/inheritance.c | 11 + expression/unreachable/inheritance.h | 5 + expression/unreachable/new.c | 23 + expression/unreachable/new.h | 2 + expression/unreachable/print.c | 11 + expression/unreachable/print.h | 3 + expression/unreachable/struct.h | 8 + expression/variable/evaluate.c | 0 expression/variable/evaluate.h | 0 expression/variable/free.c | 11 + expression/variable/free.h | 3 + expression/variable/inheritance.c | 11 + expression/variable/inheritance.h | 5 + expression/variable/new.c | 27 + expression/variable/new.h | 4 + expression/variable/print.c | 16 + expression/variable/print.h | 3 + expression/variable/struct.h | 10 + flake.nix | 5 +- main.c | 241 ++------- memory/smalloc.c | 19 + memory/smalloc.h | 2 + misc/sat_add.c | 30 ++ misc/sat_add.h | 3 + parse.c | 0 parse.h | 0 python/__pycache__/build.cpython-312.pyc | Bin 0 -> 3183 bytes python/__pycache__/run.cpython-312.pyc | Bin 0 -> 1220 bytes python/__pycache__/sha256.cpython-312.pyc | Bin 0 -> 1027 bytes python/build.py | 143 ++++++ python/run.py | 26 + python/sha256.py | 13 + repl/repl.c | 0 repl/repl.h | 0 result | 1 + run | 86 ++++ scope/assign.c | 0 scope/assign.h | 0 scope/declare.c | 0 scope/declare.h | 0 scope/foreach.c | 30 ++ scope/foreach.h | 6 + scope/free.c | 8 + scope/free.h | 2 + scope/has.c | 0 scope/has.h | 0 scope/lookup.c | 0 scope/lookup.h | 0 scope/new.c | 96 ++++ scope/new.h | 2 + scope/struct.h | 6 + scope/variable/compare.c | 21 + scope/variable/compare.h | 2 + scope/variable/free.c | 10 + scope/variable/free.h | 2 + scope/variable/new.c | 22 + scope/variable/new.h | 4 + scope/variable/struct.h | 8 + simplifications/free.c | 13 + simplifications/free.h | 5 + simplifications/lookup.c | 0 simplifications/lookup.h | 0 simplifications/new.c | 246 +++++++++ simplifications/new.h | 7 + simplifications/struct.h | 10 + string/compare.c | 13 + string/compare.h | 4 + string/free.c | 15 + string/free.h | 3 + string/inc.c | 17 + string/inc.h | 3 + string/new.c | 27 + string/new.h | 3 + string/print.c | 12 + string/print.h | 3 + string/struct.h | 9 + structs/operators.h | 12 + test | 8 + truthtable_set/add.c | 36 ++ truthtable_set/add.h | 4 + truthtable_set/discard.c | 32 ++ truthtable_set/discard.h | 4 + truthtable_set/foreach.c | 19 + truthtable_set/foreach.h | 6 + truthtable_set/free.c | 11 + truthtable_set/free.h | 5 + truthtable_set/is_empty.c | 14 + truthtable_set/is_empty.h | 3 + truthtable_set/new.c | 39 ++ truthtable_set/new.h | 2 + truthtable_set/struct.h | 10 + typedefs/truthtable_t.h | 5 + 172 files changed, 3039 insertions(+), 194 deletions(-) create mode 100644 avl/avl.c create mode 100644 avl/avl.h create mode 100644 calculate.c create mode 100644 calculate.h create mode 100644 cmdln/free.c create mode 100644 cmdln/free.h create mode 100644 cmdln/print_usage.c create mode 100644 cmdln/print_usage.h create mode 100644 cmdln/process.c create mode 100644 cmdln/process.h create mode 100644 cmdln/struct.h create mode 100644 debug.c create mode 100644 debug.h create mode 100644 defines/M.h create mode 100644 defines/N.h create mode 100644 defines/W.h create mode 100644 defines/X.h create mode 100644 defines/Y.h create mode 100644 defines/Z.h create mode 100644 expression/and/evaluate.c create mode 100644 expression/and/evaluate.h create mode 100644 expression/and/free.c create mode 100644 expression/and/free.h create mode 100644 expression/and/inheritance.c create mode 100644 expression/and/inheritance.h create mode 100644 expression/and/new.c create mode 100644 expression/and/new.h create mode 100644 expression/and/print.c create mode 100644 expression/and/print.h create mode 100644 expression/and/struct.h create mode 100644 expression/evaluate.c create mode 100644 expression/evaluate.h create mode 100644 expression/free.c create mode 100644 expression/free.h create mode 100644 expression/inc.c create mode 100644 expression/inc.h create mode 100644 expression/inheritance.h create mode 100644 expression/literal/evaluate.c create mode 100644 expression/literal/evaluate.h create mode 100644 expression/literal/free.c create mode 100644 expression/literal/free.h create mode 100644 expression/literal/inheritance.c create mode 100644 expression/literal/inheritance.h create mode 100644 expression/literal/new.c create mode 100644 expression/literal/new.h create mode 100644 expression/literal/print.c create mode 100644 expression/literal/print.h create mode 100644 expression/literal/struct.h create mode 100644 expression/new.c create mode 100644 expression/new.h create mode 100644 expression/not/evaluate.c create mode 100644 expression/not/evaluate.h create mode 100644 expression/not/free.c create mode 100644 expression/not/free.h create mode 100644 expression/not/inheritance.c create mode 100644 expression/not/inheritance.h create mode 100644 expression/not/new.c create mode 100644 expression/not/new.h create mode 100644 expression/not/print.c create mode 100644 expression/not/print.h create mode 100644 expression/not/struct.h create mode 100644 expression/or/evaluate.c create mode 100644 expression/or/evaluate.h create mode 100644 expression/or/free.c create mode 100644 expression/or/free.h create mode 100644 expression/or/inheritance.c create mode 100644 expression/or/inheritance.h create mode 100644 expression/or/new.c create mode 100644 expression/or/new.h create mode 100644 expression/or/print.c create mode 100644 expression/or/print.h create mode 100644 expression/or/struct.h create mode 100644 expression/print.c create mode 100644 expression/print.h create mode 100644 expression/struct.h create mode 100644 expression/unreachable/evaluate.c create mode 100644 expression/unreachable/evaluate.h create mode 100644 expression/unreachable/free.c create mode 100644 expression/unreachable/free.h create mode 100644 expression/unreachable/inheritance.c create mode 100644 expression/unreachable/inheritance.h create mode 100644 expression/unreachable/new.c create mode 100644 expression/unreachable/new.h create mode 100644 expression/unreachable/print.c create mode 100644 expression/unreachable/print.h create mode 100644 expression/unreachable/struct.h create mode 100644 expression/variable/evaluate.c create mode 100644 expression/variable/evaluate.h create mode 100644 expression/variable/free.c create mode 100644 expression/variable/free.h create mode 100644 expression/variable/inheritance.c create mode 100644 expression/variable/inheritance.h create mode 100644 expression/variable/new.c create mode 100644 expression/variable/new.h create mode 100644 expression/variable/print.c create mode 100644 expression/variable/print.h create mode 100644 expression/variable/struct.h create mode 100644 memory/smalloc.c create mode 100644 memory/smalloc.h create mode 100644 misc/sat_add.c create mode 100644 misc/sat_add.h create mode 100644 parse.c create mode 100644 parse.h create mode 100644 python/__pycache__/build.cpython-312.pyc create mode 100644 python/__pycache__/run.cpython-312.pyc create mode 100644 python/__pycache__/sha256.cpython-312.pyc create mode 100644 python/build.py create mode 100644 python/run.py create mode 100644 python/sha256.py create mode 100644 repl/repl.c create mode 100644 repl/repl.h create mode 120000 result create mode 100755 run create mode 100644 scope/assign.c create mode 100644 scope/assign.h create mode 100644 scope/declare.c create mode 100644 scope/declare.h create mode 100644 scope/foreach.c create mode 100644 scope/foreach.h create mode 100644 scope/free.c create mode 100644 scope/free.h create mode 100644 scope/has.c create mode 100644 scope/has.h create mode 100644 scope/lookup.c create mode 100644 scope/lookup.h create mode 100644 scope/new.c create mode 100644 scope/new.h create mode 100644 scope/struct.h create mode 100644 scope/variable/compare.c create mode 100644 scope/variable/compare.h create mode 100644 scope/variable/free.c create mode 100644 scope/variable/free.h create mode 100644 scope/variable/new.c create mode 100644 scope/variable/new.h create mode 100644 scope/variable/struct.h create mode 100644 simplifications/free.c create mode 100644 simplifications/free.h create mode 100644 simplifications/lookup.c create mode 100644 simplifications/lookup.h create mode 100644 simplifications/new.c create mode 100644 simplifications/new.h create mode 100644 simplifications/struct.h create mode 100644 string/compare.c create mode 100644 string/compare.h create mode 100644 string/free.c create mode 100644 string/free.h create mode 100644 string/inc.c create mode 100644 string/inc.h create mode 100644 string/new.c create mode 100644 string/new.h create mode 100644 string/print.c create mode 100644 string/print.h create mode 100644 string/struct.h create mode 100644 structs/operators.h create mode 100644 test create mode 100644 truthtable_set/add.c create mode 100644 truthtable_set/add.h create mode 100644 truthtable_set/discard.c create mode 100644 truthtable_set/discard.h create mode 100644 truthtable_set/foreach.c create mode 100644 truthtable_set/foreach.h create mode 100644 truthtable_set/free.c create mode 100644 truthtable_set/free.h create mode 100644 truthtable_set/is_empty.c create mode 100644 truthtable_set/is_empty.h create mode 100644 truthtable_set/new.c create mode 100644 truthtable_set/new.h create mode 100644 truthtable_set/struct.h create mode 100644 typedefs/truthtable_t.h diff --git a/.gitignore b/.gitignore index 82c8caf..b60fc28 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ stats.ods bin/ typescript .main.c.swp +.build-cache/ +__pycache__ diff --git a/avl/avl.c b/avl/avl.c new file mode 100644 index 0000000..927379f --- /dev/null +++ b/avl/avl.c @@ -0,0 +1,596 @@ +/***************************************************************************** + + avl.c - Source code for the AVL-tree library. + + Copyright (C) 1998 Michael H. Buselli + Copyright (C) 2000-2002 Wessel Dankers + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Augmented AVL-tree. Original by Michael H. Buselli . + + Modified by Wessel Dankers to add a bunch of bloat to + the sourcecode, change the interface and squash a few bugs. + Mail him if you find new bugs. + +*****************************************************************************/ + +#include +#include +#include + +#include "avl.h" + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wconversion" + +static void avl_rebalance(avl_tree_t *, avl_node_t *); + +#ifdef AVL_COUNT +#define NODE_COUNT(n) ((n) ? (n)->count : 0) +#define L_COUNT(n) (NODE_COUNT((n)->left)) +#define R_COUNT(n) (NODE_COUNT((n)->right)) +#define CALC_COUNT(n) (L_COUNT(n) + R_COUNT(n) + 1) +#endif + +#ifdef AVL_DEPTH +#define NODE_DEPTH(n) ((n) ? (n)->depth : 0) +#define L_DEPTH(n) (NODE_DEPTH((n)->left)) +#define R_DEPTH(n) (NODE_DEPTH((n)->right)) +#define CALC_DEPTH(n) ((L_DEPTH(n)>R_DEPTH(n)?L_DEPTH(n):R_DEPTH(n)) + 1) +#endif + +#ifndef AVL_DEPTH +/* Also known as ffs() (from BSD) */ +static int lg(unsigned int u) { + int r = 1; + if(!u) return 0; + if(u & 0xffff0000) { u >>= 16; r += 16; } + if(u & 0x0000ff00) { u >>= 8; r += 8; } + if(u & 0x000000f0) { u >>= 4; r += 4; } + if(u & 0x0000000c) { u >>= 2; r += 2; } + if(u & 0x00000002) r++; + return r; +} +#endif + +static int avl_check_balance(avl_node_t *avlnode) { +#ifdef AVL_DEPTH + int d; + d = R_DEPTH(avlnode) - L_DEPTH(avlnode); + return d<-1?-1:d>1?1:0; +#else +/* int d; + * d = lg(R_COUNT(avlnode)) - lg(L_COUNT(avlnode)); + * d = d<-1?-1:d>1?1:0; + */ +#ifdef AVL_COUNT + int pl, r; + + pl = lg(L_COUNT(avlnode)); + r = R_COUNT(avlnode); + + if(r>>pl+1) + return 1; + if(pl<2 || r>>pl-2) + return 0; + return -1; +#else +#error No balancing possible. +#endif +#endif +} + +#ifdef AVL_COUNT +unsigned int avl_count(const avl_tree_t *avltree) { + return NODE_COUNT(avltree->top); +} + +avl_node_t *avl_at(const avl_tree_t *avltree, unsigned int index) { + avl_node_t *avlnode; + unsigned int c; + + avlnode = avltree->top; + + while(avlnode) { + c = L_COUNT(avlnode); + + if(index < c) { + avlnode = avlnode->left; + } else if(index > c) { + avlnode = avlnode->right; + index -= c+1; + } else { + return avlnode; + } + } + return NULL; +} + +unsigned int avl_index(const avl_node_t *avlnode) { + avl_node_t *next; + unsigned int c; + + c = L_COUNT(avlnode); + + while((next = avlnode->parent)) { + if(avlnode == next->right) + c += L_COUNT(next) + 1; + avlnode = next; + } + + return c; +} +#endif + +int avl_search_closest(const avl_tree_t *avltree, const void *item, avl_node_t **avlnode) { + avl_node_t *node; + avl_compare_t cmp; + int c; + + if(!avlnode) + avlnode = &node; + + node = avltree->top; + + if(!node) + return *avlnode = NULL, 0; + + cmp = avltree->cmp; + + for(;;) { + c = cmp(item, node->item); + + if(c < 0) { + if(node->left) + node = node->left; + else + return *avlnode = node, -1; + } else if(c > 0) { + if(node->right) + node = node->right; + else + return *avlnode = node, 1; + } else { + return *avlnode = node, 0; + } + } +} + +/* + * avl_search: + * Return a pointer to a node with the given item in the tree. + * If no such item is in the tree, then NULL is returned. + */ +avl_node_t *avl_search(const avl_tree_t *avltree, const void *item) { + avl_node_t *node; + return avl_search_closest(avltree, item, &node) ? NULL : node; +} + +avl_tree_t *avl_init_tree(avl_tree_t *rc, avl_compare_t cmp, avl_freeitem_t freeitem) { + if(rc) { + rc->head = NULL; + rc->tail = NULL; + rc->top = NULL; + rc->cmp = cmp; + rc->freeitem = freeitem; + } + return rc; +} + +avl_tree_t *avl_alloc_tree(avl_compare_t cmp, avl_freeitem_t freeitem) { + return avl_init_tree(malloc(sizeof(avl_tree_t)), cmp, freeitem); +} + +void avl_clear_tree(avl_tree_t *avltree) { + avltree->top = avltree->head = avltree->tail = NULL; +} + +void avl_free_nodes(avl_tree_t *avltree) { + avl_node_t *node, *next; + avl_freeitem_t freeitem; + + freeitem = avltree->freeitem; + + for(node = avltree->head; node; node = next) { + next = node->next; + if(freeitem) + freeitem(node->item); + free(node); + } + + avl_clear_tree(avltree); +} + +/* + * avl_free_tree: + * Free all memory used by this tree. If freeitem is not NULL, then + * it is assumed to be a destructor for the items referenced in the avl_ + * tree, and they are deleted as well. + */ +void avl_free_tree(avl_tree_t *avltree) { + avl_free_nodes(avltree); + free(avltree); +} + +static void avl_clear_node(avl_node_t *newnode) { + newnode->left = newnode->right = NULL; + #ifdef AVL_COUNT + newnode->count = 1; + #endif + #ifdef AVL_DEPTH + newnode->depth = 1; + #endif +} + +avl_node_t *avl_init_node(avl_node_t *newnode, void *item) { + if(newnode) { +/* avl_clear_node(newnode); */ + newnode->item = item; + } + return newnode; +} + +avl_node_t *avl_insert_top(avl_tree_t *avltree, avl_node_t *newnode) { + avl_clear_node(newnode); + newnode->prev = newnode->next = newnode->parent = NULL; + avltree->head = avltree->tail = avltree->top = newnode; + return newnode; +} + +avl_node_t *avl_insert_before(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode) { + if(!node) + return avltree->tail + ? avl_insert_after(avltree, avltree->tail, newnode) + : avl_insert_top(avltree, newnode); + + if(node->left) + return avl_insert_after(avltree, node->prev, newnode); + + avl_clear_node(newnode); + + newnode->next = node; + newnode->parent = node; + + newnode->prev = node->prev; + if(node->prev) + node->prev->next = newnode; + else + avltree->head = newnode; + node->prev = newnode; + + node->left = newnode; + avl_rebalance(avltree, node); + return newnode; +} + +avl_node_t *avl_insert_after(avl_tree_t *avltree, avl_node_t *node, avl_node_t *newnode) { + if(!node) + return avltree->head + ? avl_insert_before(avltree, avltree->head, newnode) + : avl_insert_top(avltree, newnode); + + if(node->right) + return avl_insert_before(avltree, node->next, newnode); + + avl_clear_node(newnode); + + newnode->prev = node; + newnode->parent = node; + + newnode->next = node->next; + if(node->next) + node->next->prev = newnode; + else + avltree->tail = newnode; + node->next = newnode; + + node->right = newnode; + avl_rebalance(avltree, node); + return newnode; +} + +avl_node_t *avl_insert_node(avl_tree_t *avltree, avl_node_t *newnode) { + avl_node_t *node; + + if(!avltree->top) + return avl_insert_top(avltree, newnode); + + switch(avl_search_closest(avltree, newnode->item, &node)) { + case -1: + return avl_insert_before(avltree, node, newnode); + case 1: + return avl_insert_after(avltree, node, newnode); + } + + return NULL; +} + +/* + * avl_insert: + * Create a new node and insert an item there. + * Returns the new node on success or NULL if no memory could be allocated. + */ +avl_node_t *avl_insert(avl_tree_t *avltree, void *item) { + avl_node_t *newnode; + + newnode = avl_init_node(malloc(sizeof(avl_node_t)), item); + if(newnode) { + if(avl_insert_node(avltree, newnode)) + return newnode; + free(newnode); + errno = EEXIST; + } + return NULL; +} + +/* + * avl_unlink_node: + * Removes the given node. Does not delete the item at that node. + * The item of the node may be freed before calling avl_unlink_node. + * (In other words, it is not referenced by this function.) + */ +void avl_unlink_node(avl_tree_t *avltree, avl_node_t *avlnode) { + avl_node_t *parent; + avl_node_t **superparent; + avl_node_t *subst, *left, *right; + avl_node_t *balnode; + + if(avlnode->prev) + avlnode->prev->next = avlnode->next; + else + avltree->head = avlnode->next; + + if(avlnode->next) + avlnode->next->prev = avlnode->prev; + else + avltree->tail = avlnode->prev; + + parent = avlnode->parent; + + superparent = parent + ? avlnode == parent->left ? &parent->left : &parent->right + : &avltree->top; + + left = avlnode->left; + right = avlnode->right; + if(!left) { + *superparent = right; + if(right) + right->parent = parent; + balnode = parent; + } else if(!right) { + *superparent = left; + left->parent = parent; + balnode = parent; + } else { + subst = avlnode->prev; + if(subst == left) { + balnode = subst; + } else { + balnode = subst->parent; + balnode->right = subst->left; + if(balnode->right) + balnode->right->parent = balnode; + subst->left = left; + left->parent = subst; + } + subst->right = right; + subst->parent = parent; + right->parent = subst; + *superparent = subst; + } + + avl_rebalance(avltree, balnode); +} + +void *avl_delete_node(avl_tree_t *avltree, avl_node_t *avlnode) { + void *item = NULL; + if(avlnode) { + item = avlnode->item; + avl_unlink_node(avltree, avlnode); + if(avltree->freeitem) + avltree->freeitem(item); + free(avlnode); + } + return item; +} + +void *avl_delete(avl_tree_t *avltree, const void *item) { + return avl_delete_node(avltree, avl_search(avltree, item)); +} + +avl_node_t *avl_fixup_node(avl_tree_t *avltree, avl_node_t *newnode) { + avl_node_t *oldnode = NULL, *node; + + if(!avltree || !newnode) + return NULL; + + node = newnode->prev; + if(node) { + oldnode = node->next; + node->next = newnode; + } else { + avltree->head = newnode; + } + + node = newnode->next; + if(node) { + oldnode = node->prev; + node->prev = newnode; + } else { + avltree->tail = newnode; + } + + node = newnode->parent; + if(node) { + if(node->left == oldnode) + node->left = newnode; + else + node->right = newnode; + } else { + oldnode = avltree->top; + avltree->top = newnode; + } + + return oldnode; +} + +/* + * avl_rebalance: + * Rebalances the tree if one side becomes too heavy. This function + * assumes that both subtrees are AVL-trees with consistant data. The + * function has the additional side effect of recalculating the count of + * the tree at this node. It should be noted that at the return of this + * function, if a rebalance takes place, the top of this subtree is no + * longer going to be the same node. + */ +void avl_rebalance(avl_tree_t *avltree, avl_node_t *avlnode) { + avl_node_t *child; + avl_node_t *gchild; + avl_node_t *parent; + avl_node_t **superparent; + + parent = avlnode; + + while(avlnode) { + parent = avlnode->parent; + + superparent = parent + ? avlnode == parent->left ? &parent->left : &parent->right + : &avltree->top; + + switch(avl_check_balance(avlnode)) { + case -1: + child = avlnode->left; + #ifdef AVL_DEPTH + if(L_DEPTH(child) >= R_DEPTH(child)) { + #else + #ifdef AVL_COUNT + if(L_COUNT(child) >= R_COUNT(child)) { + #else + #error No balancing possible. + #endif + #endif + avlnode->left = child->right; + if(avlnode->left) + avlnode->left->parent = avlnode; + child->right = avlnode; + avlnode->parent = child; + *superparent = child; + child->parent = parent; + #ifdef AVL_COUNT + avlnode->count = CALC_COUNT(avlnode); + child->count = CALC_COUNT(child); + #endif + #ifdef AVL_DEPTH + avlnode->depth = CALC_DEPTH(avlnode); + child->depth = CALC_DEPTH(child); + #endif + } else { + gchild = child->right; + avlnode->left = gchild->right; + if(avlnode->left) + avlnode->left->parent = avlnode; + child->right = gchild->left; + if(child->right) + child->right->parent = child; + gchild->right = avlnode; + if(gchild->right) + gchild->right->parent = gchild; + gchild->left = child; + if(gchild->left) + gchild->left->parent = gchild; + *superparent = gchild; + gchild->parent = parent; + #ifdef AVL_COUNT + avlnode->count = CALC_COUNT(avlnode); + child->count = CALC_COUNT(child); + gchild->count = CALC_COUNT(gchild); + #endif + #ifdef AVL_DEPTH + avlnode->depth = CALC_DEPTH(avlnode); + child->depth = CALC_DEPTH(child); + gchild->depth = CALC_DEPTH(gchild); + #endif + } + break; + case 1: + child = avlnode->right; + #ifdef AVL_DEPTH + if(R_DEPTH(child) >= L_DEPTH(child)) { + #else + #ifdef AVL_COUNT + if(R_COUNT(child) >= L_COUNT(child)) { + #else + #error No balancing possible. + #endif + #endif + avlnode->right = child->left; + if(avlnode->right) + avlnode->right->parent = avlnode; + child->left = avlnode; + avlnode->parent = child; + *superparent = child; + child->parent = parent; + #ifdef AVL_COUNT + avlnode->count = CALC_COUNT(avlnode); + child->count = CALC_COUNT(child); + #endif + #ifdef AVL_DEPTH + avlnode->depth = CALC_DEPTH(avlnode); + child->depth = CALC_DEPTH(child); + #endif + } else { + gchild = child->left; + avlnode->right = gchild->left; + if(avlnode->right) + avlnode->right->parent = avlnode; + child->left = gchild->right; + if(child->left) + child->left->parent = child; + gchild->left = avlnode; + if(gchild->left) + gchild->left->parent = gchild; + gchild->right = child; + if(gchild->right) + gchild->right->parent = gchild; + *superparent = gchild; + gchild->parent = parent; + #ifdef AVL_COUNT + avlnode->count = CALC_COUNT(avlnode); + child->count = CALC_COUNT(child); + gchild->count = CALC_COUNT(gchild); + #endif + #ifdef AVL_DEPTH + avlnode->depth = CALC_DEPTH(avlnode); + child->depth = CALC_DEPTH(child); + gchild->depth = CALC_DEPTH(gchild); + #endif + } + break; + default: + #ifdef AVL_COUNT + avlnode->count = CALC_COUNT(avlnode); + #endif + #ifdef AVL_DEPTH + avlnode->depth = CALC_DEPTH(avlnode); + #endif + } + avlnode = parent; + } +} + +#pragma GCC diagnostic pop diff --git a/avl/avl.h b/avl/avl.h new file mode 100644 index 0000000..9662816 --- /dev/null +++ b/avl/avl.h @@ -0,0 +1,186 @@ +/***************************************************************************** + + avl.h - Source code for the AVL-tree library. + + Copyright (C) 1998 Michael H. Buselli + Copyright (C) 2000-2002 Wessel Dankers + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Augmented AVL-tree. Original by Michael H. Buselli . + + Modified by Wessel Dankers to add a bunch of bloat to + the sourcecode, change the interface and squash a few bugs. + Mail him if you find new bugs. + +*****************************************************************************/ + +#ifndef _AVL_H +#define _AVL_H + +/* We need either depths, counts or both (the latter being the default) */ +#if !defined(AVL_DEPTH) && !defined(AVL_COUNT) +#define AVL_DEPTH +#define AVL_COUNT +#endif + +/* User supplied function to compare two items like strcmp() does. + * For example: cmp(a,b) will return: + * -1 if a < b + * 0 if a = b + * 1 if a > b + */ +typedef int (*avl_compare_t)(const void *, const void *); + +/* User supplied function to delete an item when a node is free()d. + * If NULL, the item is not free()d. + */ +typedef void (*avl_freeitem_t)(void *); + +typedef struct avl_node_t { + struct avl_node_t *next; + struct avl_node_t *prev; + struct avl_node_t *parent; + struct avl_node_t *left; + struct avl_node_t *right; + void *item; +#ifdef AVL_COUNT + unsigned int count; +#endif +#ifdef AVL_DEPTH + unsigned char depth; +#endif +} avl_node_t; + +typedef struct avl_tree_t { + avl_node_t *head; + avl_node_t *tail; + avl_node_t *top; + avl_compare_t cmp; + avl_freeitem_t freeitem; +} avl_tree_t; + +/* Initializes a new tree for elements that will be ordered using + * the supplied strcmp()-like function. + * Returns the value of avltree (even if it's NULL). + * O(1) */ +extern avl_tree_t *avl_init_tree(avl_tree_t *avltree, avl_compare_t, avl_freeitem_t); + +/* Allocates and initializes a new tree for elements that will be + * ordered using the supplied strcmp()-like function. + * Returns NULL if memory could not be allocated. + * O(1) */ +extern avl_tree_t *avl_alloc_tree(avl_compare_t, avl_freeitem_t); + +/* Frees the entire tree efficiently. Nodes will be free()d. + * If the tree's freeitem is not NULL it will be invoked on every item. + * O(n) */ +extern void avl_free_tree(avl_tree_t *); + +/* Reinitializes the tree structure for reuse. Nothing is free()d. + * Compare and freeitem functions are left alone. + * O(1) */ +extern void avl_clear_tree(avl_tree_t *); + +/* Free()s all nodes in the tree but leaves the tree itself. + * If the tree's freeitem is not NULL it will be invoked on every item. + * O(n) */ +extern void avl_free_nodes(avl_tree_t *); + +/* Initializes memory for use as a node. Returns NULL if avlnode is NULL. + * O(1) */ +extern avl_node_t *avl_init_node(avl_node_t *avlnode, void *item); + +/* Insert an item into the tree and return the new node. + * Returns NULL and sets errno if memory for the new node could not be + * allocated or if the node is already in the tree (EEXIST). + * O(lg n) */ +extern avl_node_t *avl_insert(avl_tree_t *, void *item); + +/* Insert a node into the tree and return it. + * Returns NULL if the node is already in the tree. + * O(lg n) */ +extern avl_node_t *avl_insert_node(avl_tree_t *, avl_node_t *); + +/* Insert a node in an empty tree. If avlnode is NULL, the tree will be + * cleared and ready for re-use. + * If the tree is not empty, the old nodes are left dangling. + * O(1) */ +extern avl_node_t *avl_insert_top(avl_tree_t *, avl_node_t *avlnode); + +/* Insert a node before another node. Returns the new node. + * If old is NULL, the item is appended to the tree. + * O(lg n) */ +extern avl_node_t *avl_insert_before(avl_tree_t *, avl_node_t *old, avl_node_t *new); + +/* Insert a node after another node. Returns the new node. + * If old is NULL, the item is prepended to the tree. + * O(lg n) */ +extern avl_node_t *avl_insert_after(avl_tree_t *, avl_node_t *old, avl_node_t *new); + +/* Deletes a node from the tree. Returns immediately if the node is NULL. + * The item will not be free()d regardless of the tree's freeitem handler. + * This function comes in handy if you need to update the search key. + * O(lg n) */ +extern void avl_unlink_node(avl_tree_t *, avl_node_t *); + +/* Deletes a node from the tree. Returns immediately if the node is NULL. + * If the tree's freeitem is not NULL, it is invoked on the item. + * If it is, returns the item. + * O(lg n) */ +extern void *avl_delete_node(avl_tree_t *, avl_node_t *); + +/* Searches for an item in the tree and deletes it if found. + * If the tree's freeitem is not NULL, it is invoked on the item. + * If it is, returns the item. + * O(lg n) */ +extern void *avl_delete(avl_tree_t *, const void *item); + +/* If exactly one node is moved in memory, this will fix the pointers + * in the tree that refer to it. It must be an exact shallow copy. + * Returns the pointer to the old position. + * O(1) */ +extern avl_node_t *avl_fixup_node(avl_tree_t *, avl_node_t *new); + +/* Searches for a node with the key closest (or equal) to the given item. + * If avlnode is not NULL, *avlnode will be set to the node found or NULL + * if the tree is empty. Return values: + * -1 if the returned node is smaller + * 0 if the returned node is equal or if the tree is empty + * 1 if the returned node is greater + * O(lg n) */ +extern int avl_search_closest(const avl_tree_t *, const void *item, avl_node_t **avlnode); + +/* Searches for the item in the tree and returns a matching node if found + * or NULL if not. + * O(lg n) */ +extern avl_node_t *avl_search(const avl_tree_t *, const void *item); + +#ifdef AVL_COUNT +/* Returns the number of nodes in the tree. + * O(1) */ +extern unsigned int avl_count(const avl_tree_t *); + +/* Searches a node by its rank in the list. Counting starts at 0. + * Returns NULL if the index exceeds the number of nodes in the tree. + * O(lg n) */ +extern avl_node_t *avl_at(const avl_tree_t *, unsigned int); + +/* Returns the rank of a node in the list. Counting starts at 0. + * O(lg n) */ +extern unsigned int avl_index(const avl_node_t *); +#endif + +#endif diff --git a/calculate.c b/calculate.c new file mode 100644 index 0000000..e69de29 diff --git a/calculate.h b/calculate.h new file mode 100644 index 0000000..e69de29 diff --git a/cmdln/free.c b/cmdln/free.c new file mode 100644 index 0000000..398fbcb --- /dev/null +++ b/cmdln/free.c @@ -0,0 +1,11 @@ + +#include + +#include "free.h" + +void free_cmdln_flags( + struct cmdln_flags* flags) +{ + TODO; +} + diff --git a/cmdln/free.h b/cmdln/free.h new file mode 100644 index 0000000..7f682a7 --- /dev/null +++ b/cmdln/free.h @@ -0,0 +1,5 @@ + +struct cmdln_flags; + +void free_cmdln_flags( + struct cmdln_flags* flags); diff --git a/cmdln/print_usage.c b/cmdln/print_usage.c new file mode 100644 index 0000000..42ef995 --- /dev/null +++ b/cmdln/print_usage.c @@ -0,0 +1,9 @@ + +#include + +#include "print_usage.h" + +void print_usage() +{ + TODO; +} diff --git a/cmdln/print_usage.h b/cmdln/print_usage.h new file mode 100644 index 0000000..86f46ec --- /dev/null +++ b/cmdln/print_usage.h @@ -0,0 +1,3 @@ + +void print_usage(void); + diff --git a/cmdln/process.c b/cmdln/process.c new file mode 100644 index 0000000..f99ec16 --- /dev/null +++ b/cmdln/process.c @@ -0,0 +1,254 @@ + +#include + +#include + +#include "struct.h" +#include "process.h" +#include "print_usage.h" + +static struct option long_options[] = { + {"print-all-and-quit", no_argument, NULL, 't'}, + {"command", required_argument, NULL, 'c'}, + {"operators", required_argument, NULL, 'o'}, + {"print-stats", no_argument, NULL, 'm'}, + {"help", no_argument, NULL, 'h'}, + {0, 0, 0, 0} +}; + +struct cmdln_flags* process_cmdln_flags( + int argc, + char* const* argv) +{ + ENTER; + + const char* command = NULL; + + bool unset_operators = true; + struct operators selected_operators = {}; + + bool unset_print_with_color = true; + bool print_with_color; + + bool print_all_and_quit = false; + bool print_stats = false; + + for (int opt, idx; + (opt = getopt_long(argc, argv, "tc:o:mh", long_options, &idx)) != -1;) + { + switch (opt) + { + case 't': + { + print_all_and_quit = true; + break; + } + + case 'c': + { + command = optarg; + break; + } + + case 'o': + { + TODO; + break; + } + + case 'm': + { + TODO; + break; + } + + case 'h': + { + print_usage(); + exit(0); + break; + } + + default: + { + print_usage(); + exit(1); + break; + } + } + } + + if (unset_operators) + { + selected_operators.not = true; + selected_operators.or = true; + selected_operators.and = true; + } + + if (unset_print_with_color) + { + if (isatty(1)) + { + print_with_color = true; + } + else + { + print_with_color = false; + } + } + + struct cmdln_flags* flags = smalloc(sizeof(*flags)); + + flags->command = command; + flags->selected_operators = selected_operators; + flags->print_with_color = print_with_color; + flags->print_stats = print_stats; + flags->print_all_and_quit = print_all_and_quit; + + EXIT; + return flags; +} + +#if 0 + +static void parse_args(int argc, char* const* argv) +{ + bool unset_operators = true; + + print_with_color = isatty(1); + + for (int opt; (opt = getopt(argc, argv, "tpyqmvc:eEo:C:B")) != -1; ) switch (opt) + { + case 't': + print_truthtable = true; + break; + + case 'p': + print_all_and_quit = true; + break; + + case 'y': + assume_yes = true; + break; + + case 'q': + quiet = true; + break; + + case 'm': + print_stats = true; + break; + + case 'v': + verbose = true; + break; + + case 'c': + command = optarg; + break; + + case 'E': + use_operators.ternary = true; + // fallthrough + + case 'e': + { + use_operators.not = true; + use_operators.or = true; + use_operators.and = true; + + use_operators.orn = true; + use_operators.nor = true; + + use_operators.andn = true; + use_operators.nand = true; + + use_operators. xor = true; + use_operators.nxor = true; + + unset_operators = false; + break; + } + + case 'o': + { + unset_operators = false; + + for (char* moving; (moving = strtok_r(NULL, ",", &optarg)); ) + { + if (!strcmp(moving, "not") || !strcmp(moving, "!")) + use_operators.not = true; + else if (!strcmp(moving, "or") || !strcmp(moving, "||")) + use_operators.or = true; + else if (!strcmp(moving, "orn") || !strcmp(moving, "|!")) + use_operators.orn = true; + else if (!strcmp(moving, "nor") || !strcmp(moving, "!|")) + use_operators.nor = true; + else if (!strcmp(moving, "and") || !strcmp(moving, "&&")) + use_operators.and = true; + else if (!strcmp(moving, "andn") || !strcmp(moving, "&!")) + use_operators.andn = true; + else if (!strcmp(moving, "nand") || !strcmp(moving, "!&")) + use_operators.nand = true; + else if (!strcmp(moving, "xor") || !strcmp(moving, "!=")) + use_operators.xor = true; + else if (!strcmp(moving, "nxor") || !strcmp(moving, "==")) + use_operators.nxor = true; + else if (!strcmp(moving, "lt") || !strcmp(moving, "<")) + use_operators.lt = true; + else if (!strcmp(moving, "lte") || !strcmp(moving, "<=")) + use_operators.lte = true; + else if (!strcmp(moving, "gt") || !strcmp(moving, ">")) + use_operators.gt = true; + else if (!strcmp(moving, "gte") || !strcmp(moving, ">=")) + use_operators.gte = true; + else if (!strcmp(moving, "ternary") || !strcmp(moving, "?:")) + use_operators.ternary = true; + else + { + assert(!"TODO"); + } + } + break; + } + + case 'C': + { + if (!strcmp(optarg, "yes") || !strcmp(optarg, "on")) + print_with_color = true; + else if (!strcmp(optarg, "no") || !strcmp(optarg, "off")) + print_with_color = false; + else if (!strcmp(optarg, "auto")) + print_with_color = isatty(1); + else + { + assert(!"TODO"); + } + + break; + } + + case 'B': + { + force_rebuild = true; + + break; + } + + default: + { + printf("Unknown option '%c'!" "\n", opt); + exit(1); + break; + } + } + + if (unset_operators) + { + use_operators.not = true; + use_operators.or = true; + use_operators.and = true; + } +} + +#endif diff --git a/cmdln/process.h b/cmdln/process.h new file mode 100644 index 0000000..b54bca0 --- /dev/null +++ b/cmdln/process.h @@ -0,0 +1,4 @@ + +struct cmdln_flags* process_cmdln_flags( + int argc, + char* const* argv); diff --git a/cmdln/struct.h b/cmdln/struct.h new file mode 100644 index 0000000..423e89c --- /dev/null +++ b/cmdln/struct.h @@ -0,0 +1,54 @@ + +#include + +#include + +struct cmdln_flags +{ + const char* command; + + struct operators selected_operators; + + bool print_stats; + bool print_all_and_quit; + + bool print_with_color; + + bool verbose; +}; + +#if 0 + +bool print_all_and_quit = false; + +const char* command = NULL; + +struct { + bool not; + + bool or, orn, nor; + + bool and, andn, nand; + + bool xor, nxor; + + bool lt, lte, gt, gte; + + bool ternary; +} use_operators; + +bool print_truthtable = false; + +bool assume_yes = false; + +bool verbose = false; + +bool print_with_color = false; + +bool print_stats = false; + +bool force_rebuild = false; + +bool quiet = false; + +#endif diff --git a/debug.c b/debug.c new file mode 100644 index 0000000..2ce3f97 --- /dev/null +++ b/debug.c @@ -0,0 +1,4 @@ + +#ifdef DEBUG_BUILD_TYPE +int debug_depth; +#endif diff --git a/debug.h b/debug.h new file mode 100644 index 0000000..28c3646 --- /dev/null +++ b/debug.h @@ -0,0 +1,46 @@ + +#ifdef DEBUG_BUILD_TYPE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct string; +struct scope; +struct expression; +struct cmdln_flags; +struct avl_tree_t; +struct truthtable_set; + +extern int debug_depth; + +#include + +#include + +#include + +#define ENTER \ + printf("%*s" "%s():" "\n", debug_depth++, "", __PRETTY_FUNCTION__); + +#define TODO \ + assert(!"TODO"); + +#define CHECK \ + assert(!"CHECK"); + +#define EXIT \ + printf("%*s" "return; // from %s" "\n", debug_depth--, "", __PRETTY_FUNCTION__); + +#endif + +#ifdef RELEASE_BUILD_TYPE +#define ENTER ; +#define TODO ; +#endif + diff --git a/defines/M.h b/defines/M.h new file mode 100644 index 0000000..9a4741b --- /dev/null +++ b/defines/M.h @@ -0,0 +1,2 @@ + +#define M (0b1111111111111111) diff --git a/defines/N.h b/defines/N.h new file mode 100644 index 0000000..b8a38c6 --- /dev/null +++ b/defines/N.h @@ -0,0 +1 @@ +#define N (65536) diff --git a/defines/W.h b/defines/W.h new file mode 100644 index 0000000..dd89190 --- /dev/null +++ b/defines/W.h @@ -0,0 +1 @@ +#define W 0b0101010101010101 diff --git a/defines/X.h b/defines/X.h new file mode 100644 index 0000000..f160d31 --- /dev/null +++ b/defines/X.h @@ -0,0 +1 @@ +#define X 0b0011001100110011 diff --git a/defines/Y.h b/defines/Y.h new file mode 100644 index 0000000..6d68678 --- /dev/null +++ b/defines/Y.h @@ -0,0 +1 @@ +#define Y 0b0000111100001111 diff --git a/defines/Z.h b/defines/Z.h new file mode 100644 index 0000000..46cf6e4 --- /dev/null +++ b/defines/Z.h @@ -0,0 +1 @@ +#define Z 0b0000000011111111 diff --git a/expression/and/evaluate.c b/expression/and/evaluate.c new file mode 100644 index 0000000..e69de29 diff --git a/expression/and/evaluate.h b/expression/and/evaluate.h new file mode 100644 index 0000000..e69de29 diff --git a/expression/and/free.c b/expression/and/free.c new file mode 100644 index 0000000..abbda4d --- /dev/null +++ b/expression/and/free.c @@ -0,0 +1,11 @@ + +#include + +#include "free.h" + +void free_and_expression( + struct expression* super) +{ + TODO; +} + diff --git a/expression/and/free.h b/expression/and/free.h new file mode 100644 index 0000000..0d72946 --- /dev/null +++ b/expression/and/free.h @@ -0,0 +1,5 @@ + +struct expression; + +void free_and_expression( + struct expression* super); diff --git a/expression/and/inheritance.c b/expression/and/inheritance.c new file mode 100644 index 0000000..08a2cc6 --- /dev/null +++ b/expression/and/inheritance.c @@ -0,0 +1,11 @@ + +#include "inheritance.h" +#include "print.h" +#include "free.h" + +struct expression_inheritance and_expression_inheritance = +{ + .print = and_expression_print, + .free = free_and_expression, +}; + diff --git a/expression/and/inheritance.h b/expression/and/inheritance.h new file mode 100644 index 0000000..d5aee3a --- /dev/null +++ b/expression/and/inheritance.h @@ -0,0 +1,5 @@ + +#include "../inheritance.h" + +extern struct expression_inheritance and_expression_inheritance; + diff --git a/expression/and/new.c b/expression/and/new.c new file mode 100644 index 0000000..01b84cd --- /dev/null +++ b/expression/and/new.c @@ -0,0 +1,27 @@ + +#include + +#include "../new.h" +#include "../inc.h" + +#include "inheritance.h" +#include "struct.h" +#include "new.h" + +struct expression* new_and_expression( + int cost, + struct expression* left, + struct expression* right) +{ + struct and_expression* this = + (void*) new_expression( + /* inheritance: */ &and_expression_inheritance, + /* cost: */ cost, + /* size: */ sizeof(*this)); + + this->left = inc_expression(left); + this->right = inc_expression(right); + + return (void*) this; +} + diff --git a/expression/and/new.h b/expression/and/new.h new file mode 100644 index 0000000..6e6c0cb --- /dev/null +++ b/expression/and/new.h @@ -0,0 +1,5 @@ + +struct expression* new_and_expression( + int cost, + struct expression* left, + struct expression* right); diff --git a/expression/and/print.c b/expression/and/print.c new file mode 100644 index 0000000..2115be8 --- /dev/null +++ b/expression/and/print.c @@ -0,0 +1,16 @@ + +#include + +#include "../print.h" + +#include "struct.h" +#include "print.h" + +void and_expression_print( + struct expression* super) +{ + struct and_expression* this = (void*) super; + + printf("("), expression_print(this->left), printf(" && "), expression_print(this->right), printf(")"); +} + diff --git a/expression/and/print.h b/expression/and/print.h new file mode 100644 index 0000000..7551522 --- /dev/null +++ b/expression/and/print.h @@ -0,0 +1,3 @@ + +void and_expression_print( + struct expression* super); diff --git a/expression/and/struct.h b/expression/and/struct.h new file mode 100644 index 0000000..cecca30 --- /dev/null +++ b/expression/and/struct.h @@ -0,0 +1,12 @@ + +#include "../struct.h" + +struct and_expression +{ + struct expression super; + + struct expression* left; + + struct expression* right; +}; + diff --git a/expression/evaluate.c b/expression/evaluate.c new file mode 100644 index 0000000..e69de29 diff --git a/expression/evaluate.h b/expression/evaluate.h new file mode 100644 index 0000000..e69de29 diff --git a/expression/free.c b/expression/free.c new file mode 100644 index 0000000..257afc2 --- /dev/null +++ b/expression/free.c @@ -0,0 +1,25 @@ + +#include + +#include "inheritance.h" +#include "struct.h" +#include "free.h" + +void free_expression( + struct expression* this) +{ + if (this) + { + if (!--this->refcount) + { + assert(this); + + assert(this->inheritance); + + assert(this->inheritance->free); + + free(this); + } + } +} + diff --git a/expression/free.h b/expression/free.h new file mode 100644 index 0000000..59d10f5 --- /dev/null +++ b/expression/free.h @@ -0,0 +1,3 @@ + +void free_expression( + struct expression* this); diff --git a/expression/inc.c b/expression/inc.c new file mode 100644 index 0000000..e3f3ecc --- /dev/null +++ b/expression/inc.c @@ -0,0 +1,17 @@ + +#include + +#include "struct.h" +#include "inc.h" + +struct expression* inc_expression( + struct expression* this) +{ + if (this) + { + this->refcount++; + } + + return this; +} + diff --git a/expression/inc.h b/expression/inc.h new file mode 100644 index 0000000..76e1d77 --- /dev/null +++ b/expression/inc.h @@ -0,0 +1,3 @@ + +struct expression* inc_expression( + struct expression* this); diff --git a/expression/inheritance.h b/expression/inheritance.h new file mode 100644 index 0000000..df90570 --- /dev/null +++ b/expression/inheritance.h @@ -0,0 +1,12 @@ + +struct expression; + +struct expression_inheritance +{ + void (*print)( + struct expression*); + + void (*free)( + struct expression*); +}; + diff --git a/expression/literal/evaluate.c b/expression/literal/evaluate.c new file mode 100644 index 0000000..e69de29 diff --git a/expression/literal/evaluate.h b/expression/literal/evaluate.h new file mode 100644 index 0000000..e69de29 diff --git a/expression/literal/free.c b/expression/literal/free.c new file mode 100644 index 0000000..e3fd86c --- /dev/null +++ b/expression/literal/free.c @@ -0,0 +1,11 @@ + +#include + +#include "free.h" + +void free_literal_expression( + struct expression* super) +{ + TODO; +} + diff --git a/expression/literal/free.h b/expression/literal/free.h new file mode 100644 index 0000000..39150c9 --- /dev/null +++ b/expression/literal/free.h @@ -0,0 +1,3 @@ + +void free_literal_expression( + struct expression* super); diff --git a/expression/literal/inheritance.c b/expression/literal/inheritance.c new file mode 100644 index 0000000..b7b0dde --- /dev/null +++ b/expression/literal/inheritance.c @@ -0,0 +1,11 @@ + +#include "inheritance.h" +#include "print.h" +#include "free.h" + +struct expression_inheritance literal_expression_inheritance = +{ + .print = literal_expression_print, + .free = free_literal_expression, +}; + diff --git a/expression/literal/inheritance.h b/expression/literal/inheritance.h new file mode 100644 index 0000000..bfaaba9 --- /dev/null +++ b/expression/literal/inheritance.h @@ -0,0 +1,5 @@ + +#include "../inheritance.h" + +extern struct expression_inheritance literal_expression_inheritance; + diff --git a/expression/literal/new.c b/expression/literal/new.c new file mode 100644 index 0000000..006b30d --- /dev/null +++ b/expression/literal/new.c @@ -0,0 +1,26 @@ + +#include + +#include "../new.h" + +#include "inheritance.h" +#include "struct.h" +#include "new.h" + +struct expression* new_literal_expression( + int cost, bool value) +{ + ENTER; + + struct literal_expression* this = + (void*) new_expression( + /* inheritance: */ &literal_expression_inheritance, + /* cost: */ cost, + /* size: */ sizeof(*this)); + + this->value = value; + + EXIT; + return (void*) this; +} + diff --git a/expression/literal/new.h b/expression/literal/new.h new file mode 100644 index 0000000..c66b667 --- /dev/null +++ b/expression/literal/new.h @@ -0,0 +1,4 @@ + +struct expression* new_literal_expression( + int cost, + bool is_one); diff --git a/expression/literal/print.c b/expression/literal/print.c new file mode 100644 index 0000000..35261fc --- /dev/null +++ b/expression/literal/print.c @@ -0,0 +1,21 @@ + +#include + +#include "struct.h" +#include "print.h" + +void literal_expression_print( + struct expression* super) +{ + struct literal_expression* this = (void*) super; + + if (this->value) + { + printf("1"); + } + else + { + printf("0"); + } +} + diff --git a/expression/literal/print.h b/expression/literal/print.h new file mode 100644 index 0000000..797a12f --- /dev/null +++ b/expression/literal/print.h @@ -0,0 +1,3 @@ + +void literal_expression_print( + struct expression* super); diff --git a/expression/literal/struct.h b/expression/literal/struct.h new file mode 100644 index 0000000..9275812 --- /dev/null +++ b/expression/literal/struct.h @@ -0,0 +1,10 @@ + +#include "../struct.h" + +struct literal_expression +{ + struct expression super; + + bool value; +}; + diff --git a/expression/new.c b/expression/new.c new file mode 100644 index 0000000..bc67027 --- /dev/null +++ b/expression/new.c @@ -0,0 +1,22 @@ + +#include + +#include "struct.h" +#include "new.h" + +struct expression* new_expression( + const struct expression_inheritance* inheritance, + int cost, + size_t size) +{ + struct expression* this = smalloc(size); + + this->inheritance = inheritance; + + this->cost = cost; + + this->refcount = 1; + + return this; +} + diff --git a/expression/new.h b/expression/new.h new file mode 100644 index 0000000..50696ce --- /dev/null +++ b/expression/new.h @@ -0,0 +1,7 @@ + +struct expression_inheritance; + +struct expression* new_expression( + const struct expression_inheritance* inheritance, + int cost, + size_t size); diff --git a/expression/not/evaluate.c b/expression/not/evaluate.c new file mode 100644 index 0000000..e69de29 diff --git a/expression/not/evaluate.h b/expression/not/evaluate.h new file mode 100644 index 0000000..e69de29 diff --git a/expression/not/free.c b/expression/not/free.c new file mode 100644 index 0000000..e9bf7cd --- /dev/null +++ b/expression/not/free.c @@ -0,0 +1,11 @@ + +#include + +#include "free.h" + +void free_not_expression( + struct expression* super) +{ + TODO; +} + diff --git a/expression/not/free.h b/expression/not/free.h new file mode 100644 index 0000000..e073fb4 --- /dev/null +++ b/expression/not/free.h @@ -0,0 +1,5 @@ + +struct expression; + +void free_not_expression( + struct expression* super); diff --git a/expression/not/inheritance.c b/expression/not/inheritance.c new file mode 100644 index 0000000..93176c9 --- /dev/null +++ b/expression/not/inheritance.c @@ -0,0 +1,11 @@ + +#include "inheritance.h" +#include "print.h" +#include "free.h" + +struct expression_inheritance not_expression_inheritance = +{ + .print = not_expression_print, + .free = free_not_expression, +}; + diff --git a/expression/not/inheritance.h b/expression/not/inheritance.h new file mode 100644 index 0000000..d2248fd --- /dev/null +++ b/expression/not/inheritance.h @@ -0,0 +1,5 @@ + +#include "../inheritance.h" + +extern struct expression_inheritance not_expression_inheritance; + diff --git a/expression/not/new.c b/expression/not/new.c new file mode 100644 index 0000000..ec677dc --- /dev/null +++ b/expression/not/new.c @@ -0,0 +1,25 @@ + +#include + +#include "../new.h" +#include "../inc.h" + +#include "inheritance.h" +#include "struct.h" +#include "new.h" + +struct expression* new_not_expression( + int cost, + struct expression* inner) +{ + struct not_expression* this = + (void*) new_expression( + /* inheritance: */ ¬_expression_inheritance, + /* cost: */ cost, + /* size: */ sizeof(*this)); + + this->inner = inc_expression(inner); + + return (void*) this; +} + diff --git a/expression/not/new.h b/expression/not/new.h new file mode 100644 index 0000000..e6809e6 --- /dev/null +++ b/expression/not/new.h @@ -0,0 +1,4 @@ + +struct expression* new_not_expression( + int cost, + struct expression* subexpression); diff --git a/expression/not/print.c b/expression/not/print.c new file mode 100644 index 0000000..a9add78 --- /dev/null +++ b/expression/not/print.c @@ -0,0 +1,16 @@ + +#include + +#include "../print.h" + +#include "struct.h" +#include "print.h" + +void not_expression_print( + struct expression* super) +{ + struct not_expression* this = (void*) super; + + printf("(!"), expression_print(this->inner), printf(")"); +} + diff --git a/expression/not/print.h b/expression/not/print.h new file mode 100644 index 0000000..2ca2666 --- /dev/null +++ b/expression/not/print.h @@ -0,0 +1,3 @@ + +void not_expression_print( + struct expression* super); diff --git a/expression/not/struct.h b/expression/not/struct.h new file mode 100644 index 0000000..38542bb --- /dev/null +++ b/expression/not/struct.h @@ -0,0 +1,10 @@ + +#include "../struct.h" + +struct not_expression +{ + struct expression super; + + struct expression* inner; +}; + diff --git a/expression/or/evaluate.c b/expression/or/evaluate.c new file mode 100644 index 0000000..e69de29 diff --git a/expression/or/evaluate.h b/expression/or/evaluate.h new file mode 100644 index 0000000..e69de29 diff --git a/expression/or/free.c b/expression/or/free.c new file mode 100644 index 0000000..b8e18a0 --- /dev/null +++ b/expression/or/free.c @@ -0,0 +1,11 @@ + +#include + +#include "free.h" + +void free_or_expression( + struct expression* super) +{ + TODO; +} + diff --git a/expression/or/free.h b/expression/or/free.h new file mode 100644 index 0000000..4dae933 --- /dev/null +++ b/expression/or/free.h @@ -0,0 +1,5 @@ + +struct expression; + +void free_or_expression( + struct expression* super); diff --git a/expression/or/inheritance.c b/expression/or/inheritance.c new file mode 100644 index 0000000..fd26c87 --- /dev/null +++ b/expression/or/inheritance.c @@ -0,0 +1,11 @@ + +#include "inheritance.h" +#include "print.h" +#include "free.h" + +struct expression_inheritance or_expression_inheritance = +{ + .print = or_expression_print, + .free = free_or_expression, +}; + diff --git a/expression/or/inheritance.h b/expression/or/inheritance.h new file mode 100644 index 0000000..9544d02 --- /dev/null +++ b/expression/or/inheritance.h @@ -0,0 +1,5 @@ + +#include "../inheritance.h" + +extern struct expression_inheritance or_expression_inheritance; + diff --git a/expression/or/new.c b/expression/or/new.c new file mode 100644 index 0000000..5341f8e --- /dev/null +++ b/expression/or/new.c @@ -0,0 +1,27 @@ + +#include + +#include "../new.h" +#include "../inc.h" + +#include "inheritance.h" +#include "struct.h" +#include "new.h" + +struct expression* new_or_expression( + int cost, + struct expression* left, + struct expression* right) +{ + struct or_expression* this = + (void*) new_expression( + /* inheritance: */ &or_expression_inheritance, + /* cost: */ cost, + /* size: */ sizeof(*this)); + + this->left = inc_expression(left); + this->right = inc_expression(right); + + return (void*) this; +} + diff --git a/expression/or/new.h b/expression/or/new.h new file mode 100644 index 0000000..ef0f4ac --- /dev/null +++ b/expression/or/new.h @@ -0,0 +1,5 @@ + +struct expression* new_or_expression( + int cost, + struct expression* left, + struct expression* right); diff --git a/expression/or/print.c b/expression/or/print.c new file mode 100644 index 0000000..edb44a0 --- /dev/null +++ b/expression/or/print.c @@ -0,0 +1,16 @@ + +#include + +#include "../print.h" + +#include "struct.h" +#include "print.h" + +void or_expression_print( + struct expression* super) +{ + struct or_expression* this = (void*) super; + + printf("("), expression_print(this->left), printf(" || "), expression_print(this->right), printf(")"); +} + diff --git a/expression/or/print.h b/expression/or/print.h new file mode 100644 index 0000000..8c63d53 --- /dev/null +++ b/expression/or/print.h @@ -0,0 +1,3 @@ + +void or_expression_print( + struct expression* super); diff --git a/expression/or/struct.h b/expression/or/struct.h new file mode 100644 index 0000000..00a5633 --- /dev/null +++ b/expression/or/struct.h @@ -0,0 +1,12 @@ + +#include "../struct.h" + +struct or_expression +{ + struct expression super; + + struct expression* left; + + struct expression* right; +}; + diff --git a/expression/print.c b/expression/print.c new file mode 100644 index 0000000..dcb269c --- /dev/null +++ b/expression/print.c @@ -0,0 +1,17 @@ + +#include + +#include "inheritance.h" +#include "struct.h" +#include "print.h" + +void expression_print( + struct expression* this) +{ + assert(this); + assert(this->inheritance); + assert(this->inheritance->print); + + (this->inheritance->print)(this); +} + diff --git a/expression/print.h b/expression/print.h new file mode 100644 index 0000000..f0a1736 --- /dev/null +++ b/expression/print.h @@ -0,0 +1,5 @@ + +struct expression; + +void expression_print( + struct expression* this); diff --git a/expression/struct.h b/expression/struct.h new file mode 100644 index 0000000..707723a --- /dev/null +++ b/expression/struct.h @@ -0,0 +1,12 @@ + +struct expression_inheritance; + +struct expression +{ + const struct expression_inheritance* inheritance; + + int cost; + + unsigned refcount; +}; + diff --git a/expression/unreachable/evaluate.c b/expression/unreachable/evaluate.c new file mode 100644 index 0000000..e69de29 diff --git a/expression/unreachable/evaluate.h b/expression/unreachable/evaluate.h new file mode 100644 index 0000000..e69de29 diff --git a/expression/unreachable/free.c b/expression/unreachable/free.c new file mode 100644 index 0000000..e538684 --- /dev/null +++ b/expression/unreachable/free.c @@ -0,0 +1,11 @@ + +#include + +#include "free.h" + +void free_unreachable_expression( + struct expression* super) +{ + TODO; +} + diff --git a/expression/unreachable/free.h b/expression/unreachable/free.h new file mode 100644 index 0000000..d8f62df --- /dev/null +++ b/expression/unreachable/free.h @@ -0,0 +1,3 @@ + +void free_unreachable_expression( + struct expression* super); diff --git a/expression/unreachable/inheritance.c b/expression/unreachable/inheritance.c new file mode 100644 index 0000000..f9afd8d --- /dev/null +++ b/expression/unreachable/inheritance.c @@ -0,0 +1,11 @@ + +#include "inheritance.h" +#include "print.h" +#include "free.h" + +struct expression_inheritance unreachable_expression_inheritance = +{ + .print = unreachable_expression_print, + .free = free_unreachable_expression, +}; + diff --git a/expression/unreachable/inheritance.h b/expression/unreachable/inheritance.h new file mode 100644 index 0000000..f77804f --- /dev/null +++ b/expression/unreachable/inheritance.h @@ -0,0 +1,5 @@ + +#include "../inheritance.h" + +extern struct expression_inheritance unreachable_expression_inheritance; + diff --git a/expression/unreachable/new.c b/expression/unreachable/new.c new file mode 100644 index 0000000..cce4b2e --- /dev/null +++ b/expression/unreachable/new.c @@ -0,0 +1,23 @@ + +#include + +#include "../new.h" + +#include "inheritance.h" +#include "struct.h" +#include "new.h" + +struct expression* new_unreachable_expression(void) +{ + ENTER; + + struct unreachable_expression* this = + (void*) new_expression( + /* inheritance: */ &unreachable_expression_inheritance, + /* cost: */ INT_MAX, + /* size: */ sizeof(*this)); + + EXIT; + return (void*) this; +} + diff --git a/expression/unreachable/new.h b/expression/unreachable/new.h new file mode 100644 index 0000000..83f4350 --- /dev/null +++ b/expression/unreachable/new.h @@ -0,0 +1,2 @@ + +struct expression* new_unreachable_expression(void); diff --git a/expression/unreachable/print.c b/expression/unreachable/print.c new file mode 100644 index 0000000..c330086 --- /dev/null +++ b/expression/unreachable/print.c @@ -0,0 +1,11 @@ + +#include + +#include "print.h" + +void unreachable_expression_print( + struct expression* super) +{ + TODO; +} + diff --git a/expression/unreachable/print.h b/expression/unreachable/print.h new file mode 100644 index 0000000..91c7dc3 --- /dev/null +++ b/expression/unreachable/print.h @@ -0,0 +1,3 @@ + +void unreachable_expression_print( + struct expression* super); diff --git a/expression/unreachable/struct.h b/expression/unreachable/struct.h new file mode 100644 index 0000000..6ed93a4 --- /dev/null +++ b/expression/unreachable/struct.h @@ -0,0 +1,8 @@ + +#include "../struct.h" + +struct unreachable_expression +{ + struct expression super; +}; + diff --git a/expression/variable/evaluate.c b/expression/variable/evaluate.c new file mode 100644 index 0000000..e69de29 diff --git a/expression/variable/evaluate.h b/expression/variable/evaluate.h new file mode 100644 index 0000000..e69de29 diff --git a/expression/variable/free.c b/expression/variable/free.c new file mode 100644 index 0000000..34e9f9c --- /dev/null +++ b/expression/variable/free.c @@ -0,0 +1,11 @@ + +#include + +#include "free.h" + +void free_variable_expression( + struct expression* super) +{ + TODO; +} + diff --git a/expression/variable/free.h b/expression/variable/free.h new file mode 100644 index 0000000..1b0f2e6 --- /dev/null +++ b/expression/variable/free.h @@ -0,0 +1,3 @@ + +void free_variable_expression( + struct expression* super); diff --git a/expression/variable/inheritance.c b/expression/variable/inheritance.c new file mode 100644 index 0000000..08748ec --- /dev/null +++ b/expression/variable/inheritance.c @@ -0,0 +1,11 @@ + +#include "inheritance.h" +#include "print.h" +#include "free.h" + +struct expression_inheritance variable_expression_inheritance = +{ + .print = variable_expression_print, + .free = free_variable_expression, +}; + diff --git a/expression/variable/inheritance.h b/expression/variable/inheritance.h new file mode 100644 index 0000000..4d4d7eb --- /dev/null +++ b/expression/variable/inheritance.h @@ -0,0 +1,5 @@ + +#include "../inheritance.h" + +extern struct expression_inheritance variable_expression_inheritance; + diff --git a/expression/variable/new.c b/expression/variable/new.c new file mode 100644 index 0000000..c323688 --- /dev/null +++ b/expression/variable/new.c @@ -0,0 +1,27 @@ + +#include + +#include "../new.h" + +#include "inheritance.h" +#include "struct.h" +#include "new.h" + +struct expression* new_variable_expression( + int cost, + struct string* name) +{ + ENTER; + + struct variable_expression* this = + (void*) new_expression( + /* inheritance: */ &variable_expression_inheritance, + /* cost: */ cost, + /* size: */ sizeof(*this)); + + this->name = inc_string(name); + + EXIT; + return (void*) this; +} + diff --git a/expression/variable/new.h b/expression/variable/new.h new file mode 100644 index 0000000..c71fee3 --- /dev/null +++ b/expression/variable/new.h @@ -0,0 +1,4 @@ + +struct expression* new_variable_expression( + int cost, + struct string* name); diff --git a/expression/variable/print.c b/expression/variable/print.c new file mode 100644 index 0000000..3d20519 --- /dev/null +++ b/expression/variable/print.c @@ -0,0 +1,16 @@ + +#include + +#include + +#include "struct.h" +#include "print.h" + +void variable_expression_print( + struct expression* super) +{ + struct variable_expression* this = (void*) super; + + string_print(this->name); +} + diff --git a/expression/variable/print.h b/expression/variable/print.h new file mode 100644 index 0000000..9229906 --- /dev/null +++ b/expression/variable/print.h @@ -0,0 +1,3 @@ + +void variable_expression_print( + struct expression* super); diff --git a/expression/variable/struct.h b/expression/variable/struct.h new file mode 100644 index 0000000..d771c5f --- /dev/null +++ b/expression/variable/struct.h @@ -0,0 +1,10 @@ + +#include "../struct.h" + +struct variable_expression +{ + struct expression super; + + struct string* name; +}; + diff --git a/flake.nix b/flake.nix index 3ae0072..2f6623f 100644 --- a/flake.nix +++ b/flake.nix @@ -25,10 +25,13 @@ pkgs.mkShell { buildInputs = with pkgs; [ gcc - gnumake readline.dev python3 ]; + + shellHook = '' + export PATH="$PWD:$PATH" + ''; }; packages.default = pkgs.stdenv.mkDerivation rec { pname = "4-variable-simplifier"; diff --git a/main.c b/main.c index 68ef906..dbe98ff 100644 --- a/main.c +++ b/main.c @@ -1,4 +1,18 @@ +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#if 0 #include #include #include @@ -14,8 +28,6 @@ #include #include -#define argv0 program_invocation_name - #ifdef ZDEBUG #define zprintf(fmt, ...) \ printf(fmt, ## __VA_ARGS__); @@ -23,186 +35,6 @@ #define zprintf(...); #endif -bool print_all_and_quit = false; - -const char* command = NULL; - -struct { - bool not; - - bool or, orn, nor; - - bool and, andn, nand; - - bool xor, nxor; - - bool lt, lte, gt, gte; - - bool ternary; -} use_operators; - -bool print_truthtable = false; - -bool assume_yes = false; - -bool verbose = false; - -bool print_with_color = false; - -bool print_stats = false; - -bool force_rebuild = false; - -bool quiet = false; - -static void parse_args(int argc, char* const* argv) -{ - bool unset_operators = true; - - print_with_color = isatty(1); - - for (int opt; (opt = getopt(argc, argv, "tpyqmvc:eEo:C:B")) != -1; ) switch (opt) - { - case 't': - print_truthtable = true; - break; - - case 'p': - print_all_and_quit = true; - break; - - case 'y': - assume_yes = true; - break; - - case 'q': - quiet = true; - break; - - case 'm': - print_stats = true; - break; - - case 'v': - verbose = true; - break; - - case 'c': - command = optarg; - break; - - case 'E': - use_operators.ternary = true; - // fallthrough - - case 'e': - { - use_operators.not = true; - use_operators.or = true; - use_operators.and = true; - - use_operators.orn = true; - use_operators.nor = true; - - use_operators.andn = true; - use_operators.nand = true; - - use_operators. xor = true; - use_operators.nxor = true; - - unset_operators = false; - break; - } - - case 'o': - { - unset_operators = false; - - for (char* moving; (moving = strtok_r(NULL, ",", &optarg)); ) - { - if (!strcmp(moving, "not") || !strcmp(moving, "!")) - use_operators.not = true; - else if (!strcmp(moving, "or") || !strcmp(moving, "||")) - use_operators.or = true; - else if (!strcmp(moving, "orn") || !strcmp(moving, "|!")) - use_operators.orn = true; - else if (!strcmp(moving, "nor") || !strcmp(moving, "!|")) - use_operators.nor = true; - else if (!strcmp(moving, "and") || !strcmp(moving, "&&")) - use_operators.and = true; - else if (!strcmp(moving, "andn") || !strcmp(moving, "&!")) - use_operators.andn = true; - else if (!strcmp(moving, "nand") || !strcmp(moving, "!&")) - use_operators.nand = true; - else if (!strcmp(moving, "xor") || !strcmp(moving, "!=")) - use_operators.xor = true; - else if (!strcmp(moving, "nxor") || !strcmp(moving, "==")) - use_operators.nxor = true; - else if (!strcmp(moving, "lt") || !strcmp(moving, "<")) - use_operators.lt = true; - else if (!strcmp(moving, "lte") || !strcmp(moving, "<=")) - use_operators.lte = true; - else if (!strcmp(moving, "gt") || !strcmp(moving, ">")) - use_operators.gt = true; - else if (!strcmp(moving, "gte") || !strcmp(moving, ">=")) - use_operators.gte = true; - else if (!strcmp(moving, "ternary") || !strcmp(moving, "?:")) - use_operators.ternary = true; - else - { - assert(!"TODO"); - } - } - break; - } - - case 'C': - { - if (!strcmp(optarg, "yes") || !strcmp(optarg, "on")) - print_with_color = true; - else if (!strcmp(optarg, "no") || !strcmp(optarg, "off")) - print_with_color = false; - else if (!strcmp(optarg, "auto")) - print_with_color = isatty(1); - else - { - assert(!"TODO"); - } - - break; - } - - case 'B': - { - force_rebuild = true; - - break; - } - - default: - { - printf("Unknown option '%c'!" "\n", opt); - exit(1); - break; - } - } - - if (unset_operators) - { - use_operators.not = true; - use_operators.or = true; - use_operators.and = true; - } -} - -#define W 0b0101010101010101 -#define X 0b0011001100110011 -#define Y 0b0000111100001111 -#define Z 0b0000000011111111 -#define M 0b1111111111111111 - -#define N (65536) - enum kind { ek_unreachable, @@ -1442,15 +1274,18 @@ uint16_t evaluate(const char* text) return truthtable; } +#endif int main(int argc, char* const* argv) { - parse_args(argc, argv); - - get_simplifications(); - - if (print_all_and_quit) + ENTER; + + struct cmdln_flags* flags = process_cmdln_flags(argc, argv); + + if (flags->print_all_and_quit) { + TODO; + #if 0 for (int i = 0; i < N; i++) { int cost = lookup[i].cost; @@ -1460,9 +1295,12 @@ int main(int argc, char* const* argv) printf("0b%016b: [%2i]: ", i, cost), print(i, 0), puts(""); } } + #endif } - else if (print_stats) + else if (flags->print_stats) { + TODO; + #if 0 printf("statistics:" "\n"); uintmax_t total_cost = 0; @@ -1515,9 +1353,18 @@ int main(int argc, char* const* argv) { puts("everything unreachable: no statistics to give"); } + #endif } - else if (command) + else if (flags->command) { + struct scope* scope = new_scope(); + + struct simplifications* simplifications = new_simplifications( + /* operators: */ &flags->selected_operators, + /* scope: */ scope); + + TODO; + #if 0 uint16_t truthtable = evaluate(command); if (print_truthtable) @@ -1534,9 +1381,16 @@ int main(int argc, char* const* argv) // printf("%2i: ", lookup[truthtable].cost), print(truthtable, 0), puts(""); print(truthtable, 0), puts(""); } + #endif + + free_simplifications(simplifications); + + free_scope(scope); } else { + TODO; + #if 0 if (!quiet) { puts("Use C-style syntax for boolean operators and expressions."); @@ -1544,8 +1398,7 @@ int main(int argc, char* const* argv) puts("Extended operators: nor is '!|', orn is '|!', nand is '!&', andn is '&!'."); puts("Comparison operators are also suppported."); } - - + for (char* line; (line = readline(">>> ")); free(line)) { if (!*line) continue; @@ -1567,12 +1420,14 @@ int main(int argc, char* const* argv) { // printf("%2i: ", lookup[truthtable].cost); printf(" "); - - print(truthtable, 0), puts(""); + print(truthtable, 0), puts(""); } } + #endif } + free_cmdln_flags(flags); + return 0; } diff --git a/memory/smalloc.c b/memory/smalloc.c new file mode 100644 index 0000000..08396e8 --- /dev/null +++ b/memory/smalloc.c @@ -0,0 +1,19 @@ + +#include + +#include + +#include "smalloc.h" + +void* smalloc(size_t size) +{ + void* ptr = malloc(size); + + if (!ptr) + { + TODO; + } + + return ptr; +} + diff --git a/memory/smalloc.h b/memory/smalloc.h new file mode 100644 index 0000000..ec7dc63 --- /dev/null +++ b/memory/smalloc.h @@ -0,0 +1,2 @@ + +void* smalloc(size_t size); diff --git a/misc/sat_add.c b/misc/sat_add.c new file mode 100644 index 0000000..9a852a3 --- /dev/null +++ b/misc/sat_add.c @@ -0,0 +1,30 @@ + +#include + +#include "sat_add.h" + +int sat_add(int x, int y) +{ + if (x == INT_MAX && y > 0) + { + assert(!"TODO"); + } + + if (x > 0 && y == INT_MAX) + { + assert(!"TODO"); + } + + if (x > 0 && y > 0) + { + assert(!"TODO"); + } + + if (x < 0 && y < 0) + { + assert(!"TODO"); + } + + return x + y; +} + diff --git a/misc/sat_add.h b/misc/sat_add.h new file mode 100644 index 0000000..b81999f --- /dev/null +++ b/misc/sat_add.h @@ -0,0 +1,3 @@ + +int sat_add(int x, int y); + diff --git a/parse.c b/parse.c new file mode 100644 index 0000000..e69de29 diff --git a/parse.h b/parse.h new file mode 100644 index 0000000..e69de29 diff --git a/python/__pycache__/build.cpython-312.pyc b/python/__pycache__/build.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..773672a326c8ce683c9da747bca7d8f6af44f4f6 GIT binary patch literal 3183 zcmbVP+iM%y89#H;NE%%%+sb-8_A%y?#W^GKu4 zj1yZs0tEsqLm*nZ5W#N2EEHVQf*~H-DJ;x7DA=}_+8o(1IB9V~Ma;qkm36T^j znaq>RB!K|aGL@&6sXV<*!?WihTJ~%bapnbfa_a>F_c&ou>UtqgT8x(Ae{yl!3bg8# zR92P*+{Gzg02EwDVGjZV;kxZ2}>6mO#+o-|BBrB5NZGP{2h&7lm9Dc2S3mA};E5QJ0IlT@-Dh!fo-C z&EXO-c+0ktKNz>i_42^JuVK!+Sy{ z*5M8c;??eb)J-Eleof)$_=eSu6(6>>ZYfUL_*nPvQMVir2_s-@JYs7c{1F-l9iH0o ziB&ghc)md5*l#GO6__&OJ4W#PXTYFy!^bK)$Z%s2u+kpQ(0DHh!P_4e$IBf?2v$w_ zE5e}R>cFd~%)Gv;QiQ|8&NA{NvWz$$w9_ZDj5*eJc99>*E^-@yy>$VgKv-YH>o^+_99OsV zZvXtw2XpgrvP5zV7LoWJvOJ=+x}J`cD&GICNOJz#o$D*t?kwC$u6%g+7xQrfx~Ado z<(4E>RaAf;Zi$!WwrxXKd4NG~Nl*&+Bvs2Q1$ge{mb7fTz`bVd;+9gf!s~BXc{QtN zUbnu*Efo|_)77k?b469r6@9ZPY2Z2xUU;3CIhzl*1nj=+g>_95Ew3uc60b>4N?jk! z-`b3qA>IAQ*wU*W^*cvaFn90eh$%FuM z`&CI;hrI7eK!xIN-Yn4xQ7U5ieu?}gYY{^)@RPXlzcHOXA9|}5r*gyr~qJ#6i#bh9a zq(a9GZ&5JDB4r3Ei*0W*B)ke^qzy^KJJ8T~%d6?BjFOk8N)SL&r_xz{>H>EURt~=^ zOPrR?1Lss0T8f)`Mk!3$;v|Zjmd8fwMR1CbD$NJ4Nd-M4=}*r-I9pYAhW|pIYkGr~ zk!EP5GSMX2>Y7RR0t$pG<4s@iamQB2-~5pSCfw*cXENt1nI;pg`Ap{RN(!Tp$(*jF z4gdvAroV+;TO%@JG9$LJ5s8^htPLkjX5vj~yT`5?kuj4Qv;8+B!zMHQAobkeWm8C) zOrk}>4f5Xu$4w^Q4)OnRI57-!c#vxP*=J0k5xlg|{PY>aR^NS?Zu$e2vBOaJ=gB7v zpDolgyI1$4)8B+fN;gtaAF0 z@mFIH-2*1kD`xb{UUc^BUwy6aMXy!I z4}8JT`|BU=b&la#@Wr<1e^cnx9PurM*zT7;6zKxi8)kTLd%_G)?tEm1&+lrxK>ajau)eQunL3WN~{?eg0&awXapxAc5t$ugxmJC8JvVR zU(c80+p+Eby*|$Lah1_Sf8cS?R?p)zTW9LjzJK5u?XNEG)4fePP@`)?^%IlsgEVMw z)%);9(;uu%e!DCKhCK5!$`&7FZLE;Zyl{o1iwNm z9&rR0QsDy*S-vZIMO>GqS#<^;@t329KZ;&b1VJ3Jh+vPx# literal 0 HcmV?d00001 diff --git a/python/__pycache__/run.cpython-312.pyc b/python/__pycache__/run.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..26449e7699d48c5be37352c2eb93c3e9efeebf94 GIT binary patch literal 1220 zcmaizO-vI(6vtbHkc5j z5l`ZYn2>m-fy9d!6BE6AfwZR$2P2Tkjo2F}-)y^W(~vmHzIprJ?0f&o`|ZzQFo0n7 z+&|WiF+zv@#alwnsVLxVB8n(ZqnYZCXD}6BqZxsUV8uL+kQ07vh?6rok9zbow2GB5Ee)=5*k=CX&j&x=xVr&bZ8rYND3&O5g(yWI=e9iFFm zdR}8+MV*Wto<-9ip3B#u1G~){(4K zT3vCZ=Q-0>9ipyic2RJAwH{Cb>TnT?au$oGOhb(ppts7R&onz48+wsoT4Eus4q2L! zO>2u9WU_fXWoDw#`$jg;I1sLB1IL;GvxW}juJ@hqIyaWLaakT%>-#0iZ|7dk9T5Ls zKq-^nBjR80-?+3H{t({k+fqL*eO%hUUFsPtg<|`GSee{BBJz6Z&4bf+)Ye^rlIVO+ z{y?Ug6AF~+oS>FvOJ2a{D&3{ap4ZsVpCuJrCR!&$uanVSgOXjzW5VU~9BSCr2HnkE zG|}Q~p+z1qgs(jr9*K|LiI2udhKJ*$@W5{LD~v;4Adog(q!|Ad7{4py*NpfXSIUCi za5d}#Hy63#=vRlxuf;g6tP4zy3U(QMC+KoD4`j^4*jX52{A24e7#O$U+mi>jr#?>? zr@th>UH?A#b@0b>>DEMPXmVek+?$%+muJhu)1&`lQJuOErp~TF=?JOHbJe<_@y`yhOJp3Zbc1m}`v-x>;i~`u literal 0 HcmV?d00001 diff --git a/python/__pycache__/sha256.cpython-312.pyc b/python/__pycache__/sha256.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec49fd74592b8a65c49b3c0367734bb12c4aa572 GIT binary patch literal 1027 zcmbtS&ubG=5T3WYN&32O&}gCQp%kjpZLOiUsU9Ry(O!xHDG2SMy3KC8Tas*eyZsS~ zP{f0|7;j0b(6i)^kb3oEx5% z`f9}qz!BecL}(kWel)6}gHE!r2)ghR7KtvR7K%ibzHwMOgV9|Hp(Wzi+CWtWx9eN$ z+}VW!xEviw3F>X+TBLJ!{;#*qE{2}_I#vfW4=PEkAwObjj+wQV{jg(dx02Jo#Eb&- z!$v-1>xNHFV@tPI4aZf9PqrMMedzRd!nAWn;+dA$4VGB7+{D!QhQ=&yIctnNR<4k> zRxI=simqwr6K6NyEEE}kNT4J%oNK7I;gDXe43-DqO0`G3k-g|n)axJdsM@5H4La%3 zB7LLmIcUl73ePvmaq%;Hj7DkPF#))WQ}M2LrUa-nal{-cU+yE1malp^9l=V9QL#9BSB? z?1GVJ{N(}hyuX^xdT{Swnzgb<+IDB{^}POoF`KD^FBLS`#A$F5mvcCeLqm)g?aOC< ze6oU3>@uG45p=KDof?1+U(xk&fM-pPZ@10Qw?Rx zQ>MR*&^yqi@dFzF@r4eY0Krf>R!NmpwP8;lY|0}IdBl@P52Vp!5uK;bI3{^^u)B0;T+=T8o5eFp&{XD{iwo3r)xtdU}Ucrl-8 WCx!}>5po346N!-NRyah)f|#G@i?}ub literal 0 HcmV?d00001 diff --git a/python/build.py b/python/build.py new file mode 100644 index 0000000..d53c182 --- /dev/null +++ b/python/build.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python3 + +# vim: sw=2 ts=2 ex: + +import os + +import glob + +from .run import run; + +from .sha256 import sha256, sha256_file; + +def build(args): + os.makedirs(".build-cache/", exist_ok = 1); + + cc = "gcc"; + + cppflags = ("-D", "_GNU_SOURCE"); + + cppflags += ("-I", "."); + + cflags = (); + + match args.build_type: + case "debug": + cppflags += ("-D", "DEBUG_BUILD_TYPE"); + + cflags += ("-g", ); + + cflags += ("-Werror", ); + cflags += ("-Wall", ); + cflags += ("-Wextra", ); + cflags += ("-Wconversion", ); + cflags += ("-Wsign-conversion", ); + cflags += ("-Wfloat-conversion", ); + cflags += ("-Warith-conversion", ); + cflags += ("-Wno-strict-prototypes", ); + cflags += ("-Wfatal-errors", ); + + cflags += ("-Wno-unused", ); + + case "release": + cppflags += ("-D", "RELEASE_BUILD_TYPE"); + + cflags += ("-Werror", ); + cflags += ("-Wall", ); + cflags += ("-Wextra", ); + cflags += ("-Wstrict-prototypes", ); + cflags += ("-Wconversion", ); + cflags += ("-Wsign-conversion", ); + cflags += ("-Wfloat-conversion", ); + cflags += ("-Warith-conversion", ); + cflags += ("-Wstrict-prototypes", ); + cflags += ("-Wfatal-errors", ); + + case _: + print("unknown build type {repr(args.build_type)}"); + exit(1); + + objs = []; + + for src in sorted(glob.glob("**/*.c", recursive = 1)): + command = (cc, ) + ("-MM", ) + cppflags + (src, ); + + shas = (sha256_file(src), ); + + dep = ".build-cache/" + sha256((command, *shas)) + ".dep"; + + if not os.path.exists(dep): + command += ("-MF", dep); + + run(command); + + with open(dep) as stream: + for header in stream.read().replace("\\\n", " ").split()[2:]: + shas += (sha256_file(header), ); + + command = (cc, ) + ("-c", ) + cppflags + cflags + (src, ); + + sha = sha256((command, *shas)); + + obj = ".build-cache/" + sha + ".o"; + + if not os.path.exists(obj): + print(f"Compiling {src} ..."); + + command += ("-o", obj); + + run(command); + + objs.append(obj); + + ld = "gcc"; + + ldflags = (); + + ldlibs = ("-lm", "-lreadline"); + + command = (ld, *ldflags, *objs, *ldlibs) + + exe = ".build-cache/" + sha256((command, )); + + if not os.path.exists(exe): + print(f"Linking ..."); + + command += ("-o", exe); + + run(command); + + return exe; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/python/run.py b/python/run.py new file mode 100644 index 0000000..9f6e466 --- /dev/null +++ b/python/run.py @@ -0,0 +1,26 @@ + +import subprocess; + +import shlex; + +def run(command): + res = subprocess.run(command, check = 0); + + if res.returncode: + print("This command failed!"); + + print("$ " + " ".join(map(shlex.quote, command))); + + exit(1); + +def print_and_run(command): + print("\033[01;38;2;100;200;100m" + "$ " + " ".join(map(shlex.quote, command)) + "\033[0m"); + + res = subprocess.run(command, check = 0); + + if res.returncode: + print("This command failed!"); + + exit(1); + + diff --git a/python/sha256.py b/python/sha256.py new file mode 100644 index 0000000..907cbf5 --- /dev/null +++ b/python/sha256.py @@ -0,0 +1,13 @@ + +import hashlib + +def sha256(x): + return hashlib.sha256(repr(x).encode()).hexdigest() + +def sha256_file(path): + try: + with open(path, "rb") as stream: + return hashlib.sha256(stream.read()).hexdigest() + except FileNotFoundError: + return hashlib.sha256(b"").hexdigest() + diff --git a/repl/repl.c b/repl/repl.c new file mode 100644 index 0000000..e69de29 diff --git a/repl/repl.h b/repl/repl.h new file mode 100644 index 0000000..e69de29 diff --git a/result b/result new file mode 120000 index 0000000..8011572 --- /dev/null +++ b/result @@ -0,0 +1 @@ +.build-cache/1945224b6ff4ad473837cbf11c1943eaafed50e3d00637c6dd6900bd6ec81d73 \ No newline at end of file diff --git a/run b/run new file mode 100755 index 0000000..89c18d1 --- /dev/null +++ b/run @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 + +# vim: sw=2 ts=2 ex: + +import sys; +import os; + +import argparse; + +from python.run import run, print_and_run; + +from python.build import build; + +def split_args(argv): + argv0 = argv[0]; + + argv = argv[1:]; + + for i, arg in enumerate(argv): + if arg == "--": + return argv0, argv[:i], argv[i+1:]; + + return argv0, argv, []; + +def parseargs(): + parser = argparse.ArgumentParser(description = "build command") + + parser.add_argument("--build-type", "--buildtype", default = "release"); + + parser.add_argument("--valgrind", action = "store_true"); + + argv0, my_args, run_args = split_args(sys.argv); + + retval = parser.parse_args(my_args); + + retval.argv0 = argv0; + + retval.run_args = run_args; + + return retval; + +def main(args): + exe = build(args); + + command = (exe, *args.run_args); + + if args.valgrind: + command = ("valgrind", "--exit-on-first-error=yes", ) + command; + + print_and_run(command); + + return 0; + +exit(main(parseargs())); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scope/assign.c b/scope/assign.c new file mode 100644 index 0000000..e69de29 diff --git a/scope/assign.h b/scope/assign.h new file mode 100644 index 0000000..e69de29 diff --git a/scope/declare.c b/scope/declare.c new file mode 100644 index 0000000..e69de29 diff --git a/scope/declare.h b/scope/declare.h new file mode 100644 index 0000000..e69de29 diff --git a/scope/foreach.c b/scope/foreach.c new file mode 100644 index 0000000..3d1ec65 --- /dev/null +++ b/scope/foreach.c @@ -0,0 +1,30 @@ + +#include + +#include + +#include "variable/struct.h" + +#include "struct.h" +#include "foreach.h" + +void scope_foreach( + const struct scope* this, + void (*foreach)( + struct string*, + truthtable_t)) +{ + ENTER; + + for (struct avl_node_t* node = this->tree->head; + node; + node = node->next) + { + const struct variable* variable = node->item; + + foreach(variable->name, variable->value); + } + + EXIT; +} + diff --git a/scope/foreach.h b/scope/foreach.h new file mode 100644 index 0000000..0aa079e --- /dev/null +++ b/scope/foreach.h @@ -0,0 +1,6 @@ + +void scope_foreach( + const struct scope* this, + void (*foreach)( + struct string*, + truthtable_t)); diff --git a/scope/free.c b/scope/free.c new file mode 100644 index 0000000..77f5e28 --- /dev/null +++ b/scope/free.c @@ -0,0 +1,8 @@ + +#include + +void free_scope(struct scope* this) +{ + TODO; +} + diff --git a/scope/free.h b/scope/free.h new file mode 100644 index 0000000..44a5c55 --- /dev/null +++ b/scope/free.h @@ -0,0 +1,2 @@ + +void free_scope(struct scope* this); diff --git a/scope/has.c b/scope/has.c new file mode 100644 index 0000000..e69de29 diff --git a/scope/has.h b/scope/has.h new file mode 100644 index 0000000..e69de29 diff --git a/scope/lookup.c b/scope/lookup.c new file mode 100644 index 0000000..e69de29 diff --git a/scope/lookup.h b/scope/lookup.h new file mode 100644 index 0000000..e69de29 diff --git a/scope/new.c b/scope/new.c new file mode 100644 index 0000000..e579944 --- /dev/null +++ b/scope/new.c @@ -0,0 +1,96 @@ + +#include + +#include + +#include +#include +#include +#include + +#include +#include + +#include "variable/new.h" +#include "variable/compare.h" +#include "variable/free.h" + +#include "struct.h" +#include "new.h" + +struct scope* new_scope() +{ + ENTER; + + struct scope* this = smalloc(sizeof(*this)); + + this->tree = avl_alloc_tree( + /* comparator: */ compare_variables, + /* free-er: */ free_variable); + + // add W: + { + struct string* w = new_string("w"); + + void* ptr = avl_insert(this->tree, new_variable(w, W)); + + assert(ptr); + + free_string(w); + } + + // add X: + { + struct string* x = new_string("x"); + + void* ptr = avl_insert(this->tree, new_variable(x, X)); + + assert(ptr); + + free_string(x); + } + + // add Y: + { + struct string* y = new_string("y"); + + void* ptr = avl_insert(this->tree, new_variable(y, Y)); + + assert(ptr); + + free_string(y); + } + + // add Z: + { + struct string* z = new_string("z"); + + void* ptr = avl_insert(this->tree, new_variable(z, Z)); + + assert(ptr); + + free_string(z); + } + + EXIT; + return this; +} + + + + + + + + + + + + + + + + + + + diff --git a/scope/new.h b/scope/new.h new file mode 100644 index 0000000..4cf3275 --- /dev/null +++ b/scope/new.h @@ -0,0 +1,2 @@ + +struct scope* new_scope(void); diff --git a/scope/struct.h b/scope/struct.h new file mode 100644 index 0000000..7a5d6f5 --- /dev/null +++ b/scope/struct.h @@ -0,0 +1,6 @@ + +struct scope +{ + struct avl_tree_t* tree; +}; + diff --git a/scope/variable/compare.c b/scope/variable/compare.c new file mode 100644 index 0000000..062cce1 --- /dev/null +++ b/scope/variable/compare.c @@ -0,0 +1,21 @@ + +#include + +#include + +#include "struct.h" +#include "compare.h" + +int compare_variables(const void* a, const void* b) +{ + ENTER; + + const struct variable * const A = a; + const struct variable * const B = b; + + int cmp = compare_string(A->name, B->name); + + EXIT; + return cmp; +} + diff --git a/scope/variable/compare.h b/scope/variable/compare.h new file mode 100644 index 0000000..668a555 --- /dev/null +++ b/scope/variable/compare.h @@ -0,0 +1,2 @@ + +int compare_variables(const void* a, const void* b); diff --git a/scope/variable/free.c b/scope/variable/free.c new file mode 100644 index 0000000..8a009fa --- /dev/null +++ b/scope/variable/free.c @@ -0,0 +1,10 @@ + +#include + +#include "free.h" + +void free_variable(void* ptr) +{ + TODO; +} + diff --git a/scope/variable/free.h b/scope/variable/free.h new file mode 100644 index 0000000..a69948c --- /dev/null +++ b/scope/variable/free.h @@ -0,0 +1,2 @@ + +void free_variable(void* ptr); diff --git a/scope/variable/new.c b/scope/variable/new.c new file mode 100644 index 0000000..3ba74de --- /dev/null +++ b/scope/variable/new.c @@ -0,0 +1,22 @@ + +#include + +#include "struct.h" +#include "new.h" + +struct variable* new_variable( + struct string* name, + truthtable_t value) +{ + ENTER; + + struct variable* this = smalloc(sizeof(*this)); + + this->name = inc_string(name); + + this->value = value; + + EXIT; + return this; +} + diff --git a/scope/variable/new.h b/scope/variable/new.h new file mode 100644 index 0000000..994a4ba --- /dev/null +++ b/scope/variable/new.h @@ -0,0 +1,4 @@ + +struct variable* new_variable( + struct string* name, + truthtable_t value); diff --git a/scope/variable/struct.h b/scope/variable/struct.h new file mode 100644 index 0000000..2d2571e --- /dev/null +++ b/scope/variable/struct.h @@ -0,0 +1,8 @@ + +struct variable +{ + struct string* name; + + truthtable_t value; +}; + diff --git a/simplifications/free.c b/simplifications/free.c new file mode 100644 index 0000000..0036cac --- /dev/null +++ b/simplifications/free.c @@ -0,0 +1,13 @@ + +#include + +#include "free.h" + +void free_simplifications( + struct simplifications* this) +{ + ENTER; + TODO; + EXIT; +} + diff --git a/simplifications/free.h b/simplifications/free.h new file mode 100644 index 0000000..fc28291 --- /dev/null +++ b/simplifications/free.h @@ -0,0 +1,5 @@ + +struct simplifications; + +void free_simplifications( + struct simplifications* this); diff --git a/simplifications/lookup.c b/simplifications/lookup.c new file mode 100644 index 0000000..e69de29 diff --git a/simplifications/lookup.h b/simplifications/lookup.h new file mode 100644 index 0000000..e69de29 diff --git a/simplifications/new.c b/simplifications/new.c new file mode 100644 index 0000000..91b23e0 --- /dev/null +++ b/simplifications/new.c @@ -0,0 +1,246 @@ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "struct.h" +#include "new.h" + +struct simplifications* new_simplifications( + const struct operators* operators, + const struct scope* scope) +{ + ENTER; + + struct simplifications* this = smalloc(sizeof(*this)); + + // initialize with unreachable: + { + struct expression* unreachable = new_unreachable_expression(); + + for (int i = 0; i < N; i++) + { + this->lookup[i] = inc_expression(unreachable); + } + + free_expression(unreachable); + } + + bool consider( + truthtable_t truthtable, + struct expression* expression) + { + if (expression->cost < this->lookup[truthtable]->cost) + { + struct expression **record = &this->lookup[truthtable]; + + free_expression(*record); + + *record = inc_expression(expression); + + return true; + } + + return false; + } + + // consider zero literal: + { + struct expression* zero = new_literal_expression( + /* cost = */ 1, + /* value = */ 0); + + consider( + /* truthtable: */ 0, + /* expression: */ zero); + + free_expression(zero); + } + + // consider one literal: + { + struct expression* one = new_literal_expression( + /* cost = */ 1, + /* value = */ 1); + + consider( + /* truthtable: */ M, + /* expression: */ one); + + free_expression(one); + } + + // introduce variables: + { + scope_foreach(scope, ({ + void foreach( + struct string* name, + truthtable_t value) + { + printf("value = %016hb\n", value); + + struct expression* variable = new_variable_expression( + /* cost: */ 1, + /* name: */ name); + + consider( + /* truthtable: */ value, + /* expression: */ variable); + + free_expression(variable); + } + + foreach; + })); + } + + struct truthtable_set* done = new_truthtable_set(); + struct truthtable_set* queued = new_truthtable_set(); + + for (unsigned i = 0; i < N; i++) + { + truthtable_set_add(queued, (truthtable_t) i); + } + + for (unsigned i = 0; i < N; i++) + { + truthtable_t truthtable = 0; + + int cost = INT_MAX; + + truthtable_set_foreach(queued, ({ + void foreach(truthtable_t element_truthtable) + { + int element_cost = this->lookup[element_truthtable]->cost; + + if (element_cost < cost) + { + truthtable = element_truthtable; + + cost = element_cost; + } + } + + foreach; + })); + + printf("queued.len = %lu\n", queued->n); + + if (cost == INT_MAX) + { + break; + } + + struct expression* expression = this->lookup[truthtable]; + + { + printf("truthtable = 0b%016hb, cost = %i: ", truthtable, cost); + + expression_print(expression), puts(""); + } + + truthtable_set_discard(queued, truthtable); + + // consider 'not': + { + struct expression* not = new_not_expression( + /* cost: */ cost + 1, + /* subexpression: */ expression); + + consider( + /* truthtable: */ (truthtable_t) ~truthtable, + /* expression: */ not); + + free_expression(not); + } + + // consider 'or' and 'and': + { + truthtable_set_foreach(done, ({ + void foreach(truthtable_t other_truthtable) + { + struct expression* const other_expression = \ + this->lookup[other_truthtable]; + + if (other_expression->cost == INT_MAX) + return; + + int op_cost = 0 \ + + cost \ + + 1 \ + + this->lookup[other_truthtable]->cost; + + struct expression* or = new_or_expression( + /* cost: */ op_cost, + /* left: */ expression, + /* right: */ other_expression); + + struct expression* and = new_and_expression( + /* cost: */ op_cost, + /* left: */ expression, + /* right: */ other_expression); + + consider( + /* truthtable: */ truthtable | other_truthtable, + /* expression: */ or); + + consider( + /* truthtable: */ truthtable & other_truthtable, + /* expression: */ and); + + free_expression(or); + free_expression(and); + } + foreach; + })); + } + + truthtable_set_add(done, truthtable); + } + + free_truthtable_set(done); + free_truthtable_set(queued); + + EXIT; + return this; +} + + + + + + + + + + + + + + + diff --git a/simplifications/new.h b/simplifications/new.h new file mode 100644 index 0000000..29414d6 --- /dev/null +++ b/simplifications/new.h @@ -0,0 +1,7 @@ + +struct operators; +struct scope; + +struct simplifications* new_simplifications( + const struct operators* operators, + const struct scope* scope); diff --git a/simplifications/struct.h b/simplifications/struct.h new file mode 100644 index 0000000..28f0f75 --- /dev/null +++ b/simplifications/struct.h @@ -0,0 +1,10 @@ + +#include + +struct expression; + +struct simplifications +{ + struct expression* lookup[N]; +}; + diff --git a/string/compare.c b/string/compare.c new file mode 100644 index 0000000..bd82e1f --- /dev/null +++ b/string/compare.c @@ -0,0 +1,13 @@ + +#include + +#include "struct.h" +#include "compare.h" + +int compare_string( + const struct string* a, + const struct string* b) +{ + return strcmp(a->data, b->data); +} + diff --git a/string/compare.h b/string/compare.h new file mode 100644 index 0000000..4e114b8 --- /dev/null +++ b/string/compare.h @@ -0,0 +1,4 @@ + +int compare_string( + const struct string* a, + const struct string* b); diff --git a/string/free.c b/string/free.c new file mode 100644 index 0000000..821a326 --- /dev/null +++ b/string/free.c @@ -0,0 +1,15 @@ + +#include + +#include "struct.h" +#include "free.h" + +void free_string( + struct string* this) +{ + if (this && !--this->refcount) + { + TODO; + } +} + diff --git a/string/free.h b/string/free.h new file mode 100644 index 0000000..cebb049 --- /dev/null +++ b/string/free.h @@ -0,0 +1,3 @@ + +void free_string( + struct string* this); diff --git a/string/inc.c b/string/inc.c new file mode 100644 index 0000000..7f90d61 --- /dev/null +++ b/string/inc.c @@ -0,0 +1,17 @@ + +#include + +#include "struct.h" +#include "inc.h" + +struct string* inc_string( + struct string* this) +{ + if (this) + { + this->refcount++; + } + + return this; +} + diff --git a/string/inc.h b/string/inc.h new file mode 100644 index 0000000..edbd190 --- /dev/null +++ b/string/inc.h @@ -0,0 +1,3 @@ + +struct string* inc_string( + struct string* this); diff --git a/string/new.c b/string/new.c new file mode 100644 index 0000000..eb6054d --- /dev/null +++ b/string/new.c @@ -0,0 +1,27 @@ + +#include + +#include "struct.h" +#include "new.h" + +struct string* new_string( + const char* data_ro) +{ + ENTER; + + size_t len = strlen(data_ro); + + char* data = malloc(len + 1); + + memcpy(data, data_ro, len + 1); + + struct string* this = smalloc(sizeof(*this)); + + this->data = data; + this->len = len; + this->refcount = 1; + + EXIT; + return this; +} + diff --git a/string/new.h b/string/new.h new file mode 100644 index 0000000..dd934ee --- /dev/null +++ b/string/new.h @@ -0,0 +1,3 @@ + +struct string* new_string( + const char* data_to); diff --git a/string/print.c b/string/print.c new file mode 100644 index 0000000..c9e498d --- /dev/null +++ b/string/print.c @@ -0,0 +1,12 @@ + +#include + +#include "struct.h" +#include "print.h" + +void string_print( + struct string* this) +{ + fwrite(this->data, 1, this->len, stdout); +} + diff --git a/string/print.h b/string/print.h new file mode 100644 index 0000000..dba1b69 --- /dev/null +++ b/string/print.h @@ -0,0 +1,3 @@ + +void string_print( + struct string* this); diff --git a/string/struct.h b/string/struct.h new file mode 100644 index 0000000..fad4d98 --- /dev/null +++ b/string/struct.h @@ -0,0 +1,9 @@ + +struct string +{ + char* data; + size_t len; + + unsigned refcount; +}; + diff --git a/structs/operators.h b/structs/operators.h new file mode 100644 index 0000000..59ebb2a --- /dev/null +++ b/structs/operators.h @@ -0,0 +1,12 @@ + +#ifndef STRUCT_OPERATORS +#define STRUCT_OPERATORS + +struct operators +{ + bool not; + bool or; + bool and; +}; + +#endif diff --git a/test b/test new file mode 100644 index 0000000..1bc7f0c --- /dev/null +++ b/test @@ -0,0 +1,8 @@ +#!/usr/bin/env python3 + +# there should be some kind of indiviual tests? +# and a framework? + +# the framework should provide a way to describe what build the +# indiviual test wants, and possibly build it + diff --git a/truthtable_set/add.c b/truthtable_set/add.c new file mode 100644 index 0000000..7538815 --- /dev/null +++ b/truthtable_set/add.c @@ -0,0 +1,36 @@ + +#include + +#include + +#include "struct.h" +#include "add.h" + +bool truthtable_set_add( + struct truthtable_set* this, + truthtable_t truthtable) +{ + bool is_new; + + struct avl_node_t* node = avl_search(this->tree, &truthtable); + + if (node) + { + TODO; + } + else + { + is_new = true; + + truthtable_t* item = smalloc(sizeof(*item)); + + *item = truthtable; + + avl_insert(this->tree, item); + + this->n++; + } + + return is_new; +} + diff --git a/truthtable_set/add.h b/truthtable_set/add.h new file mode 100644 index 0000000..d34c878 --- /dev/null +++ b/truthtable_set/add.h @@ -0,0 +1,4 @@ + +bool truthtable_set_add( + struct truthtable_set* this, + truthtable_t truthtable); diff --git a/truthtable_set/discard.c b/truthtable_set/discard.c new file mode 100644 index 0000000..4d1c9f9 --- /dev/null +++ b/truthtable_set/discard.c @@ -0,0 +1,32 @@ + +#include + +#include + +#include "struct.h" +#include "discard.h" + +bool truthtable_set_discard( + struct truthtable_set* this, + truthtable_t truthtable) +{ + struct avl_node_t* node = avl_search(this->tree, &truthtable); + + bool was_present; + + if (node) + { + was_present = true; + + avl_delete_node(this->tree, node); + + this->n--; + } + else + { + TODO; + } + + return was_present; +} + diff --git a/truthtable_set/discard.h b/truthtable_set/discard.h new file mode 100644 index 0000000..a2877e6 --- /dev/null +++ b/truthtable_set/discard.h @@ -0,0 +1,4 @@ + +bool truthtable_set_discard( + struct truthtable_set* this, + truthtable_t truthtable); diff --git a/truthtable_set/foreach.c b/truthtable_set/foreach.c new file mode 100644 index 0000000..3aad14d --- /dev/null +++ b/truthtable_set/foreach.c @@ -0,0 +1,19 @@ + +#include + +#include + +#include "struct.h" +#include "foreach.h" + +void truthtable_set_foreach( + const struct truthtable_set* this, + void (*foreach)( + truthtable_t)) +{ + for (struct avl_node_t* node = this->tree->head; node; node = node->next) + { + foreach(*(truthtable_t*) node->item); + } +} + diff --git a/truthtable_set/foreach.h b/truthtable_set/foreach.h new file mode 100644 index 0000000..11ad390 --- /dev/null +++ b/truthtable_set/foreach.h @@ -0,0 +1,6 @@ + +void truthtable_set_foreach( + const struct truthtable_set* this, + void (*foreach)( + truthtable_t)); + diff --git a/truthtable_set/free.c b/truthtable_set/free.c new file mode 100644 index 0000000..5445020 --- /dev/null +++ b/truthtable_set/free.c @@ -0,0 +1,11 @@ + +#include + +#include "free.h" + +void free_truthtable_set( + struct truthtable_set* this) +{ + TODO; +} + diff --git a/truthtable_set/free.h b/truthtable_set/free.h new file mode 100644 index 0000000..d16acdf --- /dev/null +++ b/truthtable_set/free.h @@ -0,0 +1,5 @@ + +struct truthtable_set; + +void free_truthtable_set( + struct truthtable_set* this); diff --git a/truthtable_set/is_empty.c b/truthtable_set/is_empty.c new file mode 100644 index 0000000..e4fbf63 --- /dev/null +++ b/truthtable_set/is_empty.c @@ -0,0 +1,14 @@ + +#include + +#include + +#include "struct.h" +#include "is_empty.h" + +bool truthtable_set_is_empty( + const struct truthtable_set* this) +{ + return !this->tree->head; +} + diff --git a/truthtable_set/is_empty.h b/truthtable_set/is_empty.h new file mode 100644 index 0000000..37218d2 --- /dev/null +++ b/truthtable_set/is_empty.h @@ -0,0 +1,3 @@ + +bool truthtable_set_is_empty( + const struct truthtable_set* this); diff --git a/truthtable_set/new.c b/truthtable_set/new.c new file mode 100644 index 0000000..c1ac70c --- /dev/null +++ b/truthtable_set/new.c @@ -0,0 +1,39 @@ + +#include + +#include + +#include "struct.h" +#include "new.h" + +static int compare_truthtables(const void* a, const void* b) +{ + const truthtable_t* A = a; + const truthtable_t* B = b; + + if (*A < *B) + return -1; + else if (*A > *B) + return +1; + else + return +0; +} + +struct truthtable_set* new_truthtable_set(void) +{ + ENTER; + + struct truthtable_set* this = smalloc(sizeof(*this)); + + struct avl_tree_t* tree = avl_alloc_tree( + /* comparator: */ compare_truthtables, + /* free-er: */ free); + + this->tree = tree; + + this->n = 0; + + EXIT; + return this; +} + diff --git a/truthtable_set/new.h b/truthtable_set/new.h new file mode 100644 index 0000000..9de4b16 --- /dev/null +++ b/truthtable_set/new.h @@ -0,0 +1,2 @@ + +struct truthtable_set* new_truthtable_set(void); diff --git a/truthtable_set/struct.h b/truthtable_set/struct.h new file mode 100644 index 0000000..a592bf5 --- /dev/null +++ b/truthtable_set/struct.h @@ -0,0 +1,10 @@ + +struct truthtable_set +{ + struct avl_tree_t* tree; + + unsigned refcount; + + size_t n; +}; + diff --git a/typedefs/truthtable_t.h b/typedefs/truthtable_t.h new file mode 100644 index 0000000..1776d83 --- /dev/null +++ b/typedefs/truthtable_t.h @@ -0,0 +1,5 @@ + +#include + +typedef uint16_t truthtable_t; +