Operators in Modula-2
Learn arithmetic, relational, logical, and set operators in Modula-2, including DIV, MOD, and operator precedence with practical Docker-ready examples
Operators are the building blocks of expressions. Modula-2 inherits Pascal’s clean operator design but refines it with stricter typing rules and a few additions that suit systems programming. Because the language is statically and strongly typed, operators are not silently overloaded across incompatible types — a REAL and an INTEGER cannot be added without an explicit conversion, and the compiler will tell you so.
Modula-2 distinguishes integer division (DIV) from real division (/), provides a true MOD operator with well-defined behavior on non-negative operands, and treats sets as first-class values with their own algebra. Logical operators read as English words (AND, OR, NOT) rather than punctuation, reinforcing the language’s emphasis on readability.
In this tutorial you’ll write a small program that exercises every major category of Modula-2 operator and observe exactly what each one produces.
Arithmetic Operators
Modula-2 provides the standard arithmetic operators, plus separate operators for integer and real division:
| Operator | Meaning | Operand types |
|---|---|---|
+ | Addition | INTEGER, CARDINAL, REAL |
- | Subtraction / unary minus | INTEGER, CARDINAL, REAL |
* | Multiplication | INTEGER, CARDINAL, REAL |
/ | Real division | REAL |
DIV | Integer (truncated) division | INTEGER, CARDINAL |
MOD | Remainder after DIV | INTEGER, CARDINAL |
Using / on integers is a compile-time error — the language forces you to choose between DIV and / deliberately.
Create a file named arithmetic.mod:
| |
WriteInt(value, width) right-justifies the integer in a field of the given width; WriteReal(value, width) formats the real in scientific notation by default.
Relational and Logical Operators
Relational operators compare two values and yield a BOOLEAN. Modula-2 supports both # and <> for “not equal” — # is the original PIM spelling, <> was added by the ISO standard.
| Operator | Meaning |
|---|---|
= | Equal |
# or <> | Not equal |
<, <= | Less, less-or-equal |
>, >= | Greater, greater-or-equal |
AND (&) | Logical conjunction |
OR | Logical disjunction |
NOT (~) | Logical negation |
AND and OR short-circuit: the right operand is only evaluated when the result is not already determined by the left.
Create a file named logic.mod:
| |
The standard library does not provide a built-in boolean printer, so a tiny WriteBool procedure keeps the output readable.
Set Operators and IN
Sets are a first-class type in Modula-2, and they carry their own algebra. The same +, -, and * symbols you saw with numbers also mean union, difference, and intersection when applied to sets — Modula-2 resolves the meaning from the operand types. The IN operator tests membership.
Create a file named sets.mod:
| |
The same + - * symbols meaning “add/subtract/multiply” for numbers also mean “union/difference/intersection” for sets — context disambiguates them.
Precedence and Assignment
Modula-2 has a famously short precedence table — only four levels — which keeps expression evaluation predictable.
| Priority | Operators |
|---|---|
| 1 (highest) | NOT, ~ |
| 2 | *, /, DIV, MOD, AND, & |
| 3 | +, -, OR |
| 4 (lowest) | =, #, <>, <, <=, >, >=, IN |
Note the trap: relational operators have the lowest priority, so a < b AND c < d parses as a < (b AND c) < d — a type error. Always parenthesize: (a < b) AND (c < d).
Assignment uses := (not =, which is the equality operator). Modula-2 has no compound assignment (+=, -=); you write the long form, or use the built-in INC and DEC procedures.
Create a file named precedence.mod:
| |
Running with Docker
Pull the image and compile each program with gm2:
| |
Expected Output
arithmetic:
a + b = 22
a - b = 12
a * b = 85
a DIV b = 3
a MOD b = 2
x / y = 3.4E+00
logic:
a < b -> TRUE
a = b -> FALSE
a # b -> TRUE
a >= 7 -> TRUE
p AND q -> FALSE
p OR q -> TRUE
NOT p -> FALSE
sets:
evens = { 0 2 4 6 8 }
primes = { 2 3 5 7 }
union = { 0 2 3 4 5 6 7 8 }
intersect = { 2 }
evens-prm = { 0 4 6 8 }
4 IN evens
4 NOT IN primes
precedence:
2 + 3 * 4 = 14
(2 + 3) * 4 = 20
result is two digits
counter = 14
Key Concepts
DIVandMODare integer-only;/is real-only. There is no implicit conversion betweenINTEGERandREAL— you must useFLOATorTRUNCto cross the boundary.#and<>both mean “not equal” —#is PIM,<>is ISO. Pick one and stay consistent within a module.- Logical operators are English words:
AND,OR,NOT.&and~are accepted PIM synonyms forANDandNOT, butAND/NOTread more clearly. ANDandORshort-circuit, so guards like(p # NIL) AND (p^.value > 0)are safe.- Sets are first-class:
+ - *overload for union/difference/intersection, andINtests membership. The base type is usually a small enumeration or subrange. - Relational operators have the lowest priority — always parenthesize boolean sub-expressions inside
AND/OR. - Assignment is
:=, equality is=— confusing them is a compile error, not a silent bug as in C. - No compound assignment operators; use
INC(x),INC(x, n),DEC(x),DEC(x, n)for the common increment/decrement idioms.
Running Today
All examples can be run using Docker:
docker pull codearchaeology/modula-2:latest
Comments
Loading comments...
Leave a Comment