changeset 761:7be7c7c5deaa

Large cleanup, breaking everything. Yay.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 09 May 2013 06:21:36 +0300
parents d345a898bda1
children 49e96e581ac8
files dmeval.c dmeval.h dmevalw.c dmevalw.h tests/evaltest.c tools/auval.c
diffstat 6 files changed, 227 insertions(+), 489 deletions(-) [+]
line wrap: on
line diff
--- a/dmeval.c	Thu May 09 06:18:52 2013 +0300
+++ b/dmeval.c	Thu May 09 06:21:36 2013 +0300
@@ -1,9 +1,39 @@
 #include "dmeval.h"
 #include <math.h>
 
-#define DM_MAX_ID_LEN  16
 #define DM_MAX_BUF     512
-#define DM_STACK_SIZE  512
+
+
+const DMEvalOper dmEvalOpers[OP_NOPERS] =
+{
+    { "-" , OT_UNARY },
+    { "~" , OT_UNARY },
+    
+    { "+" , OT_LEFT },
+    { "-" , OT_LEFT },
+    { "*" , OT_LEFT },
+    { "/" , OT_LEFT },
+    { "%" , OT_LEFT },
+
+
+    { "<<", OT_LEFT },
+    { ">>", OT_LEFT },
+
+    { "&" , OT_LEFT },
+    { "|" , OT_LEFT },
+    { "^" , OT_LEFT },
+
+    { ">" , OT_LEFT },
+    { "<" , OT_LEFT },
+    { ">=", OT_LEFT },
+    { "<=", OT_LEFT },
+
+    { "FUNC"   , OT_NONE },
+    { "VAR"    , OT_NONE },
+    { "CONST"  , OT_NONE },
+
+    { "SUBEXPR", OT_NONE },
+};
 
 
 /* Function definitions
@@ -34,7 +64,7 @@
 
 /* Some basic functions
  */
-static const DMEvalId dm_eval_basic[] =
+static const DMEvalSymbol dmEvalBasicFuncs[] =
 {
     { "sin",  ID_FUNC, 1, func_sin, NULL, 0 },
     { "cos",  ID_FUNC, 1, func_cos, NULL, 0 },
@@ -44,10 +74,10 @@
     { "pi",   ID_CVAR, 0, NULL, NULL, DM_PI },
 };
 
-static const int ndm_eval_basic = sizeof(dm_eval_basic) / sizeof(dm_eval_basic[0]);
+static const int ndmEvalBasicFuncs = sizeof(dmEvalBasicFuncs) / sizeof(dmEvalBasicFuncs[0]);
 
 
-void dm_eval_err_v(DMEvalContext *ev, const char *fmt, va_list ap)
+void dmEvalErrorV(DMEvalContext *ev, const char *fmt, va_list ap)
 {
 #if 1
     char *tmp = dm_strdup_vprintf(fmt, ap);
@@ -67,46 +97,46 @@
 }
 
 
-void dm_eval_err(DMEvalContext *ev, const char *fmt, ...)
+void dmEvalError(DMEvalContext *ev, const char *fmt, ...)
 {
     va_list ap;
     va_start(ap, fmt);
-    dm_eval_err_v(ev, fmt, ap);
+    dmEvalErrorV(ev, fmt, ap);
     va_end(ap);
 }
 
 
-DMEvalId *dm_eval_find_id(DMEvalContext *ev, const char *name)
+DMEvalSymbol *dmEvalContextFindSymbol(DMEvalContext *ev, const char *name)
 {
     int i;
-    if (ev->ids == NULL)
+    if (ev->symbols == NULL)
         return NULL;
 
-    for (i = 0; i < ev->nids; i++)
+    for (i = 0; i < ev->nsymbols; i++)
     {
-        if (strcmp(ev->ids[i].name, name) == 0)
-            return &(ev->ids[i]);
+        if (strcmp(ev->symbols[i].name, name) == 0)
+            return &(ev->symbols[i]);
     }
     
     return NULL;
 }
 
 
-static DMEvalId *dm_eval_add_id(DMEvalContext *ev, const char *name, const int type)
+static DMEvalSymbol *dmEvalContextAddSymbol(DMEvalContext *ev, const char *name, const int type)
 {
-    DMEvalId *id = dm_eval_find_id(ev, name);
+    DMEvalSymbol *id = dmEvalContextFindSymbol(ev, name);
     if (id != NULL)
         return NULL;
 
-    ev->ids = dmRealloc(ev->ids, sizeof(DMEvalId) * (ev->nids + 1));
-    if (ev->ids == NULL)
+    ev->symbols = dmRealloc(ev->symbols, sizeof(DMEvalSymbol) * (ev->nsymbols + 1));
+    if (ev->symbols == NULL)
     {
-        dm_eval_err(ev, "Could not reallocate eval ids array (#%d). Fatal error.\n", ev->nids + 1);
+        dmEvalError(ev, "Could not reallocate eval symbols array (#%d). Fatal error.\n", ev->nsymbols + 1);
         return NULL;
     }
     
-    id = &(ev->ids[ev->nids]);
-    ev->nids++;
+    id = &(ev->symbols[ev->nsymbols]);
+    ev->nsymbols++;
 
     id->name = dm_strdup(name);
     id->type = type;
@@ -117,9 +147,9 @@
 }
 
 
-DMEvalId *dm_eval_add_var(DMEvalContext *ev, const char *name, DMValue *var)
+DMEvalSymbol *dmEvalContextAddVar(DMEvalContext *ev, const char *name, DMValue *var)
 {
-    DMEvalId *id = dm_eval_add_id(ev, name, ID_VAR);
+    DMEvalSymbol *id = dmEvalContextAddSymbol(ev, name, ID_VAR);
     if (id == NULL)
         return NULL;
     
@@ -128,9 +158,9 @@
 }
 
 
-DMEvalId *dm_eval_add_const(DMEvalContext *ev, const char *name, DMValue value)
+DMEvalSymbol *dmEvalContextAddConst(DMEvalContext *ev, const char *name, DMValue value)
 {
-    DMEvalId *id = dm_eval_add_id(ev, name, ID_CVAR);
+    DMEvalSymbol *id = dmEvalContextAddSymbol(ev, name, ID_CVAR);
     if (id == NULL)
         return NULL;
     
@@ -139,9 +169,9 @@
 }
 
 
