# Control Flow: If and While Expressions

These notes were taken from the Essentials of Interpretation course by Dmitry Soshnikov and part of the Essentials of Interpretation series.

In the previous post, we talked about variables, environments, blocks and how they handle scoping in a programming language. In this post, we'll take a look at control flow, more especifically, if and while expressions.

## If Expressions: handling conditions

To better understand how to approach if expressions, let's take a look at their structure and syntax.

```
(if <condition>
<consequent>
<alternate>)
```

We have the `if`

expression, the condition, if the condition evaluates to `true`

, it goes to the first branch, the `consequent`

, if it's `false`

, it goes to the `alternate`

branch.

Starting with tests, here's a simple expression that's easy to understand.

```
test(
eva,
`(begin
(var x 10)
(var y 0)
(if (> x 10)
(set y 20)
(set y 30))
y)`,
30,
);
```

We define the variables `x`

and `y`

. If the `x`

is greater than `10`

, it will assign `20`

to `y`

, if not, it will assign `30`

. In this case, `x`

is equal to `10`

, so `y`

will be `30`

at the end of this code block.

Let's go for the implementation now. When we have an if expression, it requires us to get all the parts of it: the tag name, the condition, the consequent, and the alternate. Here it is:

```
if (exp[0] === 'if') {
const [_tag, condition, consequent, alternate] = exp;
// ...
}
```

The rest of the implementation is pretty simple. First, we need to evaluate the condition. If it evaluates to `true`

, we return the evaluation of the `consequent`

expression. If it evaluates to `false`

, we should return the evaluation of the `alternate`

expression.

```
if (exp[0] === 'if') {
const [_tag, condition, consequent, alternate] = exp;
return this.eval(condition, env)
? this.eval(consequent, env)
: this.eval(alternate, env);
}
```

But executing it still doesn't work as we are still required to implement the comparison operators.

As we learned in the previous post about global vs local scope and environments, we can add all the comparison operators as built-in expressions of the language. That way, we don't actually need to parse and evaluate them.

```
const GlobalEnvironment = new Environment({
// ...
'>': (op1, op2) => {
return op1 > op2;
},
'<': (op1, op2) => {
return op1 < op2;
},
'<=': (op1, op2) => {
return op1 <= op2;
},
'>=': (op1, op2) => {
return op1 >= op2;
},
'=': (op1, op2) => {
return op1 === op2;
},
// ...
});
```

Now, it passes the check when running the test.

Just to make sure all comparison operators work, I added more tests to cover them all.

```
test(
eva,
`(begin
(if (>= 10 10)
1
2))`,
1,
);
test(
eva,
`(begin
(if (<= 10 10)
1
2))`,
1,
);
test(
eva,
`(begin
(if (= 10 10)
1
2))`,
1,
);
test(
eva,
`(begin
(if (< 10 10)
1
2))`,
2,
);
```

## While Expressions: looping

The structure of while expressions reminds me a lot of if expressions. But it doesn't have the `consequent`

and `alternate`

part, it has only a body of expressions.

Let's start with the test:

```
test(
eva,
`(begin
(var counter 0)
(var result 0)
(while (< counter 10)
(begin
(set counter (+ counter 1))
(set result (+ result 1))))
result)`,
10,
);
```

We start with a `counter`

and a `result`

as `0`

. For every loop, it will increment the counter and the result. When the counter reaches `10`

or more than `10`

, it will stop the loop.

In this case, it will stop when the `counter`

and the `result`

are `10`

. So the whole block of code will evaluate to `10`

.

Here’s the implementation:

```
if (exp[0] === 'while') {
const [_, condition, body] = exp;
let result;
while (this.eval(condition, env)) {
result = this.eval(body, env);
}
return result;
}
```

We get the `condition`

and the `body`

.

We'll keep evaluating the `condition`

while it keeps being evaluated to `true`

. For every loop, it will evaluate the `body`

and the value produced in this process will be stored in the `result`

variable.

That way, the last time it evaluates the body will be the value we want to return from this while expression.

Running the tests again, it passes.

## Final words

In this fourth post of the series, we talked about if and while expressions and how to handle controle flow in a programming language.

Here are some resources you can use:

- Programming Language Research: a bunch of resources about my studies on Programming Language Theory & Applied PLT
- Essentials of Interpretation repo
- Essentials of Interpretation course
- Compiler Engineering courses

**newsletter**if you're enjoying this blog. ❤