changeset 740:48c48e94d87f

More work on the evaluator. Still broken, of course.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 22 Apr 2013 09:37:34 +0300
parents 8bf67daf4030
children 9efcdbe5a299
files dmeval.c dmeval.h dmevalw.c
diffstat 3 files changed, 168 insertions(+), 103 deletions(-) [+]
line wrap: on
line diff
--- a/dmeval.c	Sun Apr 21 20:40:54 2013 +0300
+++ b/dmeval.c	Mon Apr 22 09:37:34 2013 +0300
@@ -242,15 +242,6 @@
 }
 
 
-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)
@@ -316,19 +307,20 @@
 
 enum
 {
-    PARSE_NONE    = 0x0000,
-    PARSE_START   = 0x1000,
-    PARSE_END     = 0x2000,
-    PARSE_ERROR   = 0x8000,
+    PARSE_NONE          = 0x0000,
+    PARSE_START         = 0x1000,
+    PARSE_END           = 0x2000,
+    PARSE_ERROR         = 0x8000,
 
-    PARSE_IDENT   = 0x0001,
-    PARSE_CONST   = 0x0002,
-    PARSE_OPER    = 0x0004, // All operators
-    PARSE_OPER2   = 0x0008, // '-' only
-    PARSE_SUBEXPR = 0x0010,
-    PARSE_ARGS    = 0x0020,
+    PARSE_IDENT         = 0x0001, // Any identifier (variable, function name)
+    PARSE_CONST         = 0x0002, // Constant value (n, n.nnn, etc)
+    PARSE_OPER          = 0x0004, // All operators
+    PARSE_OPER_UNARY    = 0x0008, // Unary operators ~, -
+    PARSE_SUBEXPR_START = 0x0010, // ( ...
+    PARSE_SUBEXPR_END   = 0x0020, // )
+    PARSE_ARGS          = 0x0040, // function args: (xxx[, yyy ...])
 
-    PARSE_NORMAL  = PARSE_CONST | PARSE_IDENT | PARSE_SUBEXPR | PARSE_OPER2,
+    PARSE_NORMAL        = PARSE_CONST | PARSE_IDENT | PARSE_SUBEXPR_START | PARSE_OPER_UNARY,
 };
 
 #define DM_CHECK(x) { if (mode & PARSE_ ## x ) { if (str[0]) strcat(str, " or "); strcat(str, # x ); } }
@@ -342,8 +334,9 @@
     DM_CHECK(IDENT);
     DM_CHECK(CONST);
     DM_CHECK(OPER);
-    DM_CHECK(OPER2);
-    DM_CHECK(SUBEXPR);
+    DM_CHECK(OPER_UNARY);
+    DM_CHECK(SUBEXPR_START);
+    DM_CHECK(SUBEXPR_END);
     DM_CHECK(ARGS);
             
     return dm_strdup(str);
@@ -402,7 +395,7 @@
                 if (ev->mode != PARSE_ERROR)
                 {
                     dm_set_mode(ev, PARSE_START);
-                    ev->expect = PARSE_OPER | PARSE_END;
+                    ev->expect = PARSE_OPER | PARSE_SUBEXPR_END;
                     c = tmp;
                 }
             }
@@ -456,7 +449,10 @@
                 dm_set_mode(ev, func != NULL ? PARSE_ARGS : PARSE_SUBEXPR);
             
             else if (*c == '-')
-                dm_set_mode(ev, (ev->prev == PARSE_START || ev->prev == PARSE_OPER) ? PARSE_OPER2 : PARSE_OPER);
+                dm_set_mode(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);
             
             else if (strchr("+*/<>%&|!^", *c))
                 dm_set_mode(ev, PARSE_OPER);