-DMEvalId *dm_eval_add_func(DMEvalContext *ev, const char *name, DMValue (*func)(DMValue *), int nargs)
+DMEvalSymbol *dmEvalContextAddFunc(DMEvalContext *ev, const char *name, DMValue (*func)(DMValue *), int nargs)
 {
-    DMEvalId *id = dm_eval_add_id(ev, name, ID_VAR);
+    DMEvalSymbol *id = dmEvalContextAddSymbol(ev, name, ID_VAR);
     if (id == NULL)
         return NULL;
     
@@ -151,7 +181,7 @@
 }
 
 
-DMEvalContext *dm_eval_new(void)
+DMEvalContext *dmEvalContextNew(void)
 {
     int i;
     DMEvalContext *ev = dmCalloc(1, sizeof(DMEvalContext));
@@ -159,10 +189,10 @@
     if (ev == NULL)
         return NULL;
 
-    for (i = 0; i < ndm_eval_basic; i++)
+    for (i = 0; i < ndmEvalBasicFuncs; i++)
     {
-        const DMEvalId *id = &dm_eval_basic[i];
-        DMEvalId *nid = dm_eval_add_id(ev, id->name, id->type);
+        const DMEvalSymbol *id = &dmEvalBasicFuncs[i];
+        DMEvalSymbol *nid = dmEvalContextAddSymbol(ev, id->name, id->type);
         nid->nargs    = id->nargs;
         nid->func     = id->func;
         nid->var      = id->var;
@@ -173,7 +203,7 @@
 }
 
 
-void dm_eval_free(DMEvalNode *node)
+void dmEvalTreeFree(DMEvalNode *node)
 {
     while (node != NULL)
     {
@@ -182,11 +212,11 @@
 
         for (i = 0; i < DM_MAX_ARGS; i++)
         {
-            dm_eval_free(node->args[i]);
+            dmEvalTreeFree(node->args[i]);
             node->args[i] = NULL;
         }
 
-        dm_eval_free(node->subexpr);
+        dmEvalTreeFree(node->subexpr);
         node->subexpr = NULL;
         dmFree(node);
         node = next;
@@ -194,7 +224,7 @@
 }
 
 
-void dm_eval_clear_err(DMEvalContext *ev)
+void dmEvalContextClear(DMEvalContext *ev)
 {
     if (ev == NULL)
         return;
@@ -205,44 +235,23 @@
 }
 
 
-void dm_eval_close(DMEvalContext *ev)
+void dmEvalContextClose(DMEvalContext *ev)
 {
     int i;
 
     if (ev == NULL)
         return;
 
-    for (i = 0; i < ev->nids; i++)
-        dmFree(ev->ids[i].name);
+    for (i = 0; i < ev->nsymbols; i++)
+        dmFree(ev->symbols[i].name);
 
-    dmFree(ev->ids);
-    dm_eval_clear_err(ev);
+    dmFree(ev->symbols);
+    dmEvalContextClear(ev);
     dmFree(ev);
 }
 
 
-static DMEvalNode *dm_eval_pop_node(DMEvalNode **list)
-{
-    DMEvalNode *node;
-
-    if (*list == NULL)
-        return NULL;
-
-    node = (*list)->prev;
-
-    if (*list != node)
-    {
-        node->prev->next = NULL;
-        (*list)->prev = node->prev;
-    }
-    else
-        *list = NULL;
-
-    return node;
-}
-
-
-static DMEvalNode *dm_eval_insert_node(DMEvalNode **list, DMEvalNode *node)
+static DMEvalNode *dmEvalInsertNode(DMEvalNode **list, DMEvalNode *node)
 {
     if (*list != NULL)
     {
@@ -261,39 +270,7 @@
 }
 
 
-static DMEvalNode *dm_eval_push_node(DMEvalNode **list, const DMEvalNode *src)
-{
-    DMEvalNode *tmp, *node = dmCalloc(1, sizeof(DMEvalNode));
-    int i;
-
-    if (node == NULL)
-        return NULL;
-
-    node->op       = src->op;
-    node->val      = src->val;
-    node->id       = src->id;
-    node->ok       = src->ok;
-
-    if (src->op == OP_SUBEXPR)
-    {
-        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);
-}
-
-
-static DMEvalNode *dm_eval_add_node(DMEvalNode **list, const int op)
+static DMEvalNode *dmEvalAddNode(DMEvalNode **list, const int op)
 {
     DMEvalNode *node = dmCalloc(1, sizeof(DMEvalNode));
     if (node == NULL)
@@ -301,7 +278,7 @@
 
     node->op = op;
 
-    return dm_eval_insert_node(list, node);
+    return dmEvalInsertNode(list, node);
 }
 
 
@@ -325,7 +302,7 @@
 
 #define DM_CHECK(x) { if (mode & PARSE_ ## x ) { if (str[0]) strcat(str, " or "); strcat(str, # x ); } }
 
-static char *dm_get_mode(int mode)
+static char *dmEvalGetMode(int mode)
 {
     char str[128] = "";
 
@@ -343,17 +320,17 @@
 }
 
 
-static void dm_set_mode(DMEvalContext *ev, const int mode)
+static void dmEvalSetMode(DMEvalContext *ev, const int mode)
 {
     if (mode != PARSE_ERROR &&
         mode != PARSE_START &&
         ev->expect != PARSE_NONE &&
         (mode & ev->expect) == 0)
     {
-        char *tmp1 = dm_get_mode(ev->expect),
-             *tmp2 = dm_get_mode(mode);
+        char *tmp1 = dmEvalGetMode(ev->expect),
+             *tmp2 = dmEvalGetMode(mode);
 
-        dm_eval_err(ev, "Expected [%s], got %s.\n", tmp1, tmp2);
+        dmEvalError(ev, "Expected [%s], got %s.\n", tmp1, tmp2);
         dmFree(tmp1);
         dmFree(tmp2);
     }
@@ -363,7 +340,7 @@
 }
 
 
-static int dm_eval_parse_expr_do(DMEvalContext *ev, DMEvalNode **list, char **str, int depth)
+static int dmEvalTokenizeExpr(DMEvalContext *ev, DMEvalNode **list, char **str, int depth)
 {
     char *c = *str;
     char tmpStr[DM_MAX_BUF + 2];
@@ -383,18 +360,18 @@
 
                 ev->expect = PARSE_NORMAL;
 
-                if ((node = dm_eval_add_node(list, OP_SUBEXPR)) == NULL)
-                    dm_set_mode(ev, PARSE_ERROR);
+                if ((node = dmEvalAddNode(list, OP_SUBEXPR)) == NULL)
+                    dmEvalSetMode(ev, PARSE_ERROR);
                 else
-                if (dm_eval_parse_expr_do(ev, &(node->subexpr), &tmp, depth + 1) != 0)
+                if (dmEvalTokenizeExpr(ev, &(node->subexpr), &tmp, depth + 1) != 0)
                 {
-                    dm_eval_err(ev, "Subexpression starting at '%s' contained errors.\n", c);
-                    dm_set_mode(ev, PARSE_ERROR);
+                    dmEvalError(ev, "Subexpression starting at '%s' contained errors.\n", c);
+                    dmEvalSetMode(ev, PARSE_ERROR);
                 }
 
                 if (ev->mode != PARSE_ERROR)
                 {
-                    dm_set_mode(ev, PARSE_START);
+                    dmEvalSetMode(ev, PARSE_START);
                     ev->expect = PARSE_OPER | PARSE_SUBEXPR_END;
                     c = tmp;
                 }
@@ -406,10 +383,10 @@
                 char *tmp = c + 1;
                 for (argIndex = 0; argIndex < func->id->nargs; argIndex++)
                 {
-                    if (dm_eval_parse_expr_do(ev, &(func->args[argIndex]), &tmp, depth + 1) != 0)
+                    if (dmEvalTokenizeExpr(ev, &(func->args[argIndex]), &tmp, depth + 1) != 0)
                     {
-                        dm_eval_err(ev, "Function argument subexpression starting at '%s' contained errors.\n", c);
-                        dm_set_mode(ev, PARSE_ERROR);
+                        dmEvalError(ev, "Function argument subexpression starting at '%s' contained errors.\n", c);
+                        dmEvalSetMode(ev, PARSE_ERROR);
                     }
                 }
 
@@ -417,7 +394,7 @@
 
                 if (ev->mode != PARSE_ERROR)
                 {
-                    dm_set_mode(ev, PARSE_START);
+                    dmEvalSetMode(ev, PARSE_START);
                     ev->expect = PARSE_OPER | PARSE_END;
                     c = tmp;
                 }
@@ -427,7 +404,7 @@
         case PARSE_START:
             // Start
             if (*c == 0)
-                dm_set_mode(ev, PARSE_END);
+                dmEvalSetMode(ev, PARSE_END);
 
             // Skip whitespace
             else if (isspace(*c))
@@ -436,37 +413,37 @@
             else if (*c == ')' || *c == ',')
             {
                 if (depth > 0)
-                    dm_set_mode(ev, PARSE_END);
+                    dmEvalSetMode(ev, PARSE_END);
                 else
                 {
-                    dm_eval_err(ev, "Invalid nesting near '%s' (depth %d).\n", c, depth);
-                    dm_set_mode(ev, PARSE_ERROR);
+                    dmEvalError(ev, "Invalid nesting near '%s' (depth %d).\n", c, depth);
+                    dmEvalSetMode(ev, PARSE_ERROR);
                 }
                 c++;
             }
             
             else if (*c == '(')
-                dm_set_mode(ev, func != NULL ? PARSE_ARGS : PARSE_SUBEXPR_START);
+                dmEvalSetMode(ev, func != NULL ? PARSE_ARGS : PARSE_SUBEXPR_START);
             
             else if (*c == '-')
-                dm_set_mode(ev, (ev->prev == PARSE_START || ev->prev == PARSE_OPER || ev->prev == PARSE_OPER_UNARY) ? PARSE_OPER_UNARY : PARSE_OPER);
+                dmEvalSetMode(ev, (ev->prev == PARSE_START || ev->prev == PARSE_OPER || ev->prev == PARSE_OPER_UNARY) ? PARSE_OPER_UNARY : PARSE_OPER);
             
             else if (*c == '~')
-                dm_set_mode(ev, PARSE_OPER_UNARY);
+                dmEvalSetMode(ev, PARSE_OPER_UNARY);
             
             else if (strchr("+*/<>%&|!^", *c))
-                dm_set_mode(ev, PARSE_OPER);
+                dmEvalSetMode(ev, PARSE_OPER);
 
             else if (isdigit(*c) || *c == '.')
-                dm_set_mode(ev, PARSE_CONST);
+                dmEvalSetMode(ev, PARSE_CONST);
 
             else if (isalpha(*c) || *c == '_')
-                dm_set_mode(ev, PARSE_IDENT);
+                dmEvalSetMode(ev, PARSE_IDENT);
             
             else
             {
-                dm_eval_err(ev, "Syntax error near '%s' (depth %d).\n", c, depth);
-                dm_set_mode(ev, PARSE_ERROR);
+                dmEvalError(ev, "Syntax error near '%s' (depth %d).\n", c, depth);
+                dmEvalSetMode(ev, PARSE_ERROR);
             }
 
             first = TRUE;
@@ -487,8 +464,8 @@
                 }
                 else
                 {
-                    dm_eval_err(ev, "Invalid constant expression near '%s'.\n", c);
-                    dm_set_mode(ev, PARSE_ERROR);
+                    dmEvalError(ev, "Invalid constant expression near '%s'.\n", c);
+                    dmEvalSetMode(ev, PARSE_ERROR);
                 }
             }
             else
@@ -507,22 +484,22 @@
                     }
                     else
                     {
-                        dm_eval_err(ev, "Invalid constant expression near '%s'.\n", c);
-                        dm_set_mode(ev, PARSE_ERROR);
+                        dmEvalError(ev, "Invalid constant expression near '%s'.\n", c);
+                        dmEvalSetMode(ev, PARSE_ERROR);
                     }
                 }
                 else
                 {
                     tmpStr[tmpStrLen] = 0;
 
-                    if ((node = dm_eval_add_node(list, OP_CONST)) == NULL)
+                    if ((node = dmEvalAddNode(list, OP_CONST)) == NULL)
                     {
-                        dm_set_mode(ev, PARSE_ERROR);
+                        dmEvalSetMode(ev, PARSE_ERROR);
                     }
                     else
                     {
                         node->val = atof(tmpStr);
-                        dm_set_mode(ev, PARSE_START);
+                        dmEvalSetMode(ev, PARSE_START);
                         ev->expect = PARSE_OPER | PARSE_END;
                     }
                 }
