forked from regb/scala-smtlib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTermsOps.scala
92 lines (73 loc) · 2.46 KB
/
TermsOps.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package smtlib.parser
import Terms._
object TermsOps {
/* ========================
Operations on Sort
========================
*/
/** Applies a function to each sort in post-order
*
* The mapping is done starting from the leaf of the sort tree. For
* each node, first apply recursively the postMap on the children
* from left to right, then apply the function to the current sort
* with the new children.
*
* @param f the function to apply. If it returns None then do not
* update the corresponding node.
* @param sort the sort to traverse
* @return the new sort after applying the mapping
*/
def postMap(f: (Sort) => Option[Sort])(sort: Sort): Sort = {
val rec = postMap(f) _
val Sort(id, subSorts) = sort
val recSorts = subSorts.map(rec)
val newSort = {
if( recSorts.zip(subSorts).exists{ case (bef, aft) => bef ne aft } )
Sort(id, recSorts)
else
sort
}
f(newSort).getOrElse(newSort)
}
/** Applies a function to each sort in pre-order
*
* The mapping is done starting from the root of the sort tree. For
* each node, first apply the function to the current node, then
* do it recursively on the children from left to right.
*
* @param f the function to apply. If it returns None then do not
* update the corresponding node
* @param sort the sort to traverse
* @return the new sort after applying the mapping
* @note this operation can diverge if f is not well formed
*/
def preMap(f: (Sort) => Option[Sort])(sort: Sort): Sort = {
val rec = preMap(f) _
val newSort = f(sort).getOrElse(sort)
val Sort(id, subSorts) = newSort
val recSorts = subSorts.map(rec)
if( recSorts.zip(subSorts).exists{ case (bef, aft) => bef ne aft } )
Sort(id, recSorts)
else
newSort
}
def postTraversal(f: (Sort) => Unit)(sort: Sort): Unit = {
val rec = postTraversal(f) _
val Sort(_, subSorts) = sort
subSorts.foreach(rec)
f(sort)
}
def preTraversal(f: (Sort) => Unit)(sort: Sort): Unit = {
val rec = preTraversal(f) _
val Sort(_, subSorts) = sort
f(sort)
subSorts.foreach(rec)
}
def fold[T](f: (Sort, Seq[T]) => T)(sort: Sort): T = {
val rec = fold(f) _
val Sort(_, ss) = sort
f(sort, ss.map(rec))
}
def exists(matcher: (Sort) => Boolean)(sort: Sort): Boolean =
fold[Boolean]({ (s, subs) => matcher(s) || subs.contains(true) } )(sort)
}