Compare commits
21 commits
main
...
dev-assign
| Author | SHA1 | Date | |
|---|---|---|---|
| 154b1b38bf | |||
| 21c7967f44 | |||
| 6529ab9818 | |||
| 08b5f47426 | |||
| 3213e1deac | |||
| 15a09a1506 | |||
| 1b9fe3b44a | |||
| ff78073433 | |||
| 7f012a32c8 | |||
| 6f326a9bcb | |||
| 8152650e06 | |||
| 99e5f2d8e6 | |||
| 6b8ff52061 | |||
| 90068e62fa | |||
| 82db0d4e03 | |||
| d9556aeae9 | |||
| 105e9306a4 | |||
| 1097f2c2d8 | |||
| 27bef1109d | |||
| 82a102c421 | |||
| cb1738376d |
212 changed files with 6477 additions and 4373 deletions
21
.gitignore
vendored
21
.gitignore
vendored
|
|
@ -1,18 +1,19 @@
|
||||||
|
|
||||||
|
bin
|
||||||
|
|
||||||
|
.simplifications.bin
|
||||||
|
.~lock.stats.ods#
|
||||||
|
stats.ods
|
||||||
|
|
||||||
|
|
||||||
simplifications.bin
|
simplifications.bin
|
||||||
|
|
||||||
.simplifier-*.bin
|
.simplifier-*.bin
|
||||||
|
|
||||||
|
.direnv/
|
||||||
|
|
||||||
|
typescript
|
||||||
|
|
||||||
vgcore.*
|
vgcore.*
|
||||||
|
|
||||||
.direnv/
|
|
||||||
.simplifications.bin
|
|
||||||
.~lock.stats.ods#
|
|
||||||
*~
|
*~
|
||||||
stats.ods
|
|
||||||
|
|
||||||
bin/
|
|
||||||
typescript
|
|
||||||
.main.c.swp
|
|
||||||
.build-cache/
|
|
||||||
__pycache__
|
|
||||||
|
|
|
||||||
18
README.md
18
README.md
|
|
@ -1,18 +0,0 @@
|
||||||
|
|
||||||
# 4 variable boolean simplifier
|
|
||||||
|
|
||||||
Boolean simplifier uses brute-force to generate all simplest expression trees
|
|
||||||
for any 4-variable truthtable. It's pretty cool! And it has a repl! and it has
|
|
||||||
colors! It uses dynamic programming to run in reasonable time.
|
|
||||||
|
|
||||||
The python script takes 6 hours, the C program takes 30 seconds.
|
|
||||||
|
|
||||||
By default, the program will simplify/re-write the given expression(s) using
|
|
||||||
only "or", "and" and "not" operators. You can tell it to use all supported
|
|
||||||
operators ("xor", "xnor", "nor", "nand", etc.) using `-e`. Or, you can
|
|
||||||
explicitly control which operators to use using `-o`. Ternary takes a long
|
|
||||||
time, so it is not included in `-e`, you have to speficially request it using
|
|
||||||
`-o`. Out of the box, it'll have to build it's cache, you can use `-B` to
|
|
||||||
force a rebuild.
|
|
||||||
|
|
||||||
|
|
||||||
596
avl/avl.c
596
avl/avl.c
|
|
@ -1,596 +0,0 @@
|
||||||
/*****************************************************************************
|
|
||||||
|
|
||||||
avl.c - Source code for the AVL-tree library.
|
|
||||||
|
|
||||||
Copyright (C) 1998 Michael H. Buselli <cosine@cosine.org>
|
|
||||||
Copyright (C) 2000-2002 Wessel Dankers <wsl@nl.linux.org>
|
|
||||||
|
|
||||||
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 <cosine@cosine.org>.
|
|
||||||
|
|
||||||
Modified by Wessel Dankers <wsl@nl.linux.org> 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 <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <errno.h>
|
|
||||||
|
|
||||||
#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
|
|
||||||
186
avl/avl.h
186
avl/avl.h
|
|
@ -1,186 +0,0 @@
|
||||||
/*****************************************************************************
|
|
||||||
|
|
||||||
avl.h - Source code for the AVL-tree library.
|
|
||||||
|
|
||||||
Copyright (C) 1998 Michael H. Buselli <cosine@cosine.org>
|
|
||||||
Copyright (C) 2000-2002 Wessel Dankers <wsl@nl.linux.org>
|
|
||||||
|
|
||||||
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 <cosine@cosine.org>.
|
|
||||||
|
|
||||||
Modified by Wessel Dankers <wsl@nl.linux.org> 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
|
|
||||||
18
buildtypes/debug.txt
Normal file
18
buildtypes/debug.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
-g
|
||||||
|
|
||||||
|
-D _GNU_SOURCE
|
||||||
|
|
||||||
|
-D ZDEBUG=1
|
||||||
|
|
||||||
|
-D DEBUG_BUILD
|
||||||
|
|
||||||
|
-I .
|
||||||
|
|
||||||
|
-Werror -Wall -Wextra -Wstrict-prototypes -Wfatal-errors
|
||||||
|
|
||||||
|
-Wno-unused
|
||||||
|
|
||||||
|
-lreadline
|
||||||
|
-lm
|
||||||
|
|
||||||
14
buildtypes/release.txt
Normal file
14
buildtypes/release.txt
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
-D _GNU_SOURCE
|
||||||
|
|
||||||
|
-D ZDEBUG=0
|
||||||
|
|
||||||
|
-I .
|
||||||
|
|
||||||
|
-O3
|
||||||
|
|
||||||
|
-Werror -Wall -Wextra -Wstrict-prototypes -Wfatal-errors
|
||||||
|
|
||||||
|
-lreadline
|
||||||
|
-lm
|
||||||
|
|
||||||
18
buildtypes/test-multithreaded.txt
Normal file
18
buildtypes/test-multithreaded.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
-g
|
||||||
|
|
||||||
|
-D _GNU_SOURCE
|
||||||
|
|
||||||
|
-D TEST_BUILD
|
||||||
|
|
||||||
|
-D MULTITHREADED_BUILD
|
||||||
|
|
||||||
|
-I .
|
||||||
|
|
||||||
|
-Werror -Wall -Wextra -Wstrict-prototypes -Wfatal-errors
|
||||||
|
|
||||||
|
-Wno-unused
|
||||||
|
|
||||||
|
-lreadline
|
||||||
|
-lm
|
||||||
|
|
||||||
18
buildtypes/test.txt
Normal file
18
buildtypes/test.txt
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
-g
|
||||||
|
|
||||||
|
-D _GNU_SOURCE
|
||||||
|
|
||||||
|
-D ZDEBUG=0
|
||||||
|
|
||||||
|
-D TEST_BUILD
|
||||||
|
|
||||||
|
-I .
|
||||||
|
|
||||||
|
-Werror -Wall -Wextra -Wstrict-prototypes -Wfatal-errors
|
||||||
|
|
||||||
|
-Wno-unused
|
||||||
|
|
||||||
|
-lreadline
|
||||||
|
-lm
|
||||||
|
|
||||||
41
calculate_assignment_simplifications.c
Normal file
41
calculate_assignment_simplifications.c
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include <defines.h>
|
||||||
|
|
||||||
|
#include <cmdln.h>
|
||||||
|
|
||||||
|
#include "simplifications.h"
|
||||||
|
#include "calculate_simplifications.h"
|
||||||
|
#include "calculate_assignment_simplifications.h"
|
||||||
|
|
||||||
|
void calculate_assignment_simplifications(
|
||||||
|
const struct cmdln_flags* flags,
|
||||||
|
struct simplifications* simps)
|
||||||
|
{
|
||||||
|
ENTER;
|
||||||
|
|
||||||
|
struct cmdln_flags flag_no_assign = *flags;
|
||||||
|
|
||||||
|
flag_no_assign.use_operators.assignment = false;
|
||||||
|
|
||||||
|
for (int a = 0; a < N; a++)
|
||||||
|
{
|
||||||
|
simps->with_vars[a] = \
|
||||||
|
calculate_simplifications(
|
||||||
|
/* cmdln flags: */ &flag_no_assign,
|
||||||
|
/* have extra variable? */ true,
|
||||||
|
/* extra variable value: */ a);
|
||||||
|
}
|
||||||
|
|
||||||
|
simps->main = calculate_simplifications(flags, false, 0);
|
||||||
|
|
||||||
|
EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
11
calculate_assignment_simplifications.h
Normal file
11
calculate_assignment_simplifications.h
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
|
struct cmdln_flags;
|
||||||
|
struct simplifications;
|
||||||
|
|
||||||
|
void calculate_assignment_simplifications(
|
||||||
|
const struct cmdln_flags* flags,
|
||||||
|
struct simplifications* simps);
|
||||||
|
|
||||||
|
#endif
|
||||||
637
calculate_simplifications.c
Normal file
637
calculate_simplifications.c
Normal file
|
|
@ -0,0 +1,637 @@
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
#include <cmdln.h>
|
||||||
|
|
||||||
|
#include <print.h>
|
||||||
|
|
||||||
|
#ifdef MULTITHREADED_BUILD
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "calculate_simplifications.h"
|
||||||
|
|
||||||
|
void helper(
|
||||||
|
const struct cmdln_flags* flags,
|
||||||
|
struct simplifications* simps,
|
||||||
|
bool have_extra_variable,
|
||||||
|
uint16_t A)
|
||||||
|
{
|
||||||
|
ENTER;
|
||||||
|
|
||||||
|
struct row* row = have_extra_variable ? &simps->with_vars[A] : &simps->main;
|
||||||
|
|
||||||
|
// init 'row->data':
|
||||||
|
{
|
||||||
|
for (int i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
row->data[i].kind = ek_unreachable;
|
||||||
|
|
||||||
|
row->data[i].cost = INT_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// heap of truthtables; key = cost
|
||||||
|
struct {
|
||||||
|
uint16_t data[N];
|
||||||
|
int n;
|
||||||
|
|
||||||
|
// truthtable -> index in 'todo'
|
||||||
|
int reverse[N];
|
||||||
|
} todo;
|
||||||
|
|
||||||
|
// init 'todo':
|
||||||
|
{
|
||||||
|
todo.n = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
todo.reverse[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t pop(void)
|
||||||
|
{
|
||||||
|
assert(todo.n > 0);
|
||||||
|
|
||||||
|
uint16_t retval = todo.data[0];
|
||||||
|
|
||||||
|
todo.reverse[retval] = -1;
|
||||||
|
|
||||||
|
uint16_t moving = todo.data[todo.n-- - 1];
|
||||||
|
|
||||||
|
int cost = row->data[moving].cost;
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
again:
|
||||||
|
{
|
||||||
|
int left = index * 2 + 1;
|
||||||
|
int right = index * 2 + 2;
|
||||||
|
|
||||||
|
uint16_t smallest = moving;
|
||||||
|
|
||||||
|
if (left < todo.n && row->data[todo.data[left]].cost < cost)
|
||||||
|
smallest = todo.data[left];
|
||||||
|
|
||||||
|
if (right < todo.n && row->data[todo.data[right]].cost < row->data[smallest].cost)
|
||||||
|
smallest = todo.data[right];
|
||||||
|
|
||||||
|
if (smallest == moving)
|
||||||
|
{
|
||||||
|
todo.data[index] = moving;
|
||||||
|
|
||||||
|
todo.reverse[moving] = index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int new = todo.reverse[smallest];
|
||||||
|
|
||||||
|
todo.data[index] = smallest;
|
||||||
|
|
||||||
|
todo.reverse[smallest] = index;
|
||||||
|
|
||||||
|
index = new;
|
||||||
|
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(uint16_t truthtable, int cost)
|
||||||
|
{
|
||||||
|
assert(todo.reverse[truthtable] == -1);
|
||||||
|
|
||||||
|
int index = todo.n++, new_index;
|
||||||
|
|
||||||
|
while (index > 0 && row->data[todo.data[new_index = (index - 1) / 2]].cost > cost)
|
||||||
|
{
|
||||||
|
todo.data[index] = todo.data[new_index];
|
||||||
|
|
||||||
|
todo.reverse[todo.data[new_index]] = index;
|
||||||
|
|
||||||
|
index = new_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
todo.data[index] = truthtable;
|
||||||
|
|
||||||
|
todo.reverse[truthtable] = index;
|
||||||
|
|
||||||
|
row->data[truthtable].cost = cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
void update(uint16_t truthtable, int cost)
|
||||||
|
{
|
||||||
|
assert(todo.reverse[truthtable] != -1);
|
||||||
|
|
||||||
|
assert(cost < row->data[truthtable].cost);
|
||||||
|
|
||||||
|
int index =todo. reverse[truthtable], new_index;
|
||||||
|
|
||||||
|
while (index > 0 && row->data[todo.data[new_index = (index - 1) / 2]].cost > cost)
|
||||||
|
{
|
||||||
|
todo.data[index] = todo.data[new_index];
|
||||||
|
|
||||||
|
todo.reverse[todo.data[new_index]] = index;
|
||||||
|
|
||||||
|
index = new_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
todo.data[index] = truthtable;
|
||||||
|
todo.reverse[truthtable] = index;
|
||||||
|
|
||||||
|
row->data[truthtable].cost = cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a list of the "done" truthtables
|
||||||
|
struct {
|
||||||
|
int headtails[N], next[N], head;
|
||||||
|
|
||||||
|
// for debugging:
|
||||||
|
#if ZDEBUG
|
||||||
|
bool in[N];
|
||||||
|
#endif
|
||||||
|
} done = {};
|
||||||
|
|
||||||
|
// init 'done':
|
||||||
|
{
|
||||||
|
done.head = -1;
|
||||||
|
|
||||||
|
for (int i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
done.headtails[i] = -1;
|
||||||
|
|
||||||
|
#if ZDEBUG
|
||||||
|
done.in[i] = false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(int index)
|
||||||
|
{
|
||||||
|
#if ZDEBUG
|
||||||
|
assert(!done.in[index]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int head = index & 1 ? index & ~(index & -index) : index, prevhead = -1;
|
||||||
|
|
||||||
|
while (done.headtails[head] == -1 || index < done.headtails[head])
|
||||||
|
{
|
||||||
|
done.headtails[head] = index;
|
||||||
|
|
||||||
|
prevhead = head, head = head & ~(head & -head);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done.headtails[head] < index)
|
||||||
|
{
|
||||||
|
if (prevhead == -1)
|
||||||
|
{
|
||||||
|
assert(done.headtails[head] == head);
|
||||||
|
|
||||||
|
done.next[head] = index;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int tophalftail = done.headtails[prevhead - 1];
|
||||||
|
|
||||||
|
assert(tophalftail != -1);
|
||||||
|
|
||||||
|
done.next[tophalftail] = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
done.head = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int n = ~index & M;
|
||||||
|
int tail = index & 1 ? index : index | (n & -n), prevtail = -1;
|
||||||
|
|
||||||
|
while (done.headtails[tail] == -1 || done.headtails[tail] < index)
|
||||||
|
{
|
||||||
|
done.headtails[tail] = index;
|
||||||
|
|
||||||
|
prevtail = tail, tail = tail | (n = ~tail & M, n & -n);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index < done.headtails[tail])
|
||||||
|
{
|
||||||
|
if (prevtail == -1)
|
||||||
|
{
|
||||||
|
assert(done.headtails[tail] == tail);
|
||||||
|
|
||||||
|
#if ZDEBUG
|
||||||
|
assert(done.in[tail]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
done.next[index] = tail;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int bottomhalfhead = done.headtails[prevtail + 1];
|
||||||
|
|
||||||
|
assert(bottomhalfhead != -1);
|
||||||
|
|
||||||
|
done.next[index] = bottomhalfhead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
done.next[index] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ZDEBUG
|
||||||
|
done.in[index] = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
append(W, 0), row->data[W].kind = ek_W;
|
||||||
|
append(X, 0), row->data[X].kind = ek_X;
|
||||||
|
append(Y, 0), row->data[Y].kind = ek_Y;
|
||||||
|
append(Z, 0), row->data[Z].kind = ek_Z;
|
||||||
|
|
||||||
|
append(0, 1), row->data[0].kind = ek_0;
|
||||||
|
append(M, 1), row->data[M].kind = ek_1;
|
||||||
|
|
||||||
|
if (have_extra_variable && todo.reverse[A] == -1)
|
||||||
|
{
|
||||||
|
append(A, 0), row->data[A].kind = ek_A;
|
||||||
|
}
|
||||||
|
|
||||||
|
// disable terminal autowrap:
|
||||||
|
if (!ZDEBUG && flags->verbose && flags->print_with_color)
|
||||||
|
{
|
||||||
|
printf("\e[?7l");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int iterations = 1; todo.n && iterations <= N; iterations++)
|
||||||
|
{
|
||||||
|
uint16_t truthtable = pop();
|
||||||
|
|
||||||
|
insert(truthtable);
|
||||||
|
|
||||||
|
int cost = row->data[truthtable].cost;
|
||||||
|
|
||||||
|
if (flags->verbose)
|
||||||
|
{
|
||||||
|
if (!ZDEBUG && flags->print_with_color)
|
||||||
|
{
|
||||||
|
printf("\e[2K");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%i of %i (%.2f%%): [%i] ",
|
||||||
|
iterations, N, (100.0 * iterations / N), cost);
|
||||||
|
|
||||||
|
if (have_extra_variable)
|
||||||
|
{
|
||||||
|
printf("a = 0b%016b, ", A);
|
||||||
|
}
|
||||||
|
|
||||||
|
print(flags, simps, row, truthtable);
|
||||||
|
|
||||||
|
puts("");
|
||||||
|
|
||||||
|
if (!ZDEBUG && flags->print_with_color)
|
||||||
|
{
|
||||||
|
printf("\e[1A");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// consider NOT:
|
||||||
|
if (flags->use_operators.not)
|
||||||
|
{
|
||||||
|
uint16_t not_truthtable = ~truthtable & M;
|
||||||
|
|
||||||
|
int not_cost = cost + 1;
|
||||||
|
|
||||||
|
if (not_cost < row->data[not_truthtable].cost)
|
||||||
|
{
|
||||||
|
if (todo.reverse[not_truthtable] == -1)
|
||||||
|
{
|
||||||
|
append(not_truthtable, not_cost);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
update(not_truthtable, not_cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
row->data[not_truthtable].kind = ek_not;
|
||||||
|
row->data[not_truthtable].left = truthtable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BINARY_OPERATOR(ekind, function) \
|
||||||
|
{ \
|
||||||
|
for (int i = done.head; i != -1; i = done.next[i]) \
|
||||||
|
{ \
|
||||||
|
{ \
|
||||||
|
uint16_t bin_truthtable = function(truthtable, i) & M; \
|
||||||
|
\
|
||||||
|
int bin_cost = 1 + cost + row->data[i].cost; \
|
||||||
|
\
|
||||||
|
if (bin_cost < row->data[bin_truthtable].cost) \
|
||||||
|
{ \
|
||||||
|
if (todo.reverse[bin_truthtable] == -1) \
|
||||||
|
append(bin_truthtable, bin_cost); \
|
||||||
|
else \
|
||||||
|
update(bin_truthtable, bin_cost); \
|
||||||
|
\
|
||||||
|
row->data[bin_truthtable].kind = ekind; \
|
||||||
|
row->data[bin_truthtable].left = truthtable; \
|
||||||
|
row->data[bin_truthtable].right = i; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
{ \
|
||||||
|
uint16_t bin_truthtable = function(i, truthtable) & M; \
|
||||||
|
\
|
||||||
|
int bin_cost = 1 + cost + row->data[i].cost; \
|
||||||
|
\
|
||||||
|
if (bin_cost < row->data[bin_truthtable].cost) \
|
||||||
|
{ \
|
||||||
|
if (todo.reverse[bin_truthtable] == -1) \
|
||||||
|
append(bin_truthtable, bin_cost); \
|
||||||
|
else \
|
||||||
|
update(bin_truthtable, bin_cost); \
|
||||||
|
\
|
||||||
|
row->data[bin_truthtable].kind = ekind; \
|
||||||
|
row->data[bin_truthtable].left = i; \
|
||||||
|
row->data[bin_truthtable].right = truthtable; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OR(a, b) ((a) | (b))
|
||||||
|
#define AND(a, b) ((a) & (b))
|
||||||
|
|
||||||
|
#define ORN(a, b) (~(a) | (b))
|
||||||
|
#define NOR(a, b) ~( (a) | (b))
|
||||||
|
#define ANDN(a, b) (~(a) & (b))
|
||||||
|
#define NAND(a, b) ~( (a) & (b))
|
||||||
|
#define XOR(a, b) (( a) ^ (b))
|
||||||
|
#define NXOR(a, b) ~( (a) ^ (b))
|
||||||
|
|
||||||
|
#define LT(a, b) ((~a) & (b))
|
||||||
|
#define LTE(a, b) ((~a) | (b))
|
||||||
|
#define GT(a, b) (( a) & ~(b))
|
||||||
|
#define GTE(a, b) (( a) | ~(b))
|
||||||
|
|
||||||
|
if (flags->use_operators.or)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_or, OR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.and)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_and, AND);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.orn)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_orn, ORN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.nor)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_nor, NOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.andn)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_andn, ANDN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.nand)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_nand, NAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.xor)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_xor, XOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.nxor)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_nxor, NXOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.lt)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_lt, LT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.lte)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_lte, LTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.gt)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_gt, GT);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.gte)
|
||||||
|
{
|
||||||
|
BINARY_OPERATOR(ek_gte, GTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.ternary)
|
||||||
|
{
|
||||||
|
for (int i = done.head; i != -1; i = done.next[i])
|
||||||
|
{
|
||||||
|
for (int j = done.head; j != -1; j = done.next[j])
|
||||||
|
{
|
||||||
|
int ternary_cost = 1 + cost + row->data[i].cost + row->data[j].cost;
|
||||||
|
|
||||||
|
#define TERNARY(C, T, F) \
|
||||||
|
{ \
|
||||||
|
uint16_t ternary_truthtable = \
|
||||||
|
((C) & (T)) | (~(C) & (F)); \
|
||||||
|
\
|
||||||
|
if (ternary_cost < row->data[ternary_truthtable].cost) \
|
||||||
|
{ \
|
||||||
|
if (todo.reverse[ternary_truthtable] == -1) \
|
||||||
|
{ \
|
||||||
|
append(ternary_truthtable, ternary_cost); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
update(ternary_truthtable, ternary_cost); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
row->data[ternary_truthtable].kind = ek_ternary; \
|
||||||
|
row->data[ternary_truthtable].cond = (C); \
|
||||||
|
row->data[ternary_truthtable].left = (T); \
|
||||||
|
row->data[ternary_truthtable].right = (F); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
|
||||||
|
TERNARY(truthtable, i, j);
|
||||||
|
TERNARY(i, truthtable, j);
|
||||||
|
TERNARY(i, j, truthtable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags->use_operators.assignment)
|
||||||
|
{
|
||||||
|
assert(row == &simps->main);
|
||||||
|
|
||||||
|
for (int t = 0; t < N; t++)
|
||||||
|
{
|
||||||
|
int using_me_cost = simps->with_vars[truthtable].data[t].cost;
|
||||||
|
|
||||||
|
if (using_me_cost < INT_MAX)
|
||||||
|
{
|
||||||
|
int assign_cost = cost + 1 + using_me_cost;
|
||||||
|
|
||||||
|
if (assign_cost < simps->main.data[t].cost)
|
||||||
|
{
|
||||||
|
if (todo.reverse[t] == -1)
|
||||||
|
{
|
||||||
|
append(t, assign_cost);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
update(t, assign_cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
row->data[t].kind = ek_assignment;
|
||||||
|
row->data[t].left = truthtable;
|
||||||
|
row->data[t].right = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear progress line, enable terminal autowrap:
|
||||||
|
if (!ZDEBUG && flags->verbose && flags->print_with_color)
|
||||||
|
{
|
||||||
|
printf("\e[2K"), printf("\e[?7h");
|
||||||
|
}
|
||||||
|
|
||||||
|
EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void calculate_simplifications(
|
||||||
|
const struct cmdln_flags* flags,
|
||||||
|
struct simplifications* simps)
|
||||||
|
{
|
||||||
|
ENTER;
|
||||||
|
|
||||||
|
if (flags->use_operators.assignment)
|
||||||
|
{
|
||||||
|
struct cmdln_flags flag_no_assign = *flags;
|
||||||
|
|
||||||
|
flag_no_assign.use_operators.assignment = false;
|
||||||
|
|
||||||
|
#ifdef MULTITHREADED_BUILD
|
||||||
|
{
|
||||||
|
int num_cores = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
|
||||||
|
zprintf("num_cores = %i" "\n", num_cores);
|
||||||
|
|
||||||
|
assert(0 < num_cores && num_cores < 100);
|
||||||
|
|
||||||
|
struct cmdln_flags flag_no_verbose = flag_no_assign;
|
||||||
|
|
||||||
|
if (!flags->quiet && flags->verbose)
|
||||||
|
{
|
||||||
|
printf(""
|
||||||
|
"note: the usual verbosity is disabled in the "
|
||||||
|
"multithreaded section" "\n"
|
||||||
|
"");
|
||||||
|
|
||||||
|
flag_no_verbose.verbose = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int starts[num_cores];
|
||||||
|
|
||||||
|
void* runner(void* _start)
|
||||||
|
{
|
||||||
|
const int* start = _start;
|
||||||
|
|
||||||
|
for (int a = *start; a < N; a += num_cores)
|
||||||
|
{
|
||||||
|
if (flags->verbose)
|
||||||
|
{
|
||||||
|
printf("a = 0b%016b" "\n", a);
|
||||||
|
}
|
||||||
|
|
||||||
|
helper(
|
||||||
|
/* cmdln flags: */ &flag_no_verbose,
|
||||||
|
/* simplifications */ simps,
|
||||||
|
/* have extra variable? */ true,
|
||||||
|
/* extra variable value: */ a);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_t handles[num_cores];
|
||||||
|
|
||||||
|
for (int i = 0; i < num_cores; i++)
|
||||||
|
{
|
||||||
|
starts[i] = i;
|
||||||
|
|
||||||
|
pthread_create(
|
||||||
|
/* handle */ &handles[i],
|
||||||
|
/* attributes: */ NULL,
|
||||||
|
/* start_routine: */ runner,
|
||||||
|
/* arg: */ &starts[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < num_cores; i++)
|
||||||
|
{
|
||||||
|
pthread_join(
|
||||||
|
/* handle: */ handles[i],
|
||||||
|
/* return value: */ (void*[1]){});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
for (int a = 0; a < N; a++)
|
||||||
|
{
|
||||||
|
helper(
|
||||||
|
/* cmdln flags: */ &flag_no_assign,
|
||||||
|
/* simplifications */ simps,
|
||||||
|
/* have extra variable? */ true,
|
||||||
|
/* extra variable value: */ a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
helper(
|
||||||
|
/* cmdln flags: */ flags,
|
||||||
|
/* simplifications */ simps,
|
||||||
|
/* have extra variable? */ false,
|
||||||
|
/* extra variable value: */ 0);
|
||||||
|
|
||||||
|
EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
13
calculate_simplifications.h
Normal file
13
calculate_simplifications.h
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include <expr.h>
|
||||||
|
|
||||||
|
#include <simplifications.h>
|
||||||
|
|
||||||
|
struct cmdln_flags;
|
||||||
|
|
||||||
|
|
||||||
|
void calculate_simplifications(
|
||||||
|
const struct cmdln_flags* flags,
|
||||||
|
struct simplifications* simps);
|
||||||
214
cmdln.c
Normal file
214
cmdln.c
Normal file
|
|
@ -0,0 +1,214 @@
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "cmdln.h"
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
struct cmdln_flags parse_args(int argc, char* const* argv)
|
||||||
|
{
|
||||||
|
struct cmdln_flags flags = {};
|
||||||
|
|
||||||
|
flags.argv0 = argv[0];
|
||||||
|
|
||||||
|
bool unset_operators = true;
|
||||||
|
|
||||||
|
bool unset_print_with_color = true;
|
||||||
|
|
||||||
|
for (int opt; (opt = getopt(argc, argv, "pyqmvc:eEo:C:B")) != -1; )
|
||||||
|
{
|
||||||
|
switch (opt)
|
||||||
|
{
|
||||||
|
case 'p':
|
||||||
|
{
|
||||||
|
flags.print_all_and_quit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'y':
|
||||||
|
{
|
||||||
|
flags.assume_yes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'q':
|
||||||
|
{
|
||||||
|
flags.quiet = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'm':
|
||||||
|
{
|
||||||
|
flags.print_max_operators_needed_and_quit = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'v':
|
||||||
|
{
|
||||||
|
flags.verbose = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'c':
|
||||||
|
{
|
||||||
|
flags.command = optarg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'E':
|
||||||
|
{
|
||||||
|
flags.use_operators.ternary = true;
|
||||||
|
}
|
||||||
|
// fallthrough
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
{
|
||||||
|
flags.use_operators.not = true;
|
||||||
|
flags.use_operators.or = true;
|
||||||
|
flags.use_operators.and = true;
|
||||||
|
|
||||||
|
flags.use_operators.orn = true;
|
||||||
|
flags.use_operators.nor = true;
|
||||||
|
|
||||||
|
flags.use_operators.andn = true;
|
||||||
|
flags.use_operators.nand = true;
|
||||||
|
|
||||||
|
flags.use_operators. xor = true;
|
||||||
|
flags.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, "!"))
|
||||||
|
{
|
||||||
|
flags.use_operators.not = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "or") || !strcmp(moving, "||"))
|
||||||
|
{
|
||||||
|
flags.use_operators.or = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "orn") || !strcmp(moving, "|!"))
|
||||||
|
{
|
||||||
|
flags.use_operators.orn = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "nor") || !strcmp(moving, "!|"))
|
||||||
|
{
|
||||||
|
flags.use_operators.nor = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "and") || !strcmp(moving, "&&"))
|
||||||
|
{
|
||||||
|
flags.use_operators.and = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "andn") || !strcmp(moving, "&!"))
|
||||||
|
{
|
||||||
|
flags.use_operators.andn = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "nand") || !strcmp(moving, "!&"))
|
||||||
|
{
|
||||||
|
flags.use_operators.nand = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "xor") || !strcmp(moving, "!="))
|
||||||
|
{
|
||||||
|
flags.use_operators.xor = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "nxor") || !strcmp(moving, "=="))
|
||||||
|
{
|
||||||
|
flags.use_operators.nxor = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "lt") || !strcmp(moving, "<"))
|
||||||
|
{
|
||||||
|
flags.use_operators.lt = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "lte") || !strcmp(moving, "<="))
|
||||||
|
{
|
||||||
|
flags.use_operators.lte = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "gt") || !strcmp(moving, ">"))
|
||||||
|
{
|
||||||
|
flags.use_operators.gt = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "gte") || !strcmp(moving, ">="))
|
||||||
|
{
|
||||||
|
flags.use_operators.gte = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "ternary") || !strcmp(moving, "?:"))
|
||||||
|
{
|
||||||
|
flags.use_operators.ternary = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(moving, "assign") || !strcmp(moving, "="))
|
||||||
|
{
|
||||||
|
flags.use_operators.assignment = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(!"TODO");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'C':
|
||||||
|
{
|
||||||
|
unset_print_with_color = false;
|
||||||
|
|
||||||
|
if (!strcmp(optarg, "yes") || !strcmp(optarg, "on"))
|
||||||
|
{
|
||||||
|
flags.print_with_color = true;
|
||||||
|
}
|
||||||
|
else if (!strcmp(optarg, "no") || !strcmp(optarg, "off"))
|
||||||
|
{
|
||||||
|
flags.print_with_color = false;
|
||||||
|
}
|
||||||
|
else if (!strcmp(optarg, "auto"))
|
||||||
|
{
|
||||||
|
flags.print_with_color = isatty(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(!"TODO");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'B':
|
||||||
|
{
|
||||||
|
flags.force_rebuild = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
assert(!"TODO");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unset_operators)
|
||||||
|
{
|
||||||
|
flags.use_operators.not = true;
|
||||||
|
flags.use_operators.or = true;
|
||||||
|
flags.use_operators.and = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unset_print_with_color)
|
||||||
|
{
|
||||||
|
flags.print_with_color = isatty(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
42
cmdln.h
Normal file
42
cmdln.h
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
struct cmdln_flags
|
||||||
|
{
|
||||||
|
const char* argv0;
|
||||||
|
|
||||||
|
const char* command;
|
||||||
|
|
||||||
|
struct use_operators {
|
||||||
|
bool not;
|
||||||
|
|
||||||
|
bool or, orn, nor;
|
||||||
|
|
||||||
|
bool and, andn, nand;
|
||||||
|
|
||||||
|
bool xor, nxor;
|
||||||
|
|
||||||
|
bool lt, lte, gt, gte;
|
||||||
|
|
||||||
|
bool ternary;
|
||||||
|
|
||||||
|
bool assignment;
|
||||||
|
} use_operators;
|
||||||
|
|
||||||
|
bool print_all_and_quit;
|
||||||
|
|
||||||
|
bool print_max_operators_needed_and_quit;
|
||||||
|
|
||||||
|
bool assume_yes;
|
||||||
|
|
||||||
|
bool verbose;
|
||||||
|
|
||||||
|
bool print_with_color;
|
||||||
|
|
||||||
|
bool force_rebuild;
|
||||||
|
|
||||||
|
bool quiet;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cmdln_flags parse_args(int argc, char* const* argv);
|
||||||
|
|
||||||
11
cmdln/free.c
11
cmdln/free.c
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include "free.h"
|
|
||||||
|
|
||||||
void free_cmdln_flags(
|
|
||||||
struct cmdln_flags* flags)
|
|
||||||
{
|
|
||||||
TODO;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
struct cmdln_flags;
|
|
||||||
|
|
||||||
void free_cmdln_flags(
|
|
||||||
struct cmdln_flags* flags);
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include "print_usage.h"
|
|
||||||
|
|
||||||
void print_usage()
|
|
||||||
{
|
|
||||||
TODO;
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
void print_usage(void);
|
|
||||||
|
|
||||||
254
cmdln/process.c
254
cmdln/process.c
|
|
@ -1,254 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include <memory/smalloc.h>
|
|
||||||
|
|
||||||
#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
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
struct cmdln_flags* process_cmdln_flags(
|
|
||||||
int argc,
|
|
||||||
char* const* argv);
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
#include <structs/operators.h>
|
|
||||||
|
|
||||||
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
|
|
||||||
6
debug.c
6
debug.c
|
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
#ifdef DEBUG_BUILD_TYPE
|
int debug_depth = 0;
|
||||||
int debug_depth;
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
55
debug.h
55
debug.h
|
|
@ -1,32 +1,31 @@
|
||||||
|
|
||||||
#ifdef DEBUG_BUILD_TYPE
|
#ifdef DEBUG_BUILD
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <inttypes.h>
|
|
||||||
#include <limits.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct string;
|
|
||||||
struct scope;
|
|
||||||
struct expression;
|
|
||||||
struct cmdln_flags;
|
|
||||||
struct avl_tree_t;
|
|
||||||
struct truthtable_set;
|
|
||||||
|
|
||||||
extern int debug_depth;
|
extern int debug_depth;
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <typedefs/truthtable_t.h>
|
#ifdef DEBUG_BUILD
|
||||||
|
#define ZDEBUG 1
|
||||||
|
#else
|
||||||
|
#define ZDEBUG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <memory/smalloc.h>
|
#ifdef DEBUG_BUILD
|
||||||
|
#define zprintf(fmt, ...) printf("%*s" fmt, debug_depth, "", ## __VA_ARGS__);
|
||||||
#include <string/inc.h>
|
#else
|
||||||
|
#define zprintf(...);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG_BUILD
|
||||||
#define ENTER \
|
#define ENTER \
|
||||||
printf("%*s" "%s():" "\n", debug_depth++, "", __PRETTY_FUNCTION__);
|
{ zprintf("%s():" "\n", __PRETTY_FUNCTION__); debug_depth++; }
|
||||||
|
|
||||||
|
#define EXIT \
|
||||||
|
{ zprintf("return" "\n"); debug_depth--; }
|
||||||
|
#else
|
||||||
|
#define ENTER ;
|
||||||
|
|
||||||
|
#define EXIT ;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TODO \
|
#define TODO \
|
||||||
assert(!"TODO");
|
assert(!"TODO");
|
||||||
|
|
@ -34,13 +33,3 @@ extern int debug_depth;
|
||||||
#define CHECK \
|
#define CHECK \
|
||||||
assert(!"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
|
|
||||||
|
|
||||||
|
|
|
||||||
9
defines.h
Normal file
9
defines.h
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
#define W 0b0101010101010101
|
||||||
|
#define X 0b0011001100110011
|
||||||
|
#define Y 0b0000111100001111
|
||||||
|
#define Z 0b0000000011111111
|
||||||
|
#define M 0b1111111111111111
|
||||||
|
|
||||||
|
#define N (65536)
|
||||||
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
|
|
||||||
#define M (0b1111111111111111)
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#define N (65536)
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#define W 0b0101010101010101
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#define X 0b0011001100110011
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#define Y 0b0000111100001111
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
#define Z 0b0000000011111111
|
|
||||||
500
evaluate.c
Normal file
500
evaluate.c
Normal file
|
|
@ -0,0 +1,500 @@
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <defines.h>
|
||||||
|
|
||||||
|
#include "evaluate.h"
|
||||||
|
|
||||||
|
uint16_t evaluate(const char* text)
|
||||||
|
{
|
||||||
|
enum {
|
||||||
|
tk_uninitialized,
|
||||||
|
|
||||||
|
tk_0,
|
||||||
|
tk_1,
|
||||||
|
|
||||||
|
tk_w,
|
||||||
|
tk_x,
|
||||||
|
tk_y,
|
||||||
|
tk_z,
|
||||||
|
|
||||||
|
tk_oparen,
|
||||||
|
tk_cparen,
|
||||||
|
|
||||||
|
tk_emark,
|
||||||
|
tk_emarkequals,
|
||||||
|
tk_emarkvbar,
|
||||||
|
tk_emarkampersand,
|
||||||
|
|
||||||
|
tk_equalsequals,
|
||||||
|
|
||||||
|
tk_vbarvbar,
|
||||||
|
tk_vbaremark,
|
||||||
|
|
||||||
|
tk_qmark,
|
||||||
|
|
||||||
|
tk_less_than,
|
||||||
|
tk_less_than_eq,
|
||||||
|
|
||||||
|
tk_greater_than,
|
||||||
|
tk_greater_than_eq,
|
||||||
|
|
||||||
|
tk_ampersandemark,
|
||||||
|
tk_ampersandampersand,
|
||||||
|
|
||||||
|
tk_colon,
|
||||||
|
|
||||||
|
tk_EOF,
|
||||||
|
} tokenkind = tk_uninitialized;
|
||||||
|
|
||||||
|
const char* moving = text;
|
||||||
|
|
||||||
|
void next_token(void)
|
||||||
|
{
|
||||||
|
while (*moving && *moving == ' ')
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
tokenkind = tk_EOF;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '0':
|
||||||
|
tokenkind = tk_0, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '1':
|
||||||
|
tokenkind = tk_1, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
tokenkind = tk_w, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
tokenkind = tk_x, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'y':
|
||||||
|
tokenkind = tk_y, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'z':
|
||||||
|
tokenkind = tk_z, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '(':
|
||||||
|
tokenkind = tk_oparen, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ')':
|
||||||
|
tokenkind = tk_cparen, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '?':
|
||||||
|
tokenkind = tk_qmark, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ':':
|
||||||
|
tokenkind = tk_colon, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// either '||' or '|!':
|
||||||
|
case '|':
|
||||||
|
{
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case '|':
|
||||||
|
tokenkind = tk_vbarvbar, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '!':
|
||||||
|
tokenkind = tk_vbaremark, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
puts("syntax error");
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// either '&&' or '&!':
|
||||||
|
case '&':
|
||||||
|
{
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case '&':
|
||||||
|
tokenkind = tk_ampersandampersand, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '!':
|
||||||
|
tokenkind = tk_ampersandemark, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
puts("syntax error");
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// either '!' or '!=' or '!&' or '!|'
|
||||||
|
case '!':
|
||||||
|
{
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
tokenkind = tk_emarkequals, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '|':
|
||||||
|
tokenkind = tk_emarkvbar, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '&':
|
||||||
|
tokenkind = tk_emarkampersand, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
tokenkind = tk_emark;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '<':
|
||||||
|
{
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
tokenkind = tk_less_than_eq, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
tokenkind = tk_less_than;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case '>':
|
||||||
|
{
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
tokenkind = tk_greater_than_eq, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
tokenkind = tk_greater_than;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// could only be '==':
|
||||||
|
case '=':
|
||||||
|
{
|
||||||
|
moving++;
|
||||||
|
|
||||||
|
switch (*moving)
|
||||||
|
{
|
||||||
|
case '=':
|
||||||
|
tokenkind = tk_equalsequals, moving++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
puts("syntax error");
|
||||||
|
exit(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(!"TODO");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next_token();
|
||||||
|
|
||||||
|
uint16_t parse_root(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_ternary(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_ors(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_ands(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_equals(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_compares(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_prefix(void)
|
||||||
|
{
|
||||||
|
uint16_t parse_primary(void)
|
||||||
|
{
|
||||||
|
uint16_t retval;
|
||||||
|
|
||||||
|
switch (tokenkind)
|
||||||
|
{
|
||||||
|
case tk_0:
|
||||||
|
retval = 0, next_token();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tk_1:
|
||||||
|
retval = M, next_token();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tk_w:
|
||||||
|
retval = W, next_token();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tk_x:
|
||||||
|
retval = X, next_token();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tk_y:
|
||||||
|
retval = Y, next_token();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tk_z:
|
||||||
|
retval = Z, next_token();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case tk_oparen:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
|
||||||
|
retval = parse_root();
|
||||||
|
|
||||||
|
if (tokenkind != tk_cparen)
|
||||||
|
{
|
||||||
|
assert(!"NOPE");
|
||||||
|
}
|
||||||
|
|
||||||
|
next_token();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(!"TODO");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokenkind == tk_emark)
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
|
||||||
|
return ~parse_prefix();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return parse_primary();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t left = parse_prefix();
|
||||||
|
|
||||||
|
again: switch (tokenkind)
|
||||||
|
{
|
||||||
|
case tk_less_than:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = (~left & parse_equals()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_less_than_eq:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = (~left | parse_equals()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_greater_than_eq:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = ( left | ~parse_equals()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_greater_than:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = ( left & ~parse_equals()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t left = parse_compares();
|
||||||
|
|
||||||
|
again: switch (tokenkind)
|
||||||
|
{
|
||||||
|
case tk_equalsequals:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = ~(left ^ parse_equals()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_emarkequals:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = left ^ parse_equals();
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t left = parse_equals();
|
||||||
|
|
||||||
|
again: switch (tokenkind)
|
||||||
|
{
|
||||||
|
case tk_ampersandampersand:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = left & parse_equals();
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_ampersandemark:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = ~left & parse_equals();
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_emarkampersand:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = ~(left & parse_equals());
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t left = parse_ands();
|
||||||
|
|
||||||
|
again: switch (tokenkind)
|
||||||
|
{
|
||||||
|
case tk_vbarvbar:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = left | parse_ands();
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_vbaremark:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = (~left | parse_ands()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
case tk_emarkvbar:
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
left = ~(left | parse_ands()) & M;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t cond = parse_ors();
|
||||||
|
|
||||||
|
if (tokenkind == tk_qmark)
|
||||||
|
{
|
||||||
|
next_token();
|
||||||
|
|
||||||
|
uint16_t left = parse_ors();
|
||||||
|
|
||||||
|
if (tokenkind != tk_colon)
|
||||||
|
{
|
||||||
|
puts("syntax error!");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
next_token();
|
||||||
|
|
||||||
|
uint16_t right = parse_ternary();
|
||||||
|
|
||||||
|
return (cond & left) | (~cond & right);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return cond;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parse_ternary();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t truthtable = parse_root();
|
||||||
|
|
||||||
|
if (tokenkind != tk_EOF)
|
||||||
|
{
|
||||||
|
puts("syntax error!");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return truthtable;
|
||||||
|
}
|
||||||
|
|
||||||
5
evaluate.h
Normal file
5
evaluate.h
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint16_t evaluate(const char* text);
|
||||||
|
|
||||||
62
expr.h
Normal file
62
expr.h
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
|
||||||
|
#ifndef STRUCT_EXPR
|
||||||
|
#define STRUCT_EXPR
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum ekind
|
||||||
|
{
|
||||||
|
ek_unreachable,
|
||||||
|
|
||||||
|
ek_0,
|
||||||
|
ek_1,
|
||||||
|
ek_W,
|
||||||
|
ek_X,
|
||||||
|
ek_Y,
|
||||||
|
ek_Z,
|
||||||
|
|
||||||
|
// very special:
|
||||||
|
ek_A,
|
||||||
|
|
||||||
|
ek_not,
|
||||||
|
ek_or,
|
||||||
|
ek_and,
|
||||||
|
|
||||||
|
ek_orn,
|
||||||
|
ek_nor,
|
||||||
|
|
||||||
|
ek_andn,
|
||||||
|
ek_nand,
|
||||||
|
|
||||||
|
ek_xor,
|
||||||
|
ek_nxor,
|
||||||
|
|
||||||
|
ek_lt,
|
||||||
|
ek_lte,
|
||||||
|
ek_gt,
|
||||||
|
ek_gte,
|
||||||
|
|
||||||
|
ek_ternary,
|
||||||
|
|
||||||
|
// also very special.
|
||||||
|
// 'left' is the variable's truthtable
|
||||||
|
// to print the requested truthtable
|
||||||
|
// look a the relavent lookup.
|
||||||
|
ek_assignment,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct expr
|
||||||
|
{
|
||||||
|
enum ekind kind;
|
||||||
|
|
||||||
|
uint16_t cond, left, right;
|
||||||
|
|
||||||
|
int cost;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include "free.h"
|
|
||||||
|
|
||||||
void free_and_expression(
|
|
||||||
struct expression* super)
|
|
||||||
{
|
|
||||||
TODO;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
struct expression;
|
|
||||||
|
|
||||||
void free_and_expression(
|
|
||||||
struct expression* super);
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
#include "inheritance.h"
|
|
||||||
#include "print.h"
|
|
||||||
#include "free.h"
|
|
||||||
|
|
||||||
struct expression_inheritance and_expression_inheritance =
|
|
||||||
{
|
|
||||||
.print = and_expression_print,
|
|
||||||
.free = free_and_expression,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
#include "../inheritance.h"
|
|
||||||
|
|
||||||
extern struct expression_inheritance and_expression_inheritance;
|
|
||||||
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
struct expression* new_and_expression(
|
|
||||||
int cost,
|
|
||||||
struct expression* left,
|
|
||||||
struct expression* right);
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#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(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
void and_expression_print(
|
|
||||||
struct expression* super);
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
#include "../struct.h"
|
|
||||||
|
|
||||||
struct and_expression
|
|
||||||
{
|
|
||||||
struct expression super;
|
|
||||||
|
|
||||||
struct expression* left;
|
|
||||||
|
|
||||||
struct expression* right;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
void free_expression(
|
|
||||||
struct expression* this);
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include "struct.h"
|
|
||||||
#include "inc.h"
|
|
||||||
|
|
||||||
struct expression* inc_expression(
|
|
||||||
struct expression* this)
|
|
||||||
{
|
|
||||||
if (this)
|
|
||||||
{
|
|
||||||
this->refcount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
struct expression* inc_expression(
|
|
||||||
struct expression* this);
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
struct expression;
|
|
||||||
|
|
||||||
struct expression_inheritance
|
|
||||||
{
|
|
||||||
void (*print)(
|
|
||||||
struct expression*);
|
|
||||||
|
|
||||||
void (*free)(
|
|
||||||
struct expression*);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include "free.h"
|
|
||||||
|
|
||||||
void free_literal_expression(
|
|
||||||
struct expression* super)
|
|
||||||
{
|
|
||||||
TODO;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
void free_literal_expression(
|
|
||||||
struct expression* super);
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
#include "inheritance.h"
|
|
||||||
#include "print.h"
|
|
||||||
#include "free.h"
|
|
||||||
|
|
||||||
struct expression_inheritance literal_expression_inheritance =
|
|
||||||
{
|
|
||||||
.print = literal_expression_print,
|
|
||||||
.free = free_literal_expression,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
#include "../inheritance.h"
|
|
||||||
|
|
||||||
extern struct expression_inheritance literal_expression_inheritance;
|
|
||||||
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
struct expression* new_literal_expression(
|
|
||||||
int cost,
|
|
||||||
bool is_one);
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
void literal_expression_print(
|
|
||||||
struct expression* super);
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
|
|
||||||
#include "../struct.h"
|
|
||||||
|
|
||||||
struct literal_expression
|
|
||||||
{
|
|
||||||
struct expression super;
|
|
||||||
|
|
||||||
bool value;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
|
|
||||||
struct expression_inheritance;
|
|
||||||
|
|
||||||
struct expression* new_expression(
|
|
||||||
const struct expression_inheritance* inheritance,
|
|
||||||
int cost,
|
|
||||||
size_t size);
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include "free.h"
|
|
||||||
|
|
||||||
void free_not_expression(
|
|
||||||
struct expression* super)
|
|
||||||
{
|
|
||||||
TODO;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
struct expression;
|
|
||||||
|
|
||||||
void free_not_expression(
|
|
||||||
struct expression* super);
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
#include "inheritance.h"
|
|
||||||
#include "print.h"
|
|
||||||
#include "free.h"
|
|
||||||
|
|
||||||
struct expression_inheritance not_expression_inheritance =
|
|
||||||
{
|
|
||||||
.print = not_expression_print,
|
|
||||||
.free = free_not_expression,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
#include "../inheritance.h"
|
|
||||||
|
|
||||||
extern struct expression_inheritance not_expression_inheritance;
|
|
||||||
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
struct expression* new_not_expression(
|
|
||||||
int cost,
|
|
||||||
struct expression* subexpression);
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#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(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
void not_expression_print(
|
|
||||||
struct expression* super);
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
|
|
||||||
#include "../struct.h"
|
|
||||||
|
|
||||||
struct not_expression
|
|
||||||
{
|
|
||||||
struct expression super;
|
|
||||||
|
|
||||||
struct expression* inner;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include "free.h"
|
|
||||||
|
|
||||||
void free_or_expression(
|
|
||||||
struct expression* super)
|
|
||||||
{
|
|
||||||
TODO;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
struct expression;
|
|
||||||
|
|
||||||
void free_or_expression(
|
|
||||||
struct expression* super);
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
#include "inheritance.h"
|
|
||||||
#include "print.h"
|
|
||||||
#include "free.h"
|
|
||||||
|
|
||||||
struct expression_inheritance or_expression_inheritance =
|
|
||||||
{
|
|
||||||
.print = or_expression_print,
|
|
||||||
.free = free_or_expression,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
#include "../inheritance.h"
|
|
||||||
|
|
||||||
extern struct expression_inheritance or_expression_inheritance;
|
|
||||||
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
struct expression* new_or_expression(
|
|
||||||
int cost,
|
|
||||||
struct expression* left,
|
|
||||||
struct expression* right);
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#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(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
void or_expression_print(
|
|
||||||
struct expression* super);
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
#include "../struct.h"
|
|
||||||
|
|
||||||
struct or_expression
|
|
||||||
{
|
|
||||||
struct expression super;
|
|
||||||
|
|
||||||
struct expression* left;
|
|
||||||
|
|
||||||
struct expression* right;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
struct expression;
|
|
||||||
|
|
||||||
void expression_print(
|
|
||||||
struct expression* this);
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
struct expression_inheritance;
|
|
||||||
|
|
||||||
struct expression
|
|
||||||
{
|
|
||||||
const struct expression_inheritance* inheritance;
|
|
||||||
|
|
||||||
int cost;
|
|
||||||
|
|
||||||
unsigned refcount;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include "free.h"
|
|
||||||
|
|
||||||
void free_unreachable_expression(
|
|
||||||
struct expression* super)
|
|
||||||
{
|
|
||||||
TODO;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
void free_unreachable_expression(
|
|
||||||
struct expression* super);
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
#include "inheritance.h"
|
|
||||||
#include "print.h"
|
|
||||||
#include "free.h"
|
|
||||||
|
|
||||||
struct expression_inheritance unreachable_expression_inheritance =
|
|
||||||
{
|
|
||||||
.print = unreachable_expression_print,
|
|
||||||
.free = free_unreachable_expression,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
|
|
||||||
#include "../inheritance.h"
|
|
||||||
|
|
||||||
extern struct expression_inheritance unreachable_expression_inheritance;
|
|
||||||
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
|
|
||||||
struct expression* new_unreachable_expression(void);
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
|
|
||||||
#include <debug.h>
|
|
||||||
|
|
||||||
#include "print.h"
|
|
||||||
|
|
||||||
void unreachable_expression_print(
|
|
||||||
struct expression* super)
|
|
||||||
{
|
|
||||||
TODO;
|
|
||||||
}
|
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue