inferRelTypesFromClause infers possible relation types for the head predicate of a single clause.
()
| 290 | |
| 291 | // inferRelTypesFromClause infers possible relation types for the head predicate of a single clause. |
| 292 | func (ic *inferContext) inferRelTypesFromClause() (ast.BaseTerm, error) { |
| 293 | clause := ic.clause |
| 294 | |
| 295 | usedVars := VarList{} |
| 296 | state := &inferState{0, usedVars, []ast.BaseTerm{}} |
| 297 | |
| 298 | if ic.decl != nil && len(ic.modes) == 1 { |
| 299 | for i, m := range ic.modes[0] { |
| 300 | v, ok := clause.Head.Args[i].(ast.Variable) |
| 301 | if !ok { |
| 302 | continue |
| 303 | } |
| 304 | if m == ast.ArgModeInput { |
| 305 | // Treat as bound variable. |
| 306 | state.usedVars = state.usedVars.Extend([]ast.Variable{v}) |
| 307 | types := []ast.BaseTerm{} |
| 308 | if len(ic.decl.Bounds) > 0 { |
| 309 | for _, b := range ic.decl.Bounds { |
| 310 | tpe := b.Bounds[i] |
| 311 | types = append(types, tpe) |
| 312 | } |
| 313 | } else { |
| 314 | types = append(types, ast.AnyBound) |
| 315 | } |
| 316 | if len(types) == 1 { |
| 317 | state.varTpe = append(state.varTpe, types[0]) |
| 318 | } else { |
| 319 | state.varTpe = append(state.varTpe, symbols.NewUnionType(types...)) |
| 320 | } |
| 321 | } |
| 322 | } |
| 323 | } |
| 324 | levels := make([][]*inferState, len(clause.Premises)+1) |
| 325 | levels[0] = []*inferState{state} |
| 326 | for i := range clause.Premises { |
| 327 | for _, state := range levels[i] { |
| 328 | nextStates, err := ic.inferRelTypesFromPremise(clause.Premises, state) |
| 329 | if err != nil { |
| 330 | continue |
| 331 | } |
| 332 | levels[i+1] = append(levels[i+1], nextStates...) |
| 333 | } |
| 334 | if len(levels[i+1]) == 0 { |
| 335 | return nil, fmt.Errorf("type mismatch: cannot find assignment that works for premise %v", clause.Premises[i]) |
| 336 | } |
| 337 | } |
| 338 | |
| 339 | // Constrain variables used in HeadTime to be of type Time. |
| 340 | if clause.HeadTime != nil { |
| 341 | var nextStates []*inferState |
| 342 | var lastErr error |
| 343 | for _, s := range levels[len(clause.Premises)] { |
| 344 | valid := true |
| 345 | if clause.HeadTime.Start.Type == ast.VariableBound { |
| 346 | if err := s.addOrRefine(clause.HeadTime.Start.Variable, ast.TimeBound); err != nil { |
| 347 | valid = false |
| 348 | lastErr = err |
| 349 | } |
no test coverage detected