Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/make/unit-tests make(1): add test demonstrating the ...



details:   https://anonhg.NetBSD.org/src/rev/d54bd3dc2a6f
branches:  trunk
changeset: 944555:d54bd3dc2a6f
user:      rillig <rillig%NetBSD.org@localhost>
date:      Sat Oct 03 17:30:54 2020 +0000

description:
make(1): add test demonstrating the Towers of Hanoi puzzle

It's not the primary task of make to handle procedure calls with
parameters, combined with lexical scoping, therefore the code does not
look as straight-forward or clean as in other programming languages.  It
feels more like squeezing a programming problem from the imperative
world into the world of declarative dependencies.

A more idiomatic way of implementing this puzzle should be as a
dependency graph since that's both the natural structure of the puzzle
and the primary domain of make.  Something like having a main target
"hanoi-5" that depends on intermediate targets of the form
"move-1.2.3.4.5-_._._._._-_._._._._", each representing a single
configuration of the stacks.  These targets could be generated
dynamically.  A benefit of this implementation would be that the puzzle
could be resumed from an arbitrary configuration, just just from the
initial configuration.

diffstat:

 usr.bin/make/unit-tests/Makefile          |   3 +-
 usr.bin/make/unit-tests/hanoi-include.exp |  32 ++++++++++++++++++++++++
 usr.bin/make/unit-tests/hanoi-include.mk  |  41 +++++++++++++++++++++++++++++++
 3 files changed, 75 insertions(+), 1 deletions(-)

diffs (98 lines):

diff -r 980f670c4320 -r d54bd3dc2a6f usr.bin/make/unit-tests/Makefile
--- a/usr.bin/make/unit-tests/Makefile  Sat Oct 03 15:38:13 2020 +0000
+++ b/usr.bin/make/unit-tests/Makefile  Sat Oct 03 17:30:54 2020 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: Makefile,v 1.158 2020/10/03 14:39:36 rillig Exp $
+# $NetBSD: Makefile,v 1.159 2020/10/03 17:30:54 rillig Exp $
 #
 # Unit tests for make(1)
 #
@@ -168,6 +168,7 @@
 TESTS+=                export-variants
 TESTS+=                forloop
 TESTS+=                forsubst
+TESTS+=                hanoi-include
 TESTS+=                impsrc
 TESTS+=                include-main
 TESTS+=                job-output-long-lines
diff -r 980f670c4320 -r d54bd3dc2a6f usr.bin/make/unit-tests/hanoi-include.exp
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.bin/make/unit-tests/hanoi-include.exp Sat Oct 03 17:30:54 2020 +0000
@@ -0,0 +1,32 @@
+Move the upper disk from stack A to stack C.
+Move the upper disk from stack A to stack B.
+Move the upper disk from stack C to stack B.
+Move the upper disk from stack A to stack C.
+Move the upper disk from stack B to stack A.
+Move the upper disk from stack B to stack C.
+Move the upper disk from stack A to stack C.
+Move the upper disk from stack A to stack B.
+Move the upper disk from stack C to stack B.
+Move the upper disk from stack C to stack A.
+Move the upper disk from stack B to stack A.
+Move the upper disk from stack C to stack B.
+Move the upper disk from stack A to stack C.
+Move the upper disk from stack A to stack B.
+Move the upper disk from stack C to stack B.
+Move the upper disk from stack A to stack C.
+Move the upper disk from stack B to stack A.
+Move the upper disk from stack B to stack C.
+Move the upper disk from stack A to stack C.
+Move the upper disk from stack B to stack A.
+Move the upper disk from stack C to stack B.
+Move the upper disk from stack C to stack A.
+Move the upper disk from stack B to stack A.
+Move the upper disk from stack B to stack C.
+Move the upper disk from stack A to stack C.
+Move the upper disk from stack A to stack B.
+Move the upper disk from stack C to stack B.
+Move the upper disk from stack A to stack C.
+Move the upper disk from stack B to stack A.
+Move the upper disk from stack B to stack C.
+Move the upper disk from stack A to stack C.
+exit status 0
diff -r 980f670c4320 -r d54bd3dc2a6f usr.bin/make/unit-tests/hanoi-include.mk
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/usr.bin/make/unit-tests/hanoi-include.mk  Sat Oct 03 17:30:54 2020 +0000
@@ -0,0 +1,41 @@
+# $NetBSD: hanoi-include.mk,v 1.1 2020/10/03 17:30:54 rillig Exp $
+#
+# Implements the Towers of Hanoi puzzle, thereby demonstrating a bunch of
+# useful programming techniques:
+#
+# * default assignment using the ?= assignment operator
+# * including the same file recursively
+# * extracting the current value of a variable using the .for loop
+# * using shell commands for calculations since make is a text processor
+# * using the :: dependency operator for adding commands to a target
+# * on-the-fly variable assignment expressions using the ::= modifier
+#
+# usage:
+#      env N=3 make -f hanoi-include.mk
+# endless loop:
+#      make -f hanoi-include.mk N=3
+
+N?=    5                       # Move this number of disks ...
+FROM?= A                       # ... from this stack ...
+VIA?=  B                       # ... via this stack ...
+TO?=   C                       # ... to this stack.
+
+.if $N == 1
+.  for from to in ${FROM} ${TO}
+all::
+       @echo "Move the upper disk from stack ${from} to stack ${to}."
+.  endfor
+.else
+_:=    ${N::!=expr $N - 1} ${TMP::=${VIA}} ${VIA::=${TO}} ${TO::=${TMP}}
+.  include "${.PARSEDIR}/${.PARSEFILE}"
+_:=    ${N::!=expr $N + 1} ${TMP::=${VIA}} ${VIA::=${TO}} ${TO::=${TMP}}
+
+.  for from to in ${FROM} ${TO}
+all::
+       @echo "Move the upper disk from stack ${from} to stack ${to}."
+.  endfor
+
+_:=    ${N::!=expr $N - 1} ${TMP::=${VIA}} ${VIA::=${FROM}} ${FROM::=${TMP}}
+.  include "${.PARSEDIR}/${.PARSEFILE}"
+_:=    ${N::!=expr $N + 1} ${TMP::=${VIA}} ${VIA::=${FROM}} ${FROM::=${TMP}}
+.endif



Home | Main Index | Thread Index | Old Index