Hi, Tadziu's opinion matters to me; I read every bit of troff he posts here because I normally learn something. :-) So I think it's worth trying to explain why the programming language side of troff could benefit from modernisation.
> I say we shouldn't change the interpretation of numeric expressions. > > 1. The arithmetic is well documented in the Troff User's Manual. Yep. And CSTR 54 is an excellent example of clear, succinct documentation. Something all those new to troff should read, and then keep going back to. > 2. It's going to make things more confusing by having n different > compatibility levels. Agreed. I'm not in favour of altering the existing binary compatibility flag. Especially since it's global in scope and distant from the code it affects. > 3. It's not necessary, because order of operations can always be > specified by using parentheses. They can. But a new syntax allows for more than just numeric expression and crude string equality tests without adding warts like 'c'a'b'c'd'e'. Source for the macro packages has benefited from .while instead of recursive macros, and I think a new syntax would also help... Many of us troff users cut their teeth in programming languages where control flow meant `IF ... GOTO' and global symbols limited to six or eight characters in large programs that did real work. Thus trained, we're happy to engage with troff's syntax. I also like sed and dc; constraints can be engaging to work in, being part of the puzzle. But new users to troff, and I think Peter's Mom can attract them, could well have been raised on C at best and Java at worst. If we're to have them step beyond the friendly macro package into doing a bit of troff, getting involved, helping keep interest going, perhaps specialised macros or preprocessors, or adding troff backends to other tools, then a nicer syntax for control flow and expressions would lower the hurdle. I'm not arguing for `.define' instead of `.de', or `.define-string-factory-visitor', just modern control flow and expression syntax. I think improving those will allow code to be clearer and more succinct. Easier to parse by newcomers, more pleasurable to write, less easy to get wrong. Here's a bit of mm picked because it uses a few `\{\'. .\" Copy to .de NS .sp .ie !''\\$2' .ds let*str \\$1 .el \{\ . ie \\n[.$]>0 \{\ . ie !\w'\\$1' .ds let*str \\*[Letns!\\*[Letnsdef]] . el \{\ . ie d Letns!\\$1 .ds let*str \\*[Letns!\\$1] . el .ds let*str \\*[Letns!copy](\\$1)\\*[Letns!to] . \} . \} . el .ds let*str \\*[Letns!\\*[Letnsdef]] .\} .ne 2 .nf \\*[let*str] .. I can skim through it and see the gist of what's going on. If I've translated it right, it could look more like .\" Copy to .de NS .sp .iff '\\$2' != '' { . ds let*str \\$1 .} else if \\n[.$] { . iff width('\\$1') == 0 { . ds let*str \\*[Letns!\\*[Letnsdef]] . } else if defined(Letns!\\$1) { . ds let*str \\*[Letns!\\$1] . } else { . ds let*str \\*[Letns!copy](\\$1)\\*[Letns!to] . } .} else { . ds let*str \\*[Letns!\\*[Letnsdef]] .} .ne 2 .nf \\*[let*str] .. On the downside, it's grown by two lines, but they're `empty' close brace ones. Upside... I think the nicer control structures allow indentation that better reflects the logic structure. Whitespace aids grokking expressions. Insisting on braces and axing the backslases around them, even though it may trample on someone's `.{' macro, lessens clutter. > If you don't like the basic design of the troff language, start from > scratch and write your own formatter using a complete redesign of the > syntax. True. But I'm happy with the basic design. Macros, traps, inline escapes, all fine. Much nicer to read than TeX. And writing something of CSTR 54's quality is beyond me. :-) However, I wonder if a preprocessor could give this new syntax à la Ratfor. For those unfamiliar with it, Ratfor was Kernighan's (yes, him again!) preprocessor for Fortran; Rational Fortran. It ignored what it didn't understand, most of Fortran, passing it straight through, but turned its constructs, e.g. a better if-statement, into Fortran. https://en.wikipedia.org/wiki/Ratfor#Features Could something work for troff in a similar way, introducing its own variables to track state during expression evaluation? I don't see why not. `.lf' could be used to keep errors referring to the original line number, though the errors from troff would mean digging into the preprocessor's expansion. It might be an easier way to prototype and experiment, and work across GNU troff, Heirloom, etc. Cheers, Ralph.