Perhaps entertainingly, here is a countdown by emulating the "Little Man Computer", invented by Stuart Madnick in 1965.
Johnicholas divert(-1) changequote([,]) # This is an implementation of the "Little Man Computer" in m4. # The LMC is a simple decimal-based accumulator machine used # for educational purposes by Stuart Madnick in 1965. # memory is a global array define([lookup], [lookup_$1]) define([store], [define([lookup_$1], [$2])]) # the program counter and accumulator both start at zero define([run], [fetch(0, 0)]) # first fetch the instruction, and increment the program counter define([fetch], [decode(lookup($1), incr($1), $2)]) # second decode the instruction into op and arg define([decode], [dispatch(eval($1 / 100), eval($1 % 100), $2, $3)]) # third, we do a dispatch on the op, to one of the executes define([dispatch], [execute_$1($2, $3, $4)]) # 1xx is ADD - add to the accum a value from memory define([execute_1], [fetch($2, eval($3 + lookup($1)))]) # 2xx is SUB - subtract from accum a value from memory define([execute_2], [fetch($2, eval($3 - lookup($1)))]) # 3xx is STORE - store from the accum into the memory define([execute_3], [store($1, $3)fetch($2, $3)]) # 5xx is LOAD - load from the memory into the accum define([execute_5], [fetch($2, lookup($1))]) # 6xx is branch unconditionally define([execute_6], [fetch($1, $3)]) # 7xx is branch-if-zero define([execute_7], [ifelse($3, 0, [fetch($1, $3)], [fetch($2, $3)])]) # 8xx is branch-if-nonnegative define([execute_8], [ifelse(eval($3 < 0, 0, [fetch($2, $3)], [fetch($1, $3)])]) # 9xx are primitives; we dispatch to some specific primitive define([execute_9], [primitive_$1($2, $3)]) # primitive 1 is ought to be read - but I'm not sure how to do it in m4 # primitive 2 is write define([primitive_2], [$2 fetch($1, $2)]) # primitive 3 is halt define([primitive_3], []) # now an actual program store([0], [599]) # load mem[99] into accum # top of loop: store([1], [902]) # write accum store([2], [705]) # if accum is zero, goto done store([3], [298]) # subtract mem[98] into accum store([4], [601]) # branch to top of loop # done: store([5], [903]) # halt # data store([98], [1]) store([99], [10]) divert[]dnl run()dnl On Wed, Aug 10, 2011 at 5:19 PM, daniel daniel <[email protected]> wrote: > Hi guys, > I felt like writing a recursive countdown macro. > > CODE: > define(countDown,`$1 > `'ifelse($1,0,,`$0'(`eval'($1 - 1)))')dnl > countDown(10) > > OUTPUT: > 10 > 9 > 8 > 7 > 6 > 5 > 4 > 3 > 2 > 1 > 0 > > DISCUSSION: > In m4, recursion is more readable with ifelse, > where the first argument of ifelse is the > terminating condition. So, in my countDown > macro, the fourth argument of ifelse is a > call to $0 with a nested eval() to subtract > one from the argument and pass the result > as the argument recursively. (The argument > is also printed with a newline at each > iteration). >
lmc.m4
Description: application/m4
