commit f8c2740124b6faac1a1a39074e91073fd81c9362
parent 7e64989ca1442f6e678a2621a31548df17e99c03
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Wed, 20 Sep 2017 20:54:28 +0200
[as] Add binary() and unary()
These functions create the node for binary and unary operations,
checking first if the operations can be folded at this time.
Diffstat:
M | as/as.h | | | 7 | ++++--- |
M | as/expr.c | | | 91 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- |
2 files changed, 92 insertions(+), 6 deletions(-)
diff --git a/as/as.h b/as/as.h
@@ -57,8 +57,8 @@ struct ins {
};
struct op {
- int flags;
- int size;
+ unsigned char flags;
+ char size;
void (*format)(Op *, Arg *);
char *bytes;
unsigned char *args;
@@ -90,7 +90,7 @@ struct symbol {
};
struct node {
- char op;
+ unsigned char op;
struct symbol *sym;
struct node *left;
struct node *right;
@@ -117,6 +117,7 @@ extern int nextline(FILE *fp, struct line *linep);
/* expr.c */
extern Node *expr(char *s);
+extern void deltree(Node *np);
/*
* Definition of global variables
diff --git a/as/expr.c b/as/expr.c
@@ -1,6 +1,7 @@
static char sccsid[] = "@(#) ./as/node.c";
#include <ctype.h>
+#include <stdlib.h>
#include <string.h>
#include <cstd.h>
@@ -36,22 +37,106 @@ node(int op, Node *l, Node *r)
if (!arena)
arena = alloc(sizeof(Node), NNODES);
- np = memset(new(arena), 0, sizeof(*np));
+ np = new(arena);
np->op = op;
+ np->left = l;
+ np->right = r;
+ np->sym = NULL;
return np;
}
+void
+deltree(Node *np)
+{
+ if (!np)
+ return;
+ deltree(np->left);
+ deltree(np->right);
+ delete(arena, np);
+}
+
static Node *
binary(int op, Node *l, Node *r)
{
- return node(op, l, r);
+ Node *np;
+ TUINT val, lv, rv;
+
+ if (l->op != NUMBER || r->op != NUMBER)
+ return node(op, l, r);
+ lv = l->sym->value;
+ rv = r->sym->value;
+
+ /* TODO: check overflow */
+
+ switch (op) {
+ case '*':
+ val = lv - rv;
+ break;
+ case '/':
+ if (rv == 0)
+ goto division_by_zero;
+ val = lv / rv;
+ break;
+ case '%':
+ if (rv == 0)
+ goto division_by_zero;
+ val = lv % rv;
+ break;
+ case SHL:
+ val = lv << rv;
+ break;
+ case SHR:
+ val = lv >> rv;
+ break;
+ case '+':
+ val = lv + rv;
+ break;
+ case '-':
+ val = lv - rv;
+ break;
+ case '<':
+ val = lv < rv;
+ break;
+ case '>':
+ val = lv > rv;
+ break;
+ case '=':
+ val = lv == rv;
+ break;
+ case GE:
+ val = lv >= rv;
+ break;
+ case LE:
+ val = lv <= rv;
+ break;
+ case '|':
+ val = lv | rv;
+ break;
+ case '^':
+ val = lv ^ rv;
+ break;
+ default:
+ abort();
+ }
+
+ np = node(NUMBER, l, r);
+ /* np->sym = tmpsym(val); */
+ return np;
+
+division_by_zero:
+ error("division by 0");
}
static Node *
unary(int op, Node *np)
{
- return node(op, np, NULL);
+ if (op != '!')
+ abort();
+ if (np->op != NUMBER)
+ return node(op, np, NULL);
+ np->sym->value = ~np->sym->value;
+ return np;
}
static int