summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2011-12-05 09:14:05 -0800
committerKaz Kylheku <kaz@kylheku.com>2011-12-05 09:14:05 -0800
commit601a5312b0b65e519584888a0f861190959516d3 (patch)
treee222266538c44850cad63fa86703b6dc1b826f49
parent7fa8698dbec1812d13d8d7a1f323329baa9a10c4 (diff)
downloadtxr-601a5312b0b65e519584888a0f861190959516d3.tar.gz
txr-601a5312b0b65e519584888a0f861190959516d3.tar.bz2
txr-601a5312b0b65e519584888a0f861190959516d3.zip
* eval.c (op_cond): Fixed behavior for singleton clauses.
(eval_init): Use existing function objects car_f, cdr_f, eq_f, eql_f and equal_f. Added identity to function table. * lib.h (eql_f): Missing declaration added. * txr.1: Documented cond, and, if, or, defun, inc, dec, set, push and pop.
-rw-r--r--ChangeLog11
-rw-r--r--RELNOTES2
-rw-r--r--eval.c19
-rw-r--r--lib.h2
-rw-r--r--txr.1213
5 files changed, 235 insertions, 12 deletions
diff --git a/ChangeLog b/ChangeLog
index 768eff4f..028cb0c1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2011-12-05 Kaz Kylheku <kaz@kylheku.com>
+
+ * eval.c (op_cond): Fixed behavior for singleton clauses.
+ (eval_init): Use existing function objects car_f, cdr_f,
+ eq_f, eql_f and equal_f. Added identity to function table.
+
+ * lib.h (eql_f): Missing declaration added.
+
+ * txr.1: Documented cond, and, if, or, defun, inc, dec,
+ set, push and pop.
+
2011-12-04 Kaz Kylheku <kaz@kylheku.com>
* parser.y (force_regular_quotes): Function removed.
diff --git a/RELNOTES b/RELNOTES
index 7cbb57af..89fde259 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -12,6 +12,8 @@
- Bugs in quasiquote.
+ - Handling of singleton clauses in cond operator.
+
diff --git a/eval.c b/eval.c
index e6ea4909..85176f7f 100644
--- a/eval.c
+++ b/eval.c
@@ -439,9 +439,11 @@ static val op_cond(val form, val env)
val iter = rest(form);
for (; iter; iter = cdr(iter)) {
- val pair = car(iter);
- if (eval(first(pair), env, form))
- return eval_progn(rest(pair), env, pair);
+ val group = car(iter);
+ val restgroup = rest(group);
+ val firstval = eval(first(group), env, group);
+ if (firstval)
+ return if3(restgroup, eval_progn(rest(group), env, group), firstval);
}
return nil;
@@ -1050,14 +1052,15 @@ void eval_init(void)
reg_fun(cons_s, func_n2(cons));
reg_fun(intern(lit("make-lazy-cons"), user_package), func_n1(make_lazy_cons));
reg_fun(intern(lit("lcons-fun"), user_package), func_n1(lcons_fun));
- reg_fun(car_s, func_n1(car));
- reg_fun(cdr_s, func_n1(car));
+ reg_fun(car_s, car_f);
+ reg_fun(cdr_s, cdr_f);
reg_fun(intern(lit("rplaca"), user_package), func_n2(rplaca));
reg_fun(intern(lit("rplacd"), user_package), func_n2(rplacd));
reg_fun(intern(lit("first"), user_package), func_n1(car));
reg_fun(intern(lit("rest"), user_package), func_n1(cdr));
reg_fun(append_s, func_n0v(appendv));
reg_fun(list_s, func_n0v(identity));
+ reg_fun(intern(lit("identity"), user_package), identity_f);
reg_fun(intern(lit("atom"), user_package), func_n1(atom));
reg_fun(intern(lit("null"), user_package), func_n1(nullp));
@@ -1086,9 +1089,9 @@ void eval_init(void)
reg_fun(intern(lit("some"), user_package), func_n3(some_satisfy));
reg_fun(intern(lit("all"), user_package), func_n3(all_satisfy));
reg_fun(intern(lit("none"), user_package), func_n3(none_satisfy));
- reg_fun(intern(lit("eq"), user_package), func_n2(eq));
- reg_fun(intern(lit("eql"), user_package), func_n2(eql));
- reg_fun(intern(lit("equal"), user_package), func_n2(equal));
+ reg_fun(intern(lit("eq"), user_package), eq_f);
+ reg_fun(intern(lit("eql"), user_package), eql_f);
+ reg_fun(intern(lit("equal"), user_package), equal_f);
reg_fun(intern(lit("+"), user_package), func_n0v(plusv));
reg_fun(intern(lit("-"), user_package), func_n1v(minusv));
diff --git a/lib.h b/lib.h
index 4375fea5..28bf0579 100644
--- a/lib.h
+++ b/lib.h
@@ -282,7 +282,7 @@ extern val nothrow_k, args_k;
extern val null_string;
extern val null_list; /* (nil) */
-extern val identity_f, equal_f, eq_f, car_f, cdr_f;
+extern val identity_f, equal_f, eql_f, eq_f, car_f, cdr_f;
extern const wchar_t *progname;
extern val prog_string;
diff --git a/txr.1 b/txr.1
index 0ad576c7..67f660d2 100644
--- a/txr.1
+++ b/txr.1
@@ -4289,12 +4289,39 @@ the interpretation of the meaning of that form is under the complete control
of that operator. The following sections list all of the operators available
in TXR Lisp.
+In these sections Syntax is indicated using these conventions:
+
+.TP
+<word>
+
+A symbol in angle brackets denotes some syntactic unit: it
+may be a symbol or compound form. The syntactic unit is explained
+in the Description section.
+
+.TP
+{syntax}* <word>*
+
+This indicates a repetition of zero or more of the given
+syntax enclosed in the braces or syntactic unit.
+
+.TP
+[syntax] [<word>]
+
+Square brackets indicate optional syntax.
+
+.TP
+alternative1 | alternative2 | ... | alternativeN
+
+Multiple syntactic variations allowed in one place are
+indicated as bar-separated items.
+
.SS Operators let and let*
.TP
Syntax:
-(let ({<sym> | (<sym> <init-form>)}*) {<body-form>}*)
-(let* ({<sym> | (<sym> <init-form>)}*) {<body-form>}*)
+(let ({<sym> | (<sym> <init-form>)}*) <body-form>*)
+
+(let* ({<sym> | (<sym> <init-form>)}*) <body-form>*)
.TP
Description:
@@ -4339,7 +4366,7 @@ Examples:
.TP
Syntax:
-(lambda ({<sym>}* [. <sym>]) {<body-form>}*)
+(lambda ({<sym>}*[. <sym>]) {<body-form>}*)
.TP
Description:
@@ -4432,16 +4459,196 @@ syntax (fun (lambda ...)) is invalid.
.SS Operator cond
+.TP
+Syntax:
+(cond {(<test> {form}*)}*)
+
+.TP
+Description:
+
+The cond operator provides a multi-branching conditional evaluation of
+forms. Enclosed in the cond form are groups of forms expressed as lists.
+Each group must be a list of at least one form.
+
+The forms are processed from left to right as follows: the first form,
+<test>, in each group is evaluated. If it evaluates true, then the remaining
+forms in that group, if any, are also evaluated. Processing then terminates and
+the result of the last form in the group is taken as the result of cond.
+If <test> is the only form in the group, then result of <test> is taken
+as the result of cond.
+
+If the first form of a group yields nil, then processing continues with the
+next group, if any. If all form groups yield nil, then the cond form yields
+nil. This holds in the case that the syntax is empty: (cond) yields nil.
+
.SS Operator if
+.TP
+Syntax:
+(if <cond> <t-form> [<e-form>])
+
+.TP
+Description:
+
+The if operator provides a simple two-way-selective evaluation control.
+The <cond> form is evaluated. If it yields true then <t-form> is
+evaluated, and that form's return value becomes the return value of the if.
+If <cond> yields false, then <e-form> is evaluated and its return value
+is taken to be that of if. If <e-form> is omitted, then the behavior is
+as if <e-form> were specified as nil.
+
.SS Operator and
+.TP
+Syntax:
+(and {<form>}*)
+
+.TP
+Description:
+
+The and operator provides three functionalities in one. It computes the
+logical "and" function over several forms. It controls evaluation (a.k.a.
+"short-circuiting"). It also allows the convenient substitution of an
+arbitrary true value in the true case.
+
+The and operator evaluates as follows. First, a return value is
+established and initialized to the value t. The forms, if any, are
+evaluated from left to right. The return value is overwritten with
+the result of each form. Evaluation stops when all forms are exhausted,
+or when any of them yields nil. When evaluation stops, the operator yields
+the return value.
+
+.TP
+Examples:
+
+(and) -> t
+
+(and (> 10 5) (stringp "foo")) -> t
+
+(and 1 2 3) -> 3
+
.SS Operator or
+.TP
+Syntax:
+(or {<form>}*)
+
+.TP
+Description:
+
+The and operator provides three functionalities in one. It computes the
+logical "and" function over several forms. It controls evaluation (a.k.a.
+"short-circuiting"). The behavior of or also provides for a simplified
+selection of the first non-nil value from a sequence of forms.
+
+The or operator evaluates as follows. First, a rturn value is
+established and initialized to the value nil. The forms, if any,
+are evaluated from left to right. The return value is overwritten
+with the result of each form. Evaluation stops when all forms are
+exhausted, or when a form yields a true value. When evaluation stops, the
+operator yields the return value.
+
+.TP
+Examples:
+
+(or) -> nil
+
+(or 1 2) -> 1
+
+(or nil 2) -> 2
+
+(or (> 10 20) (stringp "foo")) -> t
+
.SS Operator defun
+.TP
+Syntax:
+(defun <name> ({<param> [. <rest-param>]}*) {<body-form>}*)
+
+Description:
+
+The defun operator introduces a new function in the global function namespace.
+
.SS Operators inc, dec, set, push and pop
+.TP
+Syntax:
+(inc <place> [<delta>])
+
+(dec <place> [<delta>])
+
+(set <place> <new-value>)
+
+(push <item> <place>)
+
+(pop <item> <place>)
+
+.TP
+Description:
+
+These destructive operators update the value of a place. A place is a storage
+location which is denoted by a form. Place forms are identical to value
+accessing forms. That is to say, any form recognized as a place by these
+operators can be evaluated by itself to retrieve the value of the storage
+location. However, the converse is false: not all forms which access storage
+location are recognized as places.
+
+With are exceptions noted below, it is an error if a place does not exist.
+For instance, a variable being assigned must exist.
+
+Literal objects which are directly specified in the source code are
+considered part of the program body. Modifying parts of these objects
+therefore gives rise to self-modifying code. The behavior of self-modifying
+code is not specified.
+
+The inc and dec update the place by adding or subtracting, respectively, a
+displacement to or from that number. If the <delta> expression is
+specified, then it is evaluated and its value is used as the increment.
+Otherwise, a default increment of 1 is used. The prior value of the place
+and the delta must be suitable operands for the + and - functions.
+(inc x) is equivalent to (set x (+ 1 x)), except that expression x
+is evaluated only once to determine the storage location. The inc
+and dec operators return the new value that was stored.
+
+The set operator overwrites the previous value of a place with a new value,
+and also returns that value.
+
+The push and pop operators operate on a place which holds a list. The push
+operator updates the list by replacing it with a new list which has a new item
+at the front, followed by the previous list. The item is returned.
+The pop operator performs the reverse operation: it removes the first item
+from the list and returns it. (push y x) is similar to
+
+ (let ((temp y)) (set x (cons temp x)) temp)
+
+except that x is evaluated only once to determine the storage place, and no
+such temporary variable is visible to the program. Similarly, (pop x) is much
+like
+
+ (let ((temp (car x))) (set x (cdr x)) temp)
+
+except that x is evaluated only once, and no such temporary variale
+is visible to the program.
+
+Currently, these forms are recognized as places:
+
+ <symbol>
+
+ (car <cons>)
+
+ (cdr <cons>)
+
+ (gethash <hash> <key> <default-value>)
+
+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
+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.
+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.
+
.SS Operators for and for*
.SS Operator dohash