2 cl-loop.c -- Common Lisp Goodness, the fast version
3 Copyright (C) 2006, 2007 Sebastian Freundt
5 Author: Sebastian Freundt <hroptatyr@sxemacs.org>
7 * This file is part of SXEmacs.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the author nor the names of any contributors
21 * may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
25 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
31 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
33 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
34 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 /* Synched up with: Not in FSF. */
45 #if !defined EMOD_CL_MONOMOD
47 REQUIRE(cl_loop, "cl");
49 #define INIT cl_loop_LTX_init
50 #define REINIT cl_loop_LTX_reinit
51 #define DEINIT cl_loop_LTX_deinit
54 emodcl_initialise_vars(Lisp_Object varform)
55 __attribute__((always_inline));
57 emodcl_step_vars(Lisp_Object varform, int varcount)
58 __attribute__((always_inline));
60 Lisp_Object Qcl_loop_sentence, Qcl_loop_sentence_p;
61 Lisp_Object Qcl_loop_for_clause, Qcl_loop_for_clause_p;
62 Lisp_Object Qcl_loop_do_clause, Qcl_loop_do_clause_p;
63 Lisp_Object Qcl_loop_with_clause, Qcl_loop_with_clause_p;
64 Lisp_Object Qcl_loop_repeat_clause, Qcl_loop_repeat_clause_p;
65 Lisp_Object Qcl_loop_append_clause, Qcl_loop_append_clause_p;
66 Lisp_Object Qcl_loop_collect_clause, Qcl_loop_collect_clause_p;
67 Lisp_Object Qcl_loop_nconc_clause, Qcl_loop_nconc_clause_p;
68 Lisp_Object Qcl_loop_return_clause, Qcl_loop_return_clause_p;
69 Lisp_Object Qcl_loop_initially_clause, Qcl_loop_initially_clause_p;
70 Lisp_Object Qcl_loop_finally_clause, Qcl_loop_finally_clause_p;
71 Lisp_Object Qcl_loop_count_clause, Qcl_loop_count_clause_p;
72 Lisp_Object Qcl_loop_sum_clause, Qcl_loop_sum_clause_p;
73 Lisp_Object Qcl_loop_maximise_clause, Qcl_loop_maximise_clause_p;
74 Lisp_Object Qcl_loop_minimise_clause, Qcl_loop_minimise_clause_p;
76 Lisp_Object Qfor, Qas;
77 Lisp_Object Qfrom, Qdownfrom, Qupfrom, Qto, Qdownto, Qupto, Qabove, Qbelow, Qby;
78 Lisp_Object Qin, Qon, Qthen, Qacross, Qeach, Qthe, Qbeing, Qof;
79 Lisp_Object Qhash_key, Qhash_keys, Qhash_value, Qhash_values, Qusing;
80 Lisp_Object Qdo, Qdoing;
82 Lisp_Object Qwith, Qequals, Qand;
84 Lisp_Object Qappend, Qappending, Qcollect, Qcollecting, Qnconc, Qnconcing;
86 Lisp_Object Qcount, Qcounting, Qsum, Qsumming;
87 Lisp_Object Qmaximise, Qmaximising, Qmaximize, Qmaximizing;
88 Lisp_Object Qminimise, Qminimising, Qminimize, Qminimizing;
89 Lisp_Object Qinitially, Qfinally;
91 static Lisp_Object Qanon_acn;
95 emodcl_initialise_vars(Lisp_Object varform)
101 /* Make space to hold the values to give the bound variables. */
102 GET_EXTERNAL_LIST_LENGTH(varform, varcount);
105 Lisp_Object temps[varcount];
106 struct gcpro ngcpro1;
108 /* wipe temps first */
109 memset(temps, 0, sizeof(Lisp_Object)*varcount);
111 /* Compute the values and store them in `temps' */
112 NGCPROn(temps, varcount);
114 LIST_LOOP_2(var, varform) {
115 Lisp_Object *value = &temps[idx++];
126 *value = Feval(XCAR(tem));
133 LIST_LOOP_2(var, varform) {
134 specbind(SYMBOLP(var) ? var : XCAR(var), temps[idx++]);
144 emodcl_step_vars(Lisp_Object varform, int varcount)
146 /* basically a let */
147 Lisp_Object temps[varcount];
148 struct gcpro ngcpro1;
151 /* wipe temps first */
152 memset(temps, 0, sizeof(Lisp_Object)*varcount);
154 /* Compute the values and store them in `temps' */
155 NGCPROn(temps, varcount);
157 LIST_LOOP_2(var, varform) {
158 Lisp_Object *value = &temps[idx++];
160 if (CONSP(var) && CONSP((tmp = XCDR(var))) &&
162 /* only if there is a step form of course */
163 *value = Feval(XCAR(XCDR(tmp)));
168 LIST_LOOP_2(var, varform) {
169 Fset(XCAR(var), temps[idx++]);
177 emodcl_initialise_vars_star(Lisp_Object varform)
179 /* basically a let* */
180 EXTERNAL_LIST_LOOP_3(var, varform, tail) {
181 Lisp_Object symbol, value, tem;
183 symbol = var, value = Qnil;
192 value = Feval(XCAR(tem));
195 specbind(symbol, value);
201 emodcl_step_vars_star(Lisp_Object varform, int unused)
203 EXTERNAL_LIST_LOOP_3(var, varform, tail) {
204 Lisp_Object symbol, value, tmp;
205 if (CONSP(var) && CONSP((tmp = XCDR(var))) &&
207 /* only if there is a step form of course */
209 value = Feval(XCAR(XCDR(tmp)));
216 static inline Lisp_Object
217 emodcl_do_obtain_result(Lisp_Object resultform)
219 /* assumes that resultform is gc-protected already */
220 Lisp_Object result = Qnil;
222 LIST_LOOP_2(form, resultform) {
223 result = Feval(form);
231 Lisp_Object varform, Lisp_Object endtest, Lisp_Object resultform,
233 int(*initialiser)(Lisp_Object), void(*stepper)(Lisp_Object, int))
235 Lisp_Object result = Qnil;
238 /* initial assignment */
239 numbervars = initialiser(varform);
242 while (NILP(Feval(endtest))) {
244 LIST_LOOP_2(form, body) {
248 internal_catch(tag, Fprogn, body, 0);
250 /* evaluate step forms */
251 stepper(varform, numbervars);
254 /* obtain a result */
255 result = emodcl_do_obtain_result(resultform);
262 cl_loop_sentence_mark(Lisp_Object obj)
264 cl_loop_sentence_t *lsen = get_dynacat(obj);
266 EMOD_CL_DEBUG_LOOP("sentence:0x%x@0x%x shall be marked...\n",
267 (unsigned int)(lsen), (unsigned int)obj);
269 mark_object(lsen->prologue);
270 mark_object(lsen->epilogue);
271 mark_object(lsen->iteration);
273 mark_object(lsen->result);
278 cl_loop_for_clause_mark(Lisp_Object obj)
280 cl_loop_for_clause_t *fc = get_dynacat(obj);
282 EMOD_CL_DEBUG_LOOP("FOR:0x%x@0x%x shall be marked...\n",
283 (unsigned int)(fc), (unsigned int)obj);
285 mark_object(fc->form1);
286 mark_object(fc->from);
290 mark_object(fc->inonacross);
292 mark_object(fc->equals);
293 mark_object(fc->then);
295 mark_object(fc->hash_keyvar);
296 mark_object(fc->hash_valvar);
298 mark_object(fc->curval);
299 mark_object(fc->curbound);
300 mark_object(fc->curstep);
305 cl_loop_do_clause_mark(Lisp_Object obj)
307 cl_loop_do_clause_t *doc = get_dynacat(obj);
309 EMOD_CL_DEBUG_LOOP("DO:0x%x@0x%x shall be marked...\n",
310 (unsigned int)(doc), (unsigned int)obj);
312 mark_object(doc->form);
317 cl_loop_with_clause_mark(Lisp_Object obj)
319 cl_loop_with_clause_t *wc = get_dynacat(obj);
321 EMOD_CL_DEBUG_LOOP("WITH:0x%x@0x%x shall be marked...\n",
322 (unsigned int)(wc), (unsigned int)obj);
324 mark_object(wc->varform);
325 mark_object(wc->valform);
326 mark_object(wc->next);
331 cl_loop_repeat_clause_mark(Lisp_Object obj)
333 cl_loop_repeat_clause_t *rc = get_dynacat(obj);
335 EMOD_CL_DEBUG_LOOP("REPEAT:0x%x@0x%x shall be marked...\n",
336 (unsigned int)(rc), (unsigned int)obj);
338 mark_object(rc->form);
343 cl_loop_inifinret_clause_mark(Lisp_Object obj)
345 cl_loop_inifinret_clause_t *rc = get_dynacat(obj);
347 EMOD_CL_DEBUG_LOOP("RETURN|INITIALLY|FINALLY:"
348 "0x%x@0x%x shall be marked...\n",
349 (unsigned int)(rc), (unsigned int)obj);
351 mark_object(rc->form);
356 cl_loop_accu_clause_mark(Lisp_Object obj)
358 cl_loop_accu_clause_t *ac = get_dynacat(obj);
360 EMOD_CL_DEBUG_LOOP("ACCU(=COLLECT|APPEND|NCONC|etc.):"
361 "0x%x@0x%x shall be marked...\n",
362 (unsigned int)(ac), (unsigned int)obj);
364 mark_object(ac->form);
365 mark_object(ac->into);
366 mark_object(ac->cur);
371 cl_loop_generic_finaliser(Lisp_Object obj, int SXE_UNUSED(for_disksave))
373 void *free_me = get_dynacat(obj);
375 EMOD_CL_DEBUG_LOOP("generic:%p@%p shall be freed\n",
376 free_me, (void*)obj);
379 set_dynacat(obj, NULL);
384 /* auxiliary stuff */
385 typedef void(*cl_loop_binder_f)(Lisp_Object, Lisp_Object);
388 cl_loop_destructuring_bind(
389 cl_loop_binder_f bindfun, Lisp_Object form, Lisp_Object value)
391 Lisp_Object tmpf, tmpv;
392 while (!NILP(form)) {
394 bindfun(form, value);
401 /* recursive approach? :| */
402 cl_loop_destructuring_bind(bindfun, tmpf, tmpv);
411 static inline Lisp_Object
412 cl_loop_make_sentence(void)
414 cl_loop_sentence_t *lsen = xnew_and_zero(cl_loop_sentence_t);
415 Lisp_Object result = make_dynacat(lsen);
417 set_dynacat_type(result, Qcl_loop_sentence);
419 XSETDLLIST(lsen->prologue, make_dllist());
420 XSETDLLIST(lsen->epilogue, make_dllist());
421 XSETDLLIST(lsen->iteration, make_dllist());
425 set_dynacat_marker(result, cl_loop_sentence_mark);
426 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
428 EMOD_CL_DEBUG_LOOP("sentence:0x%x shall be wrapped to 0x%x...\n",
429 (unsigned int)lsen, (unsigned int)result);
435 cl_loop_make_for_clause(Lisp_Object form1)
437 cl_loop_for_clause_t *fc = xnew_and_zero(cl_loop_for_clause_t);
438 Lisp_Object result = make_dynacat(fc);
440 set_dynacat_type(result, Qcl_loop_for_clause);
443 fc->for_subclause = FOR_INVALID_CLAUSE;
445 /* arith subclause */
449 /* by default we increment and compare with equalp */
450 fc->byop = ASE_BINARY_OP_SUM;
451 fc->torel = ASE_BINARY_REL_LESSP;
452 fc->torel_strictp = 0;
454 /* in/on subclauses */
455 fc->inonacross = Qnil;
462 fc->hash_keyvar = Qnil;
463 fc->hash_valvar = Qnil;
465 /* for parallel bind */
471 fc->curbound = Qzero;
475 set_dynacat_marker(result, cl_loop_for_clause_mark);
476 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
478 EMOD_CL_DEBUG_LOOP("FOR:0x%x shall be wrapped to 0x%x...\n",
479 (unsigned int)fc, (unsigned int)result);
485 cl_loop_make_do_clause(Lisp_Object form1)
487 cl_loop_do_clause_t *doc = xnew_and_zero(cl_loop_do_clause_t);
488 Lisp_Object result = make_dynacat(doc);
490 set_dynacat_type(result, Qcl_loop_do_clause);
494 set_dynacat_marker(result, cl_loop_do_clause_mark);
495 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
497 EMOD_CL_DEBUG_LOOP("DO:0x%x shall be wrapped to 0x%x...\n",
498 (unsigned int)doc, (unsigned int)result);
504 cl_loop_make_repeat_clause(Lisp_Object form)
506 cl_loop_repeat_clause_t *rc = xnew_and_zero(cl_loop_repeat_clause_t);
507 Lisp_Object result = make_dynacat(rc);
509 set_dynacat_type(result, Qcl_loop_repeat_clause);
514 set_dynacat_marker(result, cl_loop_repeat_clause_mark);
515 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
517 EMOD_CL_DEBUG_LOOP("REPEAT:0x%x shall be wrapped to 0x%x...\n",
518 (unsigned int)rc, (unsigned int)result);
524 cl_loop_make_return_clause(Lisp_Object form)
526 cl_loop_inifinret_clause_t *rc =
527 xnew_and_zero(cl_loop_inifinret_clause_t);
528 Lisp_Object result = make_dynacat(rc);
530 set_dynacat_type(result, Qcl_loop_return_clause);
534 set_dynacat_marker(result, cl_loop_inifinret_clause_mark);
535 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
537 EMOD_CL_DEBUG_LOOP("RETURN:0x%x shall be wrapped to 0x%x...\n",
538 (unsigned int)rc, (unsigned int)result);
544 cl_loop_make_initially_clause(Lisp_Object form)
546 cl_loop_inifinret_clause_t *rc =
547 xnew_and_zero(cl_loop_inifinret_clause_t);
548 Lisp_Object result = make_dynacat(rc);
550 set_dynacat_type(result, Qcl_loop_initially_clause);
554 set_dynacat_marker(result, cl_loop_inifinret_clause_mark);
555 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
557 EMOD_CL_DEBUG_LOOP("INITIALLY:0x%x shall be wrapped to 0x%x...\n",
558 (unsigned int)rc, (unsigned int)result);
564 cl_loop_make_finally_clause(Lisp_Object form)
566 cl_loop_inifinret_clause_t *rc =
567 xnew_and_zero(cl_loop_inifinret_clause_t);
568 Lisp_Object result = make_dynacat(rc);
570 set_dynacat_type(result, Qcl_loop_finally_clause);
574 set_dynacat_marker(result, cl_loop_inifinret_clause_mark);
575 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
577 EMOD_CL_DEBUG_LOOP("FINALLY:0x%x shall be wrapped to 0x%x...\n",
578 (unsigned int)rc, (unsigned int)result);
583 /* maybe a generic cl_loop_make_accu_clause? */
585 cl_loop_make_append_clause(Lisp_Object form)
587 cl_loop_accu_clause_t *ac = xnew_and_zero(cl_loop_accu_clause_t);
588 Lisp_Object result = make_dynacat(ac);
590 set_dynacat_type(result, Qcl_loop_append_clause);
596 set_dynacat_marker(result, cl_loop_accu_clause_mark);
597 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
599 EMOD_CL_DEBUG_LOOP("APPEND:0x%x shall be wrapped to 0x%x...\n",
600 (unsigned int)ac, (unsigned int)result);
606 cl_loop_make_collect_clause(Lisp_Object form)
608 cl_loop_accu_clause_t *ac = xnew_and_zero(cl_loop_accu_clause_t);
609 Lisp_Object result = make_dynacat(ac);
611 set_dynacat_type(result, Qcl_loop_collect_clause);
617 set_dynacat_marker(result, cl_loop_accu_clause_mark);
618 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
620 EMOD_CL_DEBUG_LOOP("COLLECT:0x%x shall be wrapped to 0x%x...\n",
621 (unsigned int)ac, (unsigned int)result);
627 cl_loop_make_nconc_clause(Lisp_Object form)
629 cl_loop_accu_clause_t *ac = xnew_and_zero(cl_loop_accu_clause_t);
630 Lisp_Object result = make_dynacat(ac);
632 set_dynacat_type(result, Qcl_loop_nconc_clause);
638 set_dynacat_marker(result, cl_loop_accu_clause_mark);
639 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
641 EMOD_CL_DEBUG_LOOP("NCONC:0x%x shall be wrapped to 0x%x...\n",
642 (unsigned int)ac, (unsigned int)result);
648 cl_loop_make_count_clause(Lisp_Object form)
650 cl_loop_accu_clause_t *ac = xnew_and_zero(cl_loop_accu_clause_t);
651 Lisp_Object result = make_dynacat(ac);
653 set_dynacat_type(result, Qcl_loop_count_clause);
659 set_dynacat_marker(result, cl_loop_accu_clause_mark);
660 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
662 EMOD_CL_DEBUG_LOOP("COUNT:0x%x shall be wrapped to 0x%x...\n",
663 (unsigned int)ac, (unsigned int)result);
669 cl_loop_make_sum_clause(Lisp_Object form)
671 cl_loop_accu_clause_t *ac = xnew_and_zero(cl_loop_accu_clause_t);
672 Lisp_Object result = make_dynacat(ac);
674 set_dynacat_type(result, Qcl_loop_sum_clause);
680 set_dynacat_marker(result, cl_loop_accu_clause_mark);
681 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
683 EMOD_CL_DEBUG_LOOP("SUM:0x%x shall be wrapped to 0x%x...\n",
684 (unsigned int)ac, (unsigned int)result);
690 cl_loop_make_maximise_clause(Lisp_Object form)
692 cl_loop_accu_clause_t *ac = xnew_and_zero(cl_loop_accu_clause_t);
693 Lisp_Object result = make_dynacat(ac);
695 set_dynacat_type(result, Qcl_loop_maximise_clause);
701 set_dynacat_marker(result, cl_loop_accu_clause_mark);
702 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
704 EMOD_CL_DEBUG_LOOP("MAXIMISE:0x%x shall be wrapped to 0x%x...\n",
705 (unsigned int)ac, (unsigned int)result);
711 cl_loop_make_minimise_clause(Lisp_Object form)
713 cl_loop_accu_clause_t *ac = xnew_and_zero(cl_loop_accu_clause_t);
714 Lisp_Object result = make_dynacat(ac);
716 set_dynacat_type(result, Qcl_loop_minimise_clause);
722 set_dynacat_marker(result, cl_loop_accu_clause_mark);
723 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
725 EMOD_CL_DEBUG_LOOP("MINIMISE:0x%x shall be wrapped to 0x%x...\n",
726 (unsigned int)ac, (unsigned int)result);
732 cl_loop_make_with_clause(Lisp_Object form)
734 cl_loop_with_clause_t *wc = xnew_and_zero(cl_loop_with_clause_t);
735 Lisp_Object result = make_dynacat(wc);
737 set_dynacat_type(result, Qcl_loop_with_clause);
744 set_dynacat_marker(result, cl_loop_with_clause_mark);
745 set_dynacat_finaliser(result, cl_loop_generic_finaliser);
747 EMOD_CL_DEBUG_LOOP("WITH:0x%x shall be wrapped to 0x%x...\n",
748 (unsigned int)wc, (unsigned int)result);
755 cl_loop_yylex(YYSTYPE *yys, Lisp_Object *scanner,
756 cl_loop_sentence_t *lsen, Lisp_Object *ctx, Lisp_Object *token)
763 tok = *token = XCAR(*scanner);
764 *scanner = XCDR(*scanner);
766 if (EQ(tok, Qrepeat)) {
767 return *yys = REPEAT;
769 if (EQ(tok, Qfor) || EQ(tok, Qas)) {
772 if (EQ(tok, Qdo) || EQ(tok, Qdoing)) {
775 if (EQ(tok, Qwith)) {
782 if (EQ(tok, Qfrom) ||
783 EQ(tok, Qdownfrom) ||
792 if (EQ(tok, Qbelow)) {
795 if (EQ(tok, Qabove)) {
807 if (EQ(tok, Qequals)) {
808 return *yys = EQUALS;
810 if (EQ(tok, Qthen)) {
813 if (EQ(tok, Qacross)) {
814 return *yys = ACROSS;
816 if (EQ(tok, Qbeing)) {
819 if (EQ(tok, Qthe) || EQ(tok, Qeach)) {
822 if (EQ(tok, Qof) || EQ(tok, Qin)) {
825 if (EQ(tok, Qhash_key) || EQ(tok, Qhash_keys)) {
826 return *yys = HASH_KEY;
828 if (EQ(tok, Qhash_value) || EQ(tok, Qhash_values)) {
829 return *yys = HASH_VALUE;
831 if (EQ(tok, Qusing)) {
834 if (EQ(tok, Qcollect) || EQ(tok, Qcollecting)) {
835 return *yys = COLLECT;
837 if (EQ(tok, Qappend) || EQ(tok, Qappending)) {
838 return *yys = APPEND;
840 if (EQ(tok, Qnconc) || EQ(tok, Qnconcing)) {
843 if (EQ(tok, Qcount) || EQ(tok, Qcount)) {
846 if (EQ(tok, Qsum) || EQ(tok, Qsumming)) {
849 if (EQ(tok, Qminimise) || EQ(tok, Qminimising) ||
850 EQ(tok, Qminimize) || EQ(tok, Qminimizing)) {
851 return *yys = MINIMISE;
853 if (EQ(tok, Qmaximise) || EQ(tok, Qmaximising) ||
854 EQ(tok, Qmaximize) || EQ(tok, Qmaximizing)) {
855 return *yys = MAXIMISE;
857 if (EQ(tok, Qinto)) {
860 if (EQ(tok, Qinitially)) {
861 return *yys = INITIALLY;
863 if (EQ(tok, Qfinally)) {
864 return *yys = FINALLY;
866 if (EQ(tok, Qreturn)) {
867 return *yys = RETURN;
874 cl_loop_yyerror(Lisp_Object *scanner, cl_loop_sentence_t *lsen,
875 Lisp_Object *ctx, Lisp_Object *token, char *msg)
877 Fsignal(Qinvalid_read_syntax, *scanner);
883 cl_loop_perform_with_pro(cl_loop_with_clause_t *wc)
885 Lisp_Object val = Feval(wc->valform);
886 if (wc->depth == 1) {
887 /* optimise for the trivial case */
888 cl_loop_destructuring_bind(specbind, wc->varform, val);
890 Lisp_Object *tmp = alloca_array(Lisp_Object, wc->depth);
896 for (i = 1; !NILP(tra); i++) {
897 cl_loop_with_clause_t *wct = get_dynacat(tra);
898 tmp[i] = Feval(wct->valform);
902 /* now specbind them */
903 cl_loop_destructuring_bind(specbind, wc->varform, tmp[0]);
905 for (i = 1; !NILP(tra); i++) {
906 cl_loop_with_clause_t *wct = get_dynacat(tra);
907 cl_loop_destructuring_bind(
908 specbind, wct->varform, tmp[i]);
915 cl_loop_perform_colappnco_pro(cl_loop_accu_clause_t *ac)
916 __attribute__((always_inline));
918 cl_loop_perform_colappnco_pro(cl_loop_accu_clause_t *ac)
920 if (ac->into == Qnull_pointer) {
921 /* generate a random symbol */
922 ac->into = Qanon_acn;
924 specbind(ac->into, ac->cur = Qnil);
928 cl_loop_perform_countsum_pro(cl_loop_accu_clause_t *ac)
929 __attribute__((always_inline));
931 cl_loop_perform_countsum_pro(cl_loop_accu_clause_t *ac)
933 if (ac->into == Qnull_pointer) {
934 /* generate a random symbol */
935 ac->into = Qanon_acn;
937 specbind(ac->into, ac->cur = Qzero);
941 cl_loop_perform_maximise_pro(cl_loop_accu_clause_t *ac)
942 __attribute__((always_inline));
944 cl_loop_perform_maximise_pro(cl_loop_accu_clause_t *ac)
946 if (ac->into == Qnull_pointer) {
947 /* generate a random symbol */
948 ac->into = Qanon_acn;
950 specbind(ac->into, ac->cur = Vninfinity);
954 cl_loop_perform_minimise_pro(cl_loop_accu_clause_t *ac)
955 __attribute__((always_inline));
957 cl_loop_perform_minimise_pro(cl_loop_accu_clause_t *ac)
959 if (ac->into == Qnull_pointer) {
960 /* generate a random symbol */
961 ac->into = Qanon_acn;
963 specbind(ac->into, ac->cur = Vpinfinity);
967 cl_loop_perform_repeat_pro(cl_loop_repeat_clause_t *rc)
968 __attribute__((always_inline));
970 cl_loop_perform_repeat_pro(cl_loop_repeat_clause_t *rc)
972 Lisp_Object lctr = Feval(rc->form);
974 rc->counter = XINT(lctr);
979 cl_loop_perform_initially_pro(cl_loop_inifinret_clause_t *rc)
980 __attribute__((always_inline));
982 cl_loop_perform_initially_pro(cl_loop_inifinret_clause_t *rc)
989 cl_loop_next_hentry(hentry_t e, const hash_table_t ht)
991 const hentry_t term = ht->hentries + ht->size;
997 while (e < term && HENTRY_CLEAR_P(++e));
1006 cl_loop_perform_for_pro_i(cl_loop_for_clause_t *fc)
1008 switch (fc->for_subclause) {
1009 case FOR_ARITHMETIC_CLAUSE:
1010 fc->curval = Feval(fc->from);
1011 fc->curbound = Feval(fc->to);
1012 fc->curstep = Feval(fc->by);
1014 case FOR_IN_SUBLIST_CLAUSE:
1015 fc->curbound = Feval(fc->inonacross);
1016 /* error handling here, make sure curbound is a cons */
1017 CHECK_CONS(fc->curbound);
1018 fc->curval = XCAR(fc->curbound);
1020 case FOR_ON_SUBLIST_CLAUSE:
1021 fc->curbound = Feval(fc->inonacross);
1022 CHECK_CONS(fc->curbound);
1023 fc->curval = fc->curbound;
1025 case FOR_ACROSS_ARRAY_CLAUSE:
1026 fc->curbound = Feval(fc->inonacross);
1027 fc->bound = XINT(Flength(fc->curbound));
1028 /* CHECK_ARRAY(fc->curbound); */
1030 fc->curval = Faref(fc->curbound, Qzero);
1032 case FOR_EQUALS_THEN_CLAUSE:
1033 fc->curval = Feval(fc->equals);
1036 case FOR_OF_HASHTABLE_CLAUSE: {
1038 fc->curbound = Feval(fc->inonacross);
1039 e = cl_loop_next_hentry(
1040 NULL, XHASH_TABLE(fc->curbound));
1041 if ((fc->ptr1 = e) == NULL) {
1047 case FOR_INVALID_CLAUSE:
1049 /* there are `for' subclauses without stuff in the prologue */
1056 cl_loop_perform_for_pro_b(cl_loop_for_clause_t *fc)
1058 switch (fc->for_subclause) {
1059 case FOR_ARITHMETIC_CLAUSE:
1060 case FOR_IN_SUBLIST_CLAUSE:
1061 case FOR_ON_SUBLIST_CLAUSE:
1062 case FOR_ACROSS_ARRAY_CLAUSE:
1063 case FOR_EQUALS_THEN_CLAUSE:
1064 cl_loop_destructuring_bind(specbind, fc->form1, fc->curval);
1067 case FOR_OF_HASHTABLE_CLAUSE: {
1068 hentry_t e = fc->ptr1;
1072 if (!NILP(fc->hash_keyvar)) {
1073 cl_loop_destructuring_bind(
1074 specbind, fc->hash_keyvar, e->key);
1076 if (!NILP(fc->hash_valvar)) {
1077 cl_loop_destructuring_bind(
1078 specbind, fc->hash_valvar, e->value);
1082 case FOR_INVALID_CLAUSE:
1084 /* there are `for' subclauses without stuff in the prologue */
1091 cl_loop_perform_for_pro(cl_loop_for_clause_t *fc)
1093 if (fc->depth == 1) {
1094 /* optimise for the trivial case */
1095 cl_loop_perform_for_pro_i(fc);
1096 cl_loop_perform_for_pro_b(fc);
1101 cl_loop_perform_for_pro_i(fc);
1103 while (!NILP(tra)) {
1104 cl_loop_for_clause_t *fct = get_dynacat(tra);
1105 cl_loop_perform_for_pro_i(fct);
1109 /* now specbind them */
1110 cl_loop_perform_for_pro_b(fc);
1112 while (!NILP(tra)) {
1113 cl_loop_for_clause_t *fct = get_dynacat(tra);
1114 cl_loop_perform_for_pro_b(fct);
1121 cl_loop_perform_for_i(cl_loop_for_clause_t *fc)
1123 /* non stepping stuff */
1124 switch (fc->for_subclause) {
1125 case FOR_EQUALS_THEN_CLAUSE:
1126 if (fc->counter++) {
1127 cl_loop_destructuring_bind(
1128 (cl_loop_binder_f)Fset, fc->form1,
1129 fc->curval = Feval(fc->then));
1132 case FOR_INVALID_CLAUSE:
1133 case FOR_ARITHMETIC_CLAUSE:
1134 case FOR_IN_SUBLIST_CLAUSE:
1135 case FOR_ON_SUBLIST_CLAUSE:
1136 case FOR_ACROSS_ARRAY_CLAUSE:
1137 case FOR_OF_HASHTABLE_CLAUSE:
1145 cl_loop_perform_for_b(cl_loop_for_clause_t *fc)
1147 switch (fc->for_subclause) {
1148 case FOR_ARITHMETIC_CLAUSE:
1149 case FOR_IN_SUBLIST_CLAUSE:
1150 case FOR_ON_SUBLIST_CLAUSE:
1151 case FOR_ACROSS_ARRAY_CLAUSE:
1152 /* bind to the value computed during the last iteration */
1153 cl_loop_destructuring_bind(
1154 (cl_loop_binder_f)Fset, fc->form1, fc->curval);
1155 case FOR_INVALID_CLAUSE:
1156 case FOR_OF_HASHTABLE_CLAUSE:
1157 case FOR_EQUALS_THEN_CLAUSE:
1162 /* most clauses step in this fun */
1163 switch (fc->for_subclause) {
1164 case FOR_EQUALS_THEN_CLAUSE:
1166 case FOR_ARITHMETIC_CLAUSE:
1167 fc->curval = ent_binop(fc->byop, fc->curval, fc->curstep);
1168 if (!fc->torel_strictp) {
1169 return ent_binrel2(fc->torel, ASE_BINARY_REL_EQUALP,
1170 fc->curval, fc->curbound);
1172 return ent_binrel(fc->torel, fc->curval, fc->curbound);
1175 case FOR_IN_SUBLIST_CLAUSE:
1176 /* error handling here, make sure curbound is a cons */
1177 fc->curbound = XCDR(fc->curbound);
1178 if (NILP(fc->curbound))
1180 fc->curval = XCAR(fc->curbound);
1183 case FOR_ON_SUBLIST_CLAUSE:
1184 /* error handling here, make sure curbound is a cons */
1185 if (NILP(fc->curval = XCDR(fc->curval)))
1189 case FOR_ACROSS_ARRAY_CLAUSE:
1191 if (fc->counter >= fc->bound)
1193 fc->curval = Faref(fc->curbound, make_int(fc->counter));
1196 case FOR_OF_HASHTABLE_CLAUSE: {
1197 hentry_t e = fc->ptr1;
1201 if (!NILP(fc->hash_keyvar)) {
1202 cl_loop_destructuring_bind(
1203 (cl_loop_binder_f)Fset,
1204 fc->hash_keyvar, e->key);
1206 if (!NILP(fc->hash_valvar)) {
1207 cl_loop_destructuring_bind(
1208 (cl_loop_binder_f)Fset,
1209 fc->hash_valvar, e->value);
1211 fc->ptr1 = cl_loop_next_hentry(e, XHASH_TABLE(fc->curbound));
1214 case FOR_INVALID_CLAUSE:
1222 cl_loop_perform_for(cl_loop_for_clause_t *fc)
1224 if (fc->depth == 1) {
1225 /* optimise for the trivial case */
1226 cl_loop_perform_for_i(fc);
1227 return cl_loop_perform_for_b(fc);
1232 cl_loop_perform_for_i(fc);
1234 while (!NILP(tra)) {
1235 cl_loop_for_clause_t *fct = get_dynacat(tra);
1236 cl_loop_perform_for_i(fct);
1240 /* now specbind them */
1241 state = cl_loop_perform_for_b(fc);
1243 while (!NILP(tra)) {
1244 cl_loop_for_clause_t *fct = get_dynacat(tra);
1245 state &= cl_loop_perform_for_b(fct);
1253 cl_loop_perform_do(cl_loop_do_clause_t *dc)
1260 cl_loop_perform_repeat(cl_loop_repeat_clause_t *rc)
1262 if (--rc->counter > 0) {
1269 cl_loop_perform_collect(cl_loop_accu_clause_t *ac)
1272 ac->cur = XCDR(ac->cur) = Fcons(Feval(ac->form), Qnil);
1274 Fset(ac->into, ac->cur = Fcons(Feval(ac->form), Qnil));
1280 cl_loop_perform_append(cl_loop_accu_clause_t *ac)
1282 Lisp_Object form = Feval(ac->form);
1285 XCDR(ac->cur) = form;
1287 Fset(ac->into, ac->cur = form);
1289 while (!NILP(XCDR(ac->cur)) && CONSP(XCDR(ac->cur)))
1290 ac->cur = XCDR(ac->cur);
1291 if (CONSP(ac->cur) && NILP(XCDR(ac->cur)))
1294 return wrong_type_argument(Qlistp, form);
1298 cl_loop_perform_nconc(cl_loop_accu_clause_t *ac)
1300 Lisp_Object form = Feval(ac->form);
1301 if (!NILP(ac->cur) && CONSP(ac->cur)) {
1302 XCDR(ac->cur) = form;
1304 Fset(ac->into, ac->cur = form);
1306 while (CONSP(ac->cur) &&
1307 !NILP(XCDR(ac->cur)) &&
1308 CONSP(XCDR(ac->cur)))
1309 ac->cur = XCDR(ac->cur);
1314 cl_loop_perform_count(cl_loop_accu_clause_t *ac)
1316 if (!NILP(Feval(ac->form))) {
1317 Fset(ac->into, ac->cur = make_int(XINT(ac->cur)+1));
1323 cl_loop_perform_sum(cl_loop_accu_clause_t *ac)
1325 Lisp_Object form = Feval(ac->form);
1328 ac->cur = ent_binop(ASE_BINARY_OP_SUM, ac->cur, form));
1333 cl_loop_perform_maximise(cl_loop_accu_clause_t *ac)
1335 Lisp_Object form = Feval(ac->form);
1337 if (ent_binrel(ASE_BINARY_REL_GREATERP, form, ac->cur))
1338 Fset(ac->into, ac->cur = form);
1343 cl_loop_perform_minimise(cl_loop_accu_clause_t *ac)
1345 Lisp_Object form = Feval(ac->form);
1347 if (ent_binrel(ASE_BINARY_REL_LESSP, form, ac->cur))
1348 Fset(ac->into, ac->cur = form);
1352 static inline Lisp_Object
1353 cl_loop_perform_accu_epi()
1354 __attribute__((always_inline));
1355 static inline Lisp_Object
1356 cl_loop_perform_accu_epi(
1357 Lisp_Object *SXE_UNUSED(result), cl_loop_accu_clause_t *ac)
1359 return symbol_value(XSYMBOL(ac->into));
1362 static inline Lisp_Object
1363 cl_loop_perform_finally_epi()
1364 __attribute__((always_inline));
1365 static inline Lisp_Object
1366 cl_loop_perform_finally_epi(
1367 Lisp_Object *SXE_UNUSED(result), cl_loop_inifinret_clause_t *rc)
1369 return Feval(rc->form);
1372 static inline Lisp_Object
1373 cl_loop_perform_return_epi()
1374 __attribute__((always_inline));
1375 static inline Lisp_Object
1376 cl_loop_perform_return_epi(
1377 Lisp_Object *result, cl_loop_inifinret_clause_t *rc)
1379 return *result = Feval(rc->form);
1384 cl_loop_prologue(Lisp_Object clause)
1388 emp = get_dynacat(clause);
1389 if (EQ(get_dynacat_type(clause), Qcl_loop_repeat_clause)) {
1390 cl_loop_perform_repeat_pro(emp);
1393 if (EQ(get_dynacat_type(clause), Qcl_loop_for_clause)) {
1394 cl_loop_perform_for_pro(emp);
1397 if (EQ(get_dynacat_type(clause), Qcl_loop_with_clause)) {
1398 cl_loop_perform_with_pro(emp);
1401 if (EQ(get_dynacat_type(clause), Qcl_loop_collect_clause)) {
1402 cl_loop_perform_colappnco_pro(emp);
1405 if (EQ(get_dynacat_type(clause), Qcl_loop_append_clause)) {
1406 cl_loop_perform_colappnco_pro(emp);
1409 if (EQ(get_dynacat_type(clause), Qcl_loop_nconc_clause)) {
1410 cl_loop_perform_colappnco_pro(emp);
1413 if (EQ(get_dynacat_type(clause), Qcl_loop_count_clause)) {
1414 cl_loop_perform_countsum_pro(emp);
1417 if (EQ(get_dynacat_type(clause), Qcl_loop_sum_clause)) {
1418 cl_loop_perform_countsum_pro(emp);
1421 if (EQ(get_dynacat_type(clause), Qcl_loop_maximise_clause)) {
1422 cl_loop_perform_maximise_pro(emp);
1425 if (EQ(get_dynacat_type(clause), Qcl_loop_minimise_clause)) {
1426 cl_loop_perform_minimise_pro(emp);
1429 if (EQ(get_dynacat_type(clause), Qcl_loop_initially_clause)) {
1430 cl_loop_perform_initially_pro(emp);
1438 cl_loop_epilogue(Lisp_Object *result, Lisp_Object clause)
1442 emp = get_dynacat(clause);
1443 if (EQ(get_dynacat_type(clause), Qcl_loop_collect_clause)) {
1444 return cl_loop_perform_accu_epi(result, emp);
1446 if (EQ(get_dynacat_type(clause), Qcl_loop_append_clause)) {
1447 return cl_loop_perform_accu_epi(result, emp);
1449 if (EQ(get_dynacat_type(clause), Qcl_loop_nconc_clause)) {
1450 return cl_loop_perform_accu_epi(result, emp);
1452 if (EQ(get_dynacat_type(clause), Qcl_loop_count_clause)) {
1453 return cl_loop_perform_accu_epi(result, emp);
1455 if (EQ(get_dynacat_type(clause), Qcl_loop_sum_clause)) {
1456 return cl_loop_perform_accu_epi(result, emp);
1458 if (EQ(get_dynacat_type(clause), Qcl_loop_maximise_clause)) {
1459 return cl_loop_perform_accu_epi(result, emp);
1461 if (EQ(get_dynacat_type(clause), Qcl_loop_minimise_clause)) {
1462 return cl_loop_perform_accu_epi(result, emp);
1464 if (EQ(get_dynacat_type(clause), Qcl_loop_return_clause)) {
1465 return cl_loop_perform_return_epi(result, emp);
1467 if (EQ(get_dynacat_type(clause), Qcl_loop_finally_clause)) {
1468 return cl_loop_perform_finally_epi(result, emp);
1470 return Qnull_pointer;
1474 cl_loop_iteration(Lisp_Object clause)
1478 emp = get_dynacat(clause);
1479 if (EQ(get_dynacat_type(clause), Qcl_loop_repeat_clause))
1480 return cl_loop_perform_repeat(emp);
1481 if (EQ(get_dynacat_type(clause), Qcl_loop_for_clause))
1482 return cl_loop_perform_for(emp);
1483 if (EQ(get_dynacat_type(clause), Qcl_loop_do_clause))
1484 return cl_loop_perform_do(emp);
1485 if (EQ(get_dynacat_type(clause), Qcl_loop_collect_clause))
1486 return cl_loop_perform_collect(emp);
1487 if (EQ(get_dynacat_type(clause), Qcl_loop_append_clause))
1488 return cl_loop_perform_append(emp);
1489 if (EQ(get_dynacat_type(clause), Qcl_loop_nconc_clause))
1490 return cl_loop_perform_nconc(emp);
1491 if (EQ(get_dynacat_type(clause), Qcl_loop_count_clause))
1492 return cl_loop_perform_count(emp);
1493 if (EQ(get_dynacat_type(clause), Qcl_loop_sum_clause))
1494 return cl_loop_perform_sum(emp);
1495 if (EQ(get_dynacat_type(clause), Qcl_loop_maximise_clause))
1496 return cl_loop_perform_maximise(emp);
1497 if (EQ(get_dynacat_type(clause), Qcl_loop_minimise_clause))
1498 return cl_loop_perform_minimise(emp);
1504 cl_loop_dllist_map(int(*fun)(Lisp_Object), dllist_t dll)
1507 dllist_item_t item = dllist_first(dll);
1515 state &= fun((Lisp_Object)item->item);
1522 cl_loop_dllist_map_return(
1523 Lisp_Object *result,
1524 Lisp_Object(*fun)(Lisp_Object*, Lisp_Object), dllist_t dll)
1526 dllist_item_t item = dllist_first(dll);
1527 Lisp_Object ret = Qnil;
1534 ret = fun(result, (Lisp_Object)item->item);
1537 if (!EQ(ret, Qnull_pointer))
1544 cl_loop_perform(cl_loop_sentence_t *lsen)
1546 dllist_t pro = XDLLIST(lsen->prologue);
1547 dllist_t epi = XDLLIST(lsen->epilogue);
1548 dllist_t iter = XDLLIST(lsen->iteration);
1549 int speccount = specpdl_depth();
1554 /* traverse the prologue */
1555 cl_loop_dllist_map(cl_loop_prologue, pro);
1556 /* traverse the iteration */
1557 while (lsen->state) {
1559 lsen->state = cl_loop_dllist_map(cl_loop_iteration, iter);
1561 /* traverse the epilogue */
1562 lsen->result = Qnull_pointer;
1563 res = cl_loop_dllist_map_return(&lsen->result, cl_loop_epilogue, epi);
1565 unbind_to(speccount, Qnil);
1567 return lsen->result;
1574 DEFUN("cl:loop-sentence", Fcl_loop_sentence, 0, UNEVALLED, 0, /*
1575 Part of The Common Lisp loop macro.
1580 Lisp_Object loop_sentence = cl_loop_make_sentence();
1581 Lisp_Object context = Qnil, token = Qnil;
1582 cl_loop_sentence_t *lsen = get_dynacat(loop_sentence);
1584 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1586 GCPRO4(args, loop_sentence, context, token);
1588 /* now parse the stuff */
1589 parse_result = cl_loop_yyparse(&args, lsen, &context, &token);
1593 return loop_sentence;
1596 DEFUN("cl:loop*", Fcl_loopX, 1, 1, 0, /*
1597 Execute LOOP-SENTENCE.
1601 Lisp_Object result = Qnil;
1602 struct gcpro gcpro1, gcpro2;
1604 CHECK_CL_LOOP_SENTENCE(loop_sentence);
1606 GCPRO2(result, loop_sentence);
1608 result = cl_loop_perform(XCL_LOOP_SENTENCE(loop_sentence));
1614 DEFUN("cl:loop", Fcl_loop, 0, UNEVALLED, 0, /*
1615 (loop CLAUSE...): The Common Lisp loop macro.
1617 Overview of valid clauses:
1618 for VAR from/upfrom/downfrom NUM to/upto/downto/above/below NUM by NUM,
1619 for VAR in LIST by FUNC, for VAR on LIST by FUNC, for VAR = INIT then EXPR,
1620 for VAR across ARRAY, repeat NUM, with VAR = INIT, while COND, until COND,
1621 always COND, never COND, thereis COND, collect EXPR into VAR,
1622 append EXPR into VAR, nconc EXPR into VAR, sum EXPR into VAR,
1623 count EXPR into VAR, maximize EXPR into VAR, minimize EXPR into VAR,
1624 if COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...],
1625 unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...],
1626 do EXPRS..., initially EXPRS..., finally EXPRS..., return EXPR,
1627 finally return EXPR, named NAME.
1629 The loop macro consists of a series of clauses, which do things like
1630 iterate variables, set conditions for exiting the loop, accumulating values
1631 to be returned as the return value of the loop, and executing arbitrary
1632 blocks of code. Each clause is proceed in turn, and the loop executes its
1633 body repeatedly until an exit condition is hit.
1635 It's important to understand that loop clauses such as `for' and `while',
1636 which look like loop-establishing constructs, don't actually *establish* a
1637 loop; the looping is established by the `loop' clause itself, which will
1638 repeatedly process its body until told to stop. `while' merely establishes
1639 a condition which, when true, causes the loop to finish, and `for' sets a
1640 variable to different values on each iteration (e.g. successive elements of
1641 a list) and sets an exit condition when there are no more values. This
1642 means, for example, that if two `for' clauses appear, you don't get two
1643 nested loops, but instead two variables that are stepped in parallel, and
1644 two exit conditions, either of which, if triggered, will cause the loop to
1645 end. Similarly for a loop with a `for' and a `while' clause. For example:
1652 In each successive iteration, X is set to the next element of the list. If
1653 there are no more elements, or if any element is nil (the `while' clause),
1654 the loop exits. Otherwise, the block of code following `do' is executed.)
1656 This example also shows that some clauses establish variable bindings --
1657 essentially like a `let' binding -- and that following clauses can
1658 reference these variables. Furthermore, the entire loop is surrounded by a
1659 block named nil (unless the `named' clause is given), so you can return
1660 from the loop using the macro `return'. (The other way to exit the loop is
1661 through the macro `loop-finish'. The difference is that some loop clauses
1662 establish or accumulate a value to be returned, and `loop-finish' returns
1663 this. `return', however, can only return an explicitly-specified value.
1664 NOTE CAREFULLY: There is a loop clause called `return' as well as a
1665 standard Lisp macro called `return'. Normally they work similarly; but if
1666 you give the loop a name with `named', you will need to use the macro
1669 Another extremely useful feature of loops is called "destructuring". If,
1670 in place of VAR, a list (possibly dotted, possibly a tree of arbitary
1671 complexity) is given, the value to be assigned is assumed to have a similar
1672 structure to the list given, and variables in the list will be matched up
1673 with corresponding elements in the structure. For example:
1676 for (x y) in '((foo 1) (bar 2) (baz 3))
1677 do (puthash x y some-hash-table))
1679 will add three elements to a hash table, mapping foo -> 1, bar -> 2, and
1680 baz -> 3. As other examples, you can conveniently process alists using
1682 (loop for (x . y) in alist do ...)
1686 (loop for (x y) on plist by #'cddr do ...)
1688 Destructuring is forgiving in that mismatches in the number of elements on
1689 either size will be handled gracefully, either by ignoring or initializing
1692 If you don't understand how a particular loop clause works, create an
1693 example and use `macroexpand-sexp' to expand the macro.
1695 In greater detail, valid clauses are:
1697 (NOTE: Keywords in lowercase; slashes separate different possibilities
1698 for keywords, some of which are synonymous; brackets indicate optional
1699 parts of the clause. In all of the clauses with `being', the word `being',
1700 the words `each' or `the', and the difference between singular and plural
1701 keywords are all just syntactic sugar. Stylistically, you should write
1702 either `being each foo' or `being the foos'.)
1704 for VAR from/upfrom/downfrom NUM1 to/upto/downto/above/below NUM2 [by NUMSTEP]
1705 Step VAR across numbers. `upfrom', `upto', and `below' explicitly
1706 indicate upward stepping; `downfrom', `downto', and `above' explicitly
1707 indicate downward stepping. (If none of these is given, the default is
1708 upward.) `to', `upto', and `downto' cause stepping to include NUM2 as
1709 the last iteration, while `above' and `below' stop just before reaching
1710 NUM2. `by' can be given to indicate a stepping increment other than 1.
1712 for VAR in LIST [by FUNC]
1713 Step VAR over elements of a LIST. FUNC specifies how to get successive
1714 sublists and defaults to `cdr'.
1716 for VAR on LIST [by FUNC]
1717 Step VAR over tails of a LIST. FUNC specifies how to get successive
1718 sublists and defaults to `cdr'.
1720 for VAR in-ref LIST [by FUNC]
1721 Step VAR over elements of a LIST, like `for ... in', except the VAR is
1722 bound using `symbol-macrolet' instead of `let'. In essence, VAR is set
1723 to a "reference" to the list element instead of the element itself;
1724 this us, you can destructively modify the list using `setf' on VAR, and
1725 any changes to the list will "magically" reflect themselves in
1726 subsequent uses of VAR.
1728 for VAR = INIT [then EXPR]
1729 Set VAR on each iteration of the loop. If only INIT is given, use it
1730 on each iteration. Otherwise, use INIT on the first iteration and EXPR
1733 for VAR across/across-ref ARRAY
1734 Step VAR across a sequence other than a list (string, vector, bit
1735 vector). If `across-ref' is given, VAR is bound using
1736 `symbol-macrolet' instead of `let' -- see above.
1738 for VAR being each/the element/elements in/of/in-ref/of-ref SEQUENCE [using (index INDEX-VAR)]
1739 Step VAR across any sequence. A variable can be specified with a
1740 `using' phrase to receive the index, starting at 0. If `in-ref' or
1741 `of-ref' is given, VAR is bound using `symbol-macrolet' instead of
1744 for VAR being each/the hash-key/hash-keys/hash-value/hash-values in/of HASH-TABLE [using (hash-value/hash-key OTHER-VAR)]
1746 for VAR being each/the hash-key/hash-keys/hash-value/hash-values in/of HASH-TABLE [using (hash-value/hash-key OTHER-VAR)]
1747 Map VAR over a hash table. The various keywords are synonymous except
1748 those that distinguish between keys and values. The `using' phrase is
1749 optional and allows both key and value to be bound.
1751 for VAR being each/the symbol/present-symbol/external-symbol/symbols/present-symbols/external-symbols in/of OBARRAY
1752 Map VAR over the symbols in an obarray. All symbol keywords are
1753 currently synonymous.
1755 for VAR being each/the extent/extents [in/of BUFFER-OR-STRING] [from POS] [to POS]
1756 Map VAR over the extents in a buffer or string, defaulting to the
1757 current buffer, the beginning and the end, respectively.
1759 for VAR being each/the interval/intervals [in/of BUFFER-OR-STRING] [property PROPERTY] [from POS] [to POS]
1760 Map VAR over the intervals without property change in a buffer or
1761 string, defaulting to the current buffer, the beginning and the end,
1762 respectively. If PROPERTY is given, iteration occurs using
1763 `next-single-property-change'; otherwise, using
1764 `next-property-change'.
1766 for VAR being each/the window/windows [in/of FRAME]
1767 Step VAR over the windows in FRAME, defaulting to the selected frame.
1769 for VAR being each/the frame/frames
1770 Step VAR over all frames.
1772 for VAR being each/the buffer/buffers [by FUNC]
1773 Step VAR over all buffers. This is actually equivalent to
1774 `for VAR in (buffer-list) [by FUNC]'.
1776 for VAR being each/the key-code/key-codes/key-seq/key-seqs/key-binding/key-bindings in KEYMAP [using (key-code/key-codes/key-seq/key-seqs/key-binding/key-bindings OTHER-VAR)]
1777 Map VAR over the entries in a keymap. Keyword `key-seq' causes
1778 recursive mapping over prefix keymaps occurring in the keymap, with VAR
1779 getting the built-up sequence (a vector). Otherwise, mapping does not
1780 occur recursively. `key-code' and `key-seq' refer to what is bound
1781 (second argument of `define-key'), and `key-binding' what it's bound to
1782 (third argument of `define-key').
1785 `as' is a synonym for `for'.
1788 `and' clauses have the same syntax as `for' clauses except that the
1789 variables in the clause are bound in parallel with a preceding
1790 `and'/`for' clause instead of in series.
1793 Set VAR to INIT once, before doing any iterations.
1796 Exit the loop if more than NUM iterations have occurred.
1799 Exit the loop if COND isn't true.
1802 Exit the loop if COND is true.
1804 collect EXPR [into VAR]
1805 Push EXPR onto the end of a list of values -- stored either in VAR or a
1806 temporary variable that will be returned as the return value of the
1807 loop if it terminates through an exit condition or a call to
1810 append EXPR [into VAR]
1811 Append EXPR (a list) onto the end of a list of values, like `collect'.
1813 nconc EXPR [into VAR]
1814 Nconc EXPR (a list) onto the end of a list of values, like `collect'.
1816 concat EXPR [into VAR]
1817 Concatenate EXPR (a string) onto the end of a string of values, like
1820 vconcat EXPR [into VAR]
1821 Concatenate EXPR (a vector) onto the end of a vector of values, like
1824 bvconcat EXPR [into VAR]
1825 Concatenate EXPR (a bit vector) onto the end of a bit vector of values,
1829 Add EXPR to a value, like `collect'.
1831 count EXPR [into VAR]
1832 If EXPR is true, increment a value by 1, like `collect'.
1834 maximize EXPR [into VAR]
1835 IF EXPR is greater than a value, replace the value with EXPR, like
1838 minimize EXPR [into VAR]
1839 IF EXPR is less than a value, replace the value with EXPR, like
1843 If COND is true, continue the loop and set the loop return value (the
1844 same value that's manipulated by `collect' and friends and is returned
1845 by a normal loop exit or an exit using `loop-finish') to t; otherwise,
1846 exit the loop and return nil. The effect is to determine and return
1847 whether a condition is true "always" (all iterations of the loop).
1850 If COND is false, continue the loop and set the loop return value (like
1851 `always') to t; otherwise, exit the loop and return nil. The effect
1852 is to determine and return whether a condition is "never" true (all
1853 iterations of the loop).
1856 If COND is true, exit the loop and return COND.
1858 if/when COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...]
1859 If COND is true, execute the directly following clause(s); otherwise,
1860 execute the clauses following `else'.
1862 unless COND CLAUSE [and CLAUSE]... else CLAUSE [and CLAUSE...]
1863 If COND is false, execute the directly following clause(s); otherwise, execute the clauses following `else'.
1866 Execute the expressions (any Lisp forms).
1869 Execute EXPR once, before doing any iterations, and after values have
1870 been set using `with'.
1873 Execute EXPR once, directly before the loop terminates. This will not
1874 be executed if the loop terminates prematurely as a result of `always',
1875 `never', `thereis', or `return'.
1878 Exit from the loop and return EXPR.
1881 Specify the value to be returned when the loop exits. (Unlike `return',
1882 this doesn't cause the loop to immediately exit; it will exit whenever
1883 it normally would have.) This takes precedence over a return value
1884 specified with `collect' and friends or `always' and friends.
1887 Specify the name for block surrounding the loop, in place of nil.
1892 Lisp_Object loop_sentence = Qnil;
1893 Lisp_Object result = Qnil;
1894 struct gcpro gcpro1, gcpro2;
1895 cl_loop_sentence_t *lsen;
1905 GCPRO2(result, loop_sentence);
1907 loop_sentence = Fcl_loop_sentence(args);
1908 lsen = get_dynacat(loop_sentence);
1909 result = cl_loop_perform(lsen);
1916 DEFUN("cl:do", Fcl_do, 2, UNEVALLED, 0, /*
1917 The Common Lisp `do' loop.
1918 Format is: (do ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)
1922 /* This function can GC */
1923 Lisp_Object varform = XCAR(args);
1924 Lisp_Object endform = XCAR(XCDR(args));
1925 Lisp_Object body = XCDR(XCDR(args));
1926 Lisp_Object result = Qnil;
1927 Lisp_Object endtest = Qnil, resultform = Qnil;
1928 struct gcpro gcpro1, gcpro2;
1929 int speccount = specpdl_depth();
1931 CHECK_CONS(varform);
1932 CHECK_CONS(endform);
1934 GCPRO2(endtest, resultform);
1936 endtest = XCAR(endform);
1937 resultform = XCDR(endform);
1940 varform, endtest, resultform, body,
1941 emodcl_initialise_vars, emodcl_step_vars);
1943 unbind_to(speccount, Qnil);
1949 DEFUN("cl:do*", Fcl_doX, 2, UNEVALLED, 0, /*
1950 The Common Lisp `do*' loop.
1951 Format is: (do* ((VAR INIT [STEP])...) (END-TEST [RESULT...]) BODY...)
1955 /* This function can GC */
1956 Lisp_Object varform = XCAR(args);
1957 Lisp_Object endform = XCAR(XCDR(args));
1958 Lisp_Object body = XCDR(XCDR(args));
1959 Lisp_Object result = Qnil;
1960 Lisp_Object endtest = Qnil, resultform = Qnil;
1961 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1962 int speccount = specpdl_depth();
1964 CHECK_CONS(varform);
1965 CHECK_CONS(endform);
1967 GCPRO4(result, endtest, resultform, body);
1969 endtest = XCAR(endform);
1970 resultform = XCDR(endform);
1973 varform, endtest, resultform, body,
1974 emodcl_initialise_vars_star, emodcl_step_vars_star);
1976 unbind_to(speccount, Qnil);
1984 DEFUN("cl:dotimes", Fcl_dotimes, 1, UNEVALLED, 0, /*
1985 The Common Lisp `dotimes' loop.
1986 Format is: (dotimes (VAR COUNT [RESULT]) BODY...)
1988 Loop a certain number of times. Evaluate BODY with VAR bound to
1989 successive integers from 0, inclusive,to COUNT, exclusive. Then
1990 evaluate RESULT to get return value, default nil.
1994 /* This function can GC */
1995 Lisp_Object varform = XCAR(args);
1996 Lisp_Object body = XCDR(args);
1997 Lisp_Object result = Qnil;
1998 Lisp_Object varsym = Qnil, varcnt = Qnil, resultform = Qnil;
1999 struct gcpro gcpro1, gcpro2, gcpro3;
2000 int speccount = specpdl_depth();
2003 CHECK_CONS(varform);
2004 CHECK_CONS(XCDR(varform));
2005 CHECK_SYMBOL(varsym = XCAR(varform));
2007 GCPRO3(result, varform, body);
2008 CHECK_NATNUM(varcnt = Feval(XCAR(XCDR(varform))));
2010 specbind(varsym, Qzero);
2011 for (j = 0; j < XUINT(varcnt); j++) {
2012 Fset(varsym, make_int(j));
2013 LIST_LOOP_2(form, body) {
2018 if (!NILP(resultform = XCDR(XCDR(varform)))) {
2019 LIST_LOOP_2(form, resultform) {
2020 result = Feval(form);
2024 unbind_to(speccount, Qnil);
2030 DEFUN("cl:dolist", Fcl_dolist, 1, UNEVALLED, 0, /*
2031 The Common Lisp `dolist' loop.
2032 Format is: (dolist (VAR LIST [RESULT]) BODY...)
2034 Evaluate BODY with VAR bound to each `car' from LIST, in turn.
2035 Then evaluate RESULT to get return value, default nil.
2039 /* This function can GC */
2040 Lisp_Object varform = XCAR(args);
2041 Lisp_Object body = XCDR(args);
2042 Lisp_Object result = Qnil;
2043 Lisp_Object varsym = Qnil, list = Qnil, resultform = Qnil;
2044 struct gcpro gcpro1, gcpro2, gcpro3;
2045 int speccount = specpdl_depth();
2047 CHECK_CONS(varform);
2048 CHECK_CONS(XCDR(varform));
2049 CHECK_SYMBOL(varsym = XCAR(varform));
2051 GCPRO3(result, varform, body);
2052 list = Feval(XCAR(XCDR(varform)));
2060 specbind(varsym, Qnil);
2061 while (!NILP(list)) {
2062 Fset(varsym, XCAR(list));
2063 LIST_LOOP_2(form, body) {
2070 if (!NILP(resultform = XCDR(XCDR(varform)))) {
2071 LIST_LOOP_2(form, resultform) {
2072 result = Feval(form);
2076 unbind_to(speccount, Qnil);
2081 extern Lisp_Object check_obarray(Lisp_Object obarray);
2083 DEFUN("cl:do-symbols", Fcl_do_symbols, 1, UNEVALLED, 0, /*
2084 The Common Lisp `dolist' loop.
2085 Format is: (do-symbols (VAR [OBARRAY [RESULT]]) BODY...)
2086 loop over all symbols.
2087 Evaluate BODY with VAR bound to each interned symbol, or to each symbol
2092 /* This function can GC */
2093 Lisp_Object varform = XCAR(args);
2094 Lisp_Object body = XCDR(args);
2095 Lisp_Object result = Qnil;
2096 Lisp_Object varsym = Qnil, obarr = Qnil, resultform = Qnil;
2097 struct gcpro gcpro1, gcpro2, gcpro3;
2098 int speccount = specpdl_depth();
2101 CHECK_CONS(varform);
2102 CHECK_SYMBOL(varsym = XCAR(varform));
2104 GCPRO3(result, varform, body);
2106 if (NILP(XCDR(varform))) {
2109 CHECK_CONS(XCDR(varform));
2110 obarr = Feval(XCAR(XCDR(varform)));
2112 obarr = check_obarray(obarr);
2114 specbind(varsym, Qnil);
2115 for (j = XVECTOR_LENGTH(obarr)-1; j >= 0; j--) {
2116 Lisp_Object tail = XVECTOR_DATA(obarr)[j];
2121 LIST_LOOP_2(form, body) {
2124 next = symbol_next(XSYMBOL(tail));
2127 XSETSYMBOL(tail, next);
2131 if (!NILP(XCDR(varform)) &&
2132 !NILP(resultform = XCDR(XCDR(varform)))) {
2133 LIST_LOOP_2(form, resultform) {
2134 result = Feval(form);
2138 unbind_to(speccount, Qnil);
2144 DEFUN("cl:do-all-symbols", Fcl_do_all_symbols, 1, UNEVALLED, 0, /*
2145 The Common Lisp `dolist' loop.
2146 Format is: (do-all-symbols (VAR [RESULT]) BODY...)
2150 /* This function can GC */
2151 Lisp_Object varform = XCAR(args);
2152 Lisp_Object body = XCDR(args);
2153 Lisp_Object result = Qnil;
2154 Lisp_Object varsym = Qnil, obarr = Qnil, resultform = Qnil;
2155 struct gcpro gcpro1, gcpro2, gcpro3;
2156 int speccount = specpdl_depth();
2159 CHECK_CONS(varform);
2160 CHECK_SYMBOL(varsym = XCAR(varform));
2162 GCPRO3(result, varform, body);
2166 specbind(varsym, Qnil);
2167 for (j = XVECTOR_LENGTH(obarr)-1; j >= 0; j--) {
2168 Lisp_Object tail = XVECTOR_DATA(obarr)[j];
2173 LIST_LOOP_2(form, body) {
2176 next = symbol_next(XSYMBOL(tail));
2179 XSETSYMBOL(tail, next);
2183 if (!NILP(resultform = XCDR(varform))) {
2184 LIST_LOOP_2(form, resultform) {
2185 result = Feval(form);
2189 unbind_to(speccount, Qnil);
2195 /* simplified initialisation */
2199 DEFSUBR(Fcl_loop_sentence);
2204 DEFSUBR(Fcl_dotimes);
2205 DEFSUBR(Fcl_dolist);
2206 DEFSUBR(Fcl_do_symbols);
2207 DEFSUBR(Fcl_do_all_symbols);
2209 DEFSYMBOL(Qcl_loop_sentence);
2210 DEFSYMBOL(Qcl_loop_sentence_p);
2211 DEFSYMBOL(Qcl_loop_for_clause);
2212 DEFSYMBOL(Qcl_loop_for_clause_p);
2213 DEFSYMBOL(Qcl_loop_do_clause);
2214 DEFSYMBOL(Qcl_loop_do_clause_p);
2215 DEFSYMBOL(Qcl_loop_with_clause);
2216 DEFSYMBOL(Qcl_loop_with_clause_p);
2217 DEFSYMBOL(Qcl_loop_repeat_clause);
2218 DEFSYMBOL(Qcl_loop_repeat_clause_p);
2219 DEFSYMBOL(Qcl_loop_append_clause);
2220 DEFSYMBOL(Qcl_loop_append_clause_p);
2221 DEFSYMBOL(Qcl_loop_collect_clause);
2222 DEFSYMBOL(Qcl_loop_collect_clause_p);
2223 DEFSYMBOL(Qcl_loop_nconc_clause);
2224 DEFSYMBOL(Qcl_loop_nconc_clause_p);
2225 DEFSYMBOL(Qcl_loop_return_clause);
2226 DEFSYMBOL(Qcl_loop_return_clause_p);
2227 DEFSYMBOL(Qcl_loop_finally_clause);
2228 DEFSYMBOL(Qcl_loop_finally_clause_p);
2229 DEFSYMBOL(Qcl_loop_initially_clause);
2230 DEFSYMBOL(Qcl_loop_initially_clause_p);
2231 DEFSYMBOL(Qcl_loop_count_clause);
2232 DEFSYMBOL(Qcl_loop_count_clause_p);
2233 DEFSYMBOL(Qcl_loop_sum_clause);
2234 DEFSYMBOL(Qcl_loop_sum_clause_p);
2235 DEFSYMBOL(Qcl_loop_minimise_clause);
2236 DEFSYMBOL(Qcl_loop_minimise_clause_p);
2237 DEFSYMBOL(Qcl_loop_maximise_clause);
2238 DEFSYMBOL(Qcl_loop_maximise_clause_p);
2243 DEFSYMBOL(Qdownfrom);
2258 DEFSYMBOL(Qhash_key);
2259 DEFSYMBOL(Qhash_keys);
2260 DEFSYMBOL(Qhash_value);
2261 DEFSYMBOL(Qhash_values);
2267 defsymbol(&Qequals, "=");
2270 DEFSYMBOL(Qappending);
2271 DEFSYMBOL(Qcollect);
2272 DEFSYMBOL(Qcollecting);
2274 DEFSYMBOL(Qnconcing);
2279 DEFSYMBOL(Qsumming);
2280 DEFSYMBOL(Qmaximise);
2281 DEFSYMBOL(Qmaximising);
2282 DEFSYMBOL(Qmaximize);
2283 DEFSYMBOL(Qmaximizing);
2284 DEFSYMBOL(Qminimise);
2285 DEFSYMBOL(Qminimising);
2286 DEFSYMBOL(Qminimize);
2287 DEFSYMBOL(Qminimizing);
2294 DEFSYMBOL(Qinitially);
2295 DEFSYMBOL(Qfinally);
2297 DEFSYMBOL(Qanon_acn);
2299 Fprovide(intern("cl-loop"));
2305 Frevoke(intern("cl-loop"));
2308 /* cl-loop.c ends here */