Skip to content

Commit 33a862f

Browse files
committed
Implement simplification for string length expression
1 parent 3944aca commit 33a862f

2 files changed

Lines changed: 47 additions & 7 deletions

File tree

ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ fun KContext.simplifyStringConcat(
1616

1717
fun KContext.simplifyStringLen(
1818
arg: KExpr<KStringSort>
19-
): KExpr<KIntSort> = mkStringLenNoSimplify(arg) // Temporarily
19+
): KExpr<KIntSort> = simplifyStringLenExpr(arg, ::mkStringLenNoSimplify)
2020

2121
fun KContext.simplifyStringToRegex(
2222
arg: KExpr<KStringSort>

ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,21 @@ package io.ksmt.expr.rewrite.simplify
22

33
import io.ksmt.KContext
44
import io.ksmt.expr.KExpr
5+
import io.ksmt.expr.KInterpretedValue
56
import io.ksmt.expr.KStringConcatExpr
67
import io.ksmt.expr.KStringLiteralExpr
8+
import io.ksmt.sort.KIntSort
9+
import io.ksmt.sort.KSort
710
import io.ksmt.sort.KStringSort
811
import io.ksmt.utils.StringUtils
912

13+
/*
14+
* String concatenation simplification
15+
* */
16+
17+
/**
18+
* Eval constants.
19+
* (concat const1 const2) ==> (const3) */
1020
inline fun KContext.simplifyStringBasicConcat(
1121
arg0: KExpr<KStringSort>,
1222
arg1: KExpr<KStringSort>,
@@ -16,26 +26,32 @@ inline fun KContext.simplifyStringBasicConcat(
1626
cont(arg0, arg1)
1727
}
1828

29+
/**
30+
* ((concat a const1) const2) ==> (concat a (concat const1 const2))
31+
* ((concat const1 (concat const2 a)) => (concat (concat const1 const2) a)
32+
* ((concat (concat a const1) (concat const2 b)) ==> (concat a (concat (concat const1 const2) b))
33+
*/
1934
inline fun KContext.simplifyStringNestedConcat(
2035
arg0: KExpr<KStringSort>,
2136
arg1: KExpr<KStringSort>,
2237
rewriteStringConcatExpr: KContext.(KExpr<KStringSort>, KExpr<KStringSort>) -> KExpr<KStringSort>,
2338
cont: (KExpr<KStringSort>, KExpr<KStringSort>) -> KExpr<KStringSort>
2439
): KExpr<KStringSort> {
40+
// ((concat a const1) const2) ==> (concat a (concat const1 const2))
2541
if (arg0 is KStringLiteralExpr && arg1 is KStringConcatExpr) {
2642
val arg1Left = arg1.arg0
2743
if (arg1Left is KStringLiteralExpr) {
2844
return rewriteStringConcatExpr(StringUtils.concatStrings(arg0, arg1Left), arg1.arg1)
2945
}
3046
}
31-
47+
// ((concat const1 (concat const2 a)) => (concat (concat const1 const2) a)
3248
if (arg1 is KStringLiteralExpr && arg0 is KStringConcatExpr) {
3349
val arg0Right = arg0.arg1
3450
if (arg0Right is KStringLiteralExpr) {
3551
return rewriteStringConcatExpr(arg0.arg0, StringUtils.concatStrings(arg0Right, arg1))
3652
}
3753
}
38-
54+
// ((concat (concat a const1) (concat const2 b)) ==> (concat a (concat (concat const1 const2) b))
3955
if (arg0 is KStringConcatExpr && arg1 is KStringConcatExpr) {
4056
val arg0Right = arg0.arg1
4157
val arg1Left = arg1.arg0
@@ -50,13 +66,37 @@ inline fun KContext.simplifyStringNestedConcat(
5066
return cont(arg0, arg1)
5167
}
5268

69+
/*
70+
* String length expression simplification
71+
* */
72+
73+
inline fun KContext.simplifyStringLenExpr(
74+
arg: KExpr<KStringSort>,
75+
cont: (KExpr<KStringSort>) -> KExpr<KIntSort>
76+
): KExpr<KIntSort> =
77+
tryEvalStringLiteralOperation(arg, { literalArg ->
78+
mkIntNum(literalArg.value.length)
79+
}) {
80+
cont(arg)
81+
}
82+
83+
inline fun <K : KSort> tryEvalStringLiteralOperation(
84+
arg: KExpr<KStringSort>,
85+
operation: (KStringLiteralExpr) -> KInterpretedValue<K>,
86+
cont: () -> KExpr<K>
87+
): KExpr<K> = if (arg is KStringLiteralExpr) {
88+
operation(arg)
89+
} else {
90+
cont()
91+
}
92+
5393
inline fun tryEvalStringLiteralOperation(
54-
lhs: KExpr<KStringSort>,
55-
rhs: KExpr<KStringSort>,
94+
arg0: KExpr<KStringSort>,
95+
arg1: KExpr<KStringSort>,
5696
operation: (KStringLiteralExpr, KStringLiteralExpr) -> KStringLiteralExpr,
5797
cont: () -> KExpr<KStringSort>
58-
): KExpr<KStringSort> = if (lhs is KStringLiteralExpr && rhs is KStringLiteralExpr) {
59-
operation(lhs, rhs)
98+
): KExpr<KStringSort> = if (arg0 is KStringLiteralExpr && arg1 is KStringLiteralExpr) {
99+
operation(arg0, arg1)
60100
} else {
61101
cont()
62102
}

0 commit comments

Comments
 (0)