[template-glib] expr-eval: short-circuit on and/or logical branches



commit 14ef84df569fc23e36e66b9c36f7bb54cf071279
Author: Christian Hergert <chergert redhat com>
Date:   Thu May 12 15:17:36 2022 -0700

    expr-eval: short-circuit on and/or logical branches
    
    Obviously you don't want to evaluate the whole tree.

 src/tmpl-expr-eval.c | 47 ++++++++++++++++++++++++++++++-----------------
 tests/test1.script   | 14 ++++++++++++++
 2 files changed, 44 insertions(+), 17 deletions(-)
---
diff --git a/src/tmpl-expr-eval.c b/src/tmpl-expr-eval.c
index 5a0ed85..eeed0f3 100644
--- a/src/tmpl-expr-eval.c
+++ b/src/tmpl-expr-eval.c
@@ -351,33 +351,46 @@ tmpl_expr_simple_eval_logical (TmplExprSimple  *node,
 
   g_value_init (return_value, G_TYPE_BOOLEAN);
 
-  if (tmpl_expr_eval_internal (node->left, scope, &left, error) &&
-      ((node->right == NULL) ||
-       tmpl_expr_eval_internal (node->right, scope, &right, error)))
+  if (!tmpl_expr_eval_internal (node->left, scope, &left, error))
+    goto failure;
+
+  switch ((int)node->type)
     {
-      switch ((int)node->type)
+    case TMPL_EXPR_AND:
+      if (!tmpl_value_as_boolean (&left))
         {
-        case TMPL_EXPR_AND:
-          g_value_set_boolean (return_value,
-                               (tmpl_value_as_boolean (&left) && tmpl_value_as_boolean (&right)));
+          g_value_set_boolean (return_value, FALSE);
           ret = TRUE;
           break;
+        }
+      if (!tmpl_expr_eval_internal (node->right, scope, &right, error))
+        goto failure;
+      g_value_set_boolean (return_value, tmpl_value_as_boolean (&right));
+      ret = TRUE;
+      break;
 
-        case TMPL_EXPR_OR:
-          g_value_set_boolean (return_value,
-                               (tmpl_value_as_boolean (&left) || tmpl_value_as_boolean (&right)));
+    case TMPL_EXPR_OR:
+      if (tmpl_value_as_boolean (&left))
+        {
+          g_value_set_boolean (return_value, TRUE);
           ret = TRUE;
           break;
-
-        default:
-          g_set_error (error,
-                       TMPL_ERROR,
-                       TMPL_ERROR_RUNTIME_ERROR,
-                       "Unknown logical operator type: %d", node->type);
-          break;
         }
+      if (!tmpl_expr_eval_internal (node->right, scope, &right, error))
+        goto failure;
+      g_value_set_boolean (return_value, tmpl_value_as_boolean (&right));
+      ret = TRUE;
+      break;
+
+    default:
+      g_set_error (error,
+                   TMPL_ERROR,
+                   TMPL_ERROR_RUNTIME_ERROR,
+                   "Unknown logical operator type: %d", node->type);
+      break;
     }
 
+failure:
   TMPL_CLEAR_VALUE (&left);
   TMPL_CLEAR_VALUE (&right);
 
diff --git a/tests/test1.script b/tests/test1.script
index 8c772a7..3056ee5 100644
--- a/tests/test1.script
+++ b/tests/test1.script
@@ -127,4 +127,18 @@ a1 = 1 < 3
 (a2 = 1) < 3
 assert(a1 == a2)
 
+scoped = 1
+ret = (true || (scoped = 2))
+assert(scoped == 1)
+assert(ret == true)
+ret = ((scoped = 2) || (scoped = 3))
+assert(scoped == 2)
+assert(ret == true)
+ret = ((scoped = 3) && (scoped = 4))
+assert(scoped == 4)
+assert(ret == true)
+ret = ((scoped = 3) && (scoped = 0))
+assert(scoped == 0)
+assert(ret == false)
+
 1234;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]