changeset 693:837ad9dcc348

More work on evaluator reordering pass.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 16 Apr 2013 19:02:42 +0300
parents 391310cfba26
children b8c8cf55c761
files dmeval.c dmeval.h
diffstat 2 files changed, 188 insertions(+), 173 deletions(-) [+]
line wrap: on
line diff
--- a/dmeval.c	Tue Apr 16 17:28:32 2013 +0300
+++ b/dmeval.c	Tue Apr 16 19:02:42 2013 +0300
@@ -273,7 +273,7 @@
 
 static DMEvalNode *dm_eval_push_node(DMEvalNode **list, DMEvalNode *src)
 {
-    DMEvalNode *node = dmCalloc(1, sizeof(DMEvalNode));
+    DMEvalNode *tmp, *node = dmCalloc(1, sizeof(DMEvalNode));
     int i;
 
     if (node == NULL)
@@ -282,10 +282,22 @@
     node->op       = src->op;
     node->val      = src->val;
     node->id       = src->id;
-    node->subexpr  = src->subexpr;
-    
-    for (i = 0; i < DM_MAX_ARGS; i++)
-        node->args[i] = src->args[i];
+    node->ok       = src->ok;
+
+    if (src->op == OP_SUBEXPR && src->subexpr != NULL)
+    {
+        for (tmp = src->subexpr; tmp != NULL; tmp = tmp->next)
+            dm_eval_push_node(&(node->subexpr), tmp);
+    }
+
+    if (src->op == OP_FUNC)
+    {
+        for (i = 0; i < src->id->nargs; i++)
+        {
+            for (tmp = src->args[i]; tmp != NULL; tmp = tmp->next)
+                dm_eval_push_node(&(node->args[i]), tmp);
+        }
+    }
 
     return dm_eval_insert_node(list, node);
 }
@@ -743,102 +755,22 @@
       LOWEST
 */
 
-
-static int dm_eval_reorder_do(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result, int pass)
+static int dm_eval_reorder_pass0(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result)
 {
     DMEvalNode *list = NULL;
+    DMEvalNode *tmp, *sub;
     int i, res;
 
-    while (node != NULL)
+    for (; node != NULL; node = node->next)
+    switch (node->op)
     {
-        DMEvalNode *tmp, *sub;
-
-        if (pass == 0)
-        switch (node->op)
-        {
-            case OP_SUB:
-                if ((tmp = dm_eval_peek_node(&list)) == NULL || tmp->op <= OP_FUNC)
-                {
-                    // Add subexpression node
-                    if ((sub = dm_eval_add_node(&list, OP_SUBEXPR)) == NULL)
-                        return -3;
-
-                    // Add this operator into subexpression
-                    dm_eval_add_node(&(sub->subexpr), node->op);
-
-                    // Next node
-                    node = node->next;
-                    if (node == NULL)
-                        return -72;
-
-                    if (node->op == OP_FUNC || node->op == OP_SUBEXPR)
-                    {
-                        // It's a function or sub-expression
-                        if ((tmp = dm_eval_push_node(&(sub->subexpr), node)) == NULL)
-                            return -178;
-                        
-                        if ((res = dm_eval_reorder_do(ev, node->subexpr, &(tmp->subexpr), pass)) != 0)
-                            return res;
-                    }
-                    else
-                        dm_eval_push_node(&(sub->subexpr), node);
-                }
-                else
-                {
-                    if (dm_eval_push_node(&list, node) == NULL)
-                        return -32;
-                }
-                
-                node = node->next;
-                break;
-            
-            default:
-                if (dm_eval_push_node(&list, node) == NULL)
-                    return -32;
-
-                node = node->next;
-                break;
-        }
-        else
-        if (pass == 1)
-        switch (node->op)
-        {
-            case OP_FUNC:
-                if ((tmp = dm_eval_push_node(&list, node)) == NULL)
-                    return -1;
-
-                for (i = 0; i < node->id->nargs; i++)
-                {
-                    if ((res = dm_eval_reorder_do(ev, node->args[i], &(tmp->args[i]), pass)) != 0)
-                        return res;
-                }
-                node = node->next;
-                break;
-
-            case OP_SUBEXPR:
-                if ((tmp = dm_eval_push_node(&list, node)) == NULL)
-                    return -1;
-
-                if ((res = dm_eval_reorder_do(ev, node->subexpr, &(tmp->subexpr), pass)) != 0)
-                    return res;
-                node = node->next;
-                break;
-
-
-            case OP_MUL:
-            case OP_DIV:
-            case OP_MOD:
-                // Pop previous node, f.e. 5*3 -> 5
-                if ((tmp = dm_eval_pop_node(&list)) == NULL)
-                    return -24;
-
+        case OP_SUB:
+            if ((tmp = dm_eval_peek_node(&list)) == NULL || tmp->op <= OP_FUNC)
+            {
                 // Add subexpression node
                 if ((sub = dm_eval_add_node(&list, OP_SUBEXPR)) == NULL)
                     return -3;
 
-                // Add popped node into subexpression
-                dm_eval_push_node(&(sub->subexpr), tmp);
-                
                 // Add this operator into subexpression
                 dm_eval_add_node(&(sub->subexpr), node->op);
 
@@ -847,96 +779,175 @@
                 if (node == NULL)
                     return -72;
 
-                if (node->op == OP_FUNC || node->op == OP_SUBEXPR)
-                {
-                    // It's a function or sub-expression
-                    if ((tmp = dm_eval_push_node(&(sub->subexpr), node)) == NULL)
-                        return -178;
-                    
-                    if ((res = dm_eval_reorder_do(ev, node->subexpr, &(tmp->subexpr), pass)) != 0)
-                        return res;
-                }
-                else
-                    dm_eval_push_node(&(sub->subexpr), node);
+                dm_eval_push_node(&(sub->subexpr), node);
+            }
+            else
+            if (dm_eval_push_node(&list, node) == NULL)
+                return -32;
+
+            break;
+
+        case OP_FUNC:
+            if ((tmp = dm_eval_push_node(&list, node)) == NULL)
+                return -1;
+
+            for (i = 0; i < node->id->nargs; i++)
+            {
+                if ((res = dm_eval_reorder(ev, node->args[i], &(tmp->args[i]))) != 0)
+                    return res;
+            }
+            break;
+        
+        case OP_SUBEXPR:
+            if ((tmp = dm_eval_push_node(&list, node)) == NULL)
+                return -1;
 
-                node = node->next;
-                break;
-            
-            case OP_LSHIFT:
-            case OP_RSHIFT:
-                // Bitshift operator precedence is .. different
-                if (dm_eval_push_node(&list, node) == NULL)
-                    return -32;
-                
-                if ((sub = dm_eval_add_node(&list, OP_SUBEXPR)) == NULL)
-                    return -3;
+            if ((res = dm_eval_reorder(ev, node->subexpr, &(tmp->subexpr))) != 0)
+                return res;
+            break;
+
+        default:
+            if (dm_eval_push_node(&list, node) == NULL)
+                return -32;
+            break;
+    }
+
+    *result = list;
+    return 0;
+}
 
-                node = node->next;
-                if (node == NULL)
-                    return -14;
+
+static int dm_eval_reorder_pass1(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result)
+{
+    DMEvalNode *list = NULL;
+    DMEvalNode *tmp, *sub;
 
-                tmp = NULL;
-                if ((res = dm_eval_reorder_do(ev, node, &tmp, pass)) != 0)
-                    return res;
-
-                sub->subexpr = tmp;
-                node = NULL;
-                break;
-
-            
-            default:
+    for (; node != NULL; node = node->next)
+    switch (node->op)
+    {
+        case OP_MUL:
+        case OP_DIV:
+        case OP_MOD:
+            if (node->ok)
+            {
                 if (dm_eval_push_node(&list, node) == NULL)
                     return -32;
+                break;
+            }
 
-                node = node->next;
-                break;
-        }
-        else
-        if (pass == 2)
-        switch (node->op)
-        {
-            case OP_ADD:
-                // Pop previous node, f.e. 5*3 -> 5
-                if ((tmp = dm_eval_pop_node(&list)) == NULL)
-                    return -24;
+            // Pop previous node, f.e. 5*3 -> 5
+            if ((tmp = dm_eval_pop_node(&list)) == NULL)
+                return -24;
+
+            // Add subexpression node
+            if ((sub = dm_eval_add_node(&list, OP_SUBEXPR)) == NULL)
+                return -3;
+
+            // Add popped node into subexpression
+            dm_eval_push_node(&(sub->subexpr), tmp);
+            
+            // Add this operator into subexpression
+            DMEvalNode *foo = dm_eval_add_node(&(sub->subexpr), node->op);
+            foo->ok = TRUE;
+
+            // Next node
+            node = node->next;
+            if (node == NULL)
+                return -72;
+
+            dm_eval_push_node(&(sub->subexpr), node);
+            break;
 
-                // Add subexpression node
-                if ((sub = dm_eval_add_node(&list, OP_SUBEXPR)) == NULL)
-                    return -3;
+        default:
+            if (dm_eval_push_node(&list, node) == NULL)
+                return -32;
+            break;
+    }
+
+    *result = list;
+    return 0;
+}
 
-                // Add popped node into subexpression
-                dm_eval_push_node(&(sub->subexpr), tmp);
-                
-                // Add this operator into subexpression
-                dm_eval_add_node(&(sub->subexpr), node->op);
+static int dm_eval_reorder_pass2(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result)
+{
+    DMEvalNode *list = NULL;
+    DMEvalNode *tmp, *sub;
+    int res;
+
+    for (; node != NULL; node = node->next)
+    switch (node->op)
+    {
+        case OP_SUB:
+        case OP_ADD:
+            // Pop previous node, f.e. 5*3 -> 5
+            if ((tmp = dm_eval_pop_node(&list)) == NULL)
+                return -24;
+
+            // Add subexpression node
+            if ((sub = dm_eval_add_node(&list, OP_SUBEXPR)) == NULL)
+                return -3;
 
-                // Next node
-                node = node->next;
-                if (node == NULL)
-                    return -72;
+            // Add popped node into subexpression
+            dm_eval_push_node(&(sub->subexpr), tmp);
+            
+            // Add this operator into subexpression
+            dm_eval_add_node(&(sub->subexpr), node->op);
+
+            // Next node
+            node = node->next;
+            if (node == NULL)
+                return -72;
+
+            dm_eval_push_node(&(sub->subexpr), node);
+            break;
+
+        default:
+            if (dm_eval_push_node(&list, node) == NULL)
+                return -32;
+            break;
+    }
+
+    *result = list;
+    return 0;
+}
+
+
+static int dm_eval_reorder_pass3(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result)
+{
+    DMEvalNode *list = NULL;
+    DMEvalNode *tmp, *sub;
+    int res;
 
-                if (node->op == OP_FUNC || node->op == OP_SUBEXPR)
-                {
-                    // It's a function or sub-expression
-                    if ((tmp = dm_eval_push_node(&(sub->subexpr), node)) == NULL)
-                        return -178;
-                    
-                    if ((res = dm_eval_reorder_do(ev, node->subexpr, &(tmp->subexpr), pass)) != 0)
-                        return res;
-                }
-                else
-                    dm_eval_push_node(&(sub->subexpr), node);
+    while (node != NULL)
+    switch (node->op)
+    {
+        case OP_LSHIFT:
+        case OP_RSHIFT:
+            // Bitshift operator precedence is .. different
+            if (dm_eval_push_node(&list, node) == NULL)
+                return -32;
+            
+            if ((sub = dm_eval_add_node(&list, OP_SUBEXPR)) == NULL)
+                return -3;
 
-                node = node->next;
-                break;
+            node = node->next;
+            if (node == NULL)
+                return -14;
+
+            tmp = NULL;
+            if ((res = dm_eval_reorder(ev, node, &tmp)) != 0)
+                return res;
 
-            default:
-                if (dm_eval_push_node(&list, node) == NULL)
-                    return -32;
+            sub->subexpr = tmp;
+            node = NULL;
+            break;
 
-                node = node->next;
-                break;
-        }
+        default:
+            if (dm_eval_push_node(&list, node) == NULL)
+                return -32;
+
+            node = node->next;
+            break;
     }
 
     *result = list;
@@ -946,16 +957,19 @@
 
 int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result)
 {
-    DMEvalNode *tmp = NULL, *tmp2 = NULL;
+    DMEvalNode *tmp1 = NULL, *tmp2 = NULL, *tmp3 = NULL;
     int res;
     
-    if ((res = dm_eval_reorder_do(ev, node, &tmp, 0)) != 0)
+    if ((res = dm_eval_reorder_pass0(ev, node, &tmp1)) != 0)
         return res;
 
-    if ((res = dm_eval_reorder_do(ev, tmp, &tmp2, 1)) != 0)
+    if ((res = dm_eval_reorder_pass1(ev, tmp1, &tmp2)) != 0)
         return res;
 
-    return dm_eval_reorder_do(ev, tmp2, result, 2);
+    if ((res = dm_eval_reorder_pass2(ev, tmp2, &tmp3)) != 0)
+        return res;
+
+    return dm_eval_reorder_pass3(ev, tmp3, result);
 }
 
 
--- a/dmeval.h	Tue Apr 16 17:28:32 2013 +0300
+++ b/dmeval.h	Tue Apr 16 19:02:42 2013 +0300
@@ -57,6 +57,7 @@
 
 typedef struct DMEvalNode
 {
+    BOOL ok;
     int op;
     DMValue val;
     DMEvalId *id;