| Time | Topic | Key Question |
|---|---|---|
| 5 min | Control Flow Graph (CFG) | What paths can execution take? |
| 5 min | Data Flow Graph (DFG) | Where do values come from and go to? |
| 5 min | Program Dependence Graph (PDG) | What depends on what? → Slicing |
| 5 min | Property-Based Testing (Hypothesis) | Does it hold for many random inputs? |
| 5 min | Concolic Testing (KLEE) | Can we explore every path? |
| 5 min | Formal Specification (Alloy) | What should the system do? |
graph TD
SRC["Source Code<br>what humans write "] --> CFG
CFG["CFG<br>what paths exist? "] --> DFG
DFG["DFG<br>where do values flow? "] --> PDG
PDG["PDG<br>what depends on what? "] --> SLC["Slicing<br>minimal relevant subset "]
SRC --> SPEC["Formal Spec — Alloy<br>is the design consistent? "]
SRC --> PROP["Property Testing — Hypothesis<br>do invariants hold? "]
SRC --> CONC["Concolic Testing — KLEE<br>what does every path do? "]
style SRC fill:#1a1a2e,stroke:#6c8cff,color:#e8e8f0
style CFG fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style DFG fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style PDG fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style SLC fill:#1a1a2e,stroke:#ffaa44,color:#e8e8f0
style SPEC fill:#1a1a2e,stroke:#ff6c8c,color:#e8e8f0
style PROP fill:#1a1a2e,stroke:#ff6c8c,color:#e8e8f0
style CONC fill:#1a1a2e,stroke:#ff6c8c,color:#e8e8f0
graph LR
SRC["Source Code<br>Python, C, Java, ... "] --> LEX["Lexer /<br>Parser "]
LEX --> AST["AST "]
AST --> SEM["Semantic<br>Analysis "]
SEM --> IR["IR / SSA<br>LLVM IR, GCC GIMPLE "]
IR --> OPT["Optimizer "]
OPT --> CG["Code Gen "]
CG --> BIN["Machine Code<br>x86, ARM, WASM "]
style SRC fill:#1a1a2e,stroke:#6c8cff,color:#e8e8f0
style LEX fill:#1a1a2e,stroke:#2a2a3a,color:#8888a0
style AST fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style SEM fill:#1a1a2e,stroke:#2a2a3a,color:#8888a0
style IR fill:#1a1a2e,stroke:#ffaa44,color:#e8e8f0
style OPT fill:#1a1a2e,stroke:#ff6c8c,color:#e8e8f0
style CG fill:#1a1a2e,stroke:#2a2a3a,color:#8888a0
style BIN fill:#1a1a2e,stroke:#6c8cff,color:#e8e8f0
%x = φ(v₁, v₂)
graph TD
A["entry: age, dist "] --> B{"age < 25 ?"}
B -- T --> C["rate = 3 "]
B -- F --> D["rate = 2 "]
C --> E{"dist > 100 ?"}
D --> E
E -- T --> F["surcharge = 20 "]
E -- F --> G["surcharge = 0 "]
F --> H["return dist*rate<br>+ surcharge "]
G --> H
style A fill:#1a1a2e,stroke:#6c8cff,color:#e8e8f0
style B fill:#1a1a2e,stroke:#ffaa44,color:#e8e8f0
style C fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style D fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style E fill:#1a1a2e,stroke:#ffaa44,color:#e8e8f0
style F fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style G fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style H fill:#1a1a2e,stroke:#6c8cff,color:#e8e8f0
graph TD
A["A: entry "] --> B{"B: i < rows ?"}
B -- F --> H["H: return (-1,-1) "]
B -- T --> C{"C: j < cols ?"}
C -- F --> G["G: i += 1 "]
C -- T --> D{"D: matrix[i][j]<br>== target ?"}
D -- T --> E["E: return (i,j) "]
D -- F --> F["F: j += 1 "]
F -->|"inner back-edge"| C
G -->|"outer back-edge"| B
style A fill:#1a1a2e,stroke:#6c8cff,color:#e8e8f0
style B fill:#1a1a2e,stroke:#ffaa44,color:#e8e8f0
style C fill:#1a1a2e,stroke:#ff6c8c,color:#e8e8f0
style D fill:#1a1a2e,stroke:#ffaa44,color:#e8e8f0
style E fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style F fill:#1a1a2e,stroke:#ff6c8c,color:#e8e8f0
style G fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style H fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
return, rate could be 3 OR 2
graph LR
subgraph age_rate ["age → rate channel"]
DA["DEF(age)<br>@ param "] -.->|def-use| UA["USE(age)<br>@ age < 25 "]
DR1["DEF(rate)<br>@ rate = 3 "] -.->|def-use| UR["USE(rate)<br>@ return "]
DR2["DEF(rate)<br>@ rate = 2 "] -.->|def-use| UR
end
subgraph dist_surcharge ["dist → surcharge channel"]
DD["DEF(dist)<br>@ param "] -.->|def-use| UD1["USE(dist)<br>@ dist > 100 "]
DD -.->|def-use| UD2["USE(dist)<br>@ return "]
DS1["DEF(surcharge)<br>@ surcharge = 20 "] -.->|def-use| US["USE(surcharge)<br>@ return "]
DS2["DEF(surcharge)<br>@ surcharge = 0 "] -.->|def-use| US
end
style DA fill:#1a1a2e,stroke:#6c8cff,color:#e8e8f0
style DR1 fill:#1a1a2e,stroke:#6c8cff,color:#e8e8f0
style DR2 fill:#1a1a2e,stroke:#6c8cff,color:#e8e8f0
style DD fill:#1a1a2e,stroke:#ff6c8c,color:#e8e8f0
style DS1 fill:#1a1a2e,stroke:#ff6c8c,color:#e8e8f0
style DS2 fill:#1a1a2e,stroke:#ff6c8c,color:#e8e8f0
style UA fill:#13131a,stroke:#2a2a3a,color:#8888a0
style UR fill:#13131a,stroke:#ffaa44,color:#e8e8f0
style UD1 fill:#13131a,stroke:#2a2a3a,color:#8888a0
style UD2 fill:#13131a,stroke:#ffaa44,color:#e8e8f0
style US fill:#13131a,stroke:#ffaa44,color:#e8e8f0
graph TD
Entry["entry "] ==>|ctrl| P1{"age < 25 ?"}
Entry ==>|ctrl| P2{"dist > 100 ?"}
Entry ==>|ctrl| RET["return<br>dist*rate+surcharge "]
P1 ==>|ctrl| S1["rate = 3 "]
P1 ==>|ctrl| S2["rate = 2 "]
P2 ==>|ctrl| S3["surcharge = 20 "]
P2 ==>|ctrl| S4["surcharge = 0 "]
Entry -.->|data| P1
Entry -.->|data| P2
Entry -.->|data| RET
S1 -.->|data| RET
S2 -.->|data| RET
S3 -.->|data| RET
S4 -.->|data| RET
style Entry fill:#1a1a2e,stroke:#6c8cff,color:#e8e8f0
style P1 fill:#1a1a2e,stroke:#ffaa44,color:#e8e8f0
style P2 fill:#1a1a2e,stroke:#ffaa44,color:#e8e8f0
style S1 fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style S2 fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style S3 fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style S4 fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style RET fill:#1a1a2e,stroke:#6c8cff,color:#e8e8f0
graph TD
R["fee(age, dist) "] --> A{"age < 25 ?"}
A -- "T: age<25" --> B1{"dist > 100 ?"}
A -- "F: age≥25" --> B2{"dist > 100 ?"}
B1 -- T --> P1["path 1:<br>3×dist + 20 "]
B1 -- F --> P2["path 2:<br>3×dist "]
B2 -- T --> P3["path 3:<br>2×dist + 20 "]
B2 -- F --> P4["path 4:<br>2×dist "]
style R fill:#1a1a2e,stroke:#6c8cff,color:#e8e8f0
style A fill:#1a1a2e,stroke:#ffaa44,color:#e8e8f0
style B1 fill:#1a1a2e,stroke:#ffaa44,color:#e8e8f0
style B2 fill:#1a1a2e,stroke:#ffaa44,color:#e8e8f0
style P1 fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style P2 fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style P3 fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style P4 fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
sig declares a set of atoms. Think of it like a class, but with no methods — only structure.one = exactly one relation. Alloy is relational: fields are binary relations, not values.
for 4 = scope bound. Alloy checks every combination within this bound. Small scope hypothesis: most bugs show up in small instances.
graph TD
SRC["Source Code<br>what humans write "] --> CFG
CFG["CFG<br>what paths exist? "] --> DFG
DFG["DFG<br>where do values flow? "] --> PDG
PDG["PDG<br>what depends on what? "] --> SLC["Slicing<br>minimal relevant subset "]
SRC --> SPEC["Formal Spec — Alloy<br>is the design consistent? "]
SRC --> PROP["Property Testing — Hypothesis<br>do invariants hold? "]
SRC --> CONC["Concolic Testing — KLEE<br>what does every path do? "]
style SRC fill:#1a1a2e,stroke:#6c8cff,color:#e8e8f0
style CFG fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style DFG fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style PDG fill:#1a1a2e,stroke:#4cde80,color:#e8e8f0
style SLC fill:#1a1a2e,stroke:#ffaa44,color:#e8e8f0
style SPEC fill:#1a1a2e,stroke:#ff6c8c,color:#e8e8f0
style PROP fill:#1a1a2e,stroke:#ff6c8c,color:#e8e8f0
style CONC fill:#1a1a2e,stroke:#ff6c8c,color:#e8e8f0