From c7b06a490f8df8427a2726c59a73fd6188fa8b3a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C5=99emysl=20Janouch?=
Date: Sun, 21 May 2017 09:47:24 +0200
Subject: [PATCH] Move native functions into the context
---
ell.c | 127 +++++++++++++++++++++++++---------------------------------
1 file changed, 55 insertions(+), 72 deletions(-)
diff --git a/ell.c b/ell.c
index b4f5f2b..870b19c 100755
--- a/ell.c
+++ b/ell.c
@@ -622,44 +622,9 @@ parser_run (struct parser *self, const char **e) {
// --- Runtime -----------------------------------------------------------------
-struct context;
-typedef bool (*handler_fn) (struct context *, struct item *, struct item **);
-
-struct native_fn {
- struct native_fn *next; ///< The next link in the chain
- handler_fn handler; ///< Internal C handler, or NULL
- char name[]; ///< The name of the function
-};
-
-struct native_fn *g_native; ///< Maps words to functions
-
-static struct native_fn *
-native_find (const char *name) {
- for (struct native_fn *fn = g_native; fn; fn = fn->next)
- if (!strcmp (fn->name, name))
- return fn;
- return NULL;
-}
-
-static bool
-native_register (const char *name, handler_fn handler) {
- struct native_fn *fn = native_find (name);
- if (!fn) {
- if (!(fn = calloc (1, sizeof *fn + strlen (name) + 1)))
- return false;
- strcpy (fn->name, name);
- fn->next = g_native;
- g_native = fn;
- }
-
- fn->handler = handler;
- return true;
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
struct context {
struct item *variables; ///< List of variables
+ struct native_fn *native; ///< Maps strings to C functions
char *error; ///< Error information
bool error_is_fatal; ///< Whether the error can be catched
@@ -668,6 +633,14 @@ struct context {
void *user_data; ///< User data
};
+typedef bool (*handler_fn) (struct context *, struct item *, struct item **);
+
+struct native_fn {
+ struct native_fn *next; ///< The next link in the chain
+ handler_fn handler; ///< Internal C handler, or NULL
+ char name[]; ///< The name of the function
+};
+
static void
context_init (struct context *ctx) {
memset (ctx, 0, sizeof *ctx);
@@ -675,6 +648,11 @@ context_init (struct context *ctx) {
static void
context_free (struct context *ctx) {
+ struct native_fn *next, *iter;
+ for (iter = ctx->native; iter; iter = next) {
+ next = iter->next;
+ free (iter);
+ }
item_free_list (ctx->variables);
free (ctx->error);
}
@@ -719,6 +697,30 @@ set (struct context *ctx, const char *name, struct item *value) {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+static struct native_fn *
+native_find (struct context *ctx, const char *name) {
+ for (struct native_fn *fn = ctx->native; fn; fn = fn->next)
+ if (!strcmp (fn->name, name))
+ return fn;
+ return NULL;
+}
+
+static bool
+native_register (struct context *ctx, const char *name, handler_fn handler) {
+ struct native_fn *fn = native_find (ctx, name);
+ if (!fn) {
+ if (!(fn = calloc (1, sizeof *fn + strlen (name) + 1)))
+ return false;
+ strcpy (fn->name, name);
+ fn->next = ctx->native;
+ ctx->native = fn;
+ }
+ fn->handler = handler;
+ return true;
+}
+
+// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
static bool
set_error (struct context *ctx, const char *format, ...) {
va_list ap;
@@ -795,10 +797,10 @@ execute_and_set_args (struct context *ctx, struct item *following) {
static bool
execute_native (struct context *ctx,
- struct native_fn *fn, struct item *next, struct item **res) {
+ struct native_fn *fn, struct item *following, struct item **result) {
struct item *args = NULL;
- bool ok = execute_args (ctx, next, &args)
- && fn->handler (ctx, args, res);
+ bool ok = execute_args (ctx, following, &args)
+ && fn->handler (ctx, args, result);
item_free_list (args);
return ok;
}
@@ -839,7 +841,7 @@ execute_statement
// Maybe something like (choose [@f1 @f2 @f3]) arg1 arg2 arg3
if (!body) {
- struct native_fn *fn = native_find (name);
+ struct native_fn *fn = native_find (ctx, name);
if (!fn)
return set_error (ctx, "unknown function: %s", name);
if (execute_native (ctx, fn, following, result))
@@ -1067,35 +1069,8 @@ defn (fn_concatenate) {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-static bool
-init_native_library (void)
-{
- return native_register ("set", fn_set)
- && native_register ("list", fn_list)
- && native_register ("if", fn_if)
- && native_register ("for", fn_for)
- && native_register ("break", fn_break)
- && native_register ("map", fn_map)
- && native_register ("filter", fn_filter)
- && native_register ("print", fn_print)
- && native_register ("..", fn_concatenate);
-}
-
-static void
-free_native_library (void) {
- struct native_fn *next, *iter;
- for (iter = g_native; iter; iter = next) {
- next = iter->next;
- free (iter);
- }
-}
-
-// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
static bool
init_runtime_library (struct context *ctx) {
- bool ok = true;
-
struct {
const char *name; ///< Name of the function
const char *definition; ///< The defining script
@@ -1105,6 +1080,7 @@ init_runtime_library (struct context *ctx) {
{ "unless", "arg cond body; if (not (eval @cond)) @body" },
};
+ bool ok = true;
for (size_t i = 0; i < N_ELEMENTS (functions); i++) {
struct parser parser;
parser_init (&parser,
@@ -1123,7 +1099,17 @@ init_runtime_library (struct context *ctx) {
item_free_list (body);
parser_free (&parser);
}
- return ok;
+
+ return ok
+ && native_register (ctx, "set", fn_set)
+ && native_register (ctx, "list", fn_list)
+ && native_register (ctx, "if", fn_if)
+ && native_register (ctx, "for", fn_for)
+ && native_register (ctx, "break", fn_break)
+ && native_register (ctx, "map", fn_map)
+ && native_register (ctx, "filter", fn_filter)
+ && native_register (ctx, "print", fn_print)
+ && native_register (ctx, "..", fn_concatenate);
}
// --- Main --------------------------------------------------------------------
@@ -1161,8 +1147,7 @@ main (int argc, char *argv[]) {
struct context ctx;
context_init (&ctx);
- if (!init_native_library ()
- || !init_runtime_library (&ctx))
+ if (!init_runtime_library (&ctx))
printf ("%s\n", "runtime library initialization failed");
struct item *result = NULL;
@@ -1176,8 +1161,6 @@ main (int argc, char *argv[]) {
if (failure)
printf ("%s: %s\n", "runtime error", failure);
context_free (&ctx);
-
- free_native_library ();
return 0;
}