@@ -531,7 +508,7 @@
 
         case PARSE_OPER_UNARY:
             {
-                int op = OP_NONE;
+                int op = OP_INVALID;
 
                 switch (*c)
                 {
@@ -539,22 +516,22 @@
                     case '~': op = OP_BIT_COMPLEMENT; c++; break;
                 }
 
-                if (op != OP_NONE)
+                if (op != OP_INVALID)
                 {
-                    if ((node = dm_eval_add_node(list, op)) != NULL)
+                    if ((node = dmEvalAddNode(list, op)) != NULL)
                     {
                         ev->expect = PARSE_NORMAL;
-                        dm_set_mode(ev, PARSE_START);
+                        dmEvalSetMode(ev, PARSE_START);
                     }
                     else
-                        dm_set_mode(ev, PARSE_ERROR);
+                        dmEvalSetMode(ev, PARSE_ERROR);
                 }
             }
             break;
 
         case PARSE_OPER:
             {
-                int op = OP_NONE;
+                int op = OP_INVALID;
 
                 switch (*c)
                 {
@@ -594,19 +571,19 @@
                         break;
 
                     default:
-                        dm_eval_err(ev, "Unknown operator '%c' at %s\n", *c, c);
-                        dm_set_mode(ev, PARSE_ERROR);
+                        dmEvalError(ev, "Unknown operator '%c' at %s\n", *c, c);
+                        dmEvalSetMode(ev, PARSE_ERROR);
                 }
 
-                if (op != OP_NONE)
+                if (op != OP_INVALID)
                 {
-                    if ((node = dm_eval_add_node(list, op)) != NULL)
+                    if ((node = dmEvalAddNode(list, op)) != NULL)
                     {
                         ev->expect = PARSE_NORMAL | PARSE_OPER_UNARY;
-                        dm_set_mode(ev, PARSE_START);
+                        dmEvalSetMode(ev, PARSE_START);
                     }
                     else
-                        dm_set_mode(ev, PARSE_ERROR);
+                        dmEvalSetMode(ev, PARSE_ERROR);
                 }
             }
             break;
