@@ -2,11 +2,21 @@ package io.ksmt.expr.rewrite.simplify
22
33import io.ksmt.KContext
44import io.ksmt.expr.KExpr
5+ import io.ksmt.expr.KInterpretedValue
56import io.ksmt.expr.KStringConcatExpr
67import io.ksmt.expr.KStringLiteralExpr
8+ import io.ksmt.sort.KIntSort
9+ import io.ksmt.sort.KSort
710import io.ksmt.sort.KStringSort
811import io.ksmt.utils.StringUtils
912
13+ /*
14+ * String concatenation simplification
15+ * */
16+
17+ /* *
18+ * Eval constants.
19+ * (concat const1 const2) ==> (const3) */
1020inline 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+ */
1934inline 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+
5393inline 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