aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Janouch <p.janouch@gmail.com>2017-05-30 02:43:42 +0200
committerPřemysl Janouch <p.janouch@gmail.com>2017-05-30 02:43:42 +0200
commit8518c1a58f63d8a1fc992616480c6202335815e8 (patch)
tree1821fc070e7db0c817cc239e1becb28e97304b50
parentd579e68051ac757c530f753b02fbf18ed1aa41b3 (diff)
downloadell-8518c1a58f63d8a1fc992616480c6202335815e8.tar.gz
ell-8518c1a58f63d8a1fc992616480c6202335815e8.tar.xz
ell-8518c1a58f63d8a1fc992616480c6202335815e8.zip
The great librarificating rename
-rw-r--r--ell.c1243
-rw-r--r--interpreter.c38
-rw-r--r--repl.c52
3 files changed, 675 insertions, 658 deletions
diff --git a/ell.c b/ell.c
index e9b5beb..52d902e 100644
--- a/ell.c
+++ b/ell.c
@@ -27,19 +27,19 @@
#include <setjmp.h>
#if defined __GNUC__
-#define ATTRIBUTE_PRINTF(x, y) __attribute__ ((format (printf, x, y)))
+#define ELL_ATTRIBUTE_PRINTF(x, y) __attribute__ ((format (printf, x, y)))
#else // ! __GNUC__
-#define ATTRIBUTE_PRINTF(x, y)
+#define ELL_ATTRIBUTE_PRINTF(x, y)
#endif // ! __GNUC__
-#define N_ELEMENTS(a) (sizeof (a) / sizeof ((a)[0]))
+#define ELL_N_ELEMENTS(a) (sizeof (a) / sizeof ((a)[0]))
// --- Utilities ---------------------------------------------------------------
-static char *format (const char *format, ...) ATTRIBUTE_PRINTF (1, 2);
+static char *ell_format (const char *format, ...) ELL_ATTRIBUTE_PRINTF (1, 2);
static char *
-vformat (const char *format, va_list ap) {
+ell_vformat (const char *format, va_list ap) {
va_list aq;
va_copy (aq, ap);
int size = vsnprintf (NULL, 0, format, aq);
@@ -56,26 +56,26 @@ vformat (const char *format, va_list ap) {
}
static char *
-format (const char *format, ...) {
+ell_format (const char *format, ...) {
va_list ap;
va_start (ap, format);
- char *result = vformat (format, ap);
+ char *result = ell_vformat (format, ap);
va_end (ap);
return result;
}
// --- Generic buffer ----------------------------------------------------------
-struct buffer {
+struct ell_buffer {
char *s; ///< Buffer data
size_t alloc, len; ///< Number of bytes allocated and used
bool memory_failure; ///< Memory allocation failed
};
-#define BUFFER_INITIALIZER { NULL, 0, 0, false }
+#define ELL_BUFFER_INITIALIZER { NULL, 0, 0, false }
static bool
-buffer_append (struct buffer *self, const void *s, size_t n) {
+ell_buffer_append (struct ell_buffer *self, const void *s, size_t n) {
if (self->memory_failure)
return false;
@@ -95,50 +95,50 @@ buffer_append (struct buffer *self, const void *s, size_t n) {
}
inline static bool
-buffer_append_c (struct buffer *self, char c) {
- return buffer_append (self, &c, 1);
+ell_buffer_append_c (struct ell_buffer *self, char c) {
+ return ell_buffer_append (self, &c, 1);
}
-// --- Data items --------------------------------------------------------------
+// --- Values ------------------------------------------------------------------
-enum item_type { ITEM_STRING, ITEM_LIST };
+enum ell_v_type { ELL_STRING, ELL_LIST };
-struct item {
- enum item_type type; ///< The type of this object
- struct item *next; ///< Next item on the list/stack
+struct ell_v {
+ enum ell_v_type type; ///< The type of this value
+ struct ell_v *next; ///< Next value in sequence
- struct item *head; ///< The head of the list
- size_t len; ///< Length of "value" (sans '\0')
- char value[]; ///< The null-terminated string value
+ struct ell_v *head; ///< The head of the list
+ size_t len; ///< Length of "string" (sans '\0')
+ char string[]; ///< The null-terminated string value
};
-static void item_free_list (struct item *);
-static struct item *new_clone_list (const struct item *);
+static void ell_free_seq (struct ell_v *);
+static struct ell_v *ell_clone_seq (const struct ell_v *);
static void
-item_free (struct item *item) {
- item_free_list (item->head);
- free (item);
+ell_free_v (struct ell_v *v) {
+ ell_free_seq (v->head);
+ free (v);
}
static void
-item_free_list (struct item *item) {
- while (item) {
- struct item *link = item;
- item = item->next;
- item_free (link);
+ell_free_seq (struct ell_v *v) {
+ while (v) {
+ struct ell_v *link = v;
+ v = v->next;
+ ell_free_v (link);
}
}
-static struct item *
-new_clone (const struct item *item) {
- size_t size = sizeof *item + item->len + 1;
- struct item *clone = malloc (size);
+static struct ell_v *
+ell_clone (const struct ell_v *v) {
+ size_t size = sizeof *v + v->len + 1;
+ struct ell_v *clone = malloc (size);
if (!clone)
return NULL;
- memcpy (clone, item, size);
- if (clone->head && !(clone->head = new_clone_list (clone->head))) {
+ memcpy (clone, v, size);
+ if (clone->head && !(clone->head = ell_clone_seq (clone->head))) {
free (clone);
return NULL;
}
@@ -146,12 +146,12 @@ new_clone (const struct item *item) {
return clone;
}
-static struct item *
-new_clone_list (const struct item *item) {
- struct item *head = NULL;
- for (struct item **out = &head; item; item = item->next) {
- if (!(*out = new_clone (item))) {
- item_free_list (head);
+static struct ell_v *
+ell_clone_seq (const struct ell_v *v) {
+ struct ell_v *head = NULL;
+ for (struct ell_v **out = &head; v; v = v->next) {
+ if (!(*out = ell_clone (v))) {
+ ell_free_seq (head);
return NULL;
}
out = &(*out)->next;
@@ -159,70 +159,71 @@ new_clone_list (const struct item *item) {
return head;
}
-static struct item *
-new_string (const char *s, size_t len) {
- struct item *item = calloc (1, sizeof *item + len + 1);
- if (!item)
+static struct ell_v *
+ell_string (const char *s, size_t len) {
+ struct ell_v *v = calloc (1, sizeof *v + len + 1);
+ if (!v)
return NULL;
- item->type = ITEM_STRING;
- item->len = len;
- memcpy (item->value, s, len);
- return item;
+ v->type = ELL_STRING;
+ v->len = len;
+ memcpy (v->string, s, len);
+ return v;
}
-static struct item *
-new_list (struct item *head) {
- struct item *item = calloc (1, sizeof *item + 1);
- if (!item) {
- item_free_list (head);
+static struct ell_v *
+ell_list (struct ell_v *head) {
+ struct ell_v *v = calloc (1, sizeof *v + 1);
+ if (!v) {
+ ell_free_seq (head);
return NULL;
}
- item->type = ITEM_LIST;
- item->head = head;
- return item;
+ v->type = ELL_LIST;
+ v->head = head;
+ return v;
}
// --- Lexer -------------------------------------------------------------------
-enum token { T_ABORT, T_LPAREN, T_RPAREN, T_LBRACKET, T_RBRACKET,
- T_LBRACE, T_RBRACE, T_STRING, T_NEWLINE, T_AT };
-
-static const char *token_names[] = {
- [T_ABORT] = "end of input",
- [T_LPAREN] = "left parenthesis",
- [T_RPAREN] = "right parenthesis",
- [T_LBRACKET] = "left bracket",
- [T_RBRACKET] = "right bracket",
- [T_LBRACE] = "left brace",
- [T_RBRACE] = "right brace",
- [T_STRING] = "string",
- [T_NEWLINE] = "newline",
- [T_AT] = "at symbol",
+enum ell_token { ELLT_ABORT, ELLT_LPAREN, ELLT_RPAREN,
+ ELLT_LBRACKET, ELLT_RBRACKET, ELLT_LBRACE, ELLT_RBRACE,
+ ELLT_STRING, ELLT_NEWLINE, ELLT_AT };
+
+static const char *ell_token_names[] = {
+ [ELLT_ABORT] = "end of input",
+ [ELLT_LPAREN] = "left parenthesis",
+ [ELLT_RPAREN] = "right parenthesis",
+ [ELLT_LBRACKET] = "left bracket",
+ [ELLT_RBRACKET] = "right bracket",
+ [ELLT_LBRACE] = "left brace",
+ [ELLT_RBRACE] = "right brace",
+ [ELLT_STRING] = "string",
+ [ELLT_NEWLINE] = "newline",
+ [ELLT_AT] = "at symbol",
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-struct lexer {
+struct ell_lexer {
const unsigned char *p; ///< Current position in input
size_t len; ///< How many bytes of input are left
unsigned line, column; ///< Current line and column
- struct buffer string; ///< Parsed string value
+ struct ell_buffer string; ///< Parsed string value
};
static void
-lexer_init (struct lexer *self, const char *p, size_t len) {
- *self = (struct lexer) { .p = (const unsigned char *) p, .len = len };
+ell_lexer_init (struct ell_lexer *self, const char *p, size_t len) {
+ *self = (struct ell_lexer) { .p = (const unsigned char *) p, .len = len };
}
static void
-lexer_free (struct lexer *self) {
+ell_lexer_free (struct ell_lexer *self) {
free (self->string.s);
}
static int
-lexer_advance (struct lexer *self) {
+ell_lexer_advance (struct ell_lexer *self) {
int c = *self->p++;
if (c == '\n') {
self->column = 0;
@@ -235,109 +236,119 @@ lexer_advance (struct lexer *self) {
}
static bool
-lexer_hexa_escape (struct lexer *self, struct buffer *output) {
- const char *alphabet = "0123456789abcdef", *h, *l;
- if (!self->len || !(h = strchr (alphabet, tolower (lexer_advance (self))))
- || !self->len || !(l = strchr (alphabet, tolower (lexer_advance (self)))))
+ell_lexer_hexa_escape (struct ell_lexer *self, struct ell_buffer *output) {
+ const char *abc = "0123456789abcdef", *h, *l;
+ if (!self->len || !(h = strchr (abc, tolower (ell_lexer_advance (self))))
+ || !self->len || !(l = strchr (abc, tolower (ell_lexer_advance (self)))))
return false;
- buffer_append_c (output, (h - alphabet) << 4 | (l - alphabet));
+ ell_buffer_append_c (output, (h - abc) << 4 | (l - abc));
return true;
}
-enum { LEXER_STRING_QUOTE = '\'', LEXER_ESCAPE = '\\', LEXER_COMMENT = '#' };
-static bool lexer_is_whitespace (int c) { return !c || c == ' ' || c == '\t'; }
+enum {
+ ELL_LEXER_STRING_QUOTE = '\'',
+ ELL_LEXER_ESCAPE = '\\',
+ ELL_LEXER_COMMENT = '#'
+};
+
+static bool ell_lexer_is_whitespace (int c) {
+ return !c || c == ' ' || c == '\t';
+}
-static unsigned char lexer_escapes[256] = {
- [LEXER_STRING_QUOTE] = LEXER_STRING_QUOTE, [LEXER_ESCAPE] = LEXER_ESCAPE,
+static unsigned char ell_lexer_escapes[256] = {
+ [ELL_LEXER_STRING_QUOTE] = ELL_LEXER_STRING_QUOTE,
+ [ELL_LEXER_ESCAPE] = ELL_LEXER_ESCAPE,
['a'] = '\a', ['b'] = '\b', ['n'] = '\n', ['r'] = '\r', ['t'] = '\t',
};
static const char *
-lexer_escape_sequence (struct lexer *self, struct buffer *output) {
+ell_lexer_escape_sequence (struct ell_lexer *self, struct ell_buffer *output) {
if (!self->len)
return "premature end of escape sequence";
- int c = lexer_advance (self);
+ int c = ell_lexer_advance (self);
if (c == 'x') {
- if (lexer_hexa_escape (self, output))
+ if (ell_lexer_hexa_escape (self, output))
return NULL;
return "invalid hexadecimal escape";
}
- if (!(c = lexer_escapes[c]))
+ if (!(c = ell_lexer_escapes[c]))
return "unknown escape sequence";
- buffer_append_c (output, c);
+ ell_buffer_append_c (output, c);
return NULL;
}
static const char *
-lexer_string (struct lexer *self, struct buffer *output) {
+ell_lexer_string (struct ell_lexer *self, struct ell_buffer *output) {
int c;
const char *e = NULL;
while (self->len) {
- if ((c = lexer_advance (self)) == LEXER_STRING_QUOTE)
+ if ((c = ell_lexer_advance (self)) == ELL_LEXER_STRING_QUOTE)
return NULL;
- if (c != LEXER_ESCAPE)
- buffer_append_c (output, c);
- else if ((e = lexer_escape_sequence (self, output)))
+ if (c != ELL_LEXER_ESCAPE)
+ ell_buffer_append_c (output, c);
+ else if ((e = ell_lexer_escape_sequence (self, output)))
return e;
}
return "premature end of string";
}
-static enum token lexer_tokens[256] = {
- ['('] = T_LPAREN, [')'] = T_RPAREN, ['['] = T_LBRACKET, [']'] = T_RBRACKET,
- ['{'] = T_LBRACE, ['}'] = T_RBRACE, [';'] = T_NEWLINE, ['\n'] = T_NEWLINE,
- ['@'] = T_AT, [LEXER_STRING_QUOTE] = T_STRING,
+static enum ell_token ell_lexer_tokens[256] = {
+ ['('] = ELLT_LPAREN, [')'] = ELLT_RPAREN,
+ ['['] = ELLT_LBRACKET, [']'] = ELLT_RBRACKET,
+ ['{'] = ELLT_LBRACE, ['}'] = ELLT_RBRACE,
+ [';'] = ELLT_NEWLINE, ['\n'] = ELLT_NEWLINE,
+ ['@'] = ELLT_AT, [ELL_LEXER_STRING_QUOTE] = ELLT_STRING,
};
-static enum token
-lexer_next (struct lexer *self, const char **e) {
- while (self->len && lexer_is_whitespace (*self->p))
- lexer_advance (self);
+static enum ell_token
+ell_lexer_next (struct ell_lexer *self, const char **e) {
+ while (self->len && ell_lexer_is_whitespace (*self->p))
+ ell_lexer_advance (self);
if (!self->len)
- return T_ABORT;
+ return ELLT_ABORT;
free (self->string.s);
- self->string = (struct buffer) BUFFER_INITIALIZER;
+ self->string = (struct ell_buffer) ELL_BUFFER_INITIALIZER;
- int c = lexer_advance (self);
- if (c == LEXER_COMMENT) {
+ int c = ell_lexer_advance (self);
+ if (c == ELL_LEXER_COMMENT) {
while (self->len)
- if (lexer_advance (self) == '\n')
- return T_NEWLINE;
- return T_ABORT;
+ if (ell_lexer_advance (self) == '\n')
+ return ELLT_NEWLINE;
+ return ELLT_ABORT;
}
- enum token token = lexer_tokens[c];
+ enum ell_token token = ell_lexer_tokens[c];
if (!token) {
- buffer_append_c (&self->string, c);
- while (self->len && !lexer_is_whitespace (*self->p)
- && !lexer_tokens[*self->p])
- buffer_append_c (&self->string, lexer_advance (self));
- return T_STRING;
+ ell_buffer_append_c (&self->string, c);
+ while (self->len && !ell_lexer_is_whitespace (*self->p)
+ && !ell_lexer_tokens[*self->p])
+ ell_buffer_append_c (&self->string, ell_lexer_advance (self));
+ return ELLT_STRING;
}
- if (token == T_STRING
- && (*e = lexer_string (self, &self->string)))
- return T_ABORT;
+ if (token == ELLT_STRING
+ && (*e = ell_lexer_string (self, &self->string)))
+ return ELLT_ABORT;
return token;
}
-static char *lexer_errorf (struct lexer *self, const char *fmt, ...)
- ATTRIBUTE_PRINTF (2, 3);
+static char *ell_lexer_errorf (struct ell_lexer *self, const char *fmt, ...)
+ ELL_ATTRIBUTE_PRINTF (2, 3);
static char *
-lexer_errorf (struct lexer *self, const char *fmt, ...) {
+ell_lexer_errorf (struct ell_lexer *self, const char *fmt, ...) {
va_list ap;
va_start (ap, fmt);
- char *description = vformat (fmt, ap);
+ char *description = ell_vformat (fmt, ap);
va_end (ap);
if (!description)
return NULL;
- char *e = format ("at or before line %u, column %u: %s",
+ char *e = ell_format ("at or before line %u, column %u: %s",
self->line + 1, self->column + 1, description);
free (description);
return e;
@@ -345,56 +356,56 @@ lexer_errorf (struct lexer *self, const char *fmt, ...) {
// --- Printing ----------------------------------------------------------------
-static void print_item_list (struct item *item);
+static void ell_print_seq (struct ell_v *v);
static bool
-print_string_needs_quoting (struct item *s) {
+ell_print_string_needs_quoting (struct ell_v *s) {
for (size_t i = 0; i < s->len; i++) {
- unsigned char c = s->value[i];
- if (lexer_is_whitespace (c) || lexer_tokens[c]
- || c == LEXER_ESCAPE || c < 32)
+ unsigned char c = s->string[i];
+ if (ell_lexer_is_whitespace (c) || ell_lexer_tokens[c]
+ || c == ELL_LEXER_ESCAPE || c < 32)
return true;
}
return s->len == 0;
}
static bool
-print_string (struct item *s) {
- if (s->type != ITEM_STRING)
+ell_print_string (struct ell_v *s) {
+ if (s->type != ELL_STRING)
return false;
- if (!print_string_needs_quoting (s)) {
- printf ("%s", s->value);
+ if (!ell_print_string_needs_quoting (s)) {
+ printf ("%s", s->string);
return true;
}
- putchar (LEXER_STRING_QUOTE);
+ putchar (ELL_LEXER_STRING_QUOTE);
for (size_t i = 0; i < s->len; i++) {
- unsigned char c = s->value[i];
+ unsigned char c = s->string[i];
if (c < 32)
printf ("\\x%02x", c);
- else if (c == LEXER_ESCAPE || c == LEXER_STRING_QUOTE)
+ else if (c == ELL_LEXER_ESCAPE || c == ELL_LEXER_STRING_QUOTE)
printf ("\\%c", c);
else
putchar (c);
}
- putchar (LEXER_STRING_QUOTE);
+ putchar (ELL_LEXER_STRING_QUOTE);
return true;
}
static bool
-print_block (struct item *list) {
- if (!list->head || strcmp (list->head->value, "block"))
+ell_print_block (struct ell_v *list) {
+ if (!list->head || strcmp (list->head->string, "block"))
return false;
list = list->head->next;
- for (struct item *line = list; line; line = line->next)
- if (line->type != ITEM_LIST)
+ for (struct ell_v *line = list; line; line = line->next)
+ if (line->type != ELL_LIST)
return false;
putchar ('{');
- for (struct item *line = list; line; line = line->next) {
+ for (struct ell_v *line = list; line; line = line->next) {
putchar (' ');
- print_item_list (line->head);
+ ell_print_seq (line->head);
putchar (line->next ? ';' : ' ');
}
putchar ('}');
@@ -402,106 +413,106 @@ print_block (struct item *list) {
}
static bool
-print_set (struct item *list) {
- if (!list->head || strcmp (list->head->value, "set")
+ell_print_set (struct ell_v *list) {
+ if (!list->head || strcmp (list->head->string, "set")
|| !list->head->next || list->head->next->next)
return false;
putchar ('@');
- print_item_list (list->head->next);
+ ell_print_seq (list->head->next);
return true;
}
static bool
-print_list (struct item *list) {
- if (!list->head || strcmp (list->head->value, "list"))
+ell_print_list (struct ell_v *list) {
+ if (!list->head || strcmp (list->head->string, "list"))
return false;
putchar ('[');
- print_item_list (list->head->next);
+ ell_print_seq (list->head->next);
putchar (']');
return true;
}
static void
-print_item (struct item *item) {
- if (print_string (item)
- || print_block (item)
- || print_set (item)
- || print_list (item))
+ell_print_v (struct ell_v *v) {
+ if (ell_print_string (v)
+ || ell_print_block (v)
+ || ell_print_set (v)
+ || ell_print_list (v))
return;
putchar ('(');
- print_item_list (item->head);
+ ell_print_seq (v->head);
putchar (')');
}
static void
-print_item_list (struct item *item) {
- for (; item; item = item->next) {
- print_item (item);
- if (item->next)
+ell_print_seq (struct ell_v *v) {
+ for (; v; v = v->next) {
+ ell_print_v (v);
+ if (v->next)
putchar (' ');
}
}
// --- Parsing -----------------------------------------------------------------
-struct parser {
- struct lexer lexer; ///< Tokenizer
+struct ell_parser {
+ struct ell_lexer lexer; ///< Tokenizer
char *error; ///< Tokenizer error
- enum token token; ///< Current token in the lexer
+ enum ell_token token; ///< Current token in the lexer
bool replace_token; ///< Replace the token
bool memory_failure; ///< Memory allocation failed
};
static void
-parser_init (struct parser *self, const char *script, size_t len) {
- memset (self, 0, sizeof *self);
- lexer_init (&self->lexer, script, len);
+ell_parser_init (struct ell_parser *p, const char *script, size_t len) {
+ memset (p, 0, sizeof *p);
+ ell_lexer_init (&p->lexer, script, len);
// As reading in tokens may cause exceptions, we wait for the first peek()
- // to replace the initial T_ABORT.
- self->replace_token = true;
+ // to replace the initial ELLT_ABORT.
+ p->replace_token = true;
}
static void
-parser_free (struct parser *self) {
- lexer_free (&self->lexer);
- if (self->error)
- free (self->error);
+ell_parser_free (struct ell_parser *p) {
+ ell_lexer_free (&p->lexer);
+ if (p->error)
+ free (p->error);
}
-static enum token
-parser_peek (struct parser *self, jmp_buf out) {
- if (self->replace_token) {
+static enum ell_token
+ell_parser_peek (struct ell_parser *p, jmp_buf out) {
+ if (p->replace_token) {
const char *e = NULL;
- self->token = lexer_next (&self->lexer, &e);
+ p->token = ell_lexer_next (&p->lexer, &e);
if (e) {
- self->memory_failure =
- !(self->error = lexer_errorf (&self->lexer, "%s", e));
+ p->memory_failure =
+ !(p->error = ell_lexer_errorf (&p->lexer, "%s", e));
longjmp (out, 1);
}
- if (self->token == T_STRING && self->lexer.string.memory_failure)
+ if (p->token == ELLT_STRING && p->lexer.string.memory_failure)
longjmp (out, 1);
- self->replace_token = false;
+ p->replace_token = false;
}
- return self->token;
+ return p->token;
}
static bool
-parser_accept (struct parser *self, enum token token, jmp_buf out) {
- return self->replace_token = (parser_peek (self, out) == token);
+ell_parser_accept (struct ell_parser *p, enum ell_token token, jmp_buf out) {
+ return p->replace_token = (ell_parser_peek (p, out) == token);
}
static void
-parser_expect (struct parser *self, enum token token, jmp_buf out) {
- if (parser_accept (self, token, out))
+ell_parser_expect (struct ell_parser *p, enum ell_token token, jmp_buf out) {
+ if (ell_parser_accept (p, token, out))
return;
- self->memory_failure = !(self->error = lexer_errorf (&self->lexer,
+ p->memory_failure = !(p->error = ell_lexer_errorf (&p->lexer,
"unexpected `%s', expected `%s'",
- token_names[self->token], token_names[token]));
+ ell_token_names[p->token], ell_token_names[token]));
longjmp (out, 1);
}
@@ -510,99 +521,99 @@ parser_expect (struct parser *self, enum token token, jmp_buf out) {
// We don't need no generator, but a few macros will come in handy.
// From time to time C just doesn't have the right features.
-#define PEEK() parser_peek (self, err)
-#define ACCEPT(token) parser_accept (self, token, err)
-#define EXPECT(token) parser_expect (self, token, err)
-#define SKIP_NL() do {} while (ACCEPT (T_NEWLINE))
+#define PEEK() ell_parser_peek (p, err)
+#define ACCEPT(token) ell_parser_accept (p, token, err)
+#define EXPECT(token) ell_parser_expect (p, token, err)
+#define SKIP_NL() do {} while (ACCEPT (ELLT_NEWLINE))
-static struct item *
-parser_check (struct parser *self, struct item *item, jmp_buf out) {
- if (!item) {
- self->memory_failure = true;
+static struct ell_v *
+ell_parser_check (struct ell_parser *p, struct ell_v *v, jmp_buf out) {
+ if (!v) {
+ p->memory_failure = true;
longjmp (out, 1);
}
- return item;
+ return v;
}
// Beware that this jumps to the "out" buffer directly
-#define CHECK(item) parser_check (self, (item), out)
+#define CHECK(v) ell_parser_check (p, (v), out)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-static struct item *
-parse_prefix_list (struct item *list, const char *name) {
- struct item *prefix;
- if (!(prefix = new_string (name, strlen (name)))) {
- item_free_list (list);
+static struct ell_v *
+ell_parse_prefix_list (struct ell_v *seq, const char *name) {
+ struct ell_v *prefix;
+ if (!(prefix = ell_string (name, strlen (name)))) {
+ ell_free_seq (seq);
return NULL;
}
- prefix->next = list;
- return new_list (prefix);
+ prefix->next = seq;
+ return ell_list (prefix);
}
-static struct item * parse_line (struct parser *self, jmp_buf out);
+static struct ell_v * ell_parse_line (struct ell_parser *p, jmp_buf out);
-static struct item *
-parse_item (struct parser *self, jmp_buf out) {
+static struct ell_v *
+ell_parse_v (struct ell_parser *p, jmp_buf out) {
jmp_buf err;
- struct item *volatile result = NULL, *volatile *tail = &result;
+ struct ell_v *volatile result = NULL, *volatile *tail = &result;
if (setjmp (err)) {
- item_free_list (result);
+ ell_free_seq (result);
longjmp (out, 1);
}
SKIP_NL ();
- if (ACCEPT (T_STRING))
- return CHECK (new_string
- (self->lexer.string.s, self->lexer.string.len));
- if (ACCEPT (T_AT)) {
- result = parse_item (self, out);
- return CHECK (parse_prefix_list (result, "set"));
+ if (ACCEPT (ELLT_STRING))
+ return CHECK (ell_string
+ (p->lexer.string.s, p->lexer.string.len));
+ if (ACCEPT (ELLT_AT)) {
+ result = ell_parse_v (p, out);
+ return CHECK (ell_parse_prefix_list (result, "set"));
}
- if (ACCEPT (T_LPAREN)) {
- while (!ACCEPT (T_RPAREN)) {
- tail = &(*tail = parse_item (self, err))->next;
+ if (ACCEPT (ELLT_LPAREN)) {
+ while (!ACCEPT (ELLT_RPAREN)) {
+ tail = &(*tail = ell_parse_v (p, err))->next;
SKIP_NL ();
}
- return CHECK (new_list (result));
+ return CHECK (ell_list (result));
}
- if (ACCEPT (T_LBRACKET)) {
- while (!ACCEPT (T_RBRACKET)) {
- tail = &(*tail = parse_item (self, err))->next;
+ if (ACCEPT (ELLT_LBRACKET)) {
+ while (!ACCEPT (ELLT_RBRACKET)) {
+ tail = &(*tail = ell_parse_v (p, err))->next;
SKIP_NL ();
}
- return CHECK (parse_prefix_list (result, "list"));
+ return CHECK (ell_parse_prefix_list (result, "list"));
}
- if (ACCEPT (T_LBRACE)) {
- while ((*tail = parse_line (self, err)))
+ if (ACCEPT (ELLT_LBRACE)) {
+ while ((*tail = ell_parse_line (p, err)))
tail = &(*tail)->next;
- EXPECT (T_RBRACE);
- return CHECK (parse_prefix_list (result, "block"));
+ EXPECT (ELLT_RBRACE);
+ return CHECK (ell_parse_prefix_list (result, "block"));
}
- self->memory_failure = !(self->error = lexer_errorf (&self->lexer,
- "unexpected `%s', expected a value", token_names[self->token]));
+ p->memory_failure = !(p->error = ell_lexer_errorf (&p->lexer,
+ "unexpected `%s', expected a value", ell_token_names[p->token]));
longjmp (out, 1);
}
-static struct item *
-parse_line (struct parser *self, jmp_buf out) {
+static struct ell_v *
+ell_parse_line (struct ell_parser *p, jmp_buf out) {
jmp_buf err;
- struct item *volatile result = NULL, *volatile *tail = &result;
+ struct ell_v *volatile result = NULL, *volatile *tail = &result;
if (setjmp (err)) {
- item_free_list (result);
+ ell_free_seq (result);
longjmp (out, 1);
}
- while (PEEK () != T_RBRACE && PEEK () != T_ABORT) {
- if (!ACCEPT (T_NEWLINE)) {
- tail = &(*tail = parse_item (self, err))->next;
+ while (PEEK () != ELLT_RBRACE && PEEK () != ELLT_ABORT) {
+ if (!ACCEPT (ELLT_NEWLINE)) {
+ tail = &(*tail = ell_parse_v (p, err))->next;
} else if (result) {
- return CHECK (new_list (result));
+ return CHECK (ell_list (result));
}
}
if (result)
- return CHECK (new_list (result));
+ return CHECK (ell_list (result));
return NULL;
}
@@ -614,140 +625,140 @@ parse_line (struct parser *self, jmp_buf out) {
#undef SKIP_NL
#undef CHECK
-static struct item *
-parser_run (struct parser *self, const char **e) {
+static struct ell_v *
+ell_parser_run (struct ell_parser *p, const char **e) {
jmp_buf err;
- struct item *volatile result = NULL, *volatile *tail = &result;
+ struct ell_v *volatile result = NULL, *volatile *tail = &result;
if (setjmp (err)) {
- item_free_list (result);
- *e = self->error;
- if (self->memory_failure || self->lexer.string.memory_failure)
+ ell_free_seq (result);
+ *e = p->error;
+ if (p->memory_failure || p->lexer.string.memory_failure)
*e = "memory allocation failure";
return NULL;
}
- while ((*tail = parse_line (self, err)))
+ while ((*tail = ell_parse_line (p, err)))
tail = &(*tail)->next;
- parser_expect (self, T_ABORT, err);
+ ell_parser_expect (p, ELLT_ABORT, err);
return result;
}
// --- Runtime -----------------------------------------------------------------
-struct context {
- struct item *globals; ///< List of global variables
- struct item *scopes; ///< Dynamic scopes from newest
- struct native_fn *native; ///< Maps strings to C functions
+struct ell {
+ struct ell_v *globals; ///< List of global variables
+ struct ell_v *scopes; ///< Dynamic scopes from newest
+ struct ell_native_fn *native; ///< Maps strings to C functions
char *error; ///< Error information
bool memory_failure; ///< Memory allocation failure
void *user_data; ///< User data
};
-typedef bool (*handler_fn) (struct context *, struct item *, struct item **);
+typedef bool (*EllHandler) (struct ell *, struct ell_v *, struct ell_v **);
-struct native_fn {
- struct native_fn *next; ///< The next link in the chain
- handler_fn handler; ///< Internal C handler, or NULL
+struct ell_native_fn {
+ struct ell_native_fn *next; ///< The next link in the chain
+ EllHandler 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);
+ell_init (struct ell *ell) {
+ memset (ell, 0, sizeof *ell);
}
static void
-context_free (struct context *ctx) {
- struct native_fn *next, *iter;
- for (iter = ctx->native; iter; iter = next) {
+ell_free (struct ell *ell) {
+ struct ell_native_fn *next, *iter;
+ for (iter = ell->native; iter; iter = next) {
next = iter->next;
free (iter);
}
- item_free_list (ctx->globals);
- item_free_list (ctx->scopes);
- free (ctx->error);
+ ell_free_seq (ell->globals);
+ ell_free_seq (ell->scopes);
+ free (ell->error);
}
static bool
-check (struct context *ctx, struct item *item) {
- return !(ctx->memory_failure |= !item);
+ell_check (struct ell *ell, struct ell_v *v) {
+ return !(ell->memory_failure |= !v);
}
-static struct item **
-scope_find (struct item **scope, const char *name) {
+static struct ell_v **
+ell_scope_find (struct ell_v **scope, const char *name) {
for (; *scope; scope = &(*scope)->next)
- if (!strcmp ((*scope)->head->value, name))
+ if (!strcmp ((*scope)->head->string, name))
return scope;
return NULL;
}
static bool
-scope_prepend (struct context *ctx, struct item **scope,
- const char *name, struct item *value) {
- struct item *key, *pair;
- if (!check (ctx, (key = new_string (name, strlen (name))))
- || !check (ctx, (pair = new_list (key)))) {
- item_free_list (value);
+ell_scope_prepend (struct ell *ell, struct ell_v **scope, const char *name,
+ struct ell_v *v) {
+ struct ell_v *key, *pair;
+ if (!ell_check (ell, (key = ell_string (name, strlen (name))))
+ || !ell_check (ell, (pair = ell_list (key)))) {
+ ell_free_seq (v);
return false;
}
- key->next = value;
+ key->next = v;
pair->next = *scope;
*scope = pair;
return true;
}
-static struct item *
-get (struct context *ctx, const char *name) {
- struct item **item;
- for (struct item *scope = ctx->scopes; scope; scope = scope->next)
- if ((item = scope_find (&scope->head, name)))
- return (*item)->head->next;
- if (!(item = scope_find (&ctx->globals, name)))
+static struct ell_v *
+ell_get (struct ell *ell, const char *name) {
+ struct ell_v **place;
+ for (struct ell_v *scope = ell->scopes; scope; scope = scope->next)
+ if ((place = ell_scope_find (&scope->head, name)))
+ return (*place)->head->next;
+ if (!(place = ell_scope_find (&ell->globals, name)))
return NULL;
- return (*item)->head->next;
+ return (*place)->head->next;
}
static bool
-set (struct context *ctx, const char *name, struct item *value) {
- struct item **item;
- for (struct item *scope = ctx->scopes; scope; scope = scope->next) {
- if ((item = scope_find (&scope->head, name))) {
- item_free_list ((*item)->head->next);
- (*item)->head->next = NULL;
- return !value
- || check (ctx, ((*item)->head->next = new_clone (value)));
+ell_set (struct ell *ell, const char *name, struct ell_v *v) {
+ struct ell_v **place;
+ for (struct ell_v *scope = ell->scopes; scope; scope = scope->next) {
+ if ((place = ell_scope_find (&scope->head, name))) {
+ ell_free_seq ((*place)->head->next);
+ (*place)->head->next = NULL;
+ return !v
+ || ell_check (ell, ((*place)->head->next = ell_clone (v)));
}
}
// Variables only get deleted by "arg" or from the global scope
- if ((item = scope_find (&ctx->globals, name))) {
- struct item *tmp = *item;
- *item = (*item)->next;
- item_free (tmp);
+ if ((place = ell_scope_find (&ell->globals, name))) {
+ struct ell_v *tmp = *place;
+ *place = (*place)->next;
+ ell_free_v (tmp);
}
- return !value || scope_prepend (ctx, &ctx->globals, name, value);
+ return !v || ell_scope_prepend (ell, &ell->globals, name, v);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-static struct native_fn *
-native_find (struct context *ctx, const char *name) {
- for (struct native_fn *fn = ctx->native; fn; fn = fn->next)
+static struct ell_native_fn *
+ell_native_find (struct ell *ell, const char *name) {
+ for (struct ell_native_fn *fn = ell->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);
+ell_native_register (struct ell *ell, const char *name, EllHandler handler) {
+ struct ell_native_fn *fn = ell_native_find (ell, 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->next = ell->native;
+ ell->native = fn;
}
fn->handler = handler;
return true;
@@ -756,39 +767,39 @@ native_register (struct context *ctx, const char *name, handler_fn handler) {
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static bool
-set_error (struct context *ctx, const char *format, ...) {
+ell_error (struct ell *ell, const char *ell_format, ...) {
va_list ap;
- va_start (ap, format);
- free (ctx->error);
- if (!(ctx->error = vformat (format, ap)))
- ctx->memory_failure = true;
+ va_start (ap, ell_format);
+ free (ell->error);
+ if (!(ell->error = ell_vformat (ell_format, ap)))
+ ell->memory_failure = true;
va_end (ap);
return false;
}
static bool
-can_modify_error (struct context *ctx) {
+ell_can_modify_error (struct ell *ell) {
// In that case, `error' is NULL and there's nothing else to do anyway.
// Errors starting with an underscore are exceptions and would not work
// with stack traces generated this way.
- return !ctx->memory_failure && ctx->error[0] != '_';
+ return !ell->memory_failure && ell->error[0] != '_';
}
-static bool execute_statement (struct context *, struct item *, struct item **);
-static bool execute_block (struct context *,
- struct item *, struct item *, struct item **);
+static bool ell_eval_statement (struct ell *, struct ell_v *, struct ell_v **);
+static bool ell_eval_block
+ (struct ell *, struct ell_v *, struct ell_v *, struct ell_v **);
static bool
-execute_args (struct context *ctx, struct item *args, struct item **result) {
+ell_eval_args (struct ell *ell, struct ell_v *args, struct ell_v **result) {
size_t i = 0;
- struct item *res = NULL, **out = &res;
+ struct ell_v *res = NULL, **out = &res;
for (; args; args = args->next) {
- struct item *evaluated = NULL;
+ struct ell_v *evaluated = NULL;
// Arguments should not evaporate, default to a nil value
- if (!execute_statement (ctx, args, &evaluated)
- || (!evaluated && !check (ctx, (evaluated = new_list (NULL)))))
+ if (!ell_eval_statement (ell, args, &evaluated)
+ || (!evaluated && !ell_check (ell, (evaluated = ell_list (NULL)))))
goto error;
- item_free_list (evaluated->next);
+ ell_free_seq (evaluated->next);
evaluated->next = NULL;
out = &(*out = evaluated)->next;
i++;
@@ -798,60 +809,60 @@ execute_args (struct context *ctx, struct item *args, struct item **result) {
error:
// Once the code flows like this, at least make some use of it
- if (can_modify_error (ctx)) {
- char *tmp = ctx->error;
- ctx->error = NULL;
- set_error (ctx, "(argument %zu) -> %s", i, tmp);
+ if (ell_can_modify_error (ell)) {
+ char *tmp = ell->error;
+ ell->error = NULL;
+ ell_error (ell, "(argument %zu) -> %s", i, tmp);
free (tmp);
}
- item_free_list (res);
+ ell_free_seq (res);
return false;
}
static bool
-execute_native (struct context *ctx, const char *name, struct item *args,
- struct item **result) {
- struct native_fn *fn = native_find (ctx, name);
+ell_eval_native (struct ell *ell, const char *name, struct ell_v *args,
+ struct ell_v **result) {
+ struct ell_native_fn *fn = ell_native_find (ell, name);
if (!fn)
- return set_error (ctx, "unknown function");
+ return ell_error (ell, "unknown function");
- struct item *arguments = NULL;
- if (!execute_args (ctx, args, &arguments))
+ struct ell_v *arguments = NULL;
+ if (!ell_eval_args (ell, args, &arguments))
return false;
- bool ok = fn->handler (ctx, arguments, result);
- item_free_list (arguments);
+ bool ok = fn->handler (ell, arguments, result);
+ ell_free_seq (arguments);
return ok;
}
static bool
-execute_resolved (struct context *ctx, struct item *body, struct item *args,
- struct item **result) {
+ell_eval_resolved (struct ell *ell, struct ell_v *body, struct ell_v *args,
+ struct ell_v **result) {
// Resolving names ecursively could be pretty fatal, let's not do that
- if (body->type == ITEM_STRING)
- return check (ctx, (*result = new_clone (body)));
- struct item *arguments = NULL;
- return execute_args (ctx, args, &arguments)
- && execute_block (ctx, body->head, arguments, result);
+ if (body->type == ELL_STRING)
+ return ell_check (ell, (*result = ell_clone (body)));
+ struct ell_v *arguments = NULL;
+ return ell_eval_args (ell, args, &arguments)
+ && ell_eval_block (ell, body->head, arguments, result);
}
static bool
-execute_item (struct context *ctx, struct item *body, struct item **result) {
- struct item *args = body->next;
- if (body->type == ITEM_STRING) {
- const char *name = body->value;
+ell_eval_value (struct ell *ell, struct ell_v *body, struct ell_v **result) {
+ struct ell_v *args = body->next;
+ if (body->type == ELL_STRING) {
+ const char *name = body->string;
if (!strcmp (name, "block"))
- return (!args || check (ctx, (args = new_clone_list (args))))
- && check (ctx, (*result = new_list (args)));
- if ((body = get (ctx, name)))
- return execute_resolved (ctx, body, args, result);
- return execute_native (ctx, name, args, result);
+ return (!args || ell_check (ell, (args = ell_clone_seq (args))))
+ && ell_check (ell, (*result = ell_list (args)));
+ if ((body = ell_get (ell, name)))
+ return ell_eval_resolved (ell, body, args, result);
+ return ell_eval_native (ell, name, args, result);
}
// When someone tries to call a block directly, we must evaluate it;
// e.g. something like `{ choose [@f1 @f2 @f3] } arg1 arg2 arg3`.
- struct item *evaluated = NULL;
- if (!execute_statement (ctx, body, &evaluated))
+ struct ell_v *evaluated = NULL;
+ if (!ell_eval_statement (ell, body, &evaluated))
return false;
// It might a bit confusing that this doesn't evaluate arguments
@@ -859,102 +870,102 @@ execute_item (struct context *ctx, struct item *body, struct item **result) {
if (!evaluated)
return true;
- bool ok = execute_resolved (ctx, evaluated, args, result);
- item_free_list (evaluated);
+ bool ok = ell_eval_resolved (ell, evaluated, args, result);
+ ell_free_seq (evaluated);
return ok;
}
static bool
-execute_statement
- (struct context *ctx, struct item *statement, struct item **result) {
- if (statement->type == ITEM_STRING)
- return check (ctx, (*result = new_clone (statement)));
+ell_eval_statement
+ (struct ell *ell, struct ell_v *statement, struct ell_v **result) {
+ if (statement->type == ELL_STRING)
+ return ell_check (ell, (*result = ell_clone (statement)));
// Executing a nil value results in no value. It's not very different from
// calling a block that returns no value--it's for our callers to resolve.
if (!statement->head
- || execute_item (ctx, statement->head, result))
+ || ell_eval_value (ell, statement->head, result))
return true;
- item_free_list (*result);
+ ell_free_seq (*result);
*result = NULL;
const char *name = "(block)";
- if (statement->head->type == ITEM_STRING)
- name = statement->head->value;
+ if (statement->head->type == ELL_STRING)
+ name = statement->head->string;
- if (can_modify_error (ctx)) {
- char *tmp = ctx->error;
- ctx->error = NULL;
- set_error (ctx, "%s -> %s", name, tmp);
+ if (ell_can_modify_error (ell)) {
+ char *tmp = ell->error;
+ ell->error = NULL;
+ ell_error (ell, "%s -> %s", name, tmp);
free (tmp);
}
return false;
}
static bool
-args_to_scope (struct context *ctx, struct item *args, struct item **scope) {
- if (!check (ctx, (args = new_list (args)))
- || !scope_prepend (ctx, scope, "args", args))
+args_to_scope (struct ell *ell, struct ell_v *args, struct ell_v **scope) {
+ if (!ell_check (ell, (args = ell_list (args)))
+ || !ell_scope_prepend (ell, scope, "args", args))
return false;
size_t i = 0;
for (args = args->head; args; args = args->next) {
char buf[16] = "";
(void) snprintf (buf, sizeof buf, "%zu", ++i);
- struct item *copy = NULL;
- if ((args && !check (ctx, (copy = new_clone (args))))
- || !scope_prepend (ctx, scope, buf, copy))
+ struct ell_v *copy = NULL;
+ if ((args && !ell_check (ell, (copy = ell_clone (args))))
+ || !ell_scope_prepend (ell, scope, buf, copy))
return false;
}
- return check (ctx, (*scope = new_list (*scope)));
+ return ell_check (ell, (*scope = ell_list (*scope)));
}
/// Execute a block and return whatever the last statement returned, eats args
static bool
-execute_block (struct context *ctx, struct item *body, struct item *args,
- struct item **result) {
- struct item *scope = NULL;
- if (!args_to_scope (ctx, args, &scope)) {
- item_free_list (scope);
+ell_eval_block (struct ell *ell, struct ell_v *body, struct ell_v *args,
+ struct ell_v **result) {
+ struct ell_v *scope = NULL;
+ if (!args_to_scope (ell, args, &scope)) {
+ ell_free_seq (scope);
return false;
}
- scope->next = ctx->scopes;
- ctx->scopes = scope;
+ scope->next = ell->scopes;
+ ell->scopes = scope;
bool ok = true;
for (; body; body = body->next) {
- item_free_list (*result);
+ ell_free_seq (*result);
*result = NULL;
- if (!(ok = execute_statement (ctx, body, result)))
+ if (!(ok = ell_eval_statement (ell, body, result)))
break;
}
- ctx->scopes = scope->next;
- item_free (scope);
+ ell->scopes = scope->next;
+ ell_free_v (scope);
return ok;
}
-// --- Runtime library ---------------------------------------------------------
+// --- Standard library --------------------------------------------------------
-#define defn(name) static bool name \
- (struct context *ctx, struct item *args, struct item **result)
+#define ell_defn(name) static bool name \
+ (struct ell *ell, struct ell_v *args, struct ell_v **result)
static bool
-execute_any (struct context *ctx, struct item *body, struct item *arg,
- struct item **result) {
- if (body->type == ITEM_STRING)
- return check (ctx, (*result = new_clone (body)));
- if (arg && !check (ctx, (arg = new_clone (arg))))
+ell_eval_any (struct ell *ell, struct ell_v *body, struct ell_v *arg,
+ struct ell_v **result) {
+ if (body->type == ELL_STRING)
+ return ell_check (ell, (*result = ell_clone (body)));
+ if (arg && !ell_check (ell, (arg = ell_clone (arg))))
return false;
- return execute_block (ctx, body->head, arg, result);
+ return ell_eval_block (ell, body->head, arg, result);
}
-static struct item *
-new_number (double n) {
+static struct ell_v *
+ell_number (double n) {
char *s;
- if (!(s = format ("%f", n)))
+ if (!(s = ell_format ("%f", n)))
return NULL;
char *p = strchr (s, 0);
@@ -963,34 +974,30 @@ new_number (double n) {
if (*p == '.')
*p = 0;
- struct item *item = new_string (s, strlen (s));
+ struct ell_v *v = ell_string (s, strlen (s));
free (s);
- return item;
+ return v;
}
-static bool
-truthy (struct item *item) {
- return item && (item->head || item->len);
-}
-
-static struct item * new_boolean (bool b) { return new_string ("1", b); }
+static bool ell_truthy (struct ell_v *v) { return v && (v->head || v->len); }
+static struct ell_v * ell_boolean (bool b) { return ell_string ("1", b); }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-defn (fn_local) {
- struct item *names = args;
- if (!names || names->type != ITEM_LIST)
- return set_error (ctx, "first argument must be a list");
+ell_defn (ell_fn_local) {
+ struct ell_v *names = args;
+ if (!names || names->type != ELL_LIST)
+ return ell_error (ell, "first argument must be a list");
// Duplicates or non-strings don't really matter to us, user's problem
- struct item **scope = &ctx->scopes->head;
+ struct ell_v **scope = &ell->scopes->head;
(void) result;
- struct item *values = names->next;
+ struct ell_v *values = names->next;
for (names = names->head; names; names = names->next) {
- struct item *value = NULL;
- if ((values && !check (ctx, (value = new_clone (values))))
- || !scope_prepend (ctx, scope, names->value, value))
+ struct ell_v *value = NULL;
+ if ((values && !ell_check (ell, (value = ell_clone (values))))
+ || !ell_scope_prepend (ell, scope, names->string, value))
return false;
if (values)
values = values->next;
@@ -998,317 +1005,346 @@ defn (fn_local) {
return true;
}
-defn (fn_set) {
- struct item *name = args;
- if (!name || name->type != ITEM_STRING)
- return set_error (ctx, "first argument must be string");
+ell_defn (ell_fn_set) {
+ struct ell_v *name = args;
+ if (!name || name->type != ELL_STRING)
+ return ell_error (ell, "first argument must be string");
- struct item *value;
- if ((value = name->next))
- return check (ctx, (value = new_clone (value)))
- && check (ctx, (*result = new_clone (value)))
- && set (ctx, name->value, value);
+ struct ell_v *v;
+ if ((v = name->next))
+ return ell_check (ell, (v = ell_clone (v)))
+ && ell_check (ell, (*result = ell_clone (v)))
+ && ell_set (ell, name->string, v);
// We return an empty list for a nil value
- if (!(value = get (ctx, name->value)))
- return check (ctx, (*result = new_list (NULL)));
- return check (ctx, (*result = new_clone (value)));
+ if (!(v = ell_get (ell, name->string)))
+ return ell_check (ell, (*result = ell_list (NULL)));
+ return ell_check (ell, (*result = ell_clone (v)));
}
-defn (fn_list) {
- struct item *values = NULL;
- if (args && !check (ctx, (values = new_clone_list (args))))
+ell_defn (ell_fn_list) {
+ struct ell_v *values = NULL;
+ if (args && !ell_check (ell, (values = ell_clone_seq (args))))
return false;
- return check (ctx, (*result = new_list (values)));
+ return ell_check (ell, (*result = ell_list (values)));
}
-defn (fn_values) {
- return !args || check (ctx, (*result = new_clone_list (args)));
+ell_defn (ell_fn_values) {
+ return !args || ell_check (ell, (*result = ell_clone_seq (args)));
}
-defn (fn_if) {
- struct item *cond, *body, *keyword;
+ell_defn (ell_fn_if) {
+ struct ell_v *cond, *body, *keyword;
for (cond = args; ; cond = keyword->next) {
if (!cond)
- return set_error (ctx, "missing condition");
+ return ell_error (ell, "missing condition");
if (!(body = cond->next))
- return set_error (ctx, "missing body");
+ return ell_error (ell, "missing body");
- struct item *res = NULL;
- if (!execute_any (ctx, cond, NULL, &res))
+ struct ell_v *res = NULL;
+ if (!ell_eval_any (ell, cond, NULL, &res))
return false;
- bool match = truthy (res);
- item_free_list (res);
+ bool match = ell_truthy (res);
+ ell_free_seq (res);
if (match)
- return execute_any (ctx, body, NULL, result);
+ return ell_eval_any (ell, body, NULL, result);
if (!(keyword = body->next))
break;
- if (keyword->type != ITEM_STRING)
- return set_error (ctx, "expected keyword, got list");
+ if (keyword->type != ELL_STRING)
+ return ell_error (ell, "expected keyword, got list");
- if (!strcmp (keyword->value, "else")) {
+ if (!strcmp (keyword->string, "else")) {
if (!(body = keyword->next))
- return set_error (ctx, "missing body");
- return execute_any (ctx, body, NULL, result);
+ return ell_error (ell, "missing body");
+ return ell_eval_any (ell, body, NULL, result);
}
- if (strcmp (keyword->value, "elif"))
- return set_error (ctx, "invalid keyword: %s", keyword->value);
+ if (strcmp (keyword->string, "elif"))
+ return ell_error (ell, "invalid keyword: %s", keyword->string);
}
return true;
}
-defn (fn_map) {
- struct item *body, *values;
+ell_defn (ell_fn_map) {
+ struct ell_v *body, *values;
if (!(body = args))
- return set_error (ctx, "first argument must be a function");
- if (!(values = body->next) || values->type != ITEM_LIST)
- return set_error (ctx, "second argument must be a list");
-
- struct item *res = NULL, **out = &res;
- for (struct item *v = values->head; v; v = v->next) {
- if (!execute_any (ctx, body, v, out)) {
- item_free_list (res);
+ return ell_error (ell, "first argument must be a function");
+ if (!(values = body->next) || values->type != ELL_LIST)
+ return ell_error (ell, "second argument must be a list");
+
+ struct ell_v *res = NULL, **out = &res;
+ for (struct ell_v *v = values->head; v; v = v->next) {
+ if (!ell_eval_any (ell, body, v, out)) {
+ ell_free_seq (res);
return false;
}
while (*out)
out = &(*out)->next;
}
- return check (ctx, (*result = new_list (res)));
+ return ell_check (ell, (*result = ell_list (res)));
}
-defn (fn_print) {
+ell_defn (ell_fn_print) {
(void) result;
for (; args; args = args->next) {
- if (args->type != ITEM_STRING)
- print_item (args);
- else if (fwrite (args->value, 1, args->len, stdout) != args->len)
- return set_error (ctx, "write failed: %s", strerror (errno));
+ if (args->type != ELL_STRING)
+ ell_print_v (args);
+ else if (fwrite (args->string, 1, args->len, stdout) != args->len)
+ return ell_error (ell, "write failed: %s", strerror (errno));
}
return true;
}
-defn (fn_concatenate) {
- struct buffer buf = BUFFER_INITIALIZER;
+ell_defn (ell_fn_cat) {
+ struct ell_buffer buf = ELL_BUFFER_INITIALIZER;
for (; args; args = args->next) {
- if (args->type != ITEM_STRING) {
+ if (args->type != ELL_STRING) {
free (buf.s);
- return set_error (ctx, "cannot concatenate lists");
+ return ell_error (ell, "cannot concatenate lists");
}
- buffer_append (&buf, args->value, args->len);
+ ell_buffer_append (&buf, args->string, args->len);
}
- bool ok = !(ctx->memory_failure |= buf.memory_failure)
- && check (ctx, (*result = new_string (buf.s, buf.len)));
+ bool ok = !(ell->memory_failure |= buf.memory_failure)
+ && ell_check (ell, (*result = ell_string (buf.s, buf.len)));
free (buf.s);
return ok;
}
-defn (fn_system) {
- struct item *command = args;
- if (!command || command->type != ITEM_STRING)
- return set_error (ctx, "first argument must be string");
+ell_defn (ell_fn_system) {
+ struct ell_v *command = args;
+ if (!command || command->type != ELL_STRING)
+ return ell_error (ell, "first argument must be string");
if (command->next)
- return set_error (ctx, "cannot deal with multiple arguments");
- return check (ctx, (*result = new_number (system (command->value))));
+ return ell_error (ell, "cannot deal with multiple arguments");
+ return ell_check (ell, (*result = ell_number (system (command->string))));
}
-defn (fn_parse) {
- struct item *body = args;
- if (!body || body->type != ITEM_STRING)
- return set_error (ctx, "first argument must be string");
+ell_defn (ell_fn_parse) {
+ struct ell_v *body = args;
+ if (!body || body->type != ELL_STRING)
+ return ell_error (ell, "first argument must be string");
- struct parser parser;
- parser_init (&parser, args->value, args->len);
+ struct ell_parser p;
+ ell_parser_init (&p, args->string, args->len);
const char *e = NULL;
- bool ok = check (ctx, (*result = new_list (parser_run (&parser, &e))));
+ bool ok = ell_check (ell, (*result = ell_list (ell_parser_run (&p, &e))));
if (e)
- ok = set_error (ctx, "%s", e);
- parser_free (&parser);
+ ok = ell_error (ell, "%s", e);
+ ell_parser_free (&p);
return ok;
}
-defn (fn_try) {
- struct item *body, *handler;
+ell_defn (ell_fn_try) {
+ struct ell_v *body, *handler;
if (!(body = args))
- return set_error (ctx, "first argument must be a function");
+ return ell_error (ell, "first argument must be a function");
if (!(handler = body->next))
- return set_error (ctx, "second argument must be a function");
- if (execute_any (ctx, body, NULL, result))
+ return ell_error (ell, "second argument must be a function");
+ if (ell_eval_any (ell, body, NULL, result))
return true;
- struct item *message;
- if (ctx->memory_failure
- || !check (ctx, (message = new_string (ctx->error, strlen (ctx->error)))))
+ struct ell_v *msg;
+ if (ell->memory_failure
+ || !ell_check (ell, (msg = ell_string (ell->error, strlen (ell->error)))))
return false;
- free (ctx->error); ctx->error = NULL;
- item_free_list (*result); *result = NULL;
+ free (ell->error); ell->error = NULL;
+ ell_free_seq (*result); *result = NULL;
- bool ok = execute_any (ctx, handler, message, result);
- item_free (message);
+ bool ok = ell_eval_any (ell, handler, msg, result);
+ ell_free_v (msg);
return ok;
}
-defn (fn_throw) {
+ell_defn (ell_fn_throw) {
(void) result;
- struct item *message = args;
- if (!message || message->type != ITEM_STRING)
- return set_error (ctx, "first argument must be string");
- return set_error (ctx, message->value);
+ struct ell_v *message = args;
+ if (!message || message->type != ELL_STRING)
+ return ell_error (ell, "first argument must be string");
+ return ell_error (ell, message->string);
}
-defn (fn_plus) {
+ell_defn (ell_fn_plus) {
double res = 0.0;
for (; args; args = args->next) {
- if (args->type != ITEM_STRING)
- return set_error (ctx, "arguments must be strings");
- res += strtod (args->value, NULL);
+ if (args->type != ELL_STRING)
+ return ell_error (ell, "arguments must be strings");
+ res += strtod (args->string, NULL);
}
- return check (ctx, (*result = new_number (res)));
+ return ell_check (ell, (*result = ell_number (res)));
}
-defn (fn_minus) {
- if (!args || args->type != ITEM_STRING)
- return set_error (ctx, "first argument must be string");
- double res = strtod (args->value, NULL);
+ell_defn (ell_fn_minus) {
+ if (!args || args->type != ELL_STRING)
+ return ell_error (ell, "first argument must be string");
+ double res = strtod (args->string, NULL);
if (!(args = args->next))
res = -res;
for (; args; args = args->next) {
- if (args->type != ITEM_STRING)
- return set_error (ctx, "arguments must be strings");
- res -= strtod (args->value, NULL);
+ if (args->type != ELL_STRING)
+ return ell_error (ell, "arguments must be strings");
+ res -= strtod (args->string, NULL);
}
- return check (ctx, (*result = new_number (res)));
+ return ell_check (ell, (*result = ell_number (res)));
}
-defn (fn_multiply) {
+ell_defn (ell_fn_multiply) {
double res = 1.0;
for (; args; args = args->next) {
- if (args->type != ITEM_STRING)
- return set_error (ctx, "arguments must be strings");
- res *= strtod (args->value, NULL);
+ if (args->type != ELL_STRING)
+ return ell_error (ell, "arguments must be strings");
+ res *= strtod (args->string, NULL);
}
- return check (ctx, (*result = new_number (res)));
+ return ell_check (ell, (*result = ell_number (res)));
}
-defn (fn_divide) {
- if (!args || args->type != ITEM_STRING)
- return set_error (ctx, "first argument must be string");
- double res = strtod (args->value, NULL), x;
+ell_defn (ell_fn_divide) {
+ if (!args || args->type != ELL_STRING)
+ return ell_error (ell, "first argument must be string");
+ double res = strtod (args->string, NULL), x;
for (args = args->next; args; args = args->next) {
- if (args->type != ITEM_STRING)
- return set_error (ctx, "arguments must be strings");
- if (!(x = strtod (args->value, NULL)))
- return set_error (ctx, "division by zero");
+ if (args->type != ELL_STRING)
+ return ell_error (ell, "arguments must be strings");
+ if (!(x = strtod (args->string, NULL)))
+ return ell_error (ell, "division by zero");
res /= x;
}
- return check (ctx, (*result = new_number (res)));
+ return ell_check (ell, (*result = ell_number (res)));
}
-defn (fn_not) {
+ell_defn (ell_fn_not) {
if (!args)
- return set_error (ctx, "missing argument");
- return check (ctx, (*result = new_boolean (!truthy (args))));
+ return ell_error (ell, "missing argument");
+ return ell_check (ell, (*result = ell_boolean (!ell_truthy (args))));
}
-defn (fn_and) {
+ell_defn (ell_fn_and) {
if (!args)
- return check (ctx, (*result = new_boolean (true)));
+ return ell_check (ell, (*result = ell_boolean (true)));
for (; args; args = args->next) {
- item_free_list (*result);
+ ell_free_seq (*result);
*result = NULL;
- if (!execute_any (ctx, args, NULL, result))
+ if (!ell_eval_any (ell, args, NULL, result))
return false;
- if (!truthy (*result))
- return check (ctx, (*result = new_boolean (false)));
+ if (!ell_truthy (*result))
+ return ell_check (ell, (*result = ell_boolean (false)));
}
return true;
}
-defn (fn_or) {
+ell_defn (ell_fn_or) {
for (; args; args = args->next) {
- if (!execute_any (ctx, args, NULL, result))
+ if (!ell_eval_any (ell, args, NULL, result))
return false;
- if (truthy (*result))
+ if (ell_truthy (*result))
return true;
- item_free_list (*result);
+ ell_free_seq (*result);
*result = NULL;
}
- return check (ctx, (*result = new_boolean (false)));
+ return ell_check (ell, (*result = ell_boolean (false)));
}
-defn (fn_eq) {
- struct item *etalon = args;
- if (!etalon || etalon->type != ITEM_STRING)
- return set_error (ctx, "first argument must be string");
+ell_defn (ell_fn_eq) {
+ struct ell_v *etalon = args;
+ if (!etalon || etalon->type != ELL_STRING)
+ return ell_error (ell, "first argument must be string");
bool res = true;
for (args = etalon->next; args; args = args->next) {
- if (args->type != ITEM_STRING)
- return set_error (ctx, "arguments must be strings");
- if (!(res &= !strcmp (etalon->value, args->value)))
+ if (args->type != ELL_STRING)
+ return ell_error (ell, "arguments must be strings");
+ if (!(res &= !strcmp (etalon->string, args->string)))
break;
}
- return check (ctx, (*result = new_boolean (res)));
+ return ell_check (ell, (*result = ell_boolean (res)));
}
-defn (fn_lt) {
- struct item *etalon = args;
- if (!etalon || etalon->type != ITEM_STRING)
- return set_error (ctx, "first argument must be string");
+ell_defn (ell_fn_lt) {
+ struct ell_v *etalon = args;
+ if (!etalon || etalon->type != ELL_STRING)
+ return ell_error (ell, "first argument must be string");
bool res = true;
for (args = etalon->next; args; args = args->next) {
- if (args->type != ITEM_STRING)
- return set_error (ctx, "arguments must be strings");
- if (!(res &= strcmp (etalon->value, args->value) < 0))
+ if (args->type != ELL_STRING)
+ return ell_error (ell, "arguments must be strings");
+ if (!(res &= strcmp (etalon->string, args->string) < 0))
break;
etalon = args;
}
- return check (ctx, (*result = new_boolean (res)));
+ return ell_check (ell, (*result = ell_boolean (res)));
}
-defn (fn_equals) {
- struct item *etalon = args;
- if (!etalon || etalon->type != ITEM_STRING)
- return set_error (ctx, "first argument must be string");
+ell_defn (ell_fn_equals) {
+ struct ell_v *etalon = args;
+ if (!etalon || etalon->type != ELL_STRING)
+ return ell_error (ell, "first argument must be string");
bool res = true;
for (args = etalon->next; args; args = args->next) {
- if (args->type != ITEM_STRING)
- return set_error (ctx, "arguments must be strings");
- if (!(res &= strtod (etalon->value, NULL)
- == strtod (args->value, NULL)))
+ if (args->type != ELL_STRING)
+ return ell_error (ell, "arguments must be strings");
+ if (!(res &= strtod (etalon->string, NULL)
+ == strtod (args->string, NULL)))
break;
}
- return check (ctx, (*result = new_boolean (res)));
+ return ell_check (ell, (*result = ell_boolean (res)));
}
-defn (fn_less) {
- struct item *etalon = args;
- if (!etalon || etalon->type != ITEM_STRING)
- return set_error (ctx, "first argument must be string");
+ell_defn (ell_fn_less) {
+ struct ell_v *etalon = args;
+ if (!etalon || etalon->type != ELL_STRING)
+ return ell_error (ell, "first argument must be string");
bool res = true;
for (args = etalon->next; args; args = args->next) {
- if (args->type != ITEM_STRING)
- return set_error (ctx, "arguments must be strings");
- if (!(res &= strtod (etalon->value, NULL) < strtod (args->value, NULL)))
+ if (args->type != ELL_STRING)
+ return ell_error (ell, "arguments must be strings");
+ if (!(res &= strtod (etalon->string, NULL)
+ < strtod (args->string, NULL)))
break;
etalon = args;
}
- return check (ctx, (*result = new_boolean (res)));
+ return ell_check (ell, (*result = ell_boolean (res)));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-const char init_program[] =
+static struct ell_handler_pair {
+ const char *name; ///< Name of function
+ EllHandler handler; ///< Handler for the function
+} ell_std_native[] = {
+ { "local", ell_fn_local },
+ { "set", ell_fn_set },
+ { "list", ell_fn_list },
+ { "values", ell_fn_values },
+ { "if", ell_fn_if },
+ { "map", ell_fn_map },
+ { "print", ell_fn_print },
+ { "..", ell_fn_cat },
+ { "system", ell_fn_system },
+ { "parse", ell_fn_parse },
+ { "try", ell_fn_try },
+ { "throw", ell_fn_throw },
+ { "+", ell_fn_plus },
+ { "-", ell_fn_minus },
+ { "*", ell_fn_multiply },
+ { "/", ell_fn_divide },
+ { "not", ell_fn_not },
+ { "and", ell_fn_and },
+ { "or", ell_fn_or },
+ { "eq?", ell_fn_eq },
+ { "lt?", ell_fn_lt },
+ { "=", ell_fn_equals },
+ { "<", ell_fn_less },
+};
+
+const char ell_std_composed[] =
"set unless { if (not (@1)) @2 }\n"
- "set filter { local [_body _list] @1 @2\n"
- " map { if (@_body @1) { @1 } } @_list }\n"
- "set for { local [_list _body] @1 @2\n"
- " try { map { @_body @1 } @_list } {\n"
- " if (ne? @1 _break) { throw @1 } } }\n"
+ "set filter { local [_body _list] @1 @2;"
+ " map { if (@_body @1) { @1 } } @_list }\n"
+ "set for { local [_list _body] @1 @2;"
+ " try { map { @_body @1 } @_list } { if (ne? @1 _break) { throw @1 } } }\n"
"set break { throw _break }\n"
// TODO: we should be able to apply them to all arguments
@@ -1318,41 +1354,22 @@ const char init_program[] =
"set >= { not (< @1 @2) }\n" "set > { < @2 @1 }\n";
static bool
-init_runtime_library (struct context *ctx) {
- if (!native_register (ctx, "local", fn_local)
- || !native_register (ctx, "set", fn_set)
- || !native_register (ctx, "list", fn_list)
- || !native_register (ctx, "values", fn_values)
- || !native_register (ctx, "if", fn_if)
- || !native_register (ctx, "map", fn_map)
- || !native_register (ctx, "print", fn_print)
- || !native_register (ctx, "..", fn_concatenate)
- || !native_register (ctx, "system", fn_system)
- || !native_register (ctx, "parse", fn_parse)
- || !native_register (ctx, "try", fn_try)
- || !native_register (ctx, "throw", fn_throw)
- || !native_register (ctx, "+", fn_plus)
- || !native_register (ctx, "-", fn_minus)
- || !native_register (ctx, "*", fn_multiply)
- || !native_register (ctx, "/", fn_divide)
- || !native_register (ctx, "not", fn_not)
- || !native_register (ctx, "and", fn_and)
- || !native_register (ctx, "or", fn_or)
- || !native_register (ctx, "eq?", fn_eq)
- || !native_register (ctx, "lt?", fn_lt)
- || !native_register (ctx, "=", fn_equals)
- || !native_register (ctx, "<", fn_less))
- return false;
+ell_std_initialize (struct ell *ell) {
+ for (size_t i = 0; i < ELL_N_ELEMENTS (ell_std_native); i++) {
+ struct ell_handler_pair *pair = &ell_std_native[i];
+ if (!ell_native_register (ell, pair->name, pair->handler))
+ return false;
+ }
- struct parser parser;
- parser_init (&parser, init_program, sizeof init_program);
+ struct ell_parser p;
+ ell_parser_init (&p, ell_std_composed, sizeof ell_std_composed);
const char *e = NULL;
- struct item *result = NULL;
- struct item *program = parser_run (&parser, &e);
- bool ok = !e && execute_block (ctx, program, NULL, &result);
- parser_free (&parser);
- item_free_list (program);
- item_free_list (result);
+ struct ell_v *result = NULL;
+ struct ell_v *program = ell_parser_run (&p, &e);
+ bool ok = !e && ell_eval_block (ell, program, NULL, &result);
+ ell_parser_free (&p);
+ ell_free_seq (program);
+ ell_free_seq (result);
return ok;
}
diff --git a/interpreter.c b/interpreter.c
index 7be4fc7..c87e0ce 100644
--- a/interpreter.c
+++ b/interpreter.c
@@ -28,44 +28,44 @@ main (int argc, char *argv[]) {
}
int c;
- struct buffer buf = BUFFER_INITIALIZER;
+ struct ell_buffer buf = ELL_BUFFER_INITIALIZER;
while ((c = fgetc (fp)) != EOF)
- buffer_append_c (&buf, c);
- buffer_append_c (&buf, 0);
+ ell_buffer_append_c (&buf, c);
+ ell_buffer_append_c (&buf, 0);
fclose (fp);
- struct parser parser;
- parser_init (&parser, buf.s, buf.len - 1);
+ struct ell_parser p;
+ ell_parser_init (&p, buf.s, buf.len - 1);
const char *e = NULL;
- struct item *program = parser_run (&parser, &e);
+ struct ell_v *program = ell_parser_run (&p, &e);
free (buf.s);
if (e) {
printf ("%s: %s\n", "parse error", e);
return 1;
}
- parser_free (&parser);
+ ell_parser_free (&p);
- struct context ctx;
- context_init (&ctx);
- if (!init_runtime_library (&ctx))
+ struct ell ell;
+ ell_init (&ell);
+ if (!ell_std_initialize (&ell))
printf ("%s\n", "runtime library initialization failed");
// In this one place we optimistically expect allocation to succeed
- struct item *args = NULL, **tail = &args;
+ struct ell_v *args = NULL, **tail = &args;
for (int i = 2; i < argc; i++)
- tail = &(*tail = new_string (argv[i], strlen (argv[i])))->next;
+ tail = &(*tail = ell_string (argv[i], strlen (argv[i])))->next;
- struct item *result = NULL;
- (void) execute_block (&ctx, program, args, &result);
- item_free_list (result);
- item_free_list (program);
+ struct ell_v *result = NULL;
+ (void) ell_eval_block (&ell, program, args, &result);
+ ell_free_seq (result);
+ ell_free_seq (program);
- const char *failure = ctx.error;
- if (ctx.memory_failure)
+ const char *failure = ell.error;
+ if (ell.memory_failure)
failure = "memory allocation failure";
if (failure)
printf ("%s: %s\n", "runtime error", failure);
- context_free (&ctx);
+ ell_free (&ell);
return 0;
}
diff --git a/repl.c b/repl.c
index fd204b0..03d832a 100644
--- a/repl.c
+++ b/repl.c
@@ -22,23 +22,23 @@
#include <readline/history.h>
static void
-run (struct context *ctx, struct item *program) {
- struct item *result = NULL;
- (void) execute_block (ctx, program, NULL, &result);
- item_free_list (program);
+run (struct ell *ell, struct ell_v *program) {
+ struct ell_v *result = NULL;
+ (void) ell_eval_block (ell, program, NULL, &result);
+ ell_free_seq (program);
- const char *failure = ctx->error;
- if (ctx->memory_failure)
+ const char *failure = ell->error;
+ if (ell->memory_failure)
failure = "memory allocation failure";
if (failure) {
printf ("\x1b[31m%s: %s\x1b[0m\n", "runtime error", failure);
- free (ctx->error);
- ctx->error = NULL;
- ctx->memory_failure = false;
+ free (ell->error);
+ ell->error = NULL;
+ ell->memory_failure = false;
} else {
- print_item_list (result);
+ ell_print_seq (result);
putchar ('\n');
- item_free_list (result);
+ ell_free_seq (result);
}
}
@@ -49,7 +49,7 @@ init_readline (void) {
return 0;
}
-struct context ctx;
+static struct ell ell;
static char **
complete (const char *text, int start, int end) {
@@ -61,18 +61,18 @@ complete (const char *text, int start, int end) {
static char *buf[128];
size_t n = 1, len = strlen (text);
- for (struct item *item = ctx.globals; item; item = item->next)
- if (n < 127 && !strncmp (item->head->value, text, len))
- buf[n++] = format ("%s", item->head->value);
- for (struct native_fn *iter = ctx.native; iter; iter = iter->next)
+ for (struct ell_v *v = ell.globals; v; v = v->next)
+ if (n < 127 && !strncmp (v->head->string, text, len))
+ buf[n++] = ell_format ("%s", v->head->string);
+ for (struct ell_native_fn *iter = ell.native; iter; iter = iter->next)
if (n < 127 && !strncmp (iter->name, text, len))
- buf[n++] = format ("%s", iter->name);
+ buf[n++] = ell_format ("%s", iter->name);
if (n < 2)
return NULL;
// This never actually completes anything, just shows the options,
// we'd have to figure out the longest common prefix
- buf[0] = format ("%s", text);
+ buf[0] = ell_format ("%s", text);
buf[n++] = NULL;
char **copy = malloc (sizeof *buf * n);
@@ -84,8 +84,8 @@ int
main (int argc, char *argv[]) {
(void) argc;
- context_init (&ctx);
- if (!init_runtime_library (&ctx))
+ ell_init (&ell);
+ if (!ell_std_initialize (&ell))
printf ("%s\n", "runtime library initialization failed");
using_history ();
@@ -96,21 +96,21 @@ main (int argc, char *argv[]) {
char *line;
while ((line = readline ("> "))) {
- struct parser parser;
- parser_init (&parser, line, strlen (line));
+ struct ell_parser p;
+ ell_parser_init (&p, line, strlen (line));
add_history (line);
const char *e = NULL;
- struct item *program = parser_run (&parser, &e);
+ struct ell_v *program = ell_parser_run (&p, &e);
free (line);
if (e)
printf ("\x1b[31m%s: %s\x1b[0m\n", "parse error", e);
else
- run (&ctx, program);
- parser_free (&parser);
+ run (&ell, program);
+ ell_parser_free (&p);
}
putchar ('\n');
- context_free (&ctx);
+ ell_free (&ell);
return 0;
}