summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-12-14 12:14:56 -0800
committerKaz Kylheku <kaz@kylheku.com>2011-12-14 12:14:56 -0800
commit535e853d369f49f8b45e35cd21dd2f7495445429 (patch)
tree3649e9f6ede9d9dc6a17ae94603a178ccabd991d
parent2353d721c0a48ace406ad955ab02cb90a52bde11 (diff)
downloadtxr-535e853d369f49f8b45e35cd21dd2f7495445429.tar.gz
txr-535e853d369f49f8b45e35cd21dd2f7495445429.tar.bz2
txr-535e853d369f49f8b45e35cd21dd2f7495445429.zip
* eval.c (op_dohash): Esbatlish anonymous block.
* txr.1: Finished documenting special operators.
-rw-r--r--ChangeLog6
-rw-r--r--eval.c8
-rw-r--r--txr.1157
3 files changed, 167 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index ef0a08f4..c5b2356d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2011-12-14 Kaz Kylheku <kaz@kylheku.com>
+ * eval.c (op_dohash): Esbatlish anonymous block.
+
+ * txr.1: Finished documenting special operators.
+
+2011-12-14 Kaz Kylheku <kaz@kylheku.com>
+
* genman.txr: Fix empty NAME section.
2011-12-14 Kaz Kylheku <kaz@kylheku.com>
diff --git a/eval.c b/eval.c
index 6ba918ed..e4931400 100644
--- a/eval.c
+++ b/eval.c
@@ -647,13 +647,19 @@ static val op_dohash(val form, val env)
val new_env = make_env(cons(keyvar, cons(valvar, nil)), nil, env);
val cell;
+ uw_block_begin (nil, result);
+
while ((cell = hash_next(&iter)) != nil) {
*cdr_l(keyvar) = car(cell);
*cdr_l(valvar) = cdr(cell);
eval_progn(body, new_env, form);
}
- return eval(resform, new_env, form);
+ result = eval(resform, new_env, form);
+
+ uw_block_end;
+
+ return result;
}
static val op_unwind_protect(val form, val env)
diff --git a/txr.1 b/txr.1
index 5aad3b1b..d9cf29c8 100644
--- a/txr.1
+++ b/txr.1
@@ -4687,15 +4687,24 @@ Currently, these forms are recognized as places:
(gethash <hash> <key> <default-value>)
+ (vecref <vector> <index>)
+
A <symbol> place denotes a variable. If the variable does not exist, it is an
-error. The (car <form>) and (cdr <form>) places denote the corresponding slots
+error.
+
+The (car <form>) and (cdr <form>) places denote the corresponding slots
of a cons cell. The <cons> form must be an expression which evaluates to a
-cons. The gethash place denotes a value stored in a hash table.
+cons.
+
+The gethash place denotes a value stored in a hash table.
The form <hash> must evaluate to a hash table. If the place does not exist
in the hash table under the given key, then the destructive operation
will create it. In that case, the <default-value> form is evaluated to
determine the initial value of the place. Otherwise it is ignored.
+The vecref place denotes a vector element, allowing vector elements
+to be treated as assignment places.
+
.SS Operators for and for*
.TP
@@ -4737,12 +4746,154 @@ allowing the return operator to be used to terminate at any point.
.SS Operator dohash
+.TP
+Syntax:
+
+(dohash (<key-var> <value-var> <hash-form> [<result-form>])
+ <body-form>*)
+
+.TP
+Description:
+
+The dohash operator iterates over a hash table. The <hash-form> expression must
+evaluate to an object of hash table type. The <key-var> and <value-var>
+arguents must be symbols suitable for use as variable names.
+Bindings are established for these variables over the scope of the
+<body-form>-s and the optional result form.
+
+For each element in the hash table, the <key-var> and <value-var>
+variables are set to the key and value of that entry, respectively,
+and each <body-form>, if there are any, is evaluated.
+
+When all of the entries of the table are thus processed, the <result-form> is
+evaluated, and its return value becomes the return value of the dohash form. If
+there is no <result-form>, the return value is nil.
+
+The <result-form> and <body-form>-s are in the scope of an implicit anonymous
+block, which means that it is possible to terminate the execution of
+dohash early using (return) or (return <value>).
+
.SS Operator unwind-protect
+.TP
+Syntax:
+
+(unwind-protect <protected-form> <cleanup-form>*)
+
+.TP
+Description:
+
+The unwind-protect operator evaluates <protected-form> in such a way that no
+matter how the execution of <protected-form> terminates, the <cleanup-form>-s
+will be executed.
+
+The cleanup forms, however, are not protected. If a cleanup form terminates via
+some non-local jump, the subsequent cleanup forms are not evaluated.
+
+Cleanup forms themselves can "hijack" a non-local control transfer such
+as an exception. If a cleanup form is evaluated during the processing of
+a dynamic control transfer such as an exception, and that cleanup form
+initiats its own dynamic control transfer, the original control transfer
+is aborted and replaced with the new one.
+
+.TP
+Example:
+
+ (block foo
+ (unwind-protect
+ (progn (return-from foo 42)
+ (format t "not reached!\en"))
+ (format t "cleanup!\n")))
+
+In this example, the protected progn form terminates by returning from
+block foo. Therefore the form does not complete and so the
+output "not reached!" is not produced. However, the cleanup form
+excecutes, producing the output "cleanup!".
+
+
.SS Operator block
+.TP
+Syntax:
+
+(block <name> <body-form>*}
+
+.TP
+Description:
+
+The block operator introduces a named block around the execution of
+some forms. The <name> argument must be a symbol. Since a block name is not
+a variable binding, keyword symbols are permitted, and so are the symbols
+t and nil. A block named by the symbol nil is slighlty special: it is
+understood to be an anonymous block.
+
+Blocks in TXR Lisp have dynamic scope. This means that the following
+situation is allowed:
+
+ (defun func () (return-from foo 42))
+ (block foo (func))
+
+The function can return from the foo block even though the foo block
+does not lexically surround foo.
+
+Thus blocks in TXR Lisp provide dynamic non-local returns, as well
+as returns out of lexical nesting.
+
+.TP
+Dialect Note:
+
+In Common Lisp, blocks are lexical. A separate mechanism consisting of
+catch and throw operators performs non-local transfer based on symbols.
+The TXR Lisp example:
+
+ (defun func () (return-from foo 42))
+ (block foo (func))
+
+is not allowed in Common Lisp, but can be transliterated to:
+
+ (defun func () (throw 'foo 42))
+ (catch 'foo (func))
+
+Note that foo is quoted in CL. This underscores the dynamic nature of
+the construct. THROW itself is a function and not an operator.
+
.SS Operators return, return-from
+.TP
+Syntax:
+
+(return [<value>])
+
+(return-from <name> [<value>])
+
+.TP
+Description:
+
+The return operator must be dynamically enclosed within an anonymous
+block (a block named by the symbol nil). It immediately terminates the
+evaluation of the innermost anonyous block which encloses it, causing
+it to return the specified value. If the value is omitted, the anonymous
+block returns nil.
+
+The return-from operator must be dynamically enclosed within a named block
+whose name matches the <name> argument. It immediately terminates the
+evaluation of the innermost such block, causing it to return the specified
+value. If the value is omitted, that block returns nil.
+
+.TP
+Example:
+
+ (block foo
+ (let ((a "abc\n")
+ (b "def\n"))
+ (pprint a *stdout*)
+ (return-from foo 42)
+ (pprint b *stdout*)))
+
+Here, the output produced is "abc". The value of b is not printed
+because the return-from terminates block foo, and so the second pprint
+form is not evaluated.
+
.SS Lisp Functions and Variables
When the first element of a compound form is a symbol denoting a function,
@@ -4797,7 +4948,7 @@ The following are Lisp functions and variables built-in to TXR.
.SS Functions reverse, nreverse
-.SS Function ldfiff
+.SS Function ldiff
.SS Function flatten