[template-glib] expr: implement user function definitions
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [template-glib] expr: implement user function definitions
- Date: Wed, 4 May 2022 20:15:35 +0000 (UTC)
commit acab44aaffabe91779f61a9fc74366be46ccf5a7
Author: Christian Hergert <chergert redhat com>
Date: Wed May 4 13:06:23 2022 -0700
expr: implement user function definitions
We always had this in the syntax, but we never actually finished the
implementation of defining functions so that the user can call them.
I'd still like to change the syntax somewhat, but this at least gets
things working so we can define those functions and use them from the
test script.
src/tmpl-expr-eval.c | 35 ++++++++++++++++++++++++++++++++
src/tmpl-expr-parser.y | 54 ++++++++++++++++++++++++++-----------------------
src/tmpl-expr-private.h | 10 +++++++++
src/tmpl-expr-types.h | 1 +
src/tmpl-expr.c | 24 ++++++++++++++++++++++
src/tmpl-expr.h | 4 ++++
tests/test1.script | 5 +++--
7 files changed, 106 insertions(+), 27 deletions(-)
---
diff --git a/src/tmpl-expr-eval.c b/src/tmpl-expr-eval.c
index a5ee4b1..79de672 100644
--- a/src/tmpl-expr-eval.c
+++ b/src/tmpl-expr-eval.c
@@ -1210,6 +1210,38 @@ tmpl_expr_require_eval (TmplExprRequire *node,
return TRUE;
}
+static gboolean
+tmpl_expr_func_eval (TmplExprFunc *node,
+ TmplScope *scope,
+ GValue *return_value,
+ GError **error)
+{
+ GPtrArray *args = NULL;
+ TmplSymbol *symbol;
+
+ g_assert (node != NULL);
+ g_assert (scope != NULL);
+ g_assert (return_value != NULL);
+
+ /* We just need to insert a symbol into @scope that includes
+ * the function defined here. If the symbol already exists,
+ * it will be replaced with this function.
+ */
+
+ if (node->symlist != NULL)
+ {
+ args = g_ptr_array_new_with_free_func (g_free);
+ for (guint i = 0; node->symlist[i]; i++)
+ g_ptr_array_add (args, g_strdup (node->symlist[i]));
+ }
+
+ symbol = tmpl_scope_get (scope, node->name);
+ tmpl_symbol_assign_expr (symbol, node->list, args);
+ g_clear_pointer (&args, g_ptr_array_unref);
+
+ return TRUE;
+}
+
static gboolean
tmpl_expr_eval_internal (TmplExpr *node,
TmplScope *scope,
@@ -1308,6 +1340,9 @@ tmpl_expr_eval_internal (TmplExpr *node,
return ret;
}
+ case TMPL_EXPR_FUNC:
+ return tmpl_expr_func_eval ((TmplExprFunc *)node, scope, return_value, error);
+
default:
break;
}
diff --git a/src/tmpl-expr-parser.y b/src/tmpl-expr-parser.y
index f2da6fd..6055847 100644
--- a/src/tmpl-expr-parser.y
+++ b/src/tmpl-expr-parser.y
@@ -44,6 +44,27 @@ tmpl_expr_parser_error (TmplExprParser *parser,
parser->error_str = g_strdup (message);
}
+static void
+add_expr_to_parser (TmplExprParser *parser,
+ TmplExpr *node)
+{
+ 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, node);
+ }
+ else
+ {
+ parser->ast = node;
+ }
+}
+
# define scanner parser->scanner
%}
@@ -74,37 +95,20 @@ expr: /* nothing */ EOL {
YYACCEPT;
}
| stmt EOL {
- 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;
- }
-
+ add_expr_to_parser (parser, $1);
YYACCEPT;
}
| FUNC NAME '(' symlist ')' '=' list EOL {
- /* todo: add ast node to define the expr on the scope
- * when evaluated.
- */
- //tmpl_scope_add_user_func (parser->scope, $2, $4, $7);
- parser->ast = NULL;
+ g_ptr_array_add ($4, NULL);
+ add_expr_to_parser (parser,
+ tmpl_expr_new_func ($2,
+ (char **)(gpointer)g_ptr_array_free ($4, FALSE),
+ $7));
+ $4 = NULL;
YYACCEPT;
}
| FUNC NAME '(' ')' '=' list EOL {
- /* todo: add ast node to define the expr on the scope
- * when evaluated.
- */
- //tmpl_scope_add_user_func (parser->scope, $2, NULL, $6);
- parser->ast = NULL;
+ add_expr_to_parser (parser, tmpl_expr_new_func ($2, NULL, $6));
YYACCEPT;
}
;
diff --git a/src/tmpl-expr-private.h b/src/tmpl-expr-private.h
index c1ebe2b..4d7a19a 100644
--- a/src/tmpl-expr-private.h
+++ b/src/tmpl-expr-private.h
@@ -143,6 +143,15 @@ typedef struct
GPtrArray *stmts;
} TmplExprStmtList;
+typedef struct
+{
+ TmplExprType type;
+ volatile gint ref_count;
+ char *name;
+ char **symlist;
+ TmplExpr *list;
+} TmplExprFunc;
+
union _TmplExpr
{
TmplExprAny any;
@@ -159,6 +168,7 @@ union _TmplExpr
TmplExprSetattr setattr;
TmplExprRequire require;
TmplExprStmtList stmt_list;
+ TmplExprFunc func;
};
G_END_DECLS
diff --git a/src/tmpl-expr-types.h b/src/tmpl-expr-types.h
index acedfb9..037d9ec 100644
--- a/src/tmpl-expr-types.h
+++ b/src/tmpl-expr-types.h
@@ -76,6 +76,7 @@ typedef enum
TMPL_EXPR_OR,
TMPL_EXPR_INVERT_BOOLEAN,
TMPL_EXPR_ARGS,
+ TMPL_EXPR_FUNC,
} TmplExprType;
typedef enum
diff --git a/src/tmpl-expr.c b/src/tmpl-expr.c
index 65099ea..18008b2 100644
--- a/src/tmpl-expr.c
+++ b/src/tmpl-expr.c
@@ -142,6 +142,12 @@ tmpl_expr_destroy (TmplExpr *self)
g_clear_pointer (&self->require.version, g_free);
break;
+ case TMPL_EXPR_FUNC:
+ g_clear_pointer (&self->func.name, g_free);
+ g_clear_pointer (&self->func.symlist, g_strfreev);
+ g_clear_pointer (&self->func.list, tmpl_expr_unref);
+ break;
+
default:
g_assert_not_reached ();
}
@@ -380,3 +386,21 @@ tmpl_expr_from_string (const gchar *str,
return ret;
}
+
+TmplExpr *
+tmpl_expr_new_func (char *name,
+ char **symlist,
+ TmplExpr *list)
+{
+ TmplExprFunc *ret;
+
+ g_return_val_if_fail (name != NULL, NULL);
+ g_return_val_if_fail (list != NULL, NULL);
+
+ ret = tmpl_expr_new (TMPL_EXPR_FUNC);
+ ret->name = name;
+ ret->symlist = symlist;
+ ret->list = list;
+
+ return (TmplExpr *)ret;
+}
diff --git a/src/tmpl-expr.h b/src/tmpl-expr.h
index 3c7a733..61bafe0 100644
--- a/src/tmpl-expr.h
+++ b/src/tmpl-expr.h
@@ -86,6 +86,10 @@ TmplExpr *tmpl_expr_new_symbol_assign (const gchar *symbol,
TmplExpr *right);
TMPL_AVAILABLE_IN_3_36
TmplExpr *tmpl_expr_new_stmt_list (GPtrArray *stmts);
+TMPL_AVAILABLE_IN_3_36
+TmplExpr *tmpl_expr_new_func (char *name,
+ char **symlist,
+ TmplExpr *list);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (TmplExpr, tmpl_expr_unref)
diff --git a/tests/test1.script b/tests/test1.script
index beaa731..147fdc6 100644
--- a/tests/test1.script
+++ b/tests/test1.script
@@ -1,5 +1,6 @@
require GLib
require Gio version "2.0"
-a = 2
-617 * a
+func multiply(x,y) = x * y;
+
+multiply(617, 2)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]