@@ -497,11 +493,23 @@
             }
             else
             {
-                if (isdigit(*c) || (*c == '.' && !decimal))
+                if (isdigit(*c))
+                {
+                    tmpStr[tmpStrLen++] = *c++;
+                }
+                else
+                if (*c == '.')
                 {
-                    if (*c == '.')
+                    if (!decimal)
+                    {
+                        tmpStr[tmpStrLen++] = *c++;
                         decimal = TRUE;
-                    tmpStr[tmpStrLen++] = *c++;
+                    }
+                    else
+                    {
+                        dm_eval_err(ev, "Invalid constant expression near '%s'.\n", c);
+                        dm_set_mode(ev, PARSE_ERROR);
+                    }
                 }
                 else
                 {
@@ -521,8 +529,30 @@
             }
             break;
 
+        case PARSE_OPER_UNARY:
+            {
+                int op = OP_NONE;
+
+                switch (*c)
+                {
+                    case '-': op = OP_SUB_UNARY; c++; break;
+                    case '~': op = OP_COMPLEMENT; c++; break;
+                }
+
+                if (op != OP_NONE)
+                {
+                    if ((node = dm_eval_add_node(list, op)) != NULL)
+                    {
+                        ev->expect = PARSE_NORMAL;
+                        dm_set_mode(ev, PARSE_START);
+                    }
+                    else
+                        dm_set_mode(ev, PARSE_ERROR);
+                }
+            }
+            break;
+
         case PARSE_OPER:
-        case PARSE_OPER2:
             {
                 int op = OP_NONE;
 
@@ -536,6 +566,7 @@
                     case '&': op = OP_AND; c++; break;
                     case '^': op = OP_XOR; c++; break;
                     case '|': op = OP_OR; c++; break;
+
                     case '>':
                         if (c[1] == '>')
                         {
@@ -544,8 +575,8 @@
                         }
                         else
                         {
-                            dm_eval_err(ev, "Syntax error near '%s'.\n", c);
-                            dm_set_mode(ev, PARSE_ERROR);
+                            op = (c[1] == '=') ? OP_GT_EQ : OP_GT;
+                            c++;
                         }
                         break;
                         
@@ -557,29 +588,21 @@
                         }
                         else
                         {
-                            dm_eval_err(ev, "Syntax error near '%s'.\n", c);
-                            dm_set_mode(ev, PARSE_ERROR);
+                            op = (c[1] == '=') ? OP_LT_EQ : OP_LT;
+                            c++;
                         }
                         break;
 
                     default:
-                        dm_eval_err(ev, "Unknown operator '%c'.\n", *c);
+                        dm_eval_err(ev, "Unknown operator '%c' at %s\n", *c, c);
                         dm_set_mode(ev, PARSE_ERROR);
                 }
 
                 if (op != OP_NONE)
                 {
-                    if (ev->mode == PARSE_OPER2 && op == OP_SUB &&
-                        (node = dm_eval_add_node(list, op)) != NULL)
+                    if ((node = dm_eval_add_node(list, op)) != NULL)
                     {
-                        ev->expect = PARSE_NORMAL;
-                        dm_set_mode(ev, PARSE_START);
-                    }
-                    else
-                    if (ev->mode == PARSE_OPER &&
-                        (node = dm_eval_add_node(list, op)) != NULL)
-                    {
-                        ev->expect = PARSE_NORMAL | PARSE_OPER2;
+                        ev->expect = PARSE_NORMAL | PARSE_OPER_UNARY;
                         dm_set_mode(ev, PARSE_START);
                     }
                     else
@@ -602,7 +625,7 @@
                 else
                 {
                     tmpStr[tmpStrLen] = 0;
-                    dm_eval_err(ev, "Identifier too long! ('%s')\n", tmpStr);
+                    dm_eval_err(ev, "Identifier too long! ('%s') near %s\n", tmpStr, c);
                 }
             }
             else
