MCPcopy
hub / github.com/google/mangle / EnsureDecl

Method EnsureDecl

analysis/validation.go:217–276  ·  view source on GitHub ↗

EnsureDecl ensures that every predicate in the program is declared. It also ensures consistency of temporal usage.

(clauses []ast.Clause)

Source from the content-addressed store, hash-verified

215// EnsureDecl ensures that every predicate in the program is declared.
216// It also ensures consistency of temporal usage.
217func (a *Analyzer) EnsureDecl(clauses []ast.Clause) error {
218 extraByName := byName(a.extraPredicates)
219 declByName := byName(a.decl)
220 for _, c := range clauses {
221 pred := c.Head.Predicate
222 name := pred.Symbol
223 // Check that the name was not defined previously (in a separate source).
224 // We may permit "distributing" definitions over source files later.
225 if decl, ok := a.extraPredicates[pred]; ok {
226 if decl.IsExtensional() && len(c.Premises) == 0 {
227 continue
228 }
229 return fmt.Errorf("predicate %v was defined previously %v", decl.DeclaredAtom.Predicate, decl)
230 }
231 if decl, ok := extraByName[name]; ok { // different arity
232 return fmt.Errorf(
233 "predicate %v was defined previously", decl.DeclaredAtom.Predicate)
234 }
235
236 // If we already have a declaration, check if it is compatible.
237 // Note that we may have multiple declarations for the same predicate
238 // (e.g. one from use and one from package).
239 if decl, ok := a.decl[pred]; ok {
240 // If we have an existing declaration, check for temporal consistency
241 if c.HeadTime != nil && !c.HeadTime.IsEternal() {
242 if !decl.IsTemporal() && !decl.IsMaybeTemporal() {
243 return fmt.Errorf("predicate %v is not declared temporal but used with temporal annotation in %v", pred, c)
244 }
245 }
246 continue
247 }
248 // Check that the name was not defined in the same source with a different arity.
249 if decl, ok := declByName[name]; ok {
250 return fmt.Errorf("%v does not match arity of %v", c.Head, decl.DeclaredAtom)
251 }
252
253 var (
254 synthDecl ast.Decl
255 err error
256 )
257 if c.Premises != nil {
258 synthDecl, err = ast.NewSyntheticDecl(c.Head) // preserve variable names.
259 } else {
260 synthDecl = ast.NewSyntheticDeclFromSym(pred)
261 }
262 if err != nil {
263 return err
264 }
265
266 // If this is a synthetic declaration and we have a temporal annotation,
267 // mark it as "MaybeTemporal" so we can check consistency later.
268 if c.HeadTime != nil && !c.HeadTime.IsEternal() {
269 synthDecl.Descr = append(synthDecl.Descr, ast.NewAtom(ast.DescrMaybeTemporal))
270 }
271
272 a.decl[pred] = synthDecl
273 declByName[pred.Symbol] = a.decl[pred]
274 }

Callers 2

AnalyzeMethod · 0.95
AnalyzeAndCheckBoundsFunction · 0.80

Calls 8

NewSyntheticDeclFunction · 0.92
NewSyntheticDeclFromSymFunction · 0.92
NewAtomFunction · 0.92
byNameFunction · 0.85
IsExtensionalMethod · 0.80
IsEternalMethod · 0.80
IsTemporalMethod · 0.80
IsMaybeTemporalMethod · 0.80

Tested by

no test coverage detected