Work on this exercise locally

This web app is a reference guide — you can read instructions, browse starter code, and view tests here. To actually complete the exercise, you need to work in your local development environment.

1Clone the repo: git clone https://github.com/weihaoqu/program-analysis-bootcamp-student
2Edit the starter file in your editor (VS Code, Vim, etc.) — replace failwith "TODO" with your implementation.
3Run the tests: dune runtest modules/module3-static-analysis/exercises/cfg-construction

CFG Construction

3. Exercise 1: CFG Construction (14 tests)

Goal: Build control flow graphs from AST statement lists. Implement the core CFG operations (add edges, query predecessors/successors) and three CFG construction patterns (sequential, if-else diamond, while loop with back edge).

Time: ~30 minutes

Files to edit:

  • exercises/cfg-construction/starter/cfg.ml -- core CFG operations
  • exercises/cfg-construction/starter/exercises.ml -- CFG construction patterns

Also provided (read-only):

  • exercises/cfg-construction/starter/cfg.mli -- interface specification

CFG patterns you will build

Sequential:          If-Else (Diamond):        While (Back Edge):

 ENTRY                  ENTRY                    ENTRY
   |                      |                        |
   v                      v                        v
  B1                   B_cond                    B_pre
   |                   /    \                      |
   v                  v      v                     v
  EXIT             B_then  B_else              B_cond  <---+
                      \    /                   /    \      |
                       v  v                 B_body   \     |
                      B_join                  |       \    |
                        |                     +--------+   |
                        v                              |
                       EXIT                          B_post
                                                       |
                                                       v
                                                      EXIT

What to implement (in order)

In cfg.ml:

#FunctionHint
1add_edge cfg src dstFind both blocks in cfg.blocks, append dst to src's succs and src to dst's preds, update the map with StringMap.add
2predecessors cfg labelStringMap.find the block, return its preds
3successors cfg labelStringMap.find the block, return its succs
4to_string cfgStringMap.fold over blocks; for each, print label, stmt count, succs, preds

In exercises.ml:

#FunctionHint
5build_cfg_sequential stmtsCreate ENTRY, B1 (all stmts), EXIT blocks; add edges ENTRY->B1->EXIT
6build_cfg_ifelse stmtsPartition around the If node; create B_cond, B_then, B_else, B_join; wire the diamond
7build_cfg_while stmtsPartition around the While node; create B_pre, B_cond, B_body, B_post; wire the back edge B_body->B_cond

Run tests

dune runtest modules/module3-static-analysis/exercises/cfg-construction/

Starter output: .EEEEE.EEEEEEE

Some tests already pass (the dots) because the provided create_block helper function works out of the box -- its tests do not depend on your TODO stubs. The E results are the tests that call your unimplemented functions. As you implement add_edge, predecessors, successors, and to_string, the middle tests will turn to dots. Then tackle exercises.ml for the remaining tests.

Hint for build_cfg_ifelse: You need to split the statement list into three parts: statements before the If, the If itself (from which you extract then_stmts and else_stmts), and statements after the If. A recursive helper or List.fold_left works well for this partitioning.

Hint for build_cfg_while: Same partitioning idea, but around the While node. Remember that B_cond is empty (the condition is implicit in the branching edges), and the key addition is the back edge from B_body to B_cond.