parent
7f9e8b2cbc
commit
f47623abda
69
ell.c
69
ell.c
|
@ -270,9 +270,9 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue