IMP Language

· 4 min · 936 words

topic/sciencecomputer science/programming languages

Overview: The “Warehouse” of Computation

If the Lambda Calculus is an elegant mathematical dream where everything is a pure, side-effect-free function evaluating to a value, IMP is the blue-collar reality of moving boxes around in a warehouse.

IMP is the theoretical “Hello World” of imperative languages. It strips away objects, types, and functions to leave only the bare essentials of how languages like C, Java, or Python actually execute: commands mutating memory over time.

In λ\lambda-calculus, computation is rewriting the code itself (β\beta-reduction). In IMP, the code remains completely static. Instead, the code issues orders that mutate an invisible, external environment.

1. Syntax

IMP is built on three syntactic pillars: Arithmetic (AExpAExp), Booleans (BExpBExp), and Commands (ComCom). Commands are the only constructs that actually do things (cause side effects). Assuming variables xVarx \in Var and integers nZn \in \mathbb{Z}:

Arithmetic Expressions (AExpAExp): (Evaluate to integers, no side effects)

a::=nxa1+a2a1a2a1×a2a ::= n \mid x \mid a_1 + a_2 \mid a_1 - a_2 \mid a_1 \times a_2

Boolean Expressions (BExpBExp): (Evaluate to truth values, no side effects)

b::=truefalsea1=a2a1a2¬bb1b2b ::= \text{true} \mid \text{false} \mid a_1 = a_2 \mid a_1 \leq a_2 \mid \neg b \mid b_1 \wedge b_2

Commands (ComCom): (Do not evaluate to values; they mutate state)

c::=skipx:=ac1;c2if b then c1 else c2while b do cc ::= \text{skip} \mid x := a \mid c_1 ; c_2 \mid \text{if } b \text{ then } c_1 \text{ else } c_2 \mid \text{while } b \text{ do } c

2. Configurations and State

Unlike pure λ\lambda-calculus (which relies on α\alpha-conversion and environment closures), IMP relies on a mutable State (or store) to track variables.

  • State (σ\sigma): A partial function mapping variables to integers, σ:VarZ\sigma : Var \to \mathbb{Z}.
  • Configuration: A tuple c,σ\langle c, \sigma \rangle representing the current point of execution.
  • State Update: σ[xn]\sigma[x \mapsto n] denotes a new state identical to σ\sigma, except that the variable xx now maps to the integer nn.
But why model State (σ\sigma) as a map?

In a physical computer, RAM is essentially a massive array of bytes, accessed via integer memory addresses. Theoretical computer science abstracts this away:

  1. Variables as Addresses: Instead of raw hex addresses, we use human-readable variable names (x,y,zVarx, y, z \in Var).
  2. Values as Contents: Instead of binary bytes, we use infinite-precision integers (nZn \in \mathbb{Z}).
    Therefore, the cleanest mathematical abstraction of a computer’s memory (or a CPU’s registers) is a partial function (a map) from variables to integers:
σ:VarZ\sigma : Var \to \mathbb{Z}

Key Insight: When you write x:=5x := 5, you aren’t substituting 55 into xx everywhere in the code (like in λ\lambda-calculus). The code stays x:=5x := 5. Instead, you are updating the map. The notation σ[xn]\sigma[x \mapsto n] means “a brand new state map that is identical to σ\sigma in every way, except if you query xx, it now returns nn.”

3. Big-Step Semantics (Natural Semantics)

Big-step semantics skip the intermediate machinery and tell you the final result. It reads like writing a standard recursive interpreter.

The judgment c,σσ\langle c, \sigma \rangle \Downarrow \sigma' means: “If you run command cc starting with memory σ\sigma, it will eventually terminate and leave memory in state σ\sigma'.”

(Note: a\Downarrow_a evaluates arithmetic to an integer; b\Downarrow_b evaluates booleans to true/false).

Skip & Assignment:

