Skip to content

Commit c98613a

Browse files
committed
Implement simplifiers for contains, toLower, toUpper, reverse operations
1 parent cdd24fe commit c98613a

3 files changed

Lines changed: 83 additions & 10 deletions

File tree

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ fun KContext.simplifyStringGe(
6060
fun KContext.simplifyStringContains(
6161
arg0: KExpr<KStringSort>,
6262
arg1: KExpr<KStringSort>
63-
): KExpr<KBoolSort> = mkStringContainsNoSimplify(arg0, arg1) // Temporarily
63+
): KExpr<KBoolSort> = simplifyStringBasicContainsExpr(arg0, arg1, ::mkStringContainsNoSimplify)
6464

6565
fun KContext.simplifyStringSingletonSub(
6666
arg0: KExpr<KStringSort>,
@@ -111,15 +111,15 @@ fun KContext.simplifyStringReplaceAllWithRegex(
111111

112112
fun KContext.simplifyStringToLower(
113113
arg: KExpr<KStringSort>
114-
): KExpr<KStringSort> = mkStringToLowerNoSimplify(arg) // Temporarily
114+
): KExpr<KStringSort> = simplifyStringBasicToLowerExpr(arg, ::mkStringToLowerNoSimplify)
115115

116116
fun KContext.simplifyStringToUpper(
117117
arg: KExpr<KStringSort>
118-
): KExpr<KStringSort> = mkStringToUpperNoSimplify(arg) // Temporarily
118+
): KExpr<KStringSort> = simplifyStringBasicToUpperExpr(arg, ::mkStringToUpperNoSimplify)
119119

120120
fun KContext.simplifyStringReverse(
121121
arg: KExpr<KStringSort>
122-
): KExpr<KStringSort> = mkStringReverseNoSimplify(arg) // Temporarily
122+
): KExpr<KStringSort> = simplifyStringBasicReverseExpr(arg, ::mkStringReverseNoSimplify)
123123

