Load scripts from files

And various fixes.
This commit is contained in:
Přemysl Eric Janouch 2017-05-18 23:27:20 +02:00
parent 7f9e8b2cbc
commit f47623abda
Signed by: p
GPG Key ID: B715679E3A361BE6
2 changed files with 46 additions and 29 deletions

67
ell.c
View File

@ -270,7 +270,7 @@ lexer_free (struct lexer *self) {
free (self->string.s); free (self->string.s);
} }
static bool lexer_is_ignored (int c) { return c == ' ' || c == '\t'; } static bool lexer_is_ignored (int c) { return strchr (" \t", c); }
static bool lexer_is_word_char (int c) { static bool lexer_is_word_char (int c) {
return !lexer_is_ignored (c) && !strchr ("()[]{}\n@#'", c); return !lexer_is_ignored (c) && !strchr ("()[]{}\n@#'", c);
} }
@ -573,7 +573,7 @@ parse_item (struct parser *self, jmp_buf out) {
while ((*tail = parse_line (self, err))) while ((*tail = parse_line (self, err)))
tail = &(*tail)->next; tail = &(*tail)->next;
EXPECT (T_RBRACE); EXPECT (T_RBRACE);
return parse_prefix_list (result, "quote"); return parse_prefix_list (new_list (result), "quote");
} }
lexer_error (&self->lexer, &self->error, lexer_error (&self->lexer, &self->error,
@ -653,13 +653,17 @@ struct native_fn {
struct native_fn *g_native; ///< Maps words to functions struct native_fn *g_native; ///< Maps words to functions
static bool static struct native_fn *
register_native (const char *name, handler_fn handler) { native_find (const char *name) {
struct native_fn *fn = NULL; for (struct native_fn *fn = g_native; fn; fn = fn->next)
for (fn = g_native; fn; fn = fn->next)
if (!strcmp (fn->name, name)) if (!strcmp (fn->name, name))
break; 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) {
if (!(fn = calloc (1, sizeof *fn + strlen (name) + 1))) if (!(fn = calloc (1, sizeof *fn + strlen (name) + 1)))
return false; return false;
@ -762,12 +766,12 @@ rename_arguments (struct context *ctx, struct item *names) {
(void) snprintf (buf, sizeof buf, "%zu", i++); (void) snprintf (buf, sizeof buf, "%zu", i++);
struct item *value = get (ctx, buf); struct item *value = get (ctx, buf);
// TODO: set to some sort of nil value?
if (!value)
return true;
if (names->type != ITEM_STRING) if (names->type != ITEM_STRING)
continue; continue;
if (value && !(value = new_clone (value))) {
ctx->memory_failure = true;
return false;
}
if (!set (ctx, names->value, value)) if (!set (ctx, names->value, value))
return false; return false;
} }
@ -803,6 +807,8 @@ execute_native (struct context *ctx,
return ok; return ok;
} }
// TODO: we should probably maintain arguments in a separate list,
// either that or at least remember the count so that we can reset them
static bool static bool
execute_args (struct context *ctx, struct item *next) { execute_args (struct context *ctx, struct item *next) {
struct item *args = NULL; struct item *args = NULL;
@ -821,8 +827,6 @@ execute_args (struct context *ctx, struct item *next) {
return true; return true;
} }
// TODO: we should probably maintain arguments in a separate list,
// either that or at least remember the count so that we can reset them
static bool static bool
execute_statement execute_statement
(struct context *ctx, struct item *statement, struct item **result) { (struct context *ctx, struct item *statement, struct item **result) {
@ -856,11 +860,7 @@ execute_statement
} }
if (!body) { if (!body) {
// TODO: this could be a function struct native_fn *fn = native_find (name);
struct native_fn *fn;
for (fn = g_native; fn; fn = fn->next)
if (!strcmp (name, fn->name))
break;
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))
@ -913,7 +913,7 @@ init_runtime_library_scripts (struct context *ctx) {
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
} functions[] = { } functions[] = {
{ "greet", "arg _name\n" "print (.. 'hello ' @_name '\\n')" }, // TODO: try to think of something useful
}; };
for (size_t i = 0; i < N_ELEMENTS (functions); i++) { for (size_t i = 0; i < N_ELEMENTS (functions); i++) {
@ -941,7 +941,7 @@ defn (fn_set) {
return set (ctx, name->value, value); return set (ctx, name->value, value);
// FIXME: how do we represent a nil value here? // FIXME: how do we represent a nil value here?
*result = get (ctx, name->value); *result = new_clone (get (ctx, name->value));
return true; return true;
} }
@ -958,7 +958,7 @@ defn (fn_print) {
return false; return false;
} }
printf ("%s\n", buf.s); printf ("%s", buf.s);
free (buf.s); free (buf.s);
return true; return true;
} }
@ -981,9 +981,9 @@ defn (fn_concatenate) {
static bool static bool
init_runtime_library (void) init_runtime_library (void)
{ {
return register_native ("..", fn_concatenate) return native_register ("..", fn_concatenate)
&& register_native ("set", fn_set) && native_register ("set", fn_set)
&& register_native ("print", fn_print); && native_register ("print", fn_print);
} }
static void static void
@ -999,11 +999,22 @@ free_runtime_library (void) {
int int
main (int argc, char *argv[]) { main (int argc, char *argv[]) {
// TODO: load the entirety of stdin FILE *fp = stdin;
const char *program = "greet 'world'"; if (argc > 1 && !(fp = fopen (argv[1], "rb"))) {
fprintf (stderr, "%s: %s\n", argv[1], strerror (errno));
return 1;
}
int c;
struct buffer buf = BUFFER_INITIALIZER;
while ((c = fgetc (fp)) != EOF)
buffer_append_c (&buf, c);
buffer_append_c (&buf, 0);
fclose (fp);
char *e = NULL; char *e = NULL;
struct item *tree = parse (program, strlen (program), &e); struct item *tree = parse (buf.s, buf.len, &e);
free (buf.s);
if (e) { if (e) {
printf ("%s: %s\n", "parse error", e); printf ("%s: %s\n", "parse error", e);
free (e); free (e);
@ -1015,7 +1026,7 @@ main (int argc, char *argv[]) {
if (!init_runtime_library () if (!init_runtime_library ()
|| !init_runtime_library_scripts (&ctx)) || !init_runtime_library_scripts (&ctx))
printf ("%s\n", "runtime library initialization failed"); printf ("%s\n", "runtime library initialization failed");
ctx.user_data = NULL;
struct item *result = NULL; struct item *result = NULL;
(void) execute (&ctx, tree->head, &result); (void) execute (&ctx, tree->head, &result);
item_free_list (result); item_free_list (result);

6
greet.ell Normal file
View File

@ -0,0 +1,6 @@
set greet {
arg _name
print 'hello ' @_name '\n'
}
greet world
greet creator