skip,σσa,σanx:=a,σσ[xn]\frac{}{\langle \text{skip}, \sigma \rangle \Downarrow \sigma} \quad \frac{\langle a, \sigma \rangle \Downarrow_a n}{\langle x := a, \sigma \rangle \Downarrow \sigma[x \mapsto n]}

Sequencing (Do c1c_1, then do c2c_2):

c1,σσc2,σσc1;c2,σσ\frac{\langle c_1, \sigma \rangle \Downarrow \sigma'' \quad \langle c_2, \sigma'' \rangle \Downarrow \sigma'}{\langle c_1 ; c_2, \sigma \rangle \Downarrow \sigma'}

If-Then-Else:

b,σbtruec1,σσif b then c1 else c2,σσ\frac{\langle b, \sigma \rangle \Downarrow_b \text{true} \quad \langle c_1, \sigma \rangle \Downarrow \sigma'}{\langle \text{if } b \text{ then } c_1 \text{ else } c_2, \sigma \rangle \Downarrow \sigma'} b,σbfalsec2,σσif b then c1 else c2,σσ\frac{\langle b, \sigma \rangle \Downarrow_b \text{false} \quad \langle c_2, \sigma \rangle \Downarrow \sigma'}{\langle \text{if } b \text{ then } c_1 \text{ else } c_2, \sigma \rangle \Downarrow \sigma'}

While Loop:

b,σbfalsewhile b do c,σσ\frac{\langle b, \sigma \rangle \Downarrow_b \text{false}}{\langle \text{while } b \text{ do } c, \sigma \rangle \Downarrow \sigma} b,σbtruec,σσwhile b do c,σσwhile b do c,σσ\frac{\langle b, \sigma \rangle \Downarrow_b \text{true} \quad \langle c, \sigma \rangle \Downarrow \sigma'' \quad \langle \text{while } b \text{ do } c, \sigma'' \rangle \Downarrow \sigma'}{\langle \text{while } b \text{ do } c, \sigma \rangle \Downarrow \sigma'}

4. Small-Step Semantics (Structural Operational Semantics)

Big-step is great, but it has a fatal flaw: it cannot describe non-terminating programs (infinite loops) or concurrency, because there is no “final state” to return.

Small-step semantics fixes this by modeling computation as a sequence of discrete, atomic ticks of a clock: c,σc,σ\langle c, \sigma \rangle \rightarrow \langle c', \sigma' \rangle. This is the imperative equivalent of step-by-step β\beta-reduction.

Assignment:
(Assuming expression aa has already reduced step-by-step to integer nn)

x:=n,σskip,σ[xn]\frac{}{\langle x := n, \sigma \rangle \rightarrow \langle \text{skip}, \sigma[x \mapsto n] \rangle}

Sequencing:

c1,σc1,σc1;c2,σc1;c2,σ\frac{\langle c_1, \sigma \rangle \rightarrow \langle c_1', \sigma' \rangle}{\langle c_1 ; c_2, \sigma \rangle \rightarrow \langle c_1' ; c_2, \sigma' \rangle} skip;c2,σc2,σ\frac{}{\langle \text{skip} ; c_2, \sigma \rangle \rightarrow \langle c_2, \sigma \rangle}

If-Then-Else:

if true then c1 else c2,σc1,σ\frac{}{\langle \text{if true then } c_1 \text{ else } c_2, \sigma \rangle \rightarrow \langle c_1, \sigma \rangle} if false then c1 else c2,σc2,σ\frac{}{\langle \text{if false then } c_1 \text{ else } c_2, \sigma \rangle \rightarrow \langle c_2, \sigma \rangle}

While Loop (The unrolling trick):
(Instead of resolving the whole loop, small-step simply unwraps one iteration and converts it into an if-statement. This allows infinite loops to just keep unrolling forever without breaking the math).

while b do c,σif b then (c;while b do c) else skip,σ\frac{}{\langle \text{while } b \text{ do } c, \sigma \rangle \rightarrow \langle \text{if } b \text{ then } (c ; \text{while } b \text{ do } c) \text{ else skip}, \sigma \rangle}