[template-glib] expr: split statement lists and args



commit 40abca131615c9fc00433a2835a13451d51ad9c4
Author: Christian Hergert <chergert redhat com>
Date:   Wed May 4 11:16:44 2022 -0700

    expr: split statement lists and args
    
    This will give us a bit more flexibility going forward so that we can have
    different syntax between the two from a scriptability standpoint.

 src/tmpl-expr-eval.c    | 52 ++++++++++++++++++++++++++++++++++++++++++-------
 src/tmpl-expr-parser.y  | 29 +++++++++++++++++++++++----
 src/tmpl-expr-private.h |  8 ++++++++
 src/tmpl-expr-types.h   |  1 +
 src/tmpl-expr.c         | 32 +++++++++++++++++++++++++++++-
 src/tmpl-expr.h         |  2 ++
 6 files changed, 112 insertions(+), 12 deletions(-)
---
diff --git a/src/tmpl-expr-eval.c b/src/tmpl-expr-eval.c
index 3003e26..7cfc4fa 100644
--- a/src/tmpl-expr-eval.c
+++ b/src/tmpl-expr-eval.c
@@ -396,10 +396,45 @@ cleanup:
 }
 
 static gboolean
-tmpl_expr_stmt_list_eval (TmplExprSimple  *node,
-                         TmplScope       *scope,
-                         GValue         *return_value,
-                         GError        **error)
+tmpl_expr_stmt_list_eval (TmplExprStmtList  *node,
+                          TmplScope         *scope,
+                          GValue            *return_value,
+                          GError           **error)
+{
+  GValue last = G_VALUE_INIT;
+
+  if G_UNLIKELY (node->stmts == NULL || node->stmts->len == 0)
+    {
+      g_set_error_literal (error,
+                           TMPL_ERROR,
+                           TMPL_ERROR_RUNTIME_ERROR,
+                           "Runtime Error: implausible TmplExprStmtList");
+      return FALSE;
+    }
+
+  for (guint i = 0; i < node->stmts->len; i++)
+    {
+      TmplExpr *stmt = g_ptr_array_index (node->stmts, i);
+
+      TMPL_CLEAR_VALUE (&last);
+
+      if (!tmpl_expr_eval_internal (stmt, scope, &last, error))
+        {
+          TMPL_CLEAR_VALUE (&last);
+          return FALSE;
+        }
+    }
+
+  *return_value = last;
+
+  return TRUE;
+}
+
+static gboolean
+tmpl_expr_args_eval (TmplExprSimple  *node,
+                     TmplScope       *scope,
+                     GValue          *return_value,
+                     GError         **error)
 {
   GValue left = G_VALUE_INIT;
   gboolean ret = FALSE;
@@ -964,7 +999,7 @@ apply_args:
           goto cleanup;
         }
 
-      if (args->any.type == TMPL_EXPR_STMT_LIST)
+      if (args->any.type == TMPL_EXPR_ARGS)
         {
           if (!tmpl_expr_eval_internal (((TmplExprSimple *)args)->left, scope, value, error))
             goto cleanup;
@@ -1097,7 +1132,7 @@ tmpl_expr_user_fn_call_eval (TmplExprUserFnCall  *node,
           return FALSE;
         }
 
-      if (params->any.type == TMPL_EXPR_STMT_LIST)
+      if (params->any.type == TMPL_EXPR_ARGS)
         {
           TmplExprSimple *simple = (TmplExprSimple *)params;
 
@@ -1218,8 +1253,11 @@ tmpl_expr_eval_internal (TmplExpr   *node,
       g_value_set_string (return_value, ((TmplExprString *)node)->value);
       return TRUE;
 
+    case TMPL_EXPR_ARGS:
+      return tmpl_expr_args_eval ((TmplExprSimple *)node, scope, return_value, error);
+
     case TMPL_EXPR_STMT_LIST:
-      return tmpl_expr_stmt_list_eval ((TmplExprSimple *)node, scope, return_value, error);
+      return tmpl_expr_stmt_list_eval ((TmplExprStmtList *)node, scope, return_value, error);
 
     case TMPL_EXPR_IF:
     case TMPL_EXPR_WHILE:
diff --git a/src/tmpl-expr-parser.y b/src/tmpl-expr-parser.y
index ba32573..202b2b9 100644
--- a/src/tmpl-expr-parser.y
+++ b/src/tmpl-expr-parser.y
@@ -74,7 +74,21 @@ expr: /* nothing */ EOL {
     YYACCEPT;
   }
   | stmt EOL {
-    parser->ast = $1;
+    if (parser->ast != NULL)
+      {
+        if (parser->ast->any.type != TMPL_EXPR_STMT_LIST)
+          {
+            GPtrArray *ar = g_ptr_array_new_with_free_func ((GDestroyNotify)tmpl_expr_unref);
+            g_ptr_array_add (ar, parser->ast);
+            parser->ast = tmpl_expr_new_stmt_list (ar);
+          }
+        g_ptr_array_add (parser->ast->stmt_list.stmts, $1);
+      }
+    else
+      {
+        parser->ast = $1;
+      }
+
     YYACCEPT;
   }
   | FUNC NAME '(' symlist ')' '=' list EOL {
@@ -110,9 +124,16 @@ stmt: IF exp THEN list {
 list: /* nothing */ { $$ = NULL; }
   | stmt ';' list {
     if ($3 == NULL)
-      $$ = $1;
+      { $$ = $1; }
+    else if ($1->any.type == TMPL_EXPR_STMT_LIST)
+      { g_ptr_array_add ($1->stmt_list.stmts, $3); }
     else
-      $$ = tmpl_expr_new_simple (TMPL_EXPR_STMT_LIST, $1, $3);
+      {
+        GPtrArray *ar = g_ptr_array_new_with_free_func ((GDestroyNotify)tmpl_expr_unref);
+        g_ptr_array_add (ar, $1);
+        g_ptr_array_add (ar, $3);
+        $$ = tmpl_expr_new_stmt_list (ar);
+      }
   }
 ;
 
@@ -191,7 +212,7 @@ exp: exp CMP exp {
 
 explist: exp
   | exp ',' explist {
-    $$ = tmpl_expr_new_simple (TMPL_EXPR_STMT_LIST, $1, $3);
+    $$ = tmpl_expr_new_simple (TMPL_EXPR_ARGS, $1, $3);
   }
 ;
 
diff --git a/src/tmpl-expr-private.h b/src/tmpl-expr-private.h
index 57a33d6..c1ebe2b 100644
--- a/src/tmpl-expr-private.h
+++ b/src/tmpl-expr-private.h
@@ -136,6 +136,13 @@ typedef struct
   volatile gint  ref_count;
 } TmplExprAny;
 
+typedef struct
+{
+  TmplExprType   type;
+  volatile gint  ref_count;
+  GPtrArray     *stmts;
+} TmplExprStmtList;
+
 union _TmplExpr
 {
   TmplExprAny          any;
@@ -151,6 +158,7 @@ union _TmplExpr
   TmplExprGetattr      getattr;
   TmplExprSetattr      setattr;
   TmplExprRequire      require;
+  TmplExprStmtList     stmt_list;
 };
 
 G_END_DECLS
diff --git a/src/tmpl-expr-types.h b/src/tmpl-expr-types.h
index d871743..acedfb9 100644
--- a/src/tmpl-expr-types.h
+++ b/src/tmpl-expr-types.h
@@ -75,6 +75,7 @@ typedef enum
   TMPL_EXPR_AND,
   TMPL_EXPR_OR,
   TMPL_EXPR_INVERT_BOOLEAN,
+  TMPL_EXPR_ARGS,
 } TmplExprType;
 
 typedef enum
diff --git a/src/tmpl-expr.c b/src/tmpl-expr.c
index 228a882..010e30e 100644
--- a/src/tmpl-expr.c
+++ b/src/tmpl-expr.c
@@ -77,7 +77,6 @@ tmpl_expr_destroy (TmplExpr *self)
     case TMPL_EXPR_LTE:
     case TMPL_EXPR_MUL:
     case TMPL_EXPR_NE:
-    case TMPL_EXPR_STMT_LIST:
     case TMPL_EXPR_SUB:
     case TMPL_EXPR_UNARY_MINUS:
     case TMPL_EXPR_USER_FN_CALL:
@@ -99,6 +98,10 @@ tmpl_expr_destroy (TmplExpr *self)
       g_clear_pointer (&self->setattr.right, tmpl_expr_unref);
       break;
 
+    case TMPL_EXPR_STMT_LIST:
+      g_clear_pointer (&self->stmt_list.stmts, g_ptr_array_unref);
+      break;
+
     case TMPL_EXPR_BOOLEAN:
     case TMPL_EXPR_NUMBER:
       break;
@@ -145,6 +148,33 @@ tmpl_expr_destroy (TmplExpr *self)
   g_slice_free (TmplExpr, self);
 }
 
+/**
+ * tmpl_expr_new_stmt_list:
+ * @stmts: (transfer full) (element-type TmplExpr): a #GPtrArray of
+ *   #TmplExpr which will be evaluated in sequence.
+ *
+ * Creates a new statement list for which the last item will be
+ * used as the "return value" from execution.
+ *
+ * Returns: (transfer full): a new #TmplExpr
+ *
+ * Since: 3.36
+ */
+TmplExpr *
+tmpl_expr_new_stmt_list (GPtrArray *stmts)
+{
+  TmplExpr *ret;
+
+  g_return_val_if_fail (stmts != NULL, NULL);
+
+  g_ptr_array_set_free_func (stmts, (GDestroyNotify)tmpl_expr_unref);
+
+  ret = tmpl_expr_new (TMPL_EXPR_STMT_LIST);
+  ((TmplExprStmtList *)ret)->stmts = g_ptr_array_ref (stmts);
+
+  return ret;
+}
+
 TmplExpr *
 tmpl_expr_new_boolean (gboolean value)
 {
diff --git a/src/tmpl-expr.h b/src/tmpl-expr.h
index c34baa4..3c7a733 100644
--- a/src/tmpl-expr.h
+++ b/src/tmpl-expr.h
@@ -84,6 +84,8 @@ TmplExpr *tmpl_expr_new_symbol_ref    (const gchar      *symbol);
 TMPL_AVAILABLE_IN_ALL
 TmplExpr *tmpl_expr_new_symbol_assign (const gchar      *symbol,
                                        TmplExpr         *right);
+TMPL_AVAILABLE_IN_3_36
+TmplExpr *tmpl_expr_new_stmt_list     (GPtrArray        *stmts);
 
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (TmplExpr, tmpl_expr_unref)
 


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