Skip to content

Commit 0e8acd9

Browse files
committed
Add topo sort lab
1 parent e71e430 commit 0e8acd9

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

build-lab.md

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
---
3+
4+
# Graph lab
5+
6+
Build system targets are often modeled as a directed acyclic graph (DAG).
7+
Each node in the graph represents a build target and each edge represents a
8+
dependency on another target. A correct build order is a topological sort: an
9+
order in which each target is only built after all of its dependencies have
10+
been built.
11+
12+
We're not going to make a whole build system from scratch, but we will
13+
implement one of the core components in your preferred programming language: a
14+
topological sort.
15+
16+
## Graph representation
17+
18+
Write a class that satisfies this interface (it need not be Python; that's just
19+
the syntax for the interface sketch pseudocode):
20+
21+
```python
22+
class Target:
23+
def name(self) -> str: ...
24+
def recipe(self) -> str: ...
25+
def dependencies(self) -> List[Target]: ...
26+
```
27+
28+
The `name` method should return the name of the target. The `recipe` method
29+
should return the command executed to build the target. The `dependencies`
30+
method should return a list of the target's dependencies.
31+
32+
## A small graph
33+
34+
Now, manually create a small graph of targets and dependencies. Try modeling
35+
the C example from `build.sh`:
36+
37+
```
38+
foo: foo.o rng.o
39+
cc -o foo foo.o rng.o
40+
41+
foo.o: foo.c rng.h
42+
cc -c foo.c
43+
44+
rng.o: rng.c rng.h
45+
cc -c rng.c
46+
47+
myls.o: myls.c
48+
cc -c myls.c
49+
50+
myls: myls.o
51+
cc -o myls myls.o
52+
```
53+
54+
You may need to change around the order (bottom-up) to get your
55+
manually-created `Target` objects to make sense.
56+
57+
## Topological sort
58+
59+
Start by writing a function `execute` that, given a target with no
60+
dependencies, prints the target's recipe.
61+
62+
Then, add another case: if the target has dependencies, execute them first.
63+
64+
Now you have a problem: if targets `A` and `B` both depend on `C`, it will
65+
execute (print) the recipe for `C` twice. To fix this, add a `set` parameter
66+
called `visited` to `execute`. Before executing a target, check if its name is
67+
in the visited set.
68+
69+
## Tests
70+
71+
What are the core properties of your program that you want to test?
72+
73+
Write tests for your topological sort. You can use the example above from
74+
`build.sh`, but you should also think smaller, and be more targeted. What is
75+
your specific test case trying to "break" in your implementation? We'll talk
76+
more about this next module.
77+
78+
## Cycles?
79+
80+
If you have a cycle in your graph, your topological sort will not work. How
81+
might you detect cycles?

0 commit comments

Comments
 (0)