WEBVTT

00:00:00.380 --> 00:00:03.880
Now let's turn our attention to compile statement.

00:00:03.880 --> 00:00:07.020
The first two statement types are pretty easy
to handle.

00:00:07.020 --> 00:00:11.800
Unconditional statements are usually assignment
expressions or procedure calls.

00:00:11.800 --> 00:00:16.960
We'll simply ask compile_expr to generate
the appropriate code.

00:00:16.960 --> 00:00:19.460
Compound statements are equally easy.

00:00:19.460 --> 00:00:24.810
We'll recursively call compile_statement to
generate code for each statement in turn.

00:00:24.810 --> 00:00:30.210
The code for statement_2 will immediately
follow the code generated for statement_1.

00:00:30.210 --> 00:00:34.050
Execution will proceed sequentially through
the code for each statement.

00:00:34.050 --> 00:00:38.900
Here we see the simplest form the conditional
statement, where we need to generate code

00:00:38.900 --> 00:00:44.470
to evaluate the test expression and then,
if the value in the register is FALSE, skip

00:00:44.470 --> 00:00:48.400
over the code that executes the statement
in the THEN clause.

00:00:48.400 --> 00:00:54.510
The simple assembly-language template uses
recursive calls to compile_expr and compile_statement

00:00:54.510 --> 00:00:59.460
to generate code for the various parts of
the IF statement.

00:00:59.460 --> 00:01:03.480
The full-blown conditional statement includes
an ELSE clause, which should be executed if

00:01:03.480 --> 00:01:06.710
the value of the test expression is FALSE.

00:01:06.710 --> 00:01:13.420
The template uses some branches and labels
to ensure the course of execution is as intended.

00:01:13.420 --> 00:01:17.549
You can see that the compilation process is
really just the application of many small

00:01:17.549 --> 00:01:23.620
templates that break the code generation task
down step-by-step into smaller and smaller

00:01:23.620 --> 00:01:28.490
tasks, generating the necessary code to glue
all the pieces together in the appropriate

00:01:28.490 --> 00:01:30.210
fashion.

00:01:30.210 --> 00:01:34.130
And here's the template for the WHILE statement,
which looks a lot like the template for the

00:01:34.130 --> 00:01:39.580
IF statement with a branch at the end that
causes the generated code to be re-executed

00:01:39.580 --> 00:01:43.490
until the value of the test expression is
FALSE.

00:01:43.490 --> 00:01:47.229
With a bit of thought, we can improve on this
template slightly.

00:01:47.229 --> 00:01:53.200
We've reorganized the code so that only a
single branch instruction (BT) is executed

00:01:53.200 --> 00:01:59.348
each iteration, instead of the two branches
(BF, BR) per iteration in the original template.

00:01:59.348 --> 00:02:05.719
Not a big deal, but little optimizations to
code inside a loop can add up to big savings

00:02:05.719 --> 00:02:08.940
in a long-running program.

00:02:08.940 --> 00:02:13.530
Just a quick comment about another common
iteration statement, the FOR loop.

00:02:13.530 --> 00:02:18.720
The FOR loop is a shorthand way of expressing
iterations where the loop index ("i" in the

00:02:18.720 --> 00:02:24.420
example shown) is run through a sequence of
values and the body of the FOR loop is executed

00:02:24.420 --> 00:02:27.640
once for each value of the loop index.

00:02:27.640 --> 00:02:32.890
The FOR loop can be transformed into the WHILE
statement shown here, which can then be compiled

00:02:32.890 --> 00:02:35.880
using the templates shown above.

00:02:35.880 --> 00:02:40.950
In this example, we've applied our templates
to generate code for the iterative implementation

00:02:40.950 --> 00:02:44.590
of the factorial function that we've seen
before.

00:02:44.590 --> 00:02:49.260
Look through the generated code and you'll
be able to match the code fragments with the

00:02:49.260 --> 00:02:51.840
templates from last couple of slides.

00:02:51.840 --> 00:02:56.590
It's not the most efficient code, but not
bad given the simplicity of the recursive-descent

00:02:56.590 --> 00:02:59.970
approach for compiling high-level programs.

00:02:59.970 --> 00:03:05.790
It's a simple matter to modify the recursive-descent
process to accommodate variable values that

00:03:05.790 --> 00:03:10.450
are stored in dedicated registers rather than
in main memory.

00:03:10.450 --> 00:03:15.170
Optimizing compilers are quite good at identifying
opportunities to keep values in registers

00:03:15.170 --> 00:03:22.040
and hence avoid the LD and ST operations needed
to access values in main memory.

00:03:22.040 --> 00:03:26.200
Using this simple optimization, the number
of instructions in the loop has gone from

00:03:26.200 --> 00:03:28.360
10 down to 4.

00:03:28.360 --> 00:03:32.540
Now the generated code is looking pretty good!

00:03:32.540 --> 00:03:36.950
But rather than keep tweaking the recursive-descent
approach, let's stop here.

00:03:36.950 --> 00:03:40.820
In the next segment, we'll see how modern
compilers take a more general approach to

00:03:40.820 --> 00:03:42.220
generating code.

00:03:42.220 --> 00:03:47.610
Still though, the first time I learned about
recursive descent, I ran home to write a simple

00:03:47.610 --> 00:03:52.280
implementation and marveled at having authored
my own compiler in an afternoon!