buildTemporalDepGraph builds a dependency graph for the program using the existing depGraph type.
(programInfo *ProgramInfo)
| 164 | |
| 165 | // buildTemporalDepGraph builds a dependency graph for the program using the existing depGraph type. |
| 166 | func buildTemporalDepGraph(programInfo *ProgramInfo) depGraph { |
| 167 | dep := make(depGraph) |
| 168 | |
| 169 | // Initialize nodes for all IDB predicates |
| 170 | for pred := range programInfo.IdbPredicates { |
| 171 | dep.initNode(pred) |
| 172 | } |
| 173 | |
| 174 | // Build edges from rule dependencies |
| 175 | for _, rule := range programInfo.Rules { |
| 176 | headPred := rule.Head.Predicate |
| 177 | dep.initNode(headPred) |
| 178 | |
| 179 | for _, premise := range rule.Premises { |
| 180 | var bodyPred ast.PredicateSym |
| 181 | switch p := premise.(type) { |
| 182 | case ast.Atom: |
| 183 | bodyPred = p.Predicate |
| 184 | case ast.NegAtom: |
| 185 | bodyPred = p.Atom.Predicate |
| 186 | case ast.TemporalLiteral: |
| 187 | switch lit := p.Literal.(type) { |
| 188 | case ast.Atom: |
| 189 | bodyPred = lit.Predicate |
| 190 | case ast.NegAtom: |
| 191 | bodyPred = lit.Atom.Predicate |
| 192 | } |
| 193 | default: |
| 194 | continue |
| 195 | } |
| 196 | |
| 197 | // Only track dependencies to IDB predicates |
| 198 | if _, isIDB := programInfo.IdbPredicates[bodyPred]; isIDB { |
| 199 | dep.addEdge(headPred, bodyPred, false) |
| 200 | } |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | return dep |
| 205 | } |
| 206 | |
| 207 | // isInSameSCC checks if two predicates are in the same strongly connected component. |
| 208 | func isInSameSCC(pred1, pred2 ast.PredicateSym, sccs []Nodeset) bool { |
no test coverage detected