diff options
author | Přemysl Janouch <p.janouch@gmail.com> | 2017-05-30 01:04:03 +0200 |
---|---|---|
committer | Přemysl Janouch <p.janouch@gmail.com> | 2017-05-30 01:04:03 +0200 |
commit | d579e68051ac757c530f753b02fbf18ed1aa41b3 (patch) | |
tree | 5585e625d8e77d66fdaf9fa1678ea59759fc95af | |
parent | 4698e522cc1182244a1b509d17a29b1cbdcba443 (diff) | |
download | ell-d579e68051ac757c530f753b02fbf18ed1aa41b3.tar.gz ell-d579e68051ac757c530f753b02fbf18ed1aa41b3.tar.xz ell-d579e68051ac757c530f753b02fbf18ed1aa41b3.zip |
"quote" -> "block"
Update README accordingly.
-rw-r--r-- | README.adoc | 33 | ||||
-rw-r--r-- | ell.c | 16 |
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>` @@ -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; |