3 .\" Manual for control flow metaprogramming
5 .\" (c) 2023, 2024 Straylight/Edgeware
8 .\"----- Licensing notice ---------------------------------------------------
10 .\" This file is part of the mLib utilities library.
12 .\" mLib is free software: you can redistribute it and/or modify it under
13 .\" the terms of the GNU Library General Public License as published by
14 .\" the Free Software Foundation; either version 2 of the License, or (at
15 .\" your option) any later version.
17 .\" mLib is distributed in the hope that it will be useful, but WITHOUT
18 .\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 .\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
20 .\" License for more details.
22 .\" You should have received a copy of the GNU Library General Public
23 .\" License along with mLib. If not, write to the Free Software
24 .\" Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
27 .\"--------------------------------------------------------------------------
28 .so ../defs.man \" @@@PRE@@@
30 .\"--------------------------------------------------------------------------
31 .TH control 3mLib "23 April 2023" "Straylight/Edgeware" "mLib utilities library"
48 .\"--------------------------------------------------------------------------
50 control \- control structure metaprogramming
52 .\"--------------------------------------------------------------------------
56 .B "#include <mLib/control.h>"
58 .BI MC_BEFORE( tag ", " stmts ") " body
59 .BI MC_AFTER( tag ", " stmts ") " body
60 .BI MC_WRAP( tag ", " before_stmt ", " onend_stmt ", " onbreak_stmt ") " body
61 .BI MC_FINALLY( tag ", " cleanup ") " body
62 .BI MC_DOWHILE( tag ", " cond ") " body
63 .BI MC_DECL( tag ", " decl ") " body
64 .BI MC_LOOPELSE( tag ", " head ") " loop_body " \fR[\fBelse " else_body \fR]
65 .BI MC_LOOPBETWEEN( tag ", " setup ", " cond ", " step ") " loop_body " \fR[\fBelse " else_body \fR]
67 .BI MC_TARGET( tag ", " stmt ") " body
68 .BI MC_GOTARGET( tag );
69 .BI MC_ALLOWELSE( tag ") " main_body " \fR[\fBelse " else_body \fR]
77 .\"--------------------------------------------------------------------------
82 defines a number of macros which are useful
83 when defining new control structures for C.
84 They are inspired by Simon Tatham's article
85 .IR "Metaprogramming custom control structures in C",
86 though these macros differ from Tatham's in a few respects.
89 Each of these macros takes a
94 is lexically like an identifier,
95 except that it may begin with a digit,
96 so, for example, plain integers are acceptable tags.
97 Each use of an action macro by a user-level macro
100 If you're writing a new prefix action macro
101 written in terms of these existing actions,
102 your macro should receive a
106 along with a distinctive component of its own,
107 down to any prefix actions that it calls;
110 from each layer should be separated by a pair of underscores.
112 Some of these macros work by wrapping a loop around the
115 This interferes with the way that `free'
119 statements within the
122 we say that these statements are
131 if it doesn't appear lexically within a loop or
135 statement that is part of the
147 for (i = 0; i < n; i++)
148 if (interestingp(i)) break;
152 Some of these macros take special care
153 to give you control over what happens when a captured
156 Alas, proper handling of
158 doesn't seem possible.
165 arguments to these macros are never captured.
167 .SS "Prefix action macros"
169 macro is the simplest to understand. Executing
171 .BI MC_BEFORE( tag ", " stmt ") " body
173 has the same effect as executing
177 except that the whole thing is syntactically a single statement,
178 so, for example, it doesn't need to be enclosed in braces
183 does not capture free
191 .BI MC_AFTER( tag ", " stmt ") " body
195 the same effect as executing
199 Again, the whole thing is syntactically a single statement.
206 statements within the
212 abruptly ends execution of the
214 immediately transferring control to the
219 .BI MC_WRAP( tag ", " before ", " onend ", " onbreak ") " body
223 the same effect as executing
232 statement, then control abruptly continues with the
242 then control abruptly continues with the
245 but this behaviour is a bug and may be fixed in the future.
249 .BI MC_FINALLY( tag ", " cleanup ") " body
251 has the same effect as executing
261 before propagating the
263 to the enclosing context.
266 statement currently causes control to continue abruptly with
268 but this behaviour is a bug and may be fixed in the future.
271 code is textually duplicated,
272 so there'll be some code bloat if this is very complex.
273 If it arranges to have private long-term state
274 then the two copies will not share this state,
275 so probably don't do this.
279 .BI MC_DOWHILE( tag ", " cond ") " body
281 has exactly the same effect as
282 .BI "do " body " while (" cond ); \fR,
283 the only difference being that the
285 appears in tail position rather than sandwiched in the middle.
288 .BI MC_DECL( tag ", " decl ") " body
289 has the same effect as
290 .BI "{ " decl "; " body " }" \fR,
295 statements are captured.
298 statement will simply abruptly terminate execution of the
306 without leaving the scope of the
308 but these behaviours are bugs and may be fixed in the future.
312 macro makes use of the fact that a
314 statement can introduce a declaration
315 into its body's scope in C99 and C++;
316 the macro is not available in C89.
322 .BI MC_LOOPELSE( head ", " tag ") "
328 results in Python-like loop behaviour.
331 must be a valid loop head with one of the forms
334 .BI "while (" cond ")"
335 .BI "for (" decl "; " cond "; " next_expr ")"
336 .BI "MC_DOWHILE(" tag ", " cond ")"
339 The resulting loop executes the same as
347 If the loop ends abruptly, as a result of
349 then control is passed to the statement following the loop
351 However, if the loop completes naturally,
367 statements within the
375 .BI MC_LOOPBETWEEN( tag ", " setup ", " cond ", " step ") "
381 is similar to executing the
387 .BI "for (" setup "; " cond "; " step ") "
391 except that, once the
396 expression evaluated,
399 evaluated and determined to be nonzero,
402 (if any) is executed before re-entering the
404 This makes it a useful place to insert
405 any kind of interstitial material,
406 e.g., printing commas between list items.
407 Note that by the time the
410 the decision has already been made
411 that another iteration will be performed,
412 and, in particular, the
416 is therefore looking at the next item to be processed,
417 not the item that has just finished being processed.
420 is textually duplicated,
421 so there'll be some code bloat if this is very complex.
422 If it somehow manages to have private long-term state
423 (e.g., as a result of declaring static variables
424 inside GCC statement expressions)
425 then the two copies will not share this state,
426 so probably don't do this.
428 .SS "Lower-level machinery"
431 .BI MC_TARGET( tag ", " stmt ") " body
433 has exactly the same effect as simply executing
437 immediately transfers control to
439 with control continuing with the following statement,
450 This is most commonly useful in loops
451 in order to arrange the correct behaviour of a free
453 within the loop body.
454 See the example below,
455 which shows the definition
463 .BI MC_ALLOWELSE( tag ") "
469 has exactly the same effect as just
473 .BI MC_GOELSE( tag );
475 transfers control immediately to
478 control then naturally transfers to the following statement as usual.
483 statements in either of
491 works by secretly inserting an
493 statement head before the
495 so things will likely to wrong if
509 will be mis-associated;
516 the resulting program text is likely to provoke a compiler warning
521 it's relatively straightforward to define a macro like
525 .ta 4n 4n+\w'\fBMC_WRAP(tag##__body, 'u \n(.lu-\n(.iu-4n
526 #define MC_LOOPELSE(tag, head) \e
527 MC_TARGET(tag##__exit, { ; }) \e
528 MC_ALLOWELSE(tag##__else) \e
529 MC_AFTER(tag##__after, { MC_GOELSE(tag##__else); }) \e
531 MC_WRAP(tag##__body, { ; }, { ; }, \e
532 { MC_GOTARGET(tag##__exit); })
534 The main `trick' for these control-flow macros is
536 which wraps up a statement as an
539 .IR "statement head" ,
544 i.e., it must be completed by following it with a
549 .BI MC_ACT( stmt ") " body
551 has the same effect as simply executing
558 is a valid statement which does nothing,
561 is also a valid statement with the same effect as
563 The only way to cause
565 to be executed is to attach a label to it and transfer control using
570 .BI MC_LABEL( tag ") " body
572 has the same effect as
578 immediately transfers control to the
582 is syntactically an action,
583 i.e., it's wrapped in
587 here are scoped to the top-level source line,
590 in this macro package.
592 All of the control-flow macros in this package are mainly constructed from
597 sometimes with one or two other statement heads thrown into the mix.
602 .ta 4n 28n 30n \n(.lu-\n(.iu-4n
603 #define MC_AFTER(tag, stmt) \e
604 MC_GOTO(tag##__body) \e
605 MC_LABEL(tag##__end) \e
608 MC_GOTO(tag##__end) \e
609 MC_LABEL(tag##__body)
611 (The unusual layout is conventional,
612 to make the overall structure of the code clear
613 despite visual interference from the labels.)
619 Control enters at the start,
620 and is immediately transferred to the
628 completes, the loop restarts,
629 transferring control to
633 Since it is enclosed in
638 control transfers to the following statement.
640 .\"--------------------------------------------------------------------------
643 Some macros cause free
647 statements to behave in unexpected ways.
649 It's rather hard to use
651 in practice without provoking
652 .RB `dangling- else '
655 The need for tagging is ugly,
656 and the restriction on having two
657 user-facing control-flow macros on the same line is objectionable.
658 The latter could be avoided
659 by using nonstandard features such as GCC's
662 but adopting that would do programmers a disservice
663 by introducing a hazard for those
664 trying to port code to other compilers which lack any such feature.
666 .\"--------------------------------------------------------------------------
673 .IR "Metaprogramming custom control structures in C",
674 .BR "https://www.chiark.greenend.org.uk/~sgtatham/mp/" .
676 .\"--------------------------------------------------------------------------
679 Mark Wooding, <mdw@distorted.org.uk>
681 .\"----- That's all, folks --------------------------------------------------