On Sat, May 17, 2025 at 3:54 PM Eric Blake <ebl...@redhat.com> wrote: > > On Sat, May 17, 2025 at 12:07:40PM -0400, Nikolaos Chatzikonstantinou wrote: > > > > I wonder if a plugin system that extends the language is a potential > > idea to explore. It could transform certain slower native m4 functions > > to e.g. Python or Scheme functions (because I'm considering rewriting > > this in Guile one day... I do not know what compels me to always think > > of reimplementing stuff). Of course m4-native functions can always be > > written since m4 is Turing complete, but they may be inefficient. > > In fact, branch-2.0 in m4.git does just that - it has experimental > code to allow loadable modules, where you can write new builtins in > any language, and as long as the .so fits the ABI that m4 expects, > dynamically expand the language at runtime. The problem is that it > has been years since anyone has tried to work on that branch (even > longer than what has gone into branch-1.6). What's more, there are so > few m4 programmers out there that you are going to have a hard time > convincing anyone to use a faster m4 with plugin modules, when they > can just use a faster language with more community knowledge from the > get-go. > > And speaking of Turing complete, Doug McIlroy has an interesting demo > at how not only is m4 Turing complete with all of its builtins, but if > you strip it down to JUST the define macro, it is still Turing > complete: > > https://www.tuhs.org/mailman3/hyperkitty/list/t...@tuhs.org/thread/7ZRYUMZ2QNKE24QWUFT7MRK74COT7BIQ/
I only briefly skimmed over it, it has some cool techniques. They definitely went the academic route to prove this by creating a model for arithmetic. I prefer the hand-wavy route: m4 is turing complete merely by supporting syscmd(). I want to share my own m4 code that I wrote when I studied m4 to fix issues with Guile's Autotools macros (haven't gotten around to that yet) Once I managed to implement lambda functions in a language that didn't originally support them I was pretty convinced of its coolness. I also managed to cram in currying, in a way completing a challenge mentioned by Kenneth J. Turner in "Exploiting the m4 Macro Language": > Unfortunately a single Curry macro cannot be defined since the number of > parameters to be fixed must be known. I amused the author by e-mailing him my solution. M4 has enough syntactic manipulation power that you can implement a lot of functional programming in it, like foldr and so on. I actually think it's a good tool to teach syntactic manipulation to talented students, *especially* if we can get an IDE (debugger?) around it, that shows all the steps of expansion. Of course debugmode() can do this, but it's a bit more technical than I'd like it to be. --- m4 source, cut here --- define(apply,`ifelse($1,`',`',$1(shift($@)))') define(id, $@) define( peel, `ifelse(eval($1 == 0),1,`id(``$2'')',eval($1 == 1),1,`id(`$2')',`peel(decr($1),$2)')') define( randhex, `esyscmd(`od -N$1 -An -tx1 /dev/urandom | tr -d " \n"')') define( lambda__aux, `define($1,$2)`$1'') define( lambda, `peel(3,``lambda__aux('lambda_``''`randhex(5), ``$1'')'')') # curry(f,arg1,...,argn) # Partially applies arg1, ..., argn to f. # Note that there must be at least one argument, i.e. n >= 1. define( curry, `lambda(`$1(shift($@),'$`'@`)')') --- m4 source, cut here ---