Source code for pyk.kore.manip
1from __future__ import annotations
2
3from typing import TYPE_CHECKING
4
5from .syntax import And, Assoc, EVar, MLQuant, Top
6
7if TYPE_CHECKING:
8 from collections.abc import Collection
9
10 from .syntax import Pattern
11
12
[docs]
13def conjuncts(pattern: Pattern) -> tuple[Pattern, ...]:
14 if isinstance(pattern, Top):
15 return ()
16 if isinstance(pattern, And):
17 return tuple(conjunct for op in pattern.ops for conjunct in conjuncts(op))
18 return (pattern,)
19
20
[docs]
21def free_occs(pattern: Pattern, *, bound_vars: Collection[str] = ()) -> dict[str, list[EVar]]:
22 occurrences: dict[str, list[EVar]] = {}
23
24 def collect(pattern: Pattern, bound_vars: set[str]) -> None:
25 if type(pattern) is EVar and pattern.name not in bound_vars:
26 if pattern.name in occurrences:
27 occurrences[pattern.name].append(pattern)
28 else:
29 occurrences[pattern.name] = [pattern]
30
31 elif isinstance(pattern, Assoc):
32 collect(pattern.app, bound_vars)
33
34 elif isinstance(pattern, MLQuant):
35 new_bound_vars = {pattern.var.name}.union(bound_vars)
36 collect(pattern.pattern, new_bound_vars)
37
38 else:
39 for sub_pattern in pattern.patterns:
40 collect(sub_pattern, bound_vars)
41
42 collect(pattern, set(bound_vars))
43 return occurrences