diff lwlib/lw_expr.c @ 387:a741d2e4869f

Various bugfixes; fixed lwobjdump to display symbols with unprintable characters more sensibly; start of a (nonfunctional for now) testing framework
author lost@l-w.ca
date Wed, 14 Jul 2010 20:15:23 -0600
parents eacdae8a1575
children 67815606c5d9
line wrap: on
line diff
--- a/lwlib/lw_expr.c	Sun May 16 13:03:17 2010 -0600
+++ b/lwlib/lw_expr.c	Wed Jul 14 20:15:23 2010 -0600
@@ -49,6 +49,13 @@
 	return -1;
 }
 
+int lw_expr_whichop(lw_expr_t e)
+{
+	if (e -> type == lw_expr_type_oper)
+		return e -> value;
+	return -1;
+}
+
 int lw_expr_specint(lw_expr_t e)
 {
 	if (e -> type == lw_expr_type_special)
@@ -198,7 +205,12 @@
 	struct lw_expr_opers *o;
 	int c = 0;
 	char buf[256];
-			
+
+	if (!E)
+	{
+		strcpy(buf, "(NULL)");
+		return;
+	}
 	for (o = E -> operands; o; o = o -> next)
 	{
 		c++;
@@ -463,7 +475,9 @@
 	return 1;
 }
 
-void lw_expr_simplify(lw_expr_t E, void *priv)
+void lw_expr_simplify(lw_expr_t E, void *priv);
+
+void lw_expr_simplify_go(lw_expr_t E, void *priv)
 {
 	struct lw_expr_opers *o;
 
@@ -920,8 +934,80 @@
 		}
 		return;
 	}
+	
+	/* handle <int> times <plus> - expand the terms - only with exactly two operands */
+	if (E -> value == lw_expr_oper_times)
+	{
+		lw_expr_t t1;
+		lw_expr_t E2;
+		lw_expr_t E3;
+		if (E -> operands && E -> operands -> next && !(E -> operands -> next -> next))
+		{
+			if (E -> operands -> p -> type  == lw_expr_type_int)
+			{
+				/* <int> TIMES <other> */
+				E2 = E -> operands -> next -> p;
+				E3 = E -> operands -> p;
+				if (E2 -> type == lw_expr_type_oper && E2 -> value == lw_expr_oper_plus)
+				{
+					lw_free(E -> operands -> next);
+					lw_free(E -> operands);
+					E -> operands = NULL;
+					E -> value = lw_expr_oper_plus;
+					
+					for (o = E2 -> operands; o; o = o -> next)
+					{
+						t1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, E3, o -> p);
+						lw_expr_add_operand(E, t1);
+					}
+					
+					lw_expr_destroy(E2);
+					lw_expr_destroy(E3);
+				}
+			}
+			else if (E -> operands -> next -> p -> type == lw_expr_type_int)
+			{
+				/* <other> TIMES <int> */
+				E2 = E -> operands -> p;
+				E3 = E -> operands -> next -> p;
+				if (E2 -> type == lw_expr_type_oper && E2 -> value == lw_expr_oper_plus)
+				{
+					lw_free(E -> operands -> next);
+					lw_free(E -> operands);
+					E -> operands = NULL;
+					E -> value = lw_expr_oper_plus;
+					
+					for (o = E2 -> operands; o; o = o -> next)
+					{
+						t1 = lw_expr_build(lw_expr_type_oper, lw_expr_oper_times, E3, o -> p);
+						lw_expr_add_operand(E, t1);
+					}
+					
+					lw_expr_destroy(E2);
+					lw_expr_destroy(E3);
+				}
+			}
+		}
+	}
 }
 
+void lw_expr_simplify(lw_expr_t E, void *priv)
+{
+	lw_expr_t te;
+	int c;
+	do
+	{
+		te = lw_expr_copy(E);
+		lw_expr_simplify_go(E, priv);
+		c = 0;
+		if (lw_expr_compare(te, E) == 0)
+			c = 1;
+		lw_expr_destroy(te);
+	}
+	while (c);
+}
+
+
 /*
 
 The following two functions are co-routines which evaluate an infix