Move native functions into the context
This commit is contained in:
parent
0f4ece8867
commit
c7b06a490f
127
ell.c
127
ell.c
|
@ -622,44 +622,9 @@ parser_run (struct parser *self, const char **e) {
|
||||||
|
|
||||||
// --- Runtime -----------------------------------------------------------------
|
// --- 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 context {
|
||||||
struct item *variables; ///< List of variables
|
struct item *variables; ///< List of variables
|
||||||
|
struct native_fn *native; ///< Maps strings to C functions
|
||||||
|
|
||||||
char *error; ///< Error information
|
char *error; ///< Error information
|
||||||
bool error_is_fatal; ///< Whether the error can be catched
|
bool error_is_fatal; ///< Whether the error can be catched
|
||||||
|
@ -668,6 +633,14 @@ struct context {
|
||||||
void *user_data; ///< User data
|
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
|
static void
|
||||||
context_init (struct context *ctx) {
|
context_init (struct context *ctx) {
|
||||||
memset (ctx, 0, sizeof *ctx);
|
memset (ctx, 0, sizeof *ctx);
|
||||||
|
@ -675,6 +648,11 @@ context_init (struct context *ctx) {
|
||||||
|
|
||||||
static void
|
static void
|
||||||
context_free (struct context *ctx) {
|
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);
|
item_free_list (ctx->variables);
|
||||||
free (ctx->error);
|
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
|
static bool
|
||||||
set_error (struct context *ctx, const char *format, ...) {
|
set_error (struct context *ctx, const char *format, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
@ -795,10 +797,10 @@ execute_and_set_args (struct context *ctx, struct item *following) {
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
execute_native (struct context *ctx,
|
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;
|
struct item *args = NULL;
|
||||||
bool ok = execute_args (ctx, next, &args)
|
bool ok = execute_args (ctx, following, &args)
|
||||||
&& fn->handler (ctx, args, res);
|
&& fn->handler (ctx, args, result);
|
||||||
item_free_list (args);
|
item_free_list (args);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
@ -839,7 +841,7 @@ execute_statement
|
||||||
// Maybe something like (choose [@f1 @f2 @f3]) arg1 arg2 arg3
|
// Maybe something like (choose [@f1 @f2 @f3]) arg1 arg2 arg3
|
||||||
|
|
||||||
if (!body) {
|
if (!body) {
|
||||||
struct native_fn *fn = native_find (name);
|
struct native_fn *fn = native_find (ctx, name);
|
||||||
if (!fn)
|
if (!fn)
|
||||||
return set_error (ctx, "unknown function: %s", name);
|
return set_error (ctx, "unknown function: %s", name);
|
||||||
if (execute_native (ctx, fn, following, result))
|
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
|
static bool
|
||||||
init_runtime_library (struct context *ctx) {
|
init_runtime_library (struct context *ctx) {
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
const char *name; ///< Name of the function
|
const char *name; ///< Name of the function
|
||||||
const char *definition; ///< The defining script
|
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" },
|
{ "unless", "arg cond body; if (not (eval @cond)) @body" },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool ok = true;
|
||||||
for (size_t i = 0; i < N_ELEMENTS (functions); i++) {
|
for (size_t i = 0; i < N_ELEMENTS (functions); i++) {
|
||||||
struct parser parser;
|
struct parser parser;
|
||||||
parser_init (&parser,
|
parser_init (&parser,
|
||||||
|
@ -1123,7 +1099,17 @@ init_runtime_library (struct context *ctx) {
|
||||||
item_free_list (body);
|
item_free_list (body);
|
||||||
parser_free (&parser);
|
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 --------------------------------------------------------------------
|
// --- Main --------------------------------------------------------------------
|
||||||
|
@ -1161,8 +1147,7 @@ main (int argc, char *argv[]) {
|
||||||
|
|
||||||
struct context ctx;
|
struct context ctx;
|
||||||
context_init (&ctx);
|
context_init (&ctx);
|
||||||
if (!init_native_library ()
|
if (!init_runtime_library (&ctx))
|
||||||
|| !init_runtime_library (&ctx))
|
|
||||||
printf ("%s\n", "runtime library initialization failed");
|
printf ("%s\n", "runtime library initialization failed");
|
||||||
|
|
||||||
struct item *result = NULL;
|
struct item *result = NULL;
|
||||||
|
@ -1176,8 +1161,6 @@ main (int argc, char *argv[]) {
|
||||||
if (failure)
|
if (failure)
|
||||||
printf ("%s: %s\n", "runtime error", failure);
|
printf ("%s: %s\n", "runtime error", failure);
|
||||||
context_free (&ctx);
|
context_free (&ctx);
|
||||||
|
|
||||||
free_native_library ();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue