[libshumate] vector: Add arithmetic expressions



commit 05e65a299e49a7694cda50e608b8511c536548a5
Author: James Westman <james jwestman net>
Date:   Sun Sep 25 14:44:12 2022 -0500

    vector: Add arithmetic expressions

 shumate/vector/shumate-vector-expression-filter.c | 97 +++++++++++++++++++++++
 tests/vector-expression.c                         |  6 ++
 2 files changed, 103 insertions(+)
---
diff --git a/shumate/vector/shumate-vector-expression-filter.c 
b/shumate/vector/shumate-vector-expression-filter.c
index 5d6bce9..7412316 100644
--- a/shumate/vector/shumate-vector-expression-filter.c
+++ b/shumate/vector/shumate-vector-expression-filter.c
@@ -37,6 +37,10 @@ typedef enum {
   EXPR_GE,
   EXPR_LE,
   EXPR_CASE,
+  EXPR_ADD,
+  EXPR_SUB,
+  EXPR_MUL,
+  EXPR_DIV,
 } ExpressionType;
 
 struct _ShumateVectorExpressionFilter
@@ -150,6 +154,26 @@ shumate_vector_expression_filter_from_json_array (JsonArray *array, GError **err
       self->type = EXPR_LE;
       expect_exprs = 2;
     }
+  else if (g_strcmp0 ("+", op) == 0)
+    {
+      self->type = EXPR_ADD;
+      expect_ge_exprs = 1;
+    }
+  else if (g_strcmp0 ("-", op) == 0)
+    {
+      self->type = EXPR_SUB;
+      expect_ge_exprs = 1;
+    }
+  else if (g_strcmp0 ("*", op) == 0)
+    {
+      self->type = EXPR_MUL;
+      expect_ge_exprs = 1;
+    }
+  else if (g_strcmp0 ("/", op) == 0)
+    {
+      self->type = EXPR_DIV;
+      expect_exprs = 2;
+    }
   else if (g_strcmp0 ("case", op) == 0)
     self->type = EXPR_CASE;
   else
@@ -382,6 +406,79 @@ shumate_vector_expression_filter_eval (ShumateVectorExpression  *expr,
       shumate_vector_value_set_boolean (out, (number < number2) ^ inverted);
       return TRUE;
 
+    case EXPR_ADD:
+      number = 0;
+
+      for (int i = 0; i < n_expressions; i ++)
+        {
+          if (!shumate_vector_expression_eval (expressions[i], scope, &value))
+            return FALSE;
+          if (!shumate_vector_value_get_number (&value, &number2))
+            return FALSE;
+
+          number += number2;
+        }
+
+      shumate_vector_value_set_number (out, number);
+      return TRUE;
+
+    case EXPR_SUB:
+      g_assert (n_expressions >= 1);
+
+      if (!shumate_vector_expression_eval (expressions[0], scope, &value))
+        return FALSE;
+      if (!shumate_vector_value_get_number (&value, &number))
+        return FALSE;
+
+      if (n_expressions == 1)
+        shumate_vector_value_set_number (out, 0 - number);
+      else
+        {
+          if (!shumate_vector_expression_eval (expressions[1], scope, &value2))
+            return FALSE;
+          if (!shumate_vector_value_get_number (&value2, &number2))
+            return FALSE;
+
+          shumate_vector_value_set_number (out, number - number2);
+        }
+      return TRUE;
+
+    case EXPR_MUL:
+      g_assert (n_expressions >= 1);
+
+      if (!shumate_vector_expression_eval (expressions[0], scope, &value))
+        return FALSE;
+      if (!shumate_vector_value_get_number (&value, &number))
+        return FALSE;
+
+      for (int i = 1; i < n_expressions; i ++)
+        {
+          if (!shumate_vector_expression_eval (expressions[i], scope, &value))
+            return FALSE;
+          if (!shumate_vector_value_get_number (&value, &number2))
+            return FALSE;
+
+          number *= number2;
+        }
+
+      shumate_vector_value_set_number (out, number);
+      return TRUE;
+
+    case EXPR_DIV:
+      if (!shumate_vector_expression_eval (expressions[0], scope, &value))
+        return FALSE;
+      if (!shumate_vector_expression_eval (expressions[1], scope, &value2))
+        return FALSE;
+
+      if (!shumate_vector_value_get_number (&value, &number))
+        return FALSE;
+      if (!shumate_vector_value_get_number (&value2, &number2))
+        return FALSE;
+
+      shumate_vector_value_set_number (out, number / number2);
+
+      return TRUE;
+
     case EXPR_CASE:
       for (int i = 0; i < n_expressions; i += 2)
         {
diff --git a/tests/vector-expression.c b/tests/vector-expression.c
index f9acc8f..f3b4daa 100644
--- a/tests/vector-expression.c
+++ b/tests/vector-expression.c
@@ -171,6 +171,12 @@ test_vector_expression_basic_filter (void)
   g_assert_true (filter ("[\"==\", [\"case\", true, 0, 1], 0]"));
   g_assert_true (filter ("[\"==\", [\"case\", false, 0, 1], 1]"));
   g_assert_true (filter ("[\"==\", [\"case\", false, 0, true, 2], 2]"));
+
+  g_assert_true (filter ("[\"==\", [\"+\", 3, 1, 7], 11]"));
+  g_assert_true (filter ("[\"==\", [\"-\", 3, 1], 2]"));
+  g_assert_true (filter ("[\"==\", [\"-\", 1], -1]"));
+  g_assert_true (filter ("[\"==\", [\"*\", 5, 6, 7], 210]"));
+  g_assert_true (filter ("[\"==\", [\"/\", 10, 4], 2.5]"));
 }
 
 


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