ReadPred reads matching facts for a single predicate with arity > 0. len(filter) must match p.Arity.
(scanner *bufio.Scanner, p ast.PredicateSym, numFacts int, filter []ast.BaseTerm, cb func(args []ast.BaseTerm) error)
| 311 | // ReadPred reads matching facts for a single predicate with arity > 0. |
| 312 | // len(filter) must match p.Arity. |
| 313 | func (SimpleColumn) readPred(scanner *bufio.Scanner, p ast.PredicateSym, numFacts int, filter []ast.BaseTerm, cb func(args []ast.BaseTerm) error) error { |
| 314 | args := make([][]ast.BaseTerm, numFacts) |
| 315 | numSkip := 0 |
| 316 | skip := make([]bool, numFacts) |
| 317 | for i := 0; i < numFacts; i++ { |
| 318 | args[i] = make([]ast.BaseTerm, p.Arity) |
| 319 | } |
| 320 | // TODO: It would be smarter to load and traverse those columns that |
| 321 | // have a filter present. |
| 322 | for j := 0; j < p.Arity; j++ { |
| 323 | for i := 0; i < numFacts; i++ { |
| 324 | if ok := scanner.Scan(); !ok { |
| 325 | return fmt.Errorf("scanning pred %v column %d fact %d: %w", p, j, i, ErrCouldNotRead) |
| 326 | } |
| 327 | if skip[i] { // Fact does not match anyway. |
| 328 | continue |
| 329 | } |
| 330 | text := scanner.Text() |
| 331 | if text[0] == '/' { |
| 332 | var err error |
| 333 | text, err = percentUnescape(text) |
| 334 | if err != nil { |
| 335 | return fmt.Errorf("unescape failed pred %v column %d fact %d: %w", p, j, i, ErrCouldNotRead) |
| 336 | } |
| 337 | } |
| 338 | e, err := parse.BaseTerm(text) |
| 339 | if err != nil { |
| 340 | return fmt.Errorf("parsing failed pred %v column %d fact %d: %w", p, j, i, err) |
| 341 | } |
| 342 | |
| 343 | c, err := functional.EvalExpr(e, nil) |
| 344 | |
| 345 | if err != nil { |
| 346 | return fmt.Errorf("evaluating failed pred %v column %d fact %d: %w", p, j, i, ErrCouldNotRead) |
| 347 | } |
| 348 | args[i][j] = c |
| 349 | if filter == nil { |
| 350 | continue |
| 351 | } |
| 352 | want, ok := filter[j].(ast.Constant) |
| 353 | if !ok { |
| 354 | continue |
| 355 | } |
| 356 | skip[i] = !want.Equals(c) |
| 357 | numSkip++ |
| 358 | } |
| 359 | } |
| 360 | for i := 0; i < numFacts; i++ { |
| 361 | if skip[i] { |
| 362 | continue |
| 363 | } |
| 364 | if err := cb(args[i]); err != nil { |
| 365 | return err |
| 366 | } |
| 367 | } |
| 368 | return nil |
| 369 | } |
| 370 |