From 601a5312b0b65e519584888a0f861190959516d3 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Mon, 5 Dec 2011 09:14:05 -0800 Subject: * 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. --- ChangeLog | 11 ++++ RELNOTES | 2 + eval.c | 19 +++--- lib.h | 2 +- txr.1 | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 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 + + * 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 * 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 + + +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}* * + +This indicates a repetition of zero or more of the given +syntax enclosed in the braces or syntactic unit. + +.TP +[syntax] [] + +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 ({ | ( )}*) {}*) -(let* ({ | ( )}*) {}*) +(let ({ | ( )}*) *) + +(let* ({ | ( )}*) *) .TP Description: @@ -4339,7 +4366,7 @@ Examples: .TP Syntax: -(lambda ({}* [. ]) {}*) +(lambda ({}*[. ]) {}*) .TP Description: @@ -4432,16 +4459,196 @@ syntax (fun (lambda ...)) is invalid. .SS Operator cond +.TP +Syntax: +(cond {( {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, +, 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 is the only form in the group, then result of 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 []) + +.TP +Description: + +The if operator provides a simple two-way-selective evaluation control. +The form is evaluated. If it yields true then is +evaluated, and that form's return value becomes the return value of the if. +If yields false, then is evaluated and its return value +is taken to be that of if. If is omitted, then the behavior is +as if were specified as nil. + .SS Operator and +.TP +Syntax: +(and {
}*) + +.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 {}*) + +.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 ({ [. ]}*) {}*) + +Description: + +The defun operator introduces a new function in the global function namespace. + .SS Operators inc, dec, set, push and pop +.TP +Syntax: +(inc []) + +(dec []) + +(set ) + +(push ) + +(pop ) + +.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 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: + + + + (car ) + + (cdr ) + + (gethash ) + +A place denotes a variable. If the variable does not exist, it is an +error. The (car ) and (cdr ) places denote the corresponding slots +of a cons cell. The form must be an expression which evaluates to a +cons. The gethash place denotes a value stored in a hash table. +The form 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 form is evaluated to +determine the initial value of the place. Otherwise it is ignored. + .SS Operators for and for* .SS Operator dohash -- cgit v1.2.3