@@ -620,21 +597,21 @@
                     first = FALSE;
                 }
 
-                if (tmpStrLen < DM_MAX_ID_LEN)
+                if (tmpStrLen < DM_MAX_BUF)
                     tmpStr[tmpStrLen++] = *c++;
                 else
                 {
                     tmpStr[tmpStrLen] = 0;
-                    dm_eval_err(ev, "Identifier too long! ('%s') near %s\n", tmpStr, c);
+                    dmEvalError(ev, "Identifier too long! ('%s') near %s\n", tmpStr, c);
                 }
             }
             else
             {
                 tmpStr[tmpStrLen] = 0;
-                DMEvalId *id = dm_eval_find_id(ev, tmpStr);
+                DMEvalSymbol *id = dmEvalContextFindSymbol(ev, tmpStr);
                 if (id != NULL)
                 {
-                    if ((node = dm_eval_add_node(list, id->type == ID_FUNC ? OP_FUNC : OP_VAR)) != NULL)
+                    if ((node = dmEvalAddNode(list, id->type == ID_FUNC ? OP_FUNC : OP_VAR)) != NULL)
                     {
                         node->id = id;
                         if (id->type == ID_FUNC)
@@ -645,15 +622,15 @@
                         else
                             ev->expect = PARSE_END | PARSE_OPER;
 
-                        dm_set_mode(ev, PARSE_START);
+                        dmEvalSetMode(ev, PARSE_START);
                     }
                     else
-                        dm_set_mode(ev, PARSE_ERROR);
+                        dmEvalSetMode(ev, PARSE_ERROR);
                 }
                 else
                 {
-                    dm_eval_err(ev, "No such identifier '%s'.\n", tmpStr);
-                    dm_set_mode(ev, PARSE_ERROR);
+                    dmEvalError(ev, "No such identifier '%s'.\n", tmpStr);
+                    dmEvalSetMode(ev, PARSE_ERROR);
                 }
             }
             break;
@@ -665,7 +642,7 @@
 }
 
 
-int dm_eval_parse_expr(DMEvalContext *ev, char *expr, DMEvalNode **result)
+int dmEvalParseExpr(DMEvalContext *ev, char *expr, DMEvalNode **result)
 {
     int ret;
 
@@ -673,210 +650,17 @@
         return -1;
 
     ev->prev = PARSE_START;
-    ret = dm_eval_parse_expr_do(ev, result, &expr, 0);
+    ret = dmEvalTokenizeExpr(ev, result, &expr, 0);
     
     return ret;
 }
 
 
-/*
-    operator precedence:
-      HIGHEST
-      "()"
-      
-      "*"
-      "/"
-      "%"
-      
-      "+"
-      "-"
-      
-      "<<"
-      ">>"
-      
-      "&"
-      "^"
-      "|"
-      LOWEST
-*/
 
