aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.adoc33
-rw-r--r--ell.c16
2 files changed, 27 insertions, 22 deletions
diff --git a/README.adoc b/README.adoc
index c091259..0cb914c 100644
--- a/README.adoc
+++ b/README.adoc
@@ -25,8 +25,8 @@ The parser, however, does a bunch of transformations:
* `[a b c]` makes a call to `(list a b c)`;
* `@var` is a shorthand for `(set var)`;
* `{ code }` is the most complex one. Each line within the curly braces is
- wrapped in parentheses, and the resulting list is quoted, so that it doesn't
- execute immediately.
+ wrapped in parentheses, and the resulting sequence is wrapped in a quoted
+ list, so that it doesn't execute immediately.
As an example, consider the following snippet:
@@ -38,13 +38,13 @@ As an example, consider the following snippet:
which gets expanded to the following:
- ((print (if (quote ((eq? (set var) foo)))
- (quote ((values 'Hello world\n')))
+ ((print (if (block (eq? (set var) foo))
+ (block (values 'Hello world\n'))
else
- (quote ((values 'Error\n'))))))
+ (block (values 'Error\n')))))
Observe that the whole program is enclosed in an implicit pair of `{}` and that
-`quote` is a very powerful special form which can replace many others if needed.
+`block` is all that's left of special forms.
For a slightly more realistic example you can have a look at 'greet.ell'.
@@ -55,20 +55,27 @@ of lists) are assigned to local variables named `1`, `2`, etc., and the full
list of them is stored in `args`.
When evaluating a command, the first argument is typically a string with its
-name and it is resolved as if `set` was called on it.
+name and it is resolved as if `set` was called on it. Lists are left for
+execution as they are.
The last expression in a block is the return value.
Special Forms
-------------
-`quote [<arg>]...`
+`block [<arg>]...`
-Like `values` but returns the arguments without any evaluation.
+Like `list` but doesn't evaluate arguments. A more appropriate name might be
+`quoted-list`, which is not as descriptive in terms of syntax. If simple
+quoting is desired, the list can be unpacked by an ordinary command.
-Standard library
+Standard Library
----------------
The standard library interprets the empty list and the empty string as false
-values, everything else is taken as true.
+values, everything else is considered true. Numbers are floating point with
+double precision, trailing zeroes are truncated.
+
+Where a `<body>` is expected, strings retain their value, and block evaluation
+is postponed as necessary.
`local <names> [<value>]...`
@@ -89,7 +96,7 @@ Return an arbitrary number of values.
`if <cond> <body> [elif <cond> <body>]... [else <body>]`
-Conditional evaluation, strings evaluate to themselves.
+Conditional evaluation.
`for <list> <body>`
@@ -129,7 +136,7 @@ Execute the body and pass any error to the handler instead of propagating it.
`throw <message>`
-Throw an error. Messages starting on an underscore don't generate backtraces
+Throw an error. Messages starting on an underscore don't generate backtraces,
which can be used to catch them.
`not <value>`
diff --git a/ell.c b/ell.c
index a3a6e34..e9b5beb 100644
--- a/ell.c
+++ b/ell.c
@@ -383,12 +383,10 @@ print_string (struct item *s) {
static bool
print_block (struct item *list) {
- if (!list->head || strcmp (list->head->value, "quote")
- || !list->head->next || list->head->next->next
- || list->head->next->type != ITEM_LIST)
+ if (!list->head || strcmp (list->head->value, "block"))
return false;
- list = list->head->next->head;
+ list = list->head->next;
for (struct item *line = list; line; line = line->next)
if (line->type != ITEM_LIST)
return false;
@@ -579,8 +577,7 @@ parse_item (struct parser *self, jmp_buf out) {
while ((*tail = parse_line (self, err)))
tail = &(*tail)->next;
EXPECT (T_RBRACE);
- result = CHECK (new_list (result));
- return CHECK (parse_prefix_list (result, "quote"));
+ return CHECK (parse_prefix_list (result, "block"));
}
self->memory_failure = !(self->error = lexer_errorf (&self->lexer,
@@ -843,8 +840,9 @@ 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;
- if (!strcmp (name, "quote"))
- return !args || check (ctx, (*result = new_clone_list (args)));
+ 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);
@@ -857,7 +855,7 @@ execute_item (struct context *ctx, struct item *body, struct item **result) {
return false;
// It might a bit confusing that this doesn't evaluate arguments
- // but neither does "quote" and there's nothing to do here
+ // but neither does "block" and there's nothing to do here
if (!evaluated)
return true;