diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2016-11-12 20:05:42 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2016-11-12 20:05:42 -0800 |
commit | 7057603b4da78bb27e7688a9d74de6025132dbbc (patch) | |
tree | 13cf400d1ae922fc2ec1e9befc15fce271a95ea4 | |
parent | b530453f8e0331955b40c741a3b5dcb4bf6084d8 (diff) | |
download | txr-7057603b4da78bb27e7688a9d74de6025132dbbc.tar.gz txr-7057603b4da78bb27e7688a9d74de6025132dbbc.tar.bz2 txr-7057603b4da78bb27e7688a9d74de6025132dbbc.zip |
Introduce case{q,ql,qual}* macros which eval keys.
* eval.c (caseq_star_s, caseql_star_s, casequal_star_s):
New symbol variables.
(me_case): Implement new macro semantics.
(eval_init): Initialize new symbol variables, and
register the symbols to the me_case macro expander.
* tests/sock-common.tl (local-addr): This function
depends on the old broken caseql semantics which
evaluate keys. Using caseql* makes it work again.
* txr.1: Document case{q,ql,qual}* macros.
-rw-r--r-- | eval.c | 22 | ||||
-rw-r--r-- | tests/sock-common.tl | 2 | ||||
-rw-r--r-- | txr.1 | 75 |
3 files changed, 95 insertions, 4 deletions
@@ -80,6 +80,7 @@ val defvar_s, defvarl_s, defparm_s, defparml_s, defun_s, defmacro_s; val tree_case_s, tree_bind_s; val sys_mark_special_s; val caseq_s, caseql_s, casequal_s; +val caseq_star_s, caseql_star_s, casequal_star_s; val memq_s, memql_s, memqual_s; val eq_s, eql_s, equal_s; val car_s, cdr_s, not_s, vecref_s; @@ -3133,12 +3134,14 @@ static val me_case(val form, val menv) val tformsym = gensym(lit("test-")); val memfuncsym, eqfuncsym; val lofnil = cons(nil, nil); + val star = tnil(casesym == caseq_star_s || casesym == caseql_star_s || + casesym == casequal_star_s); list_collect_decl (condpairs, ptail); - if (casesym == caseq_s) { + if (casesym == caseq_s || casesym == caseq_star_s) { memfuncsym = memq_s; eqfuncsym = eq_s; - } else if (casesym == caseql_s) { + } else if (casesym == caseql_s || casesym == caseql_star_s) { memfuncsym = memql_s; eqfuncsym = eql_s; } else { @@ -3158,7 +3161,14 @@ static val me_case(val form, val menv) if (keys == t) eval_error(form_orig, lit("~s: symbol t used as key"), casesym, nao); - if (opt_compat && opt_compat <= 156) { + if (star) { + if (atom(keys)) + keys = eval(keys, nil, form); + else + keys = eval(cons(list_s, keys), nil, form); + } + + if (opt_compat && opt_compat <= 156 && !star) { ptail = list_collect(ptail, cons(list(if3(atom(keys), eqfuncsym, memfuncsym), tformsym, @@ -4734,6 +4744,9 @@ void eval_init(void) caseq_s = intern(lit("caseq"), user_package); caseql_s = intern(lit("caseql"), user_package); casequal_s = intern(lit("casequal"), user_package); + caseq_star_s = intern(lit("caseq*"), user_package); + caseql_star_s = intern(lit("caseql*"), user_package); + casequal_star_s = intern(lit("casequal*"), user_package); memq_s = intern(lit("memq"), user_package); memql_s = intern(lit("memql"), user_package); memqual_s = intern(lit("memqual"), user_package); @@ -4910,6 +4923,9 @@ void eval_init(void) reg_mac(caseq_s, me_case); reg_mac(caseql_s, me_case); reg_mac(casequal_s, me_case); + reg_mac(caseq_star_s, me_case); + reg_mac(caseql_star_s, me_case); + reg_mac(casequal_star_s, me_case); reg_mac(intern(lit("tb"), user_package), me_tb); reg_mac(intern(lit("tc"), user_package), me_tc); reg_mac(opip_s, me_opip); diff --git a/tests/sock-common.tl b/tests/sock-common.tl index 63f31c83..8fed8f23 100644 --- a/tests/sock-common.tl +++ b/tests/sock-common.tl @@ -1,5 +1,5 @@ (defun local-addr (family port) - (caseql family + (caseql* family (af-inet (new sockaddr-in addr inaddr-loopback port port)) (af-inet6 (new sockaddr-in6 addr in6addr-loopback port port)))) @@ -13243,6 +13243,81 @@ uses ...) .cble +.coNP Macros @, caseq* @ caseql* and @ casequal* +.synb +.mets (caseq* < test-form << normal-clause * <> [ else-clause ]) +.mets (caseql* < test-form << normal-clause * <> [ else-clause ]) +.mets (casequal* < test-form << normal-clause * <> [ else-clause ]) +.syne +.desc +The +.codn caseq* , +.codn caseql* , +and +.code casequal* +macros are similar to the macros +.codn caseq , +.codn caseql , +and +.codn casequal , +differing from them in only the following regard. The +.metn normal-clause , +of these macros has the form +.cblk +.mets >> ( evaluated-key << form *) +.cble +where +.code evaluated-key +is either an atom, which is evaluated to produce a key, or else +else a compound form, whose elements are evaluated as forms, producing +multiple keys. This evaluation takes place at macro-expansion time, +in the dynamic environment. + +The +.meta else-clause +works the same way under these macros as under +.code caseq +.IR "et al" . + +Note that although in a +.metn normal-clause , +.meta evaluated-key +must not be the atom +.codn t , +there is no restriction against it being +an atom which evaluates to +.code t. +In this situation, the value +.code t +has no special meaning. + +The +.meta evaluated-key +expressions are evaluated in the order in which they appear in +the construct, at the time the +.codn caseq* , +.code caseql* +or +.code casequal* +macro is expanded. + +Note: these macros allow the use of variables and global symbol +macros as case keys. + +.TP* Example: + +.cblk + (defvarl red 0) + (defvarl green 1) + (defvarl blue 2) + + (let ((color blue)) + (caseql* color + (red "hot") + ((green blue) "cool"))) + --> "cool" +.cble + .coNP Operator/function @ if .synb .mets (if < cond < t-form <> [ e-form ]) |