-static int dm_eval_reorder_pass0(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result)
-{
-    DMEvalNode *tmp;
-    int i, res;
-
-    for (; node != NULL; node = node->next)
-    switch (node->op)
-    {
-        case OP_FUNC:
-            if ((tmp = dm_eval_add_node(result, OP_FUNC)) == NULL)
-                return -1;
-
-            tmp->id = node->id;
-
-            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_add_node(result, OP_SUBEXPR)) == NULL)
-                return -1;
-
-            if ((res = dm_eval_reorder(ev, node->subexpr, &(tmp->subexpr))) != 0)
-                return res;
-            break;
-
-        default:
-            if (dm_eval_push_node(result, node) == NULL)
-                return -32;
-            break;
-    }
-
-    return 0;
-}
-
-
-static int dm_eval_reorder_pass1(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result,
-    const int op1, const int op2, const int op3)
-{
-    DMEvalNode *sub;
-
-    for (; node != NULL; node = node->next)
-    {
-        if (!node->ok && node->op == op1 &&
-            (node->prev == NULL || node->prev->op < OP_FUNC))
-        {
-            if (node->next == NULL || node->next->op == op2)
-            {
-                if (dm_eval_push_node(result, node) == NULL)
-                    return -32;
-            }
-            else
-            {
-                // Add subexpression node
-                if ((sub = dm_eval_add_node(result, 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;
-
-                dm_eval_push_node(&(sub->subexpr), node);
-            }
-        }
-        else
-        if (dm_eval_push_node(result, node) == NULL)
-            return -32;
-    }
 
 
-    return 0;
-}
 
-
-static int dm_eval_reorder_passN(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result,
-    const int op1, const int op2, const int op3)
-{
-    DMEvalNode *tmp, *sub, *foo;
-
-    for (; node != NULL; node = node->next)
-    {
-        if (!node->ok && (node->op == op1 || node->op == op2 || node->op == op3))
-        {
-            // Pop previous node, f.e. 5*3 -> 5
-            if ((tmp = dm_eval_pop_node(result)) == NULL)
-                return -24;
-
-            // Add subexpression node
-            if ((sub = dm_eval_add_node(result, OP_SUBEXPR)) == NULL)
-                return DMERR_MALLOC;
-
-            // Add popped node into subexpression
-            dm_eval_push_node(&(sub->subexpr), tmp);
-            
-            // Add this operator into subexpression
-            if ((foo = dm_eval_add_node(&(sub->subexpr), node->op)) == NULL)
-                return DMERR_MALLOC;
-
-            foo->ok = TRUE;
-
-            // Next node
-            node = node->next;
-            if (node == NULL)
-                return -72;
-
-            dm_eval_push_node(&(sub->subexpr), node);
-        }
-        else
-        if (dm_eval_push_node(result, node) == NULL)
-            return -32;
-    }
-
-    return 0;
-}
-
-
-#if 1
-#define RO_DEBUG(x, y) do { fprintf(stderr, x); dm_print_optree(stderr, ev, y); } while (0)
-#else
-#define RO_DEBUG(x, y) /* stub */
-#endif
-
-
-int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result)
-{
-    DMEvalNode *tmp1 = NULL, *tmp2 = NULL, *tmp3 = NULL, *tmp4 = NULL, *tmp5 = NULL;
-    int res;
-
-    RO_DEBUG("REORD: ", node);
-    
-    // Pass 0
-    if ((res = dm_eval_reorder_pass0(ev, node, &tmp1)) != 0)
-        goto out;
-    RO_DEBUG("PASS0: ", tmp1);
-
-    // Pass 1
-    if ((res = dm_eval_reorder_pass1(ev, tmp1, &tmp2, OP_BIT_COMPLEMENT, -1, -1)) != 0)
-        goto out;
-    RO_DEBUG("PASS1: ", tmp2);
-
-    // Pass 2
-    if ((res = dm_eval_reorder_pass1(ev, tmp2, &tmp3, OP_SUB_UNARY, -1, -1)) != 0)
-        goto out;
-    RO_DEBUG("PASS2: ", tmp2);
-
-    // Pass 2
-    if ((res = dm_eval_reorder_passN(ev, tmp3, &tmp4, OP_MUL, OP_DIV, OP_MOD)) != 0)
-        goto out;
-    RO_DEBUG("PASS3: ", tmp2);
-
-    // Pass 3
-    if ((res = dm_eval_reorder_passN(ev, tmp4, &tmp5, OP_SUB, OP_ADD, -1)) != 0)
-        goto out;
-    RO_DEBUG("PASS4: ", tmp3);
-
-    res = dm_eval_reorder_passN(ev, tmp5, result, OP_BIT_LSHIFT, OP_BIT_RSHIFT, -1);
-    RO_DEBUG("PASS5: ", *result);
-
-out:
-    dm_eval_free(tmp1);
-    dm_eval_free(tmp2);
-    dm_eval_free(tmp3);
-    dm_eval_free(tmp4);
-    dm_eval_free(tmp5);
-
-    return res;
-}
-
-
-static int dm_eval_get(DMEvalContext *ev, const DMEvalNode *node, DMValue *result)
+static int dmEvalGet(DMEvalContext *ev, const DMEvalNode *node, DMValue *result)
 {
     if (node == NULL)
         return -32;
@@ -895,7 +679,7 @@
             break;
 
         case OP_SUBEXPR:
-            return dm_eval_exec(ev, node->subexpr, result);
+            return dmEvalTreeExecute(ev, node->subexpr, result);
         
         case OP_FUNC:
             {
@@ -903,7 +687,7 @@
                 int i;
                 for (i = 0; i < node->id->nargs; i++)
                 {
-                    if (dm_eval_exec(ev, node->args[i], &tmp[i]) != 0)
+                    if (dmEvalTreeExecute(ev, node->args[i], &tmp[i]) != 0)
                         return -1;
                 }
                 
@@ -919,7 +703,7 @@
 }
 
 
-int dm_eval_exec(DMEvalContext *ev, DMEvalNode *tree, DMValue *presult)
+int dmEvalTreeExecute(DMEvalContext *ev, DMEvalNode *tree, DMValue *presult)
 {
     DMValue result = 0;
     DMEvalNode *node = tree;
@@ -940,7 +724,7 @@
             case OP_MUL:
             case OP_DIV:
             case OP_MOD:
-                if (dm_eval_get(ev, node->next, &tmp) != 0)
+                if (dmEvalGet(ev, node->next, &tmp) != 0)
                     return -6;
                 
                 switch (node->op)
@@ -948,7 +732,7 @@
                     case OP_DIV:
                         if (tmp == 0)
                         {
-                            dm_eval_err(ev, "Division by zero.\n");
+                            dmEvalError(ev, "Division by zero.\n");
                             return -1;
                         }
                         result /= tmp;
@@ -959,7 +743,7 @@
                     case OP_MOD:
                         if (tmp == 0)
                         {
-                            dm_eval_err(ev, "Division by zero.\n");
+                            dmEvalError(ev, "Division by zero.\n");
                             return -1;
                         }
                         result = DMCONVTYPE result % DMCONVTYPE tmp;
@@ -967,12 +751,12 @@
 
                     case OP_BIT_LSHIFT:
                         if (tmp > 31)
-                            dm_eval_err(ev, "Left shift count >= width of type");
+                            dmEvalError(ev, "Left shift count >= width of type");
                         result = DMCONVTYPE result << DMCONVTYPE tmp; break;
 
                     case OP_BIT_RSHIFT:
                         if (tmp > 31)
-                            dm_eval_err(ev, "Right shift count >= width of type");
+                            dmEvalError(ev, "Right shift count >= width of type");
                         result = DMCONVTYPE result >> DMCONVTYPE tmp; break;
 
                     case OP_BIT_AND:     result = DMCONVTYPE result & DMCONVTYPE tmp; break;
@@ -987,7 +771,7 @@
             case OP_SUB:
             case OP_SUB_UNARY:
             case OP_BIT_COMPLEMENT:
-                if (dm_eval_get(ev, node->next, &tmp) != 0)
+                if (dmEvalGet(ev, node->next, &tmp) != 0)
                     return -6;
                 
                 switch (node->op)
@@ -1002,9 +786,9 @@
                 break;
 
             default:
-                if (dm_eval_get(ev, node, &result) != 0)
+                if (dmEvalGet(ev, node, &result) != 0)
                 {
-                    dm_eval_err(ev, "Invalid opcode %d in node %p.\n", node->op, node);
+                    dmEvalError(ev, "Invalid opcode %d in node %p.\n", node->op, node);
                     return -4;
                 }
         }
--- a/dmeval.h	Thu May 09 06:18:52 2013 +0300
+++ b/dmeval.h	Thu May 09 06:21:36 2013 +0300
@@ -2,6 +2,7 @@
 #define DMEVAL_H
 
 #include "dmlib.h"
+#include <stdio.h>
 
 
 typedef double DMValue;
@@ -11,8 +12,8 @@
 
 enum
 {
-    // No-op
-    OP_NONE,
+    OP_SUB_UNARY,
+    OP_BIT_COMPLEMENT,
 
     OP_ADD,
     OP_SUB,
@@ -20,9 +21,6 @@
     OP_DIV,
     OP_MOD,
 
-    OP_SUB_UNARY,
-    OP_BIT_COMPLEMENT,
-
     OP_BIT_LSHIFT,
     OP_BIT_RSHIFT,
 
@@ -38,20 +36,31 @@
     // Special ops
     OP_FUNC,
     OP_VAR,
+    OP_CONST,
     OP_SUBEXPR,
-    OP_CONST,
 
     // Total number of operators
-    OP_NOPERS
-} DMOper;
+    OP_NOPERS,
+
+    OP_INVALID
+} DMEvalOperId;
 
 
 enum
 {
+    OT_NONE,
+
     OT_LEFT,      // Left-associative
     OT_RIGHT,     // Right-associative
     OT_UNARY,
-} DMOperType;
+} DMEvalOperType;
+
+
+typedef struct
+{
+    char *name;
+    int type;
+} DMEvalOper;
 
 
 enum
@@ -59,7 +68,7 @@
     ID_FUNC,
     ID_VAR,
     ID_CVAR,
-} DMEvalIdType;
+} DMEvalSymbolType;
 
 
 typedef struct