@@ -679,35 +702,12 @@
 
 static int dm_eval_reorder_pass0(DMEvalContext *ev, const DMEvalNode *node, DMEvalNode **result)
 {
-    DMEvalNode *tmp, *sub;
+    DMEvalNode *tmp;
     int i, res;
 
     for (; node != NULL; node = node->next)
     switch (node->op)
     {
-        case OP_SUB:
-            if ((tmp = dm_eval_peek_node(result)) == NULL || tmp->op <= OP_FUNC)
-            {
-                // 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;
-
-            break;
-
         case OP_FUNC:
             if ((tmp = dm_eval_add_node(result, OP_FUNC)) == NULL)
                 return -1;
@@ -739,6 +739,48 @@
 }
 
 
+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)
 {
@@ -781,7 +823,7 @@
 }
 
 
-#if 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 */
@@ -790,43 +832,46 @@
 
 int dm_eval_reorder(DMEvalContext *ev, DMEvalNode *node, DMEvalNode **result)
 {
-    DMEvalNode *tmp1 = NULL, *tmp2 = NULL, *tmp3 = NULL;
+    DMEvalNode *tmp1 = NULL, *tmp2 = NULL, *tmp3 = NULL, *tmp4 = NULL, *tmp5 = NULL;
     int res;
 
     RO_DEBUG("REORD: ", node);
     
-    res = dm_eval_reorder_pass0(ev, node, &tmp1);
+    // Pass 0
+    if ((res = dm_eval_reorder_pass0(ev, node, &tmp1)) != 0)
+        goto out;
     RO_DEBUG("PASS0: ", tmp1);
-    
-    if (res != 0)
-    {
-        dm_eval_free(tmp1);
-        return res;
-    }
+
+    // Pass 1
+    if ((res = dm_eval_reorder_pass1(ev, tmp1, &tmp2, OP_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);
 
-    res = dm_eval_reorder_passN(ev, tmp1, &tmp2, OP_MUL, OP_DIV, OP_MOD);
-    RO_DEBUG("PASS1: ", 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_LSHIFT, OP_RSHIFT, -1);
+    RO_DEBUG("PASS5: ", *result);
+
+out:
     dm_eval_free(tmp1);
-    
-    if (res != 0)
-    {
-        dm_eval_free(tmp2);
-        return res;
-    }
+    dm_eval_free(tmp2);
+    dm_eval_free(tmp3);
+    dm_eval_free(tmp4);
+    dm_eval_free(tmp5);
 
-    res = dm_eval_reorder_passN(ev, tmp2, &tmp3, OP_SUB, OP_ADD, -1);
-    RO_DEBUG("PASS2: ", tmp3);
-    dm_eval_free(tmp2);
-    if (res != 0)
-    {
-        dm_eval_free(tmp3);
-        return res;
-    }
-
-    res = dm_eval_reorder_passN(ev, tmp3, result, OP_LSHIFT, OP_RSHIFT, -1);
-    RO_DEBUG("PASS3: ", *result);
-    dm_eval_free(tmp3);
-    
     return res;
 }
 
@@ -940,6 +985,8 @@
             
             case OP_ADD:
             case OP_SUB:
+            case OP_SUB_UNARY:
+            case OP_COMPLEMENT:
                 if (dm_eval_get(ev, node->next, &tmp) != 0)
                     return -6;
                 
@@ -947,6 +994,8 @@
                 {
                     case OP_ADD: result += tmp; break;
                     case OP_SUB: result -= tmp; break;
+                    case OP_SUB_UNARY: result -= tmp; break;
+                    case OP_COMPLEMENT: result = DMCONVTYPE ~(DMCONVTYPE tmp); break;
                 }
 
                 node = node->next;
--- a/dmeval.h	Sun Apr 21 20:40:54 2013 +0300
+++ b/dmeval.h	Mon Apr 22 09:37:34 2013 +0300
@@ -19,13 +19,21 @@
     OP_DIV,
     OP_MOD,
 
+    OP_SUB_UNARY,
+    OP_COMPLEMENT,
+
     OP_LSHIFT,
     OP_RSHIFT,
 
     OP_AND,
     OP_OR,
     OP_XOR,
-    
+
+    OP_GT,
+    OP_LT,
+    OP_GT_EQ,
+    OP_LT_EQ,
+
     // Special ops
     OP_FUNC,
     OP_VAR,
--- a/dmevalw.c	Sun Apr 21 20:40:54 2013 +0300
+++ b/dmevalw.c	Mon Apr 22 09:37:34 2013 +0300
@@ -9,18 +9,26 @@
     "*",
     "/",
     "%",
-    
+
+    "#",
+    "~",
+
     "<<",
     ">>",
-    
+
     "&",
     "|",
     "^",
-    
+
+    ">",
+    "<",
+    ">=",
+    "<=",
+
     "FUNC",
     "VAR",
     "SUBEXPR",
-    "CONST"
+    "CONST",
 };