Re: recursive countDown macro

Johnicholas Hines <[email protected]>
Newsgroups gmane.comp.gnu.m4.general
Message-ID <CAEpeLrOppHi_-54MDLBnxh2XFVWsG0TJttRFGzu3ENBGQ4hiig@mail.gmail.com>
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 (application/x-m4, 2.1 KB) - not displayed
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.