Analyze identifies the extensional and intensional predicates of a program, checks every rule and that all references to built-in predicates and functions used in transforms are valid.
(program []ast.Clause)
| 278 | // Analyze identifies the extensional and intensional predicates of a program, checks every rule and that |
| 279 | // all references to built-in predicates and functions used in transforms are valid. |
| 280 | func (a *Analyzer) Analyze(program []ast.Clause) (*ProgramInfo, error) { |
| 281 | if err := a.EnsureDecl(program); err != nil { |
| 282 | return nil, err |
| 283 | } |
| 284 | // Resolve MaybeTemporal descriptors to Temporal. |
| 285 | for sym, decl := range a.decl { |
| 286 | if decl.IsMaybeTemporal() { |
| 287 | newDescr := make([]ast.Atom, 0, len(decl.Descr)) |
| 288 | temporalAtom := ast.NewAtom(ast.DescrTemporal) |
| 289 | maybeTemporalAtom := ast.NewAtom(ast.DescrMaybeTemporal) |
| 290 | for _, d := range decl.Descr { |
| 291 | if !d.Equals(maybeTemporalAtom) { |
| 292 | newDescr = append(newDescr, d) |
| 293 | } |
| 294 | } |
| 295 | newDescr = append(newDescr, temporalAtom) |
| 296 | decl.Descr = newDescr |
| 297 | a.decl[sym] = decl |
| 298 | } |
| 299 | } |
| 300 | globalDecls := make(map[ast.PredicateSym]ast.Decl) |
| 301 | for p, d := range a.extraPredicates { |
| 302 | globalDecls[p] = d |
| 303 | } |
| 304 | for p, d := range a.decl { |
| 305 | globalDecls[p] = d |
| 306 | if errs := CheckDecl(d); errs != nil { |
| 307 | return nil, multierr.Combine(errs...) |
| 308 | } |
| 309 | } |
| 310 | desugaredDecls, err := symbols.CheckAndDesugar(globalDecls) |
| 311 | if err != nil { |
| 312 | return nil, err |
| 313 | } |
| 314 | edbSymbols := make(map[ast.PredicateSym]struct{}) |
| 315 | idbSymbols := make(map[ast.PredicateSym]struct{}) |
| 316 | var initialFacts []ast.Atom |
| 317 | var initialFactTimes []*ast.Interval |
| 318 | var rules []ast.Clause |
| 319 | rulesMap := make(map[ast.PredicateSym][]ast.Clause) |
| 320 | for _, clause := range program { |
| 321 | clause = RewriteClause(desugaredDecls, clause) |
| 322 | |
| 323 | // Normalize TemporalAtom to TemporalLiteral (or bare Atom) for consistent analysis |
| 324 | if clause.Premises != nil { |
| 325 | for i, premise := range clause.Premises { |
| 326 | if ta, ok := premise.(ast.TemporalAtom); ok { |
| 327 | if ta.Interval == nil { |
| 328 | clause.Premises[i] = ta.Atom |
| 329 | } else { |
| 330 | clause.Premises[i] = ast.TemporalLiteral{ |
| 331 | Literal: ta.Atom, |
| 332 | Interval: ta.Interval, |
| 333 | } |
| 334 | } |
| 335 | } |
| 336 | } |
| 337 | } |