124124
fun KContext.simplifyStringIsDigit(
125125
arg: KExpr<KStringSort>

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

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package io.ksmt.expr.rewrite.simplify
22

33
import io.ksmt.KContext
4-
import io.ksmt.expr.KExpr
5-
import io.ksmt.expr.KInterpretedValue
6-
import io.ksmt.expr.KStringConcatExpr
7-
import io.ksmt.expr.KStringLiteralExpr
4+
import io.ksmt.expr.*
85
import io.ksmt.sort.KBoolSort
96
import io.ksmt.sort.KIntSort
107
import io.ksmt.sort.KSort
@@ -77,8 +74,8 @@ inline fun KContext.simplifyStringLenExpr(
7774
arg: KExpr<KStringSort>,
7875
cont: (KExpr<KStringSort>) -> KExpr<KIntSort>
7976
): KExpr<KIntSort> =
80-
tryEvalStringLiteralOperation(arg, { literalArg ->
81-
mkIntNum(literalArg.value.length)
77+
tryEvalStringLiteralOperation(arg, {
78+
a -> StringUtils.getStringLen(a)
8279
}) {
8380
cont(arg)
8481
}
@@ -157,6 +154,52 @@ inline fun KContext.simplifyStringBasicGeExpr(
157154
cont(arg0, arg1)
158155
}
159156

157+
/*
158+
* String contains expression simplifications
159+
* */
160+
161+
/** Basic simplify string contains expression
162+
* (str_contains strConst1 strConst2) ==> boolConst */
163+
inline fun KContext.simplifyStringBasicContainsExpr(
164+
arg0: KExpr<KStringSort>,
165+
arg1: KExpr<KStringSort>,
166+
cont: (KExpr<KStringSort>, KExpr<KStringSort>) -> KExpr<KBoolSort>
167+
): KExpr<KBoolSort> =
168+
tryEvalStringLiteralOperation(arg0, arg1, { a0, a1 -> StringUtils.stringContains(a0, a1) }) {
169+
cont(arg0, arg1)
170+
}
171+
172+
/*
173+
* String to lower/upper case expression simplifications
174+
* */
175+
176+
/** Converting all letters of a string constant to lowercase. */
177+
inline fun KContext.simplifyStringBasicToLowerExpr(
178+
arg: KExpr<KStringSort>,
179+
cont: (KExpr<KStringSort>) -> KExpr<KStringSort>
180+
): KExpr<KStringSort> =
181+
tryEvalStringLiteralOperation(arg, { a -> StringUtils.stringToLowerCase(a) }) {
182+
cont(arg)
183+
}
184+
185+
/** Converting all letters of a string constant to uppercase. */
186+
inline fun KContext.simplifyStringBasicToUpperExpr(
187+
arg: KExpr<KStringSort>,
188+
cont: (KExpr<KStringSort>) -> KExpr<KStringSort>
189+
): KExpr<KStringSort> =
190+
tryEvalStringLiteralOperation(arg, { a -> StringUtils.stringToUpperCase(a) }) {
191+
cont(arg)
192+
}
193+
194+
/** Reverses a string constant */
195+
inline fun KContext.simplifyStringBasicReverseExpr(
196+
arg: KExpr<KStringSort>,
197+
cont: (KExpr<KStringSort>) -> KExpr<KStringSort>
198+
): KExpr<KStringSort> =
199+
tryEvalStringLiteralOperation(arg, { a -> StringUtils.stringReverse(a) }) {
200+
cont(arg)
201+
}
202+
160203
inline fun <K : KSort> tryEvalStringLiteralOperation(
161204
arg: KExpr<KStringSort>,
162205
operation: (KStringLiteralExpr) -> KInterpretedValue<K>,

ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
package io.ksmt.utils
22

3+
import io.ksmt.expr.KInt32NumExpr
4+
import io.ksmt.expr.KInt64NumExpr
5+
import io.ksmt.expr.KIntBigNumExpr
6+
import io.ksmt.expr.KIntNumExpr
37
import io.ksmt.expr.KInterpretedValue
48
import io.ksmt.expr.KStringLiteralExpr
59
import io.ksmt.sort.KBoolSort
610

711
object StringUtils {
812

13+
@JvmStatic
14+
fun getStringLen(arg: KStringLiteralExpr): KIntNumExpr = with (arg.ctx) {
15+
mkIntNum(arg.value.length)
16+
}
17+
918
@JvmStatic
1019
fun concatStrings(lhs: KStringLiteralExpr, rhs: KStringLiteralExpr): KStringLiteralExpr = with (lhs.ctx) {
1120
mkStringLiteral(lhs.value + rhs.value)
@@ -40,4 +49,25 @@ object StringUtils {
4049
fun stringGe(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue<KBoolSort> = with (arg0.ctx) {
4150
mkBool(arg0.value >= arg1.value).uncheckedCast()
4251
}
52+
53+
@JvmStatic
54+
fun stringContains(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue<KBoolSort> = with (arg0.ctx) {
55+
mkBool(arg0.value.contains(arg1.value)).uncheckedCast()
56+
}
57+
58+
@JvmStatic
59+
fun stringToLowerCase(arg: KStringLiteralExpr): KStringLiteralExpr = with (arg.ctx) {
60+
mkStringLiteral(arg.value.lowercase())
61+
}
62+
63+
@JvmStatic
64+
fun stringToUpperCase(arg: KStringLiteralExpr): KStringLiteralExpr = with (arg.ctx) {
65+
mkStringLiteral(arg.value.uppercase())
66+
}
67+
68+
@JvmStatic
69+
fun stringReverse(arg: KStringLiteralExpr): KStringLiteralExpr = with (arg.ctx) {
70+
mkStringLiteral(arg.value.reversed())
71+
}
72+
4373
}

0 commit comments

Comments
 (0)