@@ -69,7 +78,7 @@
     int nargs;
     DMValue (*func)(DMValue arg[DM_MAX_ARGS]);
     DMValue *var, cvalue;
-} DMEvalId;
+} DMEvalSymbol;
 
 
 typedef struct DMEvalNode
@@ -77,9 +86,10 @@
     BOOL ok;
     int op;
     DMValue val;
-    DMEvalId *id;
+    DMEvalSymbol *id;
 
     struct DMEvalNode *args[DM_MAX_ARGS];
+
     struct DMEvalNode *subexpr, *next, *prev;
 } DMEvalNode;
 
@@ -89,26 +99,35 @@
     BOOL err;
     char *errStr;
     
-    int nids;
-    DMEvalId *ids;
+    int nsymbols;
+    DMEvalSymbol *symbols;
 
     int mode, prev, expect;
 } DMEvalContext;
 
 
-DMEvalId *dm_eval_find_id(DMEvalContext *ev, const char *name);
-DMEvalId *dm_eval_add_var(DMEvalContext *ev, const char *name, DMValue *var);
-DMEvalId *dm_eval_add_const(DMEvalContext *ev, const char *name, DMValue value);
-DMEvalId *dm_eval_add_func(DMEvalContext *ev, const char *name, DMValue (*func)(DMValue *), int nargs);
+// Evaluation context management
+DMEvalContext * dmEvalContextNew(void);
+void            dmEvalContextClose(DMEvalContext *ev);
+void            dmEvalContextClear(DMEvalContext *ev);
+
 
-DMEvalContext *dm_eval_new(void);
-void dm_eval_close(DMEvalContext *ev);
-void dm_eval_free(DMEvalNode *node);
-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_exec(DMEvalContext *ev, DMEvalNode *tree, DMValue *presult);
+// Symbol management
+DMEvalSymbol *  dmEvalContextFindSymbol(DMEvalContext *ev, const char *name);
+DMEvalSymbol *  dmEvalContextAddVar(DMEvalContext *ev, const char *name, DMValue *var);
+DMEvalSymbol *  dmEvalContextAddConst(DMEvalContext *ev, const char *name, DMValue value);
+DMEvalSymbol *  dmEvalContextAddFunc(DMEvalContext *ev, const char *name, DMValue (*func)(DMValue *), int nargs);
 
 
+// Evaluation trees, tokenization, parsing
+int   dmEvalParseExpr(DMEvalContext *ev, char *expr, DMEvalNode **plist);
+int   dmEvalTreeExecute(DMEvalContext *ev, DMEvalNode *tree, DMValue *presult);
+void  dmEvalTreeFree(DMEvalNode *node);
+
+
+void dmEvalPrintOpTree(FILE *out, DMEvalContext *ev, DMEvalNode *node);
+
+
+extern const DMEvalOper dmEvalOpers[OP_NOPERS];
+
 #endif // DMEVAL_H
--- a/dmevalw.c	Thu May 09 06:18:52 2013 +0300
+++ b/dmevalw.c	Thu May 09 06:21:36 2013 +0300
@@ -1,38 +1,7 @@
-#include "dmevalw.h"
+#include "dmeval.h"
 
 
-static const char *dm_oper_names[OP_NOPERS] =
-{
-    "NONE",
-    "+",
-    "-",
-    "*",
-    "/",
-    "%",
-
-    "#",
-    "~",
-
-    "<<",
-    ">>",
-
-    "&",
-    "|",
-    "^",
-
-    ">",
-    "<",
-    ">=",
-    "<=",
-
-    "FUNC",
-    "VAR",
-    "SUBEXPR",
-    "CONST",
-};
-
-
-static void dm_print_optree_do(FILE *out, DMEvalContext *ev, DMEvalNode *node, const int level)
+void dmDoEvalPrintOpTree(FILE *out, DMEvalContext *ev, DMEvalNode *node, int level)
 {
     int i;
     while (node != NULL)
@@ -43,7 +12,7 @@
                 fprintf(out, "%s(", node->id != NULL ? node->id->name : "?ERROR");
                 for (i = 0; i < node->id->nargs; i++)
                 {
-                    dm_print_optree_do(out, ev, node->args[i], level + 1);
+                    dmDoEvalPrintOpTree(out, ev, node->args[i], level + 1);
                     if (i < node->id->nargs - 1)
                         fprintf(out, ",");
                 }
@@ -61,15 +30,15 @@
             case OP_SUBEXPR:
                 fprintf(out, "(");
                 if (node->subexpr != NULL)
-                    dm_print_optree_do(out, ev, node->subexpr, level + 1);
+                    dmDoEvalPrintOpTree(out, ev, node->subexpr, level + 1);
                 else
                     fprintf(out, "?ERROR");
                 fprintf(out, ")");
                 break;
 
             default:
-                if (node->op > 0 && node->op < OP_NOPERS)
-                    fprintf(out, "%s", dm_oper_names[node->op]);
+                if (node->op >= 0 && node->op < OP_NOPERS)
+                    fprintf(out, "%s", dmEvalOpers[node->op].name);
                 else
                     fprintf(out, "ERROR!");
                 break;
@@ -79,8 +48,8 @@
 }
 
 
-void dm_print_optree(FILE *out, DMEvalContext *ev, DMEvalNode *node)
+void dmEvalPrintOpTree(FILE *out, DMEvalContext *ev, DMEvalNode *node)
 {
-    dm_print_optree_do(out, ev, node, 0);
+    dmDoEvalPrintOpTree(out, ev, node, 0);
     fprintf(out, "\n");
 }
--- a/dmevalw.h	Thu May 09 06:18:52 2013 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,10 +0,0 @@
-#ifndef DMEVALW_H
-#define DMEVALW_H
-
-#include "dmeval.h"
-#include <stdio.h>
-
-void dm_print_optree(FILE *out, DMEvalContext *ev, DMEvalNode *node);
-
-
-#endif // DMEVALW_H
--- a/tests/evaltest.c	Thu May 09 06:18:52 2013 +0300
+++ b/tests/evaltest.c	Thu May 09 06:21:36 2013 +0300
@@ -1,12 +1,11 @@
 #include "dmlib.h"
 #include "dmeval.h"
-#include "dmevalw.h"
 #include "dmargs.h"
 
 
 BOOL    optBenchmark = FALSE,
         optFloor = FALSE;
-char *  optFormula = "";
+char *  optExpression = "";
 
 
 DMOptArg optList[] =
@@ -14,7 +13,7 @@
     { 0, '?', "help",       "Show this help", OPT_NONE },
     { 1, 'v', "verbose",    "Be more verbose", OPT_NONE },
     { 2, 'b', "benchmark",  "Run in benchmark mode", OPT_NONE },
-    { 3, 'e', "expression", "Next argument is the expression/formula", OPT_ARGREQ },
+    { 3, 'e', "expression", "Next argument is the expression", OPT_ARGREQ },
     { 4, 'f', "floor",      "Clamp/floor the result value", OPT_NONE },
 };
 
@@ -23,7 +22,7 @@
 
 void argShowHelp()
 {
-    dmPrintBanner(stdout, dmProgName, "[options] [-e] '<formula>'");
+    dmPrintBanner(stdout, dmProgName, "[options] [-e] '<expression>'");
     dmArgsPrintHelp(stdout, optList, optListN);
 }
 
@@ -46,7 +45,7 @@
         break;
 
     case 3:
-        optFormula = optArg;
+        optExpression = optArg;
         break; 
 
     case 4:
@@ -64,15 +63,15 @@
 
 BOOL argHandleNonOpt(char *currArg)
 {
-    optFormula = currArg;
+    optExpression = currArg;
     return TRUE;
 }
 
 
 int main(int argc, char *argv[])
 {
-    DMEvalContext *ev = dm_eval_new();
-    DMEvalNode *parsed = NULL, *ordered = NULL;
+    DMEvalContext *ev = dmEvalContextNew();
+    DMEvalNode *expr = NULL;
     DMValue result, t, f = 44100.0f;
     int ret;
 
@@ -85,54 +84,41 @@
 
 
     // Register some variables
-    dm_eval_add_var(ev, "t", &t);
-    dm_eval_add_var(ev, "f", &f);
+    dmEvalContextAddVar(ev, "t", &t);
+    dmEvalContextAddVar(ev, "f", &f);
 
 
     // Parse expression
-    ret = dm_eval_parse_expr(ev, optFormula, &parsed);
+    ret = dmEvalParseExpr(ev, optExpression, &expr);
     dmMsg(1, "parse ret=%d\n", ret);
     if (ev->err)
         dmError("%s\n", ev->errStr);
 
     if (dmVerbosity > 0)
-        dm_print_optree(stdout, ev, parsed);
+        dmEvalPrintOpTree(stdout, ev, expr);
     
     if (ret != 0)
         return -1;
+    
+    // Benchmark or execute
+    dmEvalContextClear(ev);
 
-    // Perform reordering
-    dm_eval_clear_err(ev);
-    
-    ret = dm_eval_reorder(ev, parsed, &ordered);
-    dmMsg(1, "reorder ret=%d\n", ret);
-    if (ev->err)
-        dmError("%s\n", ev->errStr);
-
-    if (dmVerbosity > 0)
-        dm_print_optree(stdout, ev, ordered);
-
-    if (ret != 0)
-        return -2;
-
-    // Benchmark or execute
     if (optBenchmark)
     {
         dmMsg(0, "Benchmarking ...\n");
         for (t = 0; t < 12500000; t++)
-            ret = dm_eval_exec(ev, ordered, &result);
+            ret = dmEvalTreeExecute(ev, expr, &result);
     }
     else
     {
-        ret = dm_eval_exec(ev, ordered, &result);
+        ret = dmEvalTreeExecute(ev, expr, &result);
         printf("%1.5f\n", optFloor ? (int) result : result);
     }
 
     dmMsg(1, "eval ret=%d\n", ret);
 
-    dm_eval_close(ev);
-    dm_eval_free(parsed);
-    dm_eval_free(ordered);
+    dmEvalContextClose(ev);
+    dmEvalTreeFree(expr);
 
     return 0;
 }
--- a/tools/auval.c	Thu May 09 06:18:52 2013 +0300
+++ b/tools/auval.c	Thu May 09 06:21:36 2013 +0300
@@ -24,10 +24,7 @@
 typedef struct
 {
     DMEvalNode *expr;
-    DMEvalContext *engine;
-
-    char *errStr;
-    int err;
+    DMEvalContext *ctx;
     
     double varTime, varFreq, varKeyTime,
            varKeyTimeRev, varKeyFreq, varUnit;
@@ -557,7 +554,7 @@
     
     data->avail = 0;
 
-    if (data->err == 0)
+    if (!data->ctx->err)
     {
         while (data->avail < len && data->avail < data->bufsize)
         {
@@ -565,7 +562,7 @@
 
             data->varKeyTimeRev = 1.0f - data->varKeyTime;
 
-            if (dm_eval_exec(data->engine, data->expr, &value) != 0)
+            if (dmEvalTreeExecute(data->ctx, data->expr, &value) != 0)
                 break;
 
             if (optScale)
@@ -591,7 +588,7 @@
                 data->varKeyTime = 1.0f;
         }
         
-        if (data->avail >= len && data->err == 0)
+        if (data->avail >= len && !data->ctx->err)
         {
             memcpy(buf, data->buf, len);
             data->pos += len;
@@ -640,14 +637,14 @@
     au_read_history(AUVAL_HISTORY_FILE, histBuf, optHistoryLen, &histMax);
 
 
-    /* Initialize evaluator engine */
-    audata.engine = dm_eval_new();
+    /* Initialize evaluator ctx */
+    audata.ctx = dmEvalContextNew();
     audata.expr = NULL;
     
-    dm_eval_add_var(audata.engine, "t", &audata.varTime);
-    dm_eval_add_var(audata.engine, "k", &audata.varKeyTime);
-    dm_eval_add_var(audata.engine, "q", &audata.varKeyTimeRev);
-    dm_eval_add_var(audata.engine, "f", &audata.varUnit);
+    dmEvalContextAddVar(audata.ctx, "t", &audata.varTime);
+    dmEvalContextAddVar(audata.ctx, "k", &audata.varKeyTime);
+    dmEvalContextAddVar(audata.ctx, "q", &audata.varKeyTimeRev);
+    dmEvalContextAddVar(audata.ctx, "f", &audata.varUnit);
 
 
     /* Initialize SDL */
@@ -1004,18 +1001,11 @@
             
             dmMutexLock(audata.mutex);
             
-            dm_eval_free(audata.expr);
-            DMEvalNode *tmp = NULL;
+            dmEvalTreeFree(audata.expr);
             audata.expr = NULL;
-            
-            audata.err = dm_eval_parse_expr(audata.engine, editBuf->data, &tmp);
-            if (audata.err == 0)
-                audata.err = dm_eval_reorder(audata.engine, tmp, &audata.expr);
-
-            dm_print_optree(stdout, audata.engine, tmp);
-            dm_print_optree(stdout, audata.engine, audata.expr);
+            audata.ctx->err = dmEvalParseExpr(audata.ctx, editBuf->data, &audata.expr);
+            dmEvalPrintOpTree(stdout, audata.ctx, audata.expr);
             printf("--\n");
-            dm_eval_free(tmp);
 
             audata.pos        = 0;
             audata.varTime    = 0;
@@ -1100,14 +1090,14 @@
                 dmMutexLock(audata.mutex);
 
                 dmFillBox3D(screen, 0, eh - 15, screen->w - 1, screen->h - 1,
-                    audata.err ? dmMapRGB(screen, 255, 0, 0) : dmMapRGB(screen, 0, 128, 64),
+                    audata.ctx->err ? dmMapRGB(screen, 255, 0, 0) : dmMapRGB(screen, 0, 128, 64),
                     dmMapRGB(screen, 200, 255, 200), 100);
 
                 au_draw_editbuf(screen, font, fontcol, 5, eh - 10, screen->w - 10, eh - 15, editBuf,
                     dmMapRGB(screen, 0, 0, 150));
                 
-                if (audata.errStr != NULL)
-                    dmDrawTTFTextConst(screen, font, fontcol, 5, screen->h - fh, audata.errStr);
+                if (audata.ctx->err && audata.ctx->errStr != NULL)
+                    dmDrawTTFTextConst(screen, font, fontcol, 5, screen->h - fh, audata.ctx->errStr);
 
                 dmMutexUnlock(audata.mutex);
             }