changeset 679:1dc7bd5f99f7

Moar work.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 16 Apr 2013 15:13:37 +0300
parents 4a08ce0997bc
children 4422a1880859
files dmeval.c dmeval.h tests/evaltest.c
diffstat 3 files changed, 119 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/dmeval.c	Tue Apr 16 15:06:43 2013 +0300
+++ b/dmeval.c	Tue Apr 16 15:13:37 2013 +0300
@@ -242,6 +242,15 @@
 }
 
 
+static DMEvalNode *dm_eval_peek_node(DMEvalNode **list)
+{
+    if (*list == NULL)
+        return NULL;
+
+    return (*list)->prev;
+}
+
+
 static DMEvalNode *dm_eval_insert_node(DMEvalNode **list, DMEvalNode *node)
 {
     if (*list != NULL)
@@ -735,15 +744,64 @@
       LOWEST
 */
 
-int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result)
+
+int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result, int pass)
 {
     DMEvalNode *list = NULL;
-    int i;
+    int i, res;
 
     while (node != NULL)
     {
-        DMEvalNode *tmp;
+        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(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:
@@ -752,54 +810,79 @@
 
                 for (i = 0; i < DM_MAX_ARGS; i++)
                 {
-                    if (dm_eval_reorder(ev, node->args[i], &(tmp->args[i])) != 0)
-                        return -2;
+                    if ((res = dm_eval_reorder(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 (dm_eval_reorder(ev, node->subexpr, &(tmp->subexpr)) != 0)
-                    return -2;
+                if ((res = dm_eval_reorder(ev, node->subexpr, &(tmp->subexpr), pass)) != 0)
+                    return res;
+                node = node->next;
                 break;
 
+
             case OP_MUL:
             case OP_DIV:
             case OP_MOD:
-                if ((tmp = dm_eval_pop_node(&list)) != NULL)
-                {
-                    DMEvalNode *sub;
+                // Pop previous node, f.e. 5*3 -> 5
+                if ((tmp = dm_eval_pop_node(&list)) == NULL)
+                    return -24;
 
-                    if ((sub = dm_eval_add_node(&list, OP_SUBEXPR)) == NULL)
-                        return -3;
+                // 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);
 
-                    dm_eval_push_node(&(sub->subexpr), tmp);
-                    dm_eval_add_node(&(sub->subexpr), node->op);
-                    node = node->next;
-                    if (node != NULL)
-                    {
-                        if (node->op == OP_FUNC || node->op == OP_SUBEXPR)
-                        {
-                            if ((tmp = dm_eval_push_node(&(sub->subexpr), node)) == NULL)
-                                return -178;
-                            
-                            if (dm_eval_reorder(ev, node->subexpr, &(tmp->subexpr)) != 0)
-                                return -66;
-                        }
-                        else
-                            dm_eval_push_node(&(sub->subexpr), node);
-                    }
-                    else
-                        return -72;
+                // 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(ev, node->subexpr, &(tmp->subexpr), pass)) != 0)
+                        return res;
                 }
                 else
-                    return -24;
+                    dm_eval_push_node(&(sub->subexpr), node);
+
+                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;
+
+                node = node->next;
+                if (node == NULL)
+                    return -14;
+
+                tmp = NULL;
+                if ((res = dm_eval_reorder(ev, node, &tmp, pass)) != 0)
+                    return res;
+
+                sub->subexpr = tmp;
+                node = NULL;
+                break;
 
             case OP_ADD:
             case OP_SUB:
@@ -812,14 +895,14 @@
             case OP_CONST:
                 if (dm_eval_push_node(&list, node) == NULL)
                     return -32;
+
+                node = node->next;
                 break;
 
             default:
                 dm_eval_err(ev, "Invalid opcode %d in node %p.\n", node->op, node);
                 return -4;
         }
-        
-        node = node->next;
     }
 
     *result = list;
--- a/dmeval.h	Tue Apr 16 15:06:43 2013 +0300
+++ b/dmeval.h	Tue Apr 16 15:13:37 2013 +0300
@@ -88,7 +88,7 @@
 void dm_eval_clear_err(DMEvalContext *ev);
 
 int dm_eval_parse_expr(DMEvalContext *ev, char *expr, DMEvalNode **result);
-int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result);
+int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result, int pass);
 int dm_eval_exec(DMEvalContext *ev, DMEvalNode *tree, DMValue *presult);
 
 void dm_print_optree(DMEvalContext *ev, DMEvalNode *node);
--- a/tests/evaltest.c	Tue Apr 16 15:06:43 2013 +0300
+++ b/tests/evaltest.c	Tue Apr 16 15:13:37 2013 +0300
@@ -67,8 +67,9 @@
     DMEvalContext *ev = dm_eval_new();
     DMEvalNode *parsed = NULL, *ordered = NULL;
     DMValue result, t, f = 44100.0f;
-    int ret;
+    int ret, i;
 
+    dmVerbosity = 2;
     optFormula = "-pi * -2";
 
     dmInitProg("evaltest", "evaltest", "0.1", NULL, NULL);