Evaluates a single premise atom by scanning facts.
(premise ast.Term, subst unionfind.UnionFind)
| 146 | |
| 147 | // Evaluates a single premise atom by scanning facts. |
| 148 | func (e naiveEngine) oneStepEvalPremise(premise ast.Term, subst unionfind.UnionFind) []unionfind.UnionFind { |
| 149 | var solutions []unionfind.UnionFind |
| 150 | switch p := premise.(type) { |
| 151 | case ast.Atom: |
| 152 | p, err := functional.EvalAtom(p, subst) |
| 153 | if err != nil { |
| 154 | return nil |
| 155 | } |
| 156 | if p.Predicate.IsBuiltin() { |
| 157 | res, nsubsts, err := builtin.Decide(p, &subst) |
| 158 | if err != nil { |
| 159 | // Treat errors in built-in predicate evaluation as false. |
| 160 | return nil |
| 161 | } |
| 162 | if !res { |
| 163 | return nil |
| 164 | } |
| 165 | for _, nsubst := range nsubsts { |
| 166 | solutions = append(solutions, *nsubst) |
| 167 | } |
| 168 | return solutions |
| 169 | } |
| 170 | // Not a built-in predicate. |
| 171 | e.store.GetFacts(p, func(fact ast.Atom) error { |
| 172 | // TODO: This could be made a lot more efficient by using a persistent |
| 173 | // data structure for composing the unionfind substitutions. |
| 174 | if newsubst, err := unionfind.UnifyTermsExtend(p.Args, fact.Args, subst); err == nil { |
| 175 | solutions = append(solutions, newsubst) |
| 176 | } |
| 177 | return nil |
| 178 | }) |
| 179 | case ast.NegAtom: |
| 180 | a, err := functional.EvalAtom(p.Atom, subst) |
| 181 | if err != nil { |
| 182 | return nil |
| 183 | } |
| 184 | e.store.GetFacts(a, func(fact ast.Atom) error { |
| 185 | if _, err := unionfind.UnifyTermsExtend(p.Atom.Args, fact.Args, subst); err != nil { |
| 186 | solutions = append(solutions, subst) |
| 187 | } |
| 188 | return nil |
| 189 | }) |
| 190 | case ast.Eq: |
| 191 | if newsubst, err := unionfind.UnifyTermsExtend([]ast.BaseTerm{p.Left}, []ast.BaseTerm{p.Right}, subst); err == nil { |
| 192 | solutions = append(solutions, newsubst) |
| 193 | } |
| 194 | case ast.Ineq: |
| 195 | if _, err := unionfind.UnifyTermsExtend([]ast.BaseTerm{p.Left}, []ast.BaseTerm{p.Right}, subst); err != nil { |
| 196 | solutions = append(solutions, subst) |
| 197 | } |
| 198 | } |
| 199 | return solutions |
| 200 | } |
no test coverage detected