Control Flow in Modula-2
Master control flow in Modula-2 - IF/ELSIF conditionals, CASE statements, FOR/WHILE/REPEAT loops, and LOOP/EXIT with runnable Docker examples using gm2
Control flow determines the order in which statements execute. As an imperative, procedural language, Modula-2 offers a complete and remarkably clean set of structured control statements - a direct inheritance from Niklaus Wirth’s design philosophy of “make it simple, make it consistent.”
What makes Modula-2 distinctive is that every control structure is fully bracketed with an explicit END. There are no dangling-else ambiguities, no reliance on indentation, and no need for begin/end blocks around multiple statements like Pascal requires. An IF ends with END, a WHILE ends with END, and a CASE ends with END. This consistency makes Modula-2 control flow predictable and readable - one of the reasons it was favored for teaching systems programming.
In this tutorial you’ll learn Modula-2’s conditional statements (IF/ELSIF/ELSE and CASE), its four loop constructs (FOR, WHILE, REPEAT, and LOOP), and the EXIT statement for breaking out of a LOOP. Notably, Modula-2 has no ternary operator and no break/continue keywords in the C sense - it uses the structured LOOP/EXIT pairing instead.
Conditionals: IF, ELSIF, ELSE
The IF statement chooses between alternatives. Multiple conditions chain together with ELSIF (a single keyword, not ELSE IF), and the whole statement closes with END. Boolean conditions use the AND, OR, and NOT keywords.
Create a file named conditionals.mod:
| |
A score of 78 fails the >= 90 and >= 80 tests but passes >= 70, so it prints “Grade: C”. Note that sub-expressions like score > 0 are wrapped in parentheses - Modula-2’s relational operators have lower precedence than AND/OR, so the parentheses are required.
CASE Statements
When you need to branch on a single value with many discrete outcomes, CASE is cleaner than a long IF/ELSIF chain. Case labels are separated by |, you can list multiple values per label or use a low..high range, and an optional ELSE handles everything not matched.
Create a file named case_demo.mod:
| |
The label 1..5 is a range covering Monday through Friday, while 6, 7 is an explicit list. With day set to 3, the first label matches and prints “Weekday”. The ELSE branch catches any value outside the defined labels - without it, an unmatched value would raise a runtime error in standard Modula-2.
FOR and WHILE Loops
Modula-2 provides two pre-test counting/conditional loops. The FOR loop iterates a control variable across a range and even supports a BY clause for custom step sizes (including negative steps for counting down). The WHILE loop runs as long as its condition holds, testing before each iteration.
Create a file named loops.mod:
| |
The WriteInt(i, 1) call prints the integer in a field at least 1 character wide. The INC(i) built-in increments the variable - it’s the idiomatic Modula-2 equivalent of i := i + 1 (with a matching DEC for decrement). The FOR loop manages its own control variable automatically, so you never write INC inside it.
LOOP, EXIT, and REPEAT
Modula-2 deliberately omits C-style break and continue. Instead, for loops whose exit point isn’t naturally at the top or bottom, it offers the LOOP statement - an unconditional loop that you escape with EXIT. The EXIT statement only ever exits the innermost enclosing LOOP (not a FOR, WHILE, or REPEAT).
The REPEAT/UNTIL loop is the post-test counterpart to WHILE: it always executes its body at least once, then tests the condition at the bottom.
Create a file named loop_control.mod:
| |
The LOOP begins at 21, immediately finds that 21 MOD 7 = 0, and EXITs on the very first iteration. The REPEAT loop doubles n starting from 1, stopping once n exceeds 16 - because the test is at the bottom, the value 16 is printed before the loop ends.
Running with Docker
Each example is a standalone program module. Pull the image once, then compile and run each file with gm2:
| |
Expected Output
Running conditionals:
Score: 78
Grade: C
Valid percentage
Running case_demo:
Day type: Weekday
Running loops:
Count up: 1 2 3 4 5
Count down: 5 4 3 2 1
Sum 1..5 = 15
Running loop_control:
First multiple of 7 >= 21: 21
Powers of 2: 1 2 4 8 16
Key Concepts
- Every control structure is explicitly closed with
END- there are no braces and no statement-groupingbegin/endblocks needed around multiple statements. ELSIFis a single keyword for chaining conditions, andELSEprovides the catch-all branch in bothIFandCASE.CASElabels use|separators and support both value lists (6, 7) and ranges (1..5); always provide anELSEto avoid runtime errors on unmatched values.- Four loop constructs serve distinct needs:
FORfor counted iteration (with optionalBYstep),WHILEfor pre-tested conditions,REPEAT/UNTILfor post-tested loops that always run once, andLOOPfor loops that exit from the middle. EXITreplacesbreakand only terminates the innermostLOOP- there is nocontinueequivalent, encouraging clearer loop structure.INCandDECare built-in procedures for incrementing and decrementing variables, idiomatic inWHILEandLOOPbodies.- Relational operators need parentheses inside boolean expressions because
AND/ORbind more tightly than comparisons (e.g.,(score > 0) AND (score < 100)). - Modula-2 has no ternary operator - all conditional selection is done with the structured
IForCASEstatements.
Running Today
All examples can be run using Docker:
docker pull codearchaeology/modula-2:latest
Comments
Loading comments...
Leave a Comment