New creates a new analyzer based on declarations and extra predicates.
(extraPredicates map[ast.PredicateSym]ast.Decl, decls []ast.Decl, boundsChecking BoundsCheckingMode)
| 184 | |
| 185 | // New creates a new analyzer based on declarations and extra predicates. |
| 186 | func New(extraPredicates map[ast.PredicateSym]ast.Decl, decls []ast.Decl, boundsChecking BoundsCheckingMode) (*Analyzer, error) { |
| 187 | extraByName := byName(extraPredicates) |
| 188 | declMap := make(map[ast.PredicateSym]ast.Decl) |
| 189 | for _, decl := range decls { |
| 190 | pred := decl.DeclaredAtom.Predicate |
| 191 | if pred == symbols.Package || pred == symbols.Use { |
| 192 | continue |
| 193 | } |
| 194 | if existing, ok := declMap[pred]; ok { |
| 195 | return nil, fmt.Errorf("predicate %v declared more than once, previous was %v", pred, existing) |
| 196 | } |
| 197 | declMap[pred] = decl |
| 198 | |
| 199 | if extraDecl, ok := extraByName[pred.Symbol]; ok { |
| 200 | // We have a user declaration for a symbol that is also known via extraPredicates. |
| 201 | if !extraDecl.IsSynthetic() { |
| 202 | return nil, fmt.Errorf("cannot redeclare %v, previous Decl %v", decl, extraDecl) |
| 203 | } |
| 204 | // We can override a synthetic decl, but arity should still match. |
| 205 | if extraDecl.DeclaredAtom.Predicate.Arity != pred.Arity { |
| 206 | return nil, fmt.Errorf("declared arity %v conflicts with extra decl %v", decl, extraDecl) |
| 207 | } |
| 208 | // Override the synthetic decl with the one we were requested to use. |
| 209 | delete(extraPredicates, pred) |
| 210 | } |
| 211 | } |
| 212 | return &Analyzer{extraPredicates, nil /* extraFunctions */, declMap, boundsChecking}, nil |
| 213 | } |
| 214 | |
| 215 | // EnsureDecl ensures that every predicate in the program is declared. |
| 216 | // It also ensures consistency of temporal usage. |