From 183449fb6fbb54c53d1262fb9c85a46793a3fc99 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 3 Dec 2024 16:50:26 +0300 Subject: [PATCH 01/84] Add string sort to core --- .../src/main/kotlin/io/ksmt/sort/KSort.kt | 12 ++++++++++++ .../main/kotlin/io/ksmt/sort/KSortVisitor.kt | 1 + .../io/ksmt/utils/DefaultValueSampler.kt | 18 +++++------------- .../io/ksmt/utils/KExprTheoryRequirement.kt | 19 +++++-------------- 4 files changed, 23 insertions(+), 27 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/sort/KSort.kt b/ksmt-core/src/main/kotlin/io/ksmt/sort/KSort.kt index 75f00a0b4..9cf610a34 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/sort/KSort.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/sort/KSort.kt @@ -46,6 +46,18 @@ class KRealSort internal constructor(ctx: KContext) : KArithSort(ctx) { override fun equals(other: Any?): Boolean = this === other || other is KRealSort } +class KStringSort internal constructor(ctx: KContext) : KSort(ctx) { + override fun accept(visitor: KSortVisitor): T = visitor.visit(this) + + override fun print(builder: StringBuilder) { + builder.append("String") + } + + override fun hashCode(): Int = hash(javaClass) + + override fun equals(other: Any?): Boolean = this === other || other is KStringSort +} + sealed class KArraySortBase(ctx: KContext) : KSort(ctx) { abstract val domainSorts: List abstract val range: R diff --git a/ksmt-core/src/main/kotlin/io/ksmt/sort/KSortVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/sort/KSortVisitor.kt index d44cb63a0..73079801c 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/sort/KSortVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/sort/KSortVisitor.kt @@ -5,6 +5,7 @@ interface KSortVisitor { fun visit(sort: KBoolSort): T fun visit(sort: KIntSort): T fun visit(sort: KRealSort): T + fun visit(sort: KStringSort): T fun visit(sort: S): T fun visit(sort: S): T fun visit(sort: KArraySort): T diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt index f4df37e27..9c5c1d838 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt @@ -2,19 +2,7 @@ package io.ksmt.utils import io.ksmt.KContext import io.ksmt.expr.KExpr -import io.ksmt.sort.KArray2Sort -import io.ksmt.sort.KArray3Sort -import io.ksmt.sort.KArrayNSort -import io.ksmt.sort.KArraySort -import io.ksmt.sort.KBoolSort -import io.ksmt.sort.KBvSort -import io.ksmt.sort.KFpRoundingModeSort -import io.ksmt.sort.KFpSort -import io.ksmt.sort.KIntSort -import io.ksmt.sort.KRealSort -import io.ksmt.sort.KSort -import io.ksmt.sort.KSortVisitor -import io.ksmt.sort.KUninterpretedSort +import io.ksmt.sort.* open class DefaultValueSampler(val ctx: KContext) : KSortVisitor> { override fun visit(sort: KBoolSort): KExpr<*> = @@ -26,6 +14,10 @@ open class DefaultValueSampler(val ctx: KContext) : KSortVisitor> { override fun visit(sort: KRealSort): KExpr<*> = ctx.realSortDefaultValue() + override fun visit(sort: KStringSort): KExpr<*> { + TODO("Not yet implemented") + } + override fun visit(sort: S): KExpr<*> = ctx.bvSortDefaultValue(sort) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt index eeb205f10..888b9a478 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt @@ -18,20 +18,7 @@ import io.ksmt.solver.KTheory.LRA import io.ksmt.solver.KTheory.NIA import io.ksmt.solver.KTheory.NRA import io.ksmt.solver.KTheory.UF -import io.ksmt.sort.KArithSort -import io.ksmt.sort.KArray2Sort -import io.ksmt.sort.KArray3Sort -import io.ksmt.sort.KArrayNSort -import io.ksmt.sort.KArraySort -import io.ksmt.sort.KBoolSort -import io.ksmt.sort.KBvSort -import io.ksmt.sort.KFpRoundingModeSort -import io.ksmt.sort.KFpSort -import io.ksmt.sort.KIntSort -import io.ksmt.sort.KRealSort -import io.ksmt.sort.KSort -import io.ksmt.sort.KSortVisitor -import io.ksmt.sort.KUninterpretedSort +import io.ksmt.sort.* class KExprTheoryRequirement(ctx: KContext) : KNonRecursiveTransformer(ctx) { val usedTheories = hashSetOf() @@ -90,6 +77,10 @@ class KExprTheoryRequirement(ctx: KContext) : KNonRecursiveTransformer(ctx) { usedTheories += LRA } + override fun visit(sort: KStringSort) { + TODO("Not yet implemented") + } + override fun visit(sort: S) { usedTheories += BV } From 25db759d3af8b2f8a820aa5715f5656bd29c7b86 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 3 Dec 2024 16:50:46 +0300 Subject: [PATCH 02/84] Add regex sort to core --- ksmt-core/src/main/kotlin/io/ksmt/sort/KSort.kt | 12 ++++++++++++ .../src/main/kotlin/io/ksmt/sort/KSortVisitor.kt | 1 + .../main/kotlin/io/ksmt/utils/DefaultValueSampler.kt | 4 ++++ .../kotlin/io/ksmt/utils/KExprTheoryRequirement.kt | 4 ++++ 4 files changed, 21 insertions(+) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/sort/KSort.kt b/ksmt-core/src/main/kotlin/io/ksmt/sort/KSort.kt index 9cf610a34..43843efca 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/sort/KSort.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/sort/KSort.kt @@ -58,6 +58,18 @@ class KStringSort internal constructor(ctx: KContext) : KSort(ctx) { override fun equals(other: Any?): Boolean = this === other || other is KStringSort } +class KRegexSort internal constructor(ctx: KContext) : KSort(ctx) { + override fun accept(visitor: KSortVisitor): T = visitor.visit(this) + + override fun print(builder: StringBuilder) { + builder.append("Regex") + } + + override fun hashCode(): Int = hash(javaClass) + + override fun equals(other: Any?): Boolean = this === other || other is KRegexSort +} + sealed class KArraySortBase(ctx: KContext) : KSort(ctx) { abstract val domainSorts: List abstract val range: R diff --git a/ksmt-core/src/main/kotlin/io/ksmt/sort/KSortVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/sort/KSortVisitor.kt index 73079801c..2260ed936 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/sort/KSortVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/sort/KSortVisitor.kt @@ -6,6 +6,7 @@ interface KSortVisitor { fun visit(sort: KIntSort): T fun visit(sort: KRealSort): T fun visit(sort: KStringSort): T + fun visit(sort: KRegexSort): T fun visit(sort: S): T fun visit(sort: S): T fun visit(sort: KArraySort): T diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt index 9c5c1d838..932285b88 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt @@ -18,6 +18,10 @@ open class DefaultValueSampler(val ctx: KContext) : KSortVisitor> { TODO("Not yet implemented") } + override fun visit(sort: KRegexSort): KExpr<*> { + TODO("Not yet implemented") + } + override fun visit(sort: S): KExpr<*> = ctx.bvSortDefaultValue(sort) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt index 888b9a478..c033d4d02 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt @@ -81,6 +81,10 @@ class KExprTheoryRequirement(ctx: KContext) : KNonRecursiveTransformer(ctx) { TODO("Not yet implemented") } + override fun visit(sort: KRegexSort) { + TODO("Not yet implemented") + } + override fun visit(sort: S) { usedTheories += BV } From 3b52e78364d2a3e68c8773f890a9061f561b154b Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 3 Dec 2024 16:59:19 +0300 Subject: [PATCH 03/84] Add string and regex sorts to context --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 4e49399f9..e7c4b2713 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -422,6 +422,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KSortVisitor import io.ksmt.sort.KUninterpretedSort @@ -591,6 +593,24 @@ open class KContext( * */ fun mkRealSort(): KRealSort = realSortCache + private val stringSortCache by lazy { + ensureContextActive { KStringSort(this) } + } + + /** + * Create a String sort. + * */ + fun mkStringSort(): KStringSort = stringSortCache + + private val regexSortCache by lazy { + ensureContextActive { KRegexSort(this) } + } + + /** + * Create a Regex sort. + * */ + fun mkRegexSort(): KRegexSort = regexSortCache + // bit-vec private val bv1SortCache: KBv1Sort by lazy { KBv1Sort(this) } private val bv8SortCache: KBv8Sort by lazy { KBv8Sort(this) } From 6815d4d7373ad13abccc5701e263981b8072487a Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 3 Dec 2024 17:30:57 +0300 Subject: [PATCH 04/84] Implement string literal's expr and decl --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 19 ++++++++++++++ .../src/main/kotlin/io/ksmt/decl/String.kt | 14 ++++++++++ .../src/main/kotlin/io/ksmt/expr/String.kt | 26 +++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt create mode 100644 ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index e7c4b2713..cea94e103 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -129,6 +129,7 @@ import io.ksmt.decl.KIntModDecl import io.ksmt.decl.KIntNumDecl import io.ksmt.decl.KIntRemDecl import io.ksmt.decl.KIntToRealDecl +import io.ksmt.decl.KStringLiteralDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl import io.ksmt.decl.KOrDecl @@ -272,6 +273,7 @@ import io.ksmt.expr.KInt64NumExpr import io.ksmt.expr.KIntBigNumExpr import io.ksmt.expr.KIntNumExpr import io.ksmt.expr.KIsIntRealExpr +import io.ksmt.expr.KStringLiteralExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr import io.ksmt.expr.KLtArithExpr @@ -729,6 +731,9 @@ open class KContext( val realSort: KRealSort get() = mkRealSort() + val stringSort: KStringSort + get() = mkStringSort() + val bv1Sort: KBv1Sort get() = mkBv1Sort() @@ -1884,6 +1889,16 @@ open class KContext( fun KExpr.toIntExpr() = mkRealToInt(this) fun KExpr.isIntExpr() = mkRealIsInt(this) + // strings + private val stringLiteralCache = mkAstInterner() + + /** + * Create a String value. + * */ + fun mkStringLiteral(value: String): KStringLiteralExpr = stringLiteralCache.createIfContextActive { + KStringLiteralExpr(this, value) + } + // bitvectors private val bv1Cache = mkAstInterner() private val bv8Cache = mkAstInterner() @@ -4483,6 +4498,10 @@ open class KContext( fun mkRealNumDecl(value: String): KRealNumDecl = KRealNumDecl(this, value) + // string + fun mkStringLiteralDecl(value: String): KStringLiteralDecl = KStringLiteralDecl(this, value) + + // Bit vectors fun mkBvDecl(value: Boolean): KDecl = KBitVec1ValueDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt new file mode 100644 index 000000000..e9527a58e --- /dev/null +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -0,0 +1,14 @@ +package io.ksmt.decl + +import io.ksmt.KContext +import io.ksmt.expr.KApp +import io.ksmt.expr.KExpr +import io.ksmt.sort.KStringSort + +class KStringLiteralDecl internal constructor( + ctx: KContext, + val value: String +) : KConstDecl(ctx, value, ctx.mkStringSort()) { + override fun apply(args: List>): KApp = ctx.mkStringLiteral(value) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt new file mode 100644 index 000000000..dbf1d32c0 --- /dev/null +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -0,0 +1,26 @@ +package io.ksmt.expr + +import io.ksmt.KContext +import io.ksmt.cache.hash +import io.ksmt.cache.structurallyEqual +import io.ksmt.decl.KStringLiteralDecl +import io.ksmt.expr.transformer.KTransformerBase +import io.ksmt.sort.KStringSort + +class KStringLiteralExpr internal constructor( + ctx: KContext, + val value: String +) : KInterpretedValue(ctx) { + override val sort: KStringSort + get() = ctx.stringSort + + override val decl: KStringLiteralDecl + get() = ctx.mkStringLiteralDecl(value) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(value) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { value } +} From e98b3869410a9e7b90383dd2cbb2d7ed14fd1eb2 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 3 Dec 2024 20:07:53 +0300 Subject: [PATCH 05/84] Implement regex literal's expr and decl --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 17 ++++++++++++ .../src/main/kotlin/io/ksmt/decl/Regex.kt | 14 ++++++++++ .../src/main/kotlin/io/ksmt/expr/Regex.kt | 27 +++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt create mode 100644 ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index cea94e103..e1c69789a 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -130,6 +130,7 @@ import io.ksmt.decl.KIntNumDecl import io.ksmt.decl.KIntRemDecl import io.ksmt.decl.KIntToRealDecl import io.ksmt.decl.KStringLiteralDecl +import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl import io.ksmt.decl.KOrDecl @@ -274,6 +275,7 @@ import io.ksmt.expr.KIntBigNumExpr import io.ksmt.expr.KIntNumExpr import io.ksmt.expr.KIsIntRealExpr import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr import io.ksmt.expr.KLtArithExpr @@ -734,6 +736,9 @@ open class KContext( val stringSort: KStringSort get() = mkStringSort() + val regexSort: KRegexSort + get() = mkRegexSort() + val bv1Sort: KBv1Sort get() = mkBv1Sort() @@ -1899,6 +1904,15 @@ open class KContext( KStringLiteralExpr(this, value) } + private val regexLiteralCache = mkAstInterner() + + /** + * Create a Regex value. + * */ + fun mkRegexLiteral(value: String): KRegexLiteralExpr = regexLiteralCache.createIfContextActive { + KRegexLiteralExpr(this, value) + } + // bitvectors private val bv1Cache = mkAstInterner() private val bv8Cache = mkAstInterner() @@ -4501,6 +4515,9 @@ open class KContext( // string fun mkStringLiteralDecl(value: String): KStringLiteralDecl = KStringLiteralDecl(this, value) + // regex + fun mkRegexLiteralDecl(value: String): KRegexLiteralDecl = KRegexLiteralDecl(this, value) + // Bit vectors fun mkBvDecl(value: Boolean): KDecl = KBitVec1ValueDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt new file mode 100644 index 000000000..7980db74c --- /dev/null +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -0,0 +1,14 @@ +package io.ksmt.decl + +import io.ksmt.KContext +import io.ksmt.expr.KApp +import io.ksmt.expr.KExpr +import io.ksmt.sort.KRegexSort + +class KRegexLiteralDecl internal constructor( + ctx: KContext, + val value: String +) : KConstDecl(ctx, value, ctx.mkRegexSort()) { + override fun apply(args: List>): KApp = ctx.mkRegexLiteral(value) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt new file mode 100644 index 000000000..31c5f5444 --- /dev/null +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -0,0 +1,27 @@ +package io.ksmt.expr + +import io.ksmt.KContext +import io.ksmt.cache.hash +import io.ksmt.cache.structurallyEqual +import io.ksmt.decl.KRegexLiteralDecl +import io.ksmt.expr.transformer.KTransformerBase +import io.ksmt.sort.KRegexSort +import io.ksmt.sort.KStringSort + +class KRegexLiteralExpr internal constructor( + ctx: KContext, + val value: String +) : KInterpretedValue(ctx) { + override val sort: KRegexSort + get() = ctx.regexSort + + override val decl: KRegexLiteralDecl + get() = ctx.mkRegexLiteralDecl(value) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(value) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { value } +} From c52235a5b7bb38cd4b7c569630a9f09176716433 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 3 Dec 2024 21:11:22 +0300 Subject: [PATCH 06/84] Implement strings concatenation --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 21 +++++++++++++++++ .../src/main/kotlin/io/ksmt/decl/String.kt | 17 ++++++++++++++ .../src/main/kotlin/io/ksmt/expr/Regex.kt | 1 - .../src/main/kotlin/io/ksmt/expr/String.kt | 23 +++++++++++++++++++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index e1c69789a..f3fba85b2 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -130,6 +130,7 @@ import io.ksmt.decl.KIntNumDecl import io.ksmt.decl.KIntRemDecl import io.ksmt.decl.KIntToRealDecl import io.ksmt.decl.KStringLiteralDecl +import io.ksmt.decl.KStringConcatDecl import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl @@ -275,6 +276,7 @@ import io.ksmt.expr.KIntBigNumExpr import io.ksmt.expr.KIntNumExpr import io.ksmt.expr.KIsIntRealExpr import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr @@ -1904,6 +1906,23 @@ open class KContext( KStringLiteralExpr(this, value) } + private val stringConcatExprCache = mkAstInterner() + + /** + * Create String concatenation (`concat`) expression. + * */ + open fun mkStringConcatExpr(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkStringConcatExprNoSimplify, ::mkStringConcatExprNoSimplify) // Add simplified version + + /** + * Create String concatenation (`concat`) expression. + * */ + open fun mkStringConcatExprNoSimplify(arg0: KExpr, arg1: KExpr): KStringConcatExpr = + stringConcatExprCache.createIfContextActive { + ensureContextMatch(arg0, arg1) + KStringConcatExpr(this, arg0, arg1) + } + private val regexLiteralCache = mkAstInterner() /** @@ -4515,6 +4534,8 @@ open class KContext( // string fun mkStringLiteralDecl(value: String): KStringLiteralDecl = KStringLiteralDecl(this, value) + fun mkStringConcatDecl(): KStringConcatDecl = KStringConcatDecl(this) + // regex fun mkRegexLiteralDecl(value: String): KRegexLiteralDecl = KRegexLiteralDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index e9527a58e..d958c8e01 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -12,3 +12,20 @@ class KStringLiteralDecl internal constructor( override fun apply(args: List>): KApp = ctx.mkStringLiteral(value) override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } + +class KStringConcatDecl internal constructor( + ctx: KContext, +) : KFuncDecl2( + ctx, + name = "concat", + resultSort = ctx.mkStringSort(), + ctx.mkStringSort(), + ctx.mkStringSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkStringConcatExprNoSimplify(arg0, arg1) +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index 31c5f5444..9ab7a083b 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -6,7 +6,6 @@ import io.ksmt.cache.structurallyEqual import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KRegexSort -import io.ksmt.sort.KStringSort class KRegexLiteralExpr internal constructor( ctx: KContext, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index dbf1d32c0..fdba1cf91 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -3,8 +3,10 @@ package io.ksmt.expr import io.ksmt.KContext import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual +import io.ksmt.decl.KDecl import io.ksmt.decl.KStringLiteralDecl import io.ksmt.expr.transformer.KTransformerBase +import io.ksmt.sort.KBvSort import io.ksmt.sort.KStringSort class KStringLiteralExpr internal constructor( @@ -24,3 +26,24 @@ class KStringLiteralExpr internal constructor( override fun internHashCode(): Int = hash(value) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { value } } + +class KStringConcatExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr +) : KApp(ctx) { + override val args: List> + get() = listOf(arg0, arg1) + + override val decl: KDecl + get() = ctx.mkStringConcatDecl() + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override val sort: KStringSort = ctx.mkStringSort() + + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) +} \ No newline at end of file From 2bdb9451779d81ce9fd79f4744450a8608380de5 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 3 Dec 2024 22:40:58 +0300 Subject: [PATCH 07/84] Implement strings length expr and decl --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 20 ++++++++++++++ .../src/main/kotlin/io/ksmt/decl/String.kt | 9 +++++++ .../src/main/kotlin/io/ksmt/expr/String.kt | 27 +++++++++++++++++-- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index f3fba85b2..d7151e801 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -131,6 +131,7 @@ import io.ksmt.decl.KIntRemDecl import io.ksmt.decl.KIntToRealDecl import io.ksmt.decl.KStringLiteralDecl import io.ksmt.decl.KStringConcatDecl +import io.ksmt.decl.KStringLenDecl import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl @@ -277,6 +278,7 @@ import io.ksmt.expr.KIntNumExpr import io.ksmt.expr.KIsIntRealExpr import io.ksmt.expr.KStringLiteralExpr import io.ksmt.expr.KStringConcatExpr +import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr @@ -1923,6 +1925,22 @@ open class KContext( KStringConcatExpr(this, arg0, arg1) } + private val stringLenExprCache = mkAstInterner() + + /** + * Create string's length expression. + * */ + open fun mkStringLen(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkStringLenNoSimplify, ::mkStringLenNoSimplify) + + /** + * Create string's length expression. + * */ + open fun mkStringLenNoSimplify(arg: KExpr): KStringLenExpr = stringLenExprCache.createIfContextActive { + ensureContextMatch(arg) + KStringLenExpr(this, arg) + } + private val regexLiteralCache = mkAstInterner() /** @@ -4536,6 +4554,8 @@ open class KContext( fun mkStringConcatDecl(): KStringConcatDecl = KStringConcatDecl(this) + fun mkStringLenDecl(): KStringLenDecl = KStringLenDecl(this) + // regex fun mkRegexLiteralDecl(value: String): KRegexLiteralDecl = KRegexLiteralDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index d958c8e01..c01a50d5e 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -3,6 +3,8 @@ package io.ksmt.decl import io.ksmt.KContext import io.ksmt.expr.KApp import io.ksmt.expr.KExpr +import io.ksmt.sort.KBoolSort +import io.ksmt.sort.KIntSort import io.ksmt.sort.KStringSort class KStringLiteralDecl internal constructor( @@ -29,3 +31,10 @@ class KStringConcatDecl internal constructor( arg1: KExpr ): KApp = mkStringConcatExprNoSimplify(arg0, arg1) } + +class KStringLenDecl internal constructor( + ctx: KContext +) : KFuncDecl1(ctx, "len", ctx.mkIntSort(), ctx.mkStringSort()) { + override fun KContext.apply(arg: KExpr): KApp = mkStringLenNoSimplify(arg) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} \ No newline at end of file diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index fdba1cf91..4ab5521ee 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -4,9 +4,12 @@ import io.ksmt.KContext import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual import io.ksmt.decl.KDecl +import io.ksmt.decl.KNotDecl +import io.ksmt.decl.KStringLenDecl import io.ksmt.decl.KStringLiteralDecl import io.ksmt.expr.transformer.KTransformerBase -import io.ksmt.sort.KBvSort +import io.ksmt.sort.KBoolSort +import io.ksmt.sort.KIntSort import io.ksmt.sort.KStringSort class KStringLiteralExpr internal constructor( @@ -46,4 +49,24 @@ class KStringConcatExpr internal constructor( override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) -} \ No newline at end of file +} + +class KStringLenExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KIntSort = ctx.intSort + + override val decl: KStringLenDecl + get() = ctx.mkStringLenDecl() + + override val args: List> + get() = listOf(arg) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} From 779b5c2531bb66d82cc401609da4f954e80df867 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 3 Dec 2024 22:56:32 +0300 Subject: [PATCH 08/84] Implement expr and decl for translation string to a regex --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 22 +++++++++++++++- .../src/main/kotlin/io/ksmt/decl/String.kt | 10 ++++++- .../src/main/kotlin/io/ksmt/expr/String.kt | 26 ++++++++++++++++--- 3 files changed, 52 insertions(+), 6 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index d7151e801..25fcd49bc 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -132,6 +132,7 @@ import io.ksmt.decl.KIntToRealDecl import io.ksmt.decl.KStringLiteralDecl import io.ksmt.decl.KStringConcatDecl import io.ksmt.decl.KStringLenDecl +import io.ksmt.decl.KStringToRegexDecl import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl @@ -279,6 +280,7 @@ import io.ksmt.expr.KIsIntRealExpr import io.ksmt.expr.KStringLiteralExpr import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLenExpr +import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr @@ -1931,7 +1933,7 @@ open class KContext( * Create string's length expression. * */ open fun mkStringLen(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkStringLenNoSimplify, ::mkStringLenNoSimplify) + mkSimplified(arg, KContext::mkStringLenNoSimplify, ::mkStringLenNoSimplify) // Add simplified version /** * Create string's length expression. @@ -1941,6 +1943,22 @@ open class KContext( KStringLenExpr(this, arg) } + private val stringToRegexExprCache = mkAstInterner() + + /** + * Create a regular expression based on a string expression. + * */ + open fun mkStringToRegex(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkStringToRegexNoSimplify, ::mkStringToRegexNoSimplify) // Add simplified version + + /** + * Create a regular expression based on a string expression. + * */ + open fun mkStringToRegexNoSimplify(arg: KExpr): KStringToRegexExpr = stringToRegexExprCache.createIfContextActive { + ensureContextMatch(arg) + KStringToRegexExpr(this, arg) + } + private val regexLiteralCache = mkAstInterner() /** @@ -4556,6 +4574,8 @@ open class KContext( fun mkStringLenDecl(): KStringLenDecl = KStringLenDecl(this) + fun mkStringToRegexDecl(): KStringToRegexDecl = KStringToRegexDecl(this) + // regex fun mkRegexLiteralDecl(value: String): KRegexLiteralDecl = KRegexLiteralDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index c01a50d5e..e7ec53258 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -5,6 +5,7 @@ import io.ksmt.expr.KApp import io.ksmt.expr.KExpr import io.ksmt.sort.KBoolSort import io.ksmt.sort.KIntSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KStringSort class KStringLiteralDecl internal constructor( @@ -37,4 +38,11 @@ class KStringLenDecl internal constructor( ) : KFuncDecl1(ctx, "len", ctx.mkIntSort(), ctx.mkStringSort()) { override fun KContext.apply(arg: KExpr): KApp = mkStringLenNoSimplify(arg) override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) -} \ No newline at end of file +} + +class KStringToRegexDecl internal constructor( + ctx: KContext +) : KFuncDecl1(ctx, "to_regex", ctx.mkRegexSort(), ctx.mkStringSort()) { + override fun KContext.apply(arg: KExpr): KApp = mkStringToRegexNoSimplify(arg) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index 4ab5521ee..3f0afd794 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -3,13 +3,11 @@ package io.ksmt.expr import io.ksmt.KContext import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual -import io.ksmt.decl.KDecl -import io.ksmt.decl.KNotDecl -import io.ksmt.decl.KStringLenDecl -import io.ksmt.decl.KStringLiteralDecl +import io.ksmt.decl.* import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KBoolSort import io.ksmt.sort.KIntSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KStringSort class KStringLiteralExpr internal constructor( @@ -70,3 +68,23 @@ class KStringLenExpr internal constructor( override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } } + +class KStringToRegexExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KRegexSort = ctx.regexSort + + override val decl: KStringToRegexDecl + get() = ctx.mkStringToRegexDecl() + + override val args: List> + get() = listOf(arg) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} From 4b8d5ad206862da4ae443b0a3109c9e1109fa3a5 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 3 Dec 2024 23:15:15 +0300 Subject: [PATCH 09/84] Implement regular expressions concatenation --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 21 ++++++++++++++++++ .../src/main/kotlin/io/ksmt/decl/Regex.kt | 17 ++++++++++++++ .../src/main/kotlin/io/ksmt/expr/Regex.kt | 22 +++++++++++++++++++ .../src/main/kotlin/io/ksmt/expr/String.kt | 1 - 4 files changed, 60 insertions(+), 1 deletion(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 25fcd49bc..39e76a88d 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -134,6 +134,7 @@ import io.ksmt.decl.KStringConcatDecl import io.ksmt.decl.KStringLenDecl import io.ksmt.decl.KStringToRegexDecl import io.ksmt.decl.KRegexLiteralDecl +import io.ksmt.decl.KRegexConcatDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl import io.ksmt.decl.KOrDecl @@ -282,6 +283,7 @@ import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KRegexLiteralExpr +import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr import io.ksmt.expr.KLtArithExpr @@ -1968,6 +1970,23 @@ open class KContext( KRegexLiteralExpr(this, value) } + private val regexConcatExprCache = mkAstInterner() + + /** + * Create Regex concatenation (`concat`) expression. + * */ + open fun mkRegexConcat(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkRegexConcatNoSimplify, ::mkRegexConcatNoSimplify) // Add simplified version + + /** + * Create Regex concatenation (`concat`) expression. + * */ + open fun mkRegexConcatNoSimplify(arg0: KExpr, arg1: KExpr): KRegexConcatExpr = + regexConcatExprCache.createIfContextActive { + ensureContextMatch(arg0, arg1) + KRegexConcatExpr(this, arg0, arg1) + } + // bitvectors private val bv1Cache = mkAstInterner() private val bv8Cache = mkAstInterner() @@ -4579,6 +4598,8 @@ open class KContext( // regex fun mkRegexLiteralDecl(value: String): KRegexLiteralDecl = KRegexLiteralDecl(this, value) + fun mkRegexConcatDecl(): KRegexConcatDecl = KRegexConcatDecl(this) + // Bit vectors fun mkBvDecl(value: Boolean): KDecl = KBitVec1ValueDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index 7980db74c..3224152a4 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -12,3 +12,20 @@ class KRegexLiteralDecl internal constructor( override fun apply(args: List>): KApp = ctx.mkRegexLiteral(value) override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } + +class KRegexConcatDecl internal constructor( + ctx: KContext, +) : KFuncDecl2( + ctx, + name = "concat", + resultSort = ctx.mkRegexSort(), + ctx.mkRegexSort(), + ctx.mkRegexSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkRegexConcatNoSimplify(arg0, arg1) +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index 9ab7a083b..7120684b9 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -3,6 +3,7 @@ package io.ksmt.expr import io.ksmt.KContext import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual +import io.ksmt.decl.KDecl import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KRegexSort @@ -24,3 +25,24 @@ class KRegexLiteralExpr internal constructor( override fun internHashCode(): Int = hash(value) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { value } } + +class KRegexConcatExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr +) : KApp(ctx) { + override val args: List> + get() = listOf(arg0, arg1) + + override val decl: KDecl + get() = ctx.mkRegexConcatDecl() + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override val sort: KRegexSort = ctx.mkRegexSort() + + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) +} \ No newline at end of file diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index 3f0afd794..dacf260a3 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -5,7 +5,6 @@ import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual import io.ksmt.decl.* import io.ksmt.expr.transformer.KTransformerBase -import io.ksmt.sort.KBoolSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRegexSort import io.ksmt.sort.KStringSort From 0099dc3c2ff8382ad390cf2c2fb8a3c0b0fd9447 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 3 Dec 2024 23:21:56 +0300 Subject: [PATCH 10/84] Implement regular expressions union --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 21 +++++++++++++++++ .../src/main/kotlin/io/ksmt/decl/Regex.kt | 17 ++++++++++++++ .../src/main/kotlin/io/ksmt/expr/Regex.kt | 23 ++++++++++++++++++- 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 39e76a88d..0be1b77e1 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -135,6 +135,7 @@ import io.ksmt.decl.KStringLenDecl import io.ksmt.decl.KStringToRegexDecl import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KRegexConcatDecl +import io.ksmt.decl.KRegexUnionDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl import io.ksmt.decl.KOrDecl @@ -284,6 +285,7 @@ import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KRegexConcatExpr +import io.ksmt.expr.KRegexUnionExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr import io.ksmt.expr.KLtArithExpr @@ -1987,6 +1989,23 @@ open class KContext( KRegexConcatExpr(this, arg0, arg1) } + private val regexUnionExprCache = mkAstInterner() + + /** + * Create Regex concatenation (`concat`) expression. + * */ + open fun mkRegexUnion(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkRegexUnionNoSimplify, ::mkRegexUnionNoSimplify) // Add simplified version + + /** + * Create Regex concatenation (`concat`) expression. + * */ + open fun mkRegexUnionNoSimplify(arg0: KExpr, arg1: KExpr): KRegexUnionExpr = + regexUnionExprCache.createIfContextActive { + ensureContextMatch(arg0, arg1) + KRegexUnionExpr(this, arg0, arg1) + } + // bitvectors private val bv1Cache = mkAstInterner() private val bv8Cache = mkAstInterner() @@ -4600,6 +4619,8 @@ open class KContext( fun mkRegexConcatDecl(): KRegexConcatDecl = KRegexConcatDecl(this) + fun mkRegexUnionDecl(): KRegexUnionDecl = KRegexUnionDecl(this) + // Bit vectors fun mkBvDecl(value: Boolean): KDecl = KBitVec1ValueDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index 3224152a4..2015e3f8c 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -29,3 +29,20 @@ class KRegexConcatDecl internal constructor( arg1: KExpr ): KApp = mkRegexConcatNoSimplify(arg0, arg1) } + +class KRegexUnionDecl internal constructor( + ctx: KContext, +) : KFuncDecl2( + ctx, + name = "union", + resultSort = ctx.mkRegexSort(), + ctx.mkRegexSort(), + ctx.mkRegexSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkRegexUnionNoSimplify(arg0, arg1) +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index 7120684b9..51d80c1ec 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -45,4 +45,25 @@ class KRegexConcatExpr internal constructor( override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) -} \ No newline at end of file +} + +class KRegexUnionExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr +) : KApp(ctx) { + override val args: List> + get() = listOf(arg0, arg1) + + override val decl: KDecl + get() = ctx.mkRegexUnionDecl() + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override val sort: KRegexSort = ctx.mkRegexSort() + + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) +} From ce1a5504a1d341df733583e325f48d1d18db1fd0 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 3 Dec 2024 23:28:40 +0300 Subject: [PATCH 11/84] Implement regular expressions intersection --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 25 +++++++++++++++++-- .../src/main/kotlin/io/ksmt/decl/Regex.kt | 17 +++++++++++++ .../src/main/kotlin/io/ksmt/expr/Regex.kt | 21 ++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 0be1b77e1..23c567e5f 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -136,6 +136,7 @@ import io.ksmt.decl.KStringToRegexDecl import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KRegexConcatDecl import io.ksmt.decl.KRegexUnionDecl +import io.ksmt.decl.KRegexIntersectionDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl import io.ksmt.decl.KOrDecl @@ -286,6 +287,7 @@ import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr +import io.ksmt.expr.KRegexIntersectionExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr import io.ksmt.expr.KLtArithExpr @@ -1992,13 +1994,13 @@ open class KContext( private val regexUnionExprCache = mkAstInterner() /** - * Create Regex concatenation (`concat`) expression. + * Create Regex union (`union`) expression. * */ open fun mkRegexUnion(arg0: KExpr, arg1: KExpr): KExpr = mkSimplified(arg0, arg1, KContext::mkRegexUnionNoSimplify, ::mkRegexUnionNoSimplify) // Add simplified version /** - * Create Regex concatenation (`concat`) expression. + * Create Regex union (`union`) expression. * */ open fun mkRegexUnionNoSimplify(arg0: KExpr, arg1: KExpr): KRegexUnionExpr = regexUnionExprCache.createIfContextActive { @@ -2006,6 +2008,23 @@ open class KContext( KRegexUnionExpr(this, arg0, arg1) } + private val regexIntersectionExprCache = mkAstInterner() + + /** + * Create Regex intersection (`intersect`) expression. + * */ + open fun mkRegexIntersection(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkRegexIntersectionNoSimplify, ::mkRegexIntersectionNoSimplify) // Add simplified version + + /** + * Create Regex intersection (`intersect`) expression. + * */ + open fun mkRegexIntersectionNoSimplify(arg0: KExpr, arg1: KExpr): KRegexIntersectionExpr = + regexIntersectionExprCache.createIfContextActive { + ensureContextMatch(arg0, arg1) + KRegexIntersectionExpr(this, arg0, arg1) + } + // bitvectors private val bv1Cache = mkAstInterner() private val bv8Cache = mkAstInterner() @@ -4621,6 +4640,8 @@ open class KContext( fun mkRegexUnionDecl(): KRegexUnionDecl = KRegexUnionDecl(this) + fun mkRegexIntersectionDecl(): KRegexIntersectionDecl = KRegexIntersectionDecl(this) + // Bit vectors fun mkBvDecl(value: Boolean): KDecl = KBitVec1ValueDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index 2015e3f8c..789a2806a 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -46,3 +46,20 @@ class KRegexUnionDecl internal constructor( arg1: KExpr ): KApp = mkRegexUnionNoSimplify(arg0, arg1) } + +class KRegexIntersectionDecl internal constructor( + ctx: KContext, +) : KFuncDecl2( + ctx, + name = "intersect", + resultSort = ctx.mkRegexSort(), + ctx.mkRegexSort(), + ctx.mkRegexSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkRegexIntersectionNoSimplify(arg0, arg1) +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index 51d80c1ec..2193daa14 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -67,3 +67,24 @@ class KRegexUnionExpr internal constructor( override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } + +class KRegexIntersectionExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr +) : KApp(ctx) { + override val args: List> + get() = listOf(arg0, arg1) + + override val decl: KDecl + get() = ctx.mkRegexIntersectionDecl() + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override val sort: KRegexSort = ctx.mkRegexSort() + + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) +} From 743b75820e955300149ab0f78f4585e3a0235b94 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 4 Dec 2024 00:05:15 +0300 Subject: [PATCH 12/84] Implement regular expressions difference and Kleene closure --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 41 +++++++++++++++++ .../src/main/kotlin/io/ksmt/decl/Regex.kt | 27 +++++++++++ .../src/main/kotlin/io/ksmt/expr/Regex.kt | 45 +++++++++++++++++++ 3 files changed, 113 insertions(+) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 23c567e5f..a833f382a 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -137,6 +137,8 @@ import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KRegexConcatDecl import io.ksmt.decl.KRegexUnionDecl import io.ksmt.decl.KRegexIntersectionDecl +import io.ksmt.decl.KRegexKleeneClosureDecl +import io.ksmt.decl.KRegexDifferenceDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl import io.ksmt.decl.KOrDecl @@ -288,6 +290,8 @@ import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr import io.ksmt.expr.KRegexIntersectionExpr +import io.ksmt.expr.KRegexKleeneClosureExpr +import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr import io.ksmt.expr.KLtArithExpr @@ -2025,6 +2029,39 @@ open class KContext( KRegexIntersectionExpr(this, arg0, arg1) } + private val regexKleeneClosureExprCache = mkAstInterner() + + /** + * Create regular expression's Kleene closure. + * */ + open fun mkRegexKleeneClosure(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkRegexKleeneClosureNoSimplify, ::mkRegexKleeneClosureNoSimplify) // Add simplified version + + /** + * Create regular expression's Kleene closure. + * */ + open fun mkRegexKleeneClosureNoSimplify(arg: KExpr): KRegexKleeneClosureExpr = regexKleeneClosureExprCache.createIfContextActive { + ensureContextMatch(arg) + KRegexKleeneClosureExpr(this, arg) + } + + private val regexDifferenceExprCache = mkAstInterner() + + /** + * Create Regex difference (`intersect`) expression. + * */ + open fun mkRegexDifference(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkRegexDifferenceNoSimplify, ::mkRegexDifferenceNoSimplify) // Add simplified version + + /** + * Create Regex difference (`intersect`) expression. + * */ + open fun mkRegexDifferenceNoSimplify(arg0: KExpr, arg1: KExpr): KRegexDifferenceExpr = + regexDifferenceExprCache.createIfContextActive { + ensureContextMatch(arg0, arg1) + KRegexDifferenceExpr(this, arg0, arg1) + } + // bitvectors private val bv1Cache = mkAstInterner() private val bv8Cache = mkAstInterner() @@ -4642,6 +4679,10 @@ open class KContext( fun mkRegexIntersectionDecl(): KRegexIntersectionDecl = KRegexIntersectionDecl(this) + fun mkRegexKleeneClosureDecl(): KRegexKleeneClosureDecl = KRegexKleeneClosureDecl(this) + + fun mkRegexDifferenceDecl(): KRegexDifferenceDecl = KRegexDifferenceDecl(this) + // Bit vectors fun mkBvDecl(value: Boolean): KDecl = KBitVec1ValueDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index 789a2806a..12e29748e 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -3,7 +3,9 @@ package io.ksmt.decl import io.ksmt.KContext import io.ksmt.expr.KApp import io.ksmt.expr.KExpr +import io.ksmt.sort.KIntSort import io.ksmt.sort.KRegexSort +import io.ksmt.sort.KStringSort class KRegexLiteralDecl internal constructor( ctx: KContext, @@ -63,3 +65,28 @@ class KRegexIntersectionDecl internal constructor( arg1: KExpr ): KApp = mkRegexIntersectionNoSimplify(arg0, arg1) } + +class KRegexKleeneClosureDecl internal constructor( + ctx: KContext +) : KFuncDecl1(ctx, "closure", ctx.mkRegexSort(), ctx.mkRegexSort()) { + override fun KContext.apply(arg: KExpr): KApp = mkRegexKleeneClosureNoSimplify(arg) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} + +class KRegexDifferenceDecl internal constructor( + ctx: KContext, +) : KFuncDecl2( + ctx, + name = "diff", + resultSort = ctx.mkRegexSort(), + ctx.mkRegexSort(), + ctx.mkRegexSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkRegexDifferenceNoSimplify(arg0, arg1) +} + diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index 2193daa14..4164d39e4 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -4,9 +4,13 @@ import io.ksmt.KContext import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual import io.ksmt.decl.KDecl +import io.ksmt.decl.KRegexKleeneClosureDecl import io.ksmt.decl.KRegexLiteralDecl +import io.ksmt.decl.KStringLenDecl import io.ksmt.expr.transformer.KTransformerBase +import io.ksmt.sort.KIntSort import io.ksmt.sort.KRegexSort +import io.ksmt.sort.KStringSort class KRegexLiteralExpr internal constructor( ctx: KContext, @@ -88,3 +92,44 @@ class KRegexIntersectionExpr internal constructor( override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } + +class KRegexKleeneClosureExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KRegexSort = ctx.regexSort + + override val decl: KRegexKleeneClosureDecl + get() = ctx.mkRegexKleeneClosureDecl() + + override val args: List> + get() = listOf(arg) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} + +class KRegexDifferenceExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr +) : KApp(ctx) { + override val args: List> + get() = listOf(arg0, arg1) + + override val decl: KDecl + get() = ctx.mkRegexDifferenceDecl() + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override val sort: KRegexSort = ctx.mkRegexSort() + + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) +} \ No newline at end of file From 3a1c7c12605747e8b8d587ed86f8a7920e429e1f Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 4 Dec 2024 00:16:26 +0300 Subject: [PATCH 13/84] Implement regular expressions Kleene cross --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 20 ++++++++++++++++ .../src/main/kotlin/io/ksmt/decl/Regex.kt | 7 ++++++ .../src/main/kotlin/io/ksmt/expr/Regex.kt | 24 ++++++++++++++++--- 3 files changed, 48 insertions(+), 3 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index a833f382a..42b04abfe 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -138,6 +138,7 @@ import io.ksmt.decl.KRegexConcatDecl import io.ksmt.decl.KRegexUnionDecl import io.ksmt.decl.KRegexIntersectionDecl import io.ksmt.decl.KRegexKleeneClosureDecl +import io.ksmt.decl.KRegexKleeneCrossDecl import io.ksmt.decl.KRegexDifferenceDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl @@ -291,6 +292,7 @@ import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr import io.ksmt.expr.KRegexIntersectionExpr import io.ksmt.expr.KRegexKleeneClosureExpr +import io.ksmt.expr.KRegexKleeneCrossExpr import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr @@ -2045,6 +2047,22 @@ open class KContext( KRegexKleeneClosureExpr(this, arg) } + private val regexKleeneCrossExprCache = mkAstInterner() + + /** + * Create regular expression's Kleene cross. + * */ + open fun mkRegexKleeneCross(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkRegexKleeneCrossNoSimplify, ::mkRegexKleeneCrossNoSimplify) // Add simplified version + + /** + * Create regular expression's Kleene cross. + * */ + open fun mkRegexKleeneCrossNoSimplify(arg: KExpr): KRegexKleeneCrossExpr = regexKleeneCrossExprCache.createIfContextActive { + ensureContextMatch(arg) + KRegexKleeneCrossExpr(this, arg) + } + private val regexDifferenceExprCache = mkAstInterner() /** @@ -4681,6 +4699,8 @@ open class KContext( fun mkRegexKleeneClosureDecl(): KRegexKleeneClosureDecl = KRegexKleeneClosureDecl(this) + fun mkRegexKleeneCrossDecl(): KRegexKleeneCrossDecl = KRegexKleeneCrossDecl(this) + fun mkRegexDifferenceDecl(): KRegexDifferenceDecl = KRegexDifferenceDecl(this) // Bit vectors diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index 12e29748e..539af0797 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -73,6 +73,13 @@ class KRegexKleeneClosureDecl internal constructor( override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } +class KRegexKleeneCrossDecl internal constructor( + ctx: KContext +) : KFuncDecl1(ctx, "kleene_cross", ctx.mkRegexSort(), ctx.mkRegexSort()) { + override fun KContext.apply(arg: KExpr): KApp = mkRegexKleeneCrossNoSimplify(arg) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} + class KRegexDifferenceDecl internal constructor( ctx: KContext, ) : KFuncDecl2( diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index 4164d39e4..cb3b95f9a 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -5,12 +5,10 @@ import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual import io.ksmt.decl.KDecl import io.ksmt.decl.KRegexKleeneClosureDecl +import io.ksmt.decl.KRegexKleeneCrossDecl import io.ksmt.decl.KRegexLiteralDecl -import io.ksmt.decl.KStringLenDecl import io.ksmt.expr.transformer.KTransformerBase -import io.ksmt.sort.KIntSort import io.ksmt.sort.KRegexSort -import io.ksmt.sort.KStringSort class KRegexLiteralExpr internal constructor( ctx: KContext, @@ -113,6 +111,26 @@ class KRegexKleeneClosureExpr internal constructor( override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } } +class KRegexKleeneCrossExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KRegexSort = ctx.regexSort + + override val decl: KRegexKleeneCrossDecl + get() = ctx.mkRegexKleeneCrossDecl() + + override val args: List> + get() = listOf(arg) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} + class KRegexDifferenceExpr internal constructor( ctx: KContext, val arg0: KExpr, From 5a139cd95719170373f9cb8bff809fbac2b49fe6 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 4 Dec 2024 01:31:12 +0300 Subject: [PATCH 14/84] Implement prefixOf and suffixOf strings' operations --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 43 +++++++++++++++++++ .../src/main/kotlin/io/ksmt/decl/String.kt | 34 +++++++++++++++ .../src/main/kotlin/io/ksmt/expr/String.kt | 43 +++++++++++++++++++ 3 files changed, 120 insertions(+) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 42b04abfe..fe364615e 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -133,6 +133,8 @@ import io.ksmt.decl.KStringLiteralDecl import io.ksmt.decl.KStringConcatDecl import io.ksmt.decl.KStringLenDecl import io.ksmt.decl.KStringToRegexDecl +import io.ksmt.decl.KSuffixOfDecl +import io.ksmt.decl.KPrefixOfDecl import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KRegexConcatDecl import io.ksmt.decl.KRegexUnionDecl @@ -287,6 +289,8 @@ import io.ksmt.expr.KStringLiteralExpr import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KStringToRegexExpr +import io.ksmt.expr.KSuffixOfExpr +import io.ksmt.expr.KPrefixOfExpr import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr @@ -1971,6 +1975,41 @@ open class KContext( KStringToRegexExpr(this, arg) } + private val suffixOfExprCache = mkAstInterner() + + /** + * Check if first string is a suffix of second. + * */ + open fun mkSuffixOf(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkSuffixOfNoSimplify, ::mkSuffixOfNoSimplify) // Add simplified version + + /** + * Check if first string is a suffix of second. + * */ + open fun mkSuffixOfNoSimplify(arg0: KExpr, arg1: KExpr): KSuffixOfExpr = + suffixOfExprCache.createIfContextActive { + ensureContextMatch(arg0, arg1) + KSuffixOfExpr(this, arg0, arg1) + } + + private val prefixOfExprCache = mkAstInterner() + + /** + * Check if first string is a prefix of second. + * */ + open fun mkPrefixOf(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkPrefixOfNoSimplify, ::mkPrefixOfNoSimplify) // Add simplified version + + /** + * Check if first string is a prefix of second. + * */ + open fun mkPrefixOfNoSimplify(arg0: KExpr, arg1: KExpr): KPrefixOfExpr = + prefixOfExprCache.createIfContextActive { + ensureContextMatch(arg0, arg1) + KPrefixOfExpr(this, arg0, arg1) + } + + private val regexLiteralCache = mkAstInterner() /** @@ -4688,6 +4727,10 @@ open class KContext( fun mkStringToRegexDecl(): KStringToRegexDecl = KStringToRegexDecl(this) + fun mkSuffixOfDecl(): KSuffixOfDecl = KSuffixOfDecl(this) + + fun mkPrefixOfDecl(): KPrefixOfDecl = KPrefixOfDecl(this) + // regex fun mkRegexLiteralDecl(value: String): KRegexLiteralDecl = KRegexLiteralDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index e7ec53258..ebbbbfe6c 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -46,3 +46,37 @@ class KStringToRegexDecl internal constructor( override fun KContext.apply(arg: KExpr): KApp = mkStringToRegexNoSimplify(arg) override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } + +class KSuffixOfDecl internal constructor( + ctx: KContext, +) : KFuncDecl2( + ctx, + name = "suffix_of", + resultSort = ctx.mkBoolSort(), + ctx.mkStringSort(), + ctx.mkStringSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkSuffixOfNoSimplify(arg0, arg1) +} + +class KPrefixOfDecl internal constructor( + ctx: KContext, +) : KFuncDecl2( + ctx, + name = "prefix_of", + resultSort = ctx.mkBoolSort(), + ctx.mkStringSort(), + ctx.mkStringSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkPrefixOfNoSimplify(arg0, arg1) +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index dacf260a3..11a9e0a12 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -5,6 +5,7 @@ import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual import io.ksmt.decl.* import io.ksmt.expr.transformer.KTransformerBase +import io.ksmt.sort.KBoolSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRegexSort import io.ksmt.sort.KStringSort @@ -87,3 +88,45 @@ class KStringToRegexExpr internal constructor( override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } } + +class KSuffixOfExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr +) : KApp(ctx) { + override val sort: KBoolSort = ctx.mkBoolSort() + + override val args: List> + get() = listOf(arg0, arg1) + + override val decl: KDecl + get() = ctx.mkSuffixOfDecl() + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) +} + +class KPrefixOfExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr +) : KApp(ctx) { + override val sort: KBoolSort = ctx.mkBoolSort() + + override val args: List> + get() = listOf(arg0, arg1) + + override val decl: KDecl + get() = ctx.mkPrefixOfDecl() + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) +} From fd259a54f7744323413fedb356e40c6ac63460a9 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 4 Dec 2024 03:05:45 +0300 Subject: [PATCH 15/84] Implement operation to check whether a string belongs to a regex --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 52 +++++++++++++------ .../src/main/kotlin/io/ksmt/decl/String.kt | 18 +++++++ .../src/main/kotlin/io/ksmt/expr/Regex.kt | 8 ++- .../src/main/kotlin/io/ksmt/expr/String.kt | 27 ++++++++-- 4 files changed, 80 insertions(+), 25 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index fe364615e..ff77557bf 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -133,6 +133,7 @@ import io.ksmt.decl.KStringLiteralDecl import io.ksmt.decl.KStringConcatDecl import io.ksmt.decl.KStringLenDecl import io.ksmt.decl.KStringToRegexDecl +import io.ksmt.decl.KStringInRegexDecl import io.ksmt.decl.KSuffixOfDecl import io.ksmt.decl.KPrefixOfDecl import io.ksmt.decl.KRegexLiteralDecl @@ -289,6 +290,7 @@ import io.ksmt.expr.KStringLiteralExpr import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KStringToRegexExpr +import io.ksmt.expr.KStringInRegexExpr import io.ksmt.expr.KSuffixOfExpr import io.ksmt.expr.KPrefixOfExpr import io.ksmt.expr.KRegexLiteralExpr @@ -1959,22 +1961,6 @@ open class KContext( KStringLenExpr(this, arg) } - private val stringToRegexExprCache = mkAstInterner() - - /** - * Create a regular expression based on a string expression. - * */ - open fun mkStringToRegex(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkStringToRegexNoSimplify, ::mkStringToRegexNoSimplify) // Add simplified version - - /** - * Create a regular expression based on a string expression. - * */ - open fun mkStringToRegexNoSimplify(arg: KExpr): KStringToRegexExpr = stringToRegexExprCache.createIfContextActive { - ensureContextMatch(arg) - KStringToRegexExpr(this, arg) - } - private val suffixOfExprCache = mkAstInterner() /** @@ -2009,6 +1995,38 @@ open class KContext( KPrefixOfExpr(this, arg0, arg1) } + private val stringToRegexExprCache = mkAstInterner() + + /** + * Create a regular expression based on a string expression. + * */ + open fun mkStringToRegex(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkStringToRegexNoSimplify, ::mkStringToRegexNoSimplify) // Add simplified version + + /** + * Create a regular expression based on a string expression. + * */ + open fun mkStringToRegexNoSimplify(arg: KExpr): KStringToRegexExpr = stringToRegexExprCache.createIfContextActive { + ensureContextMatch(arg) + KStringToRegexExpr(this, arg) + } + + private val stringInRegexExprCache = mkAstInterner() + + /** + * Check if a string belongs to the language defined by the regular expression. + * */ + open fun mkStringInRegex(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkStringInRegexNoSimplify, ::mkStringInRegexNoSimplify) // Add simplified version + + /** + * Check if a string belongs to the language defined by the regular expression. + * */ + open fun mkStringInRegexNoSimplify(arg0: KExpr, arg1: KExpr): KStringInRegexExpr = + stringInRegexExprCache.createIfContextActive { + ensureContextMatch(arg0, arg1) + KStringInRegexExpr(this, arg0, arg1) + } private val regexLiteralCache = mkAstInterner() @@ -4727,6 +4745,8 @@ open class KContext( fun mkStringToRegexDecl(): KStringToRegexDecl = KStringToRegexDecl(this) + fun mkStringInRegexDecl(): KStringInRegexDecl = KStringInRegexDecl(this) + fun mkSuffixOfDecl(): KSuffixOfDecl = KSuffixOfDecl(this) fun mkPrefixOfDecl(): KPrefixOfDecl = KPrefixOfDecl(this) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index ebbbbfe6c..03cadc769 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -3,6 +3,7 @@ package io.ksmt.decl import io.ksmt.KContext import io.ksmt.expr.KApp import io.ksmt.expr.KExpr +import io.ksmt.sort.KSort import io.ksmt.sort.KBoolSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRegexSort @@ -47,6 +48,23 @@ class KStringToRegexDecl internal constructor( override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } +class KStringInRegexDecl internal constructor( + ctx: KContext, +) : KFuncDecl2( + ctx, + name = "in_regex", + resultSort = ctx.mkBoolSort(), + ctx.mkStringSort(), + ctx.mkRegexSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkStringInRegexNoSimplify(arg0, arg1) +} + class KSuffixOfDecl internal constructor( ctx: KContext, ) : KFuncDecl2( diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index cb3b95f9a..bba138513 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -3,12 +3,10 @@ package io.ksmt.expr import io.ksmt.KContext import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual -import io.ksmt.decl.KDecl -import io.ksmt.decl.KRegexKleeneClosureDecl -import io.ksmt.decl.KRegexKleeneCrossDecl -import io.ksmt.decl.KRegexLiteralDecl +import io.ksmt.decl.* import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KRegexSort +import io.ksmt.sort.KStringSort class KRegexLiteralExpr internal constructor( ctx: KContext, @@ -150,4 +148,4 @@ class KRegexDifferenceExpr internal constructor( override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) -} \ No newline at end of file +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index 11a9e0a12..a9a9901ef 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -5,10 +5,8 @@ import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual import io.ksmt.decl.* import io.ksmt.expr.transformer.KTransformerBase -import io.ksmt.sort.KBoolSort -import io.ksmt.sort.KIntSort -import io.ksmt.sort.KRegexSort -import io.ksmt.sort.KStringSort +import io.ksmt.sort.* +import io.ksmt.utils.cast class KStringLiteralExpr internal constructor( ctx: KContext, @@ -89,6 +87,27 @@ class KStringToRegexExpr internal constructor( override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } } +class KStringInRegexExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr +) : KApp(ctx) { + override val sort: KBoolSort = ctx.mkBoolSort() + + override val args: List> + get() = listOf(arg0.cast(), arg1.cast()) + + override val decl: KDecl + get() = ctx.mkStringInRegexDecl() + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) +} + class KSuffixOfExpr internal constructor( ctx: KContext, val arg0: KExpr, From 2a500d7bec0c0443de9bebb3fd3847c4901063f3 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 4 Dec 2024 03:47:39 +0300 Subject: [PATCH 16/84] Implement operations for comparing strings --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 84 +++++++++++++++ .../src/main/kotlin/io/ksmt/decl/Regex.kt | 2 - .../src/main/kotlin/io/ksmt/decl/String.kt | 25 ++++- .../src/main/kotlin/io/ksmt/expr/Regex.kt | 6 +- .../src/main/kotlin/io/ksmt/expr/String.kt | 102 +++++++++++++++++- 5 files changed, 211 insertions(+), 8 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index ff77557bf..d07ed3e9c 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -136,6 +136,10 @@ import io.ksmt.decl.KStringToRegexDecl import io.ksmt.decl.KStringInRegexDecl import io.ksmt.decl.KSuffixOfDecl import io.ksmt.decl.KPrefixOfDecl +import io.ksmt.decl.KStringLtDecl +import io.ksmt.decl.KStringLeDecl +import io.ksmt.decl.KStringGtDecl +import io.ksmt.decl.KStringGeDecl import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KRegexConcatDecl import io.ksmt.decl.KRegexUnionDecl @@ -293,6 +297,10 @@ import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KStringInRegexExpr import io.ksmt.expr.KSuffixOfExpr import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringLtExpr +import io.ksmt.expr.KStringLeExpr +import io.ksmt.expr.KStringGtExpr +import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr @@ -1995,6 +2003,74 @@ open class KContext( KPrefixOfExpr(this, arg0, arg1) } + private val stringLtCache = mkAstInterner() + + /** + * Create a lexicographic ordering (`<` (less)) expression. + * */ + open fun mkStringLt(lhs: KExpr, rhs: KExpr): KExpr = + mkSimplified(lhs, rhs, KContext::mkStringLtNoSimplify, ::mkStringLtNoSimplify) + + /** + * Create a lexicographic ordering (`<` (less)) expression. + * */ + open fun mkStringLtNoSimplify(lhs: KExpr, rhs: KExpr): KStringLtExpr = + stringLtCache.createIfContextActive { + ensureContextMatch(lhs, rhs) + KStringLtExpr(this, lhs, rhs) + } + + private val stringLeCache = mkAstInterner() + + /** + * Create a lexicographic ordering reflexive closure (`<=` (less or equal)) expression. + * */ + open fun mkStringLe(lhs: KExpr, rhs: KExpr): KExpr = + mkSimplified(lhs, rhs, KContext::mkStringLeNoSimplify, ::mkStringLeNoSimplify) + + /** + * Create a lexicographic ordering reflexive closure (`<=` (less or equal)) expression. + * */ + open fun mkStringLeNoSimplify(lhs: KExpr, rhs: KExpr): KStringLeExpr = + stringLeCache.createIfContextActive { + ensureContextMatch(lhs, rhs) + KStringLeExpr(this, lhs, rhs) + } + + private val stringGtCache = mkAstInterner() + + /** + * Create a lexicographic ordering (`>` (greater)) expression. + * */ + open fun mkStringGt(lhs: KExpr, rhs: KExpr): KExpr = + mkSimplified(lhs, rhs, KContext::mkStringGtNoSimplify, ::mkStringGtNoSimplify) + + /** + * Create a lexicographic ordering (`>` (greater)) expression. + * */ + open fun mkStringGtNoSimplify(lhs: KExpr, rhs: KExpr): KStringGtExpr = + stringGtCache.createIfContextActive { + ensureContextMatch(lhs, rhs) + KStringGtExpr(this, lhs, rhs) + } + + private val stringGeCache = mkAstInterner() + + /** + * Create a lexicographic ordering reflexive closure (`>=` (greater or equal)) expression. + * */ + open fun mkStringGe(lhs: KExpr, rhs: KExpr): KExpr = + mkSimplified(lhs, rhs, KContext::mkStringGeNoSimplify, ::mkStringGeNoSimplify) + + /** + * Create a lexicographic ordering reflexive closure (`>=` (greater or equal)) expression. + * */ + open fun mkStringGeNoSimplify(lhs: KExpr, rhs: KExpr): KStringGeExpr = + stringGeCache.createIfContextActive { + ensureContextMatch(lhs, rhs) + KStringGeExpr(this, lhs, rhs) + } + private val stringToRegexExprCache = mkAstInterner() /** @@ -4751,6 +4827,14 @@ open class KContext( fun mkPrefixOfDecl(): KPrefixOfDecl = KPrefixOfDecl(this) + fun mkStringLtDecl(): KStringLtDecl = KStringLtDecl(this) + + fun mkStringLeDecl(): KStringLeDecl = KStringLeDecl(this) + + fun mkStringGtDecl(): KStringGtDecl = KStringGtDecl(this) + + fun mkStringGeDecl(): KStringGeDecl = KStringGeDecl(this) + // regex fun mkRegexLiteralDecl(value: String): KRegexLiteralDecl = KRegexLiteralDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index 539af0797..6a338fcf6 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -3,9 +3,7 @@ package io.ksmt.decl import io.ksmt.KContext import io.ksmt.expr.KApp import io.ksmt.expr.KExpr -import io.ksmt.sort.KIntSort import io.ksmt.sort.KRegexSort -import io.ksmt.sort.KStringSort class KRegexLiteralDecl internal constructor( ctx: KContext, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index 03cadc769..f40d3ad98 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -3,7 +3,6 @@ package io.ksmt.decl import io.ksmt.KContext import io.ksmt.expr.KApp import io.ksmt.expr.KExpr -import io.ksmt.sort.KSort import io.ksmt.sort.KBoolSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRegexSort @@ -98,3 +97,27 @@ class KPrefixOfDecl internal constructor( arg1: KExpr ): KApp = mkPrefixOfNoSimplify(arg0, arg1) } + +class KStringLtDecl internal constructor(ctx: KContext) : + KFuncDecl2(ctx, "stringLt", ctx.mkBoolSort(), ctx.mkStringSort(), ctx.mkStringSort()) { + override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkStringLtNoSimplify(arg0, arg1) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} + +class KStringLeDecl internal constructor(ctx: KContext) : + KFuncDecl2(ctx, "stringLe", ctx.mkBoolSort(), ctx.mkStringSort(), ctx.mkStringSort()) { + override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkStringLeNoSimplify(arg0, arg1) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} + +class KStringGtDecl internal constructor(ctx: KContext) : + KFuncDecl2(ctx, "stringGt", ctx.mkBoolSort(), ctx.mkStringSort(), ctx.mkStringSort()) { + override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkStringGtNoSimplify(arg0, arg1) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} + +class KStringGeDecl internal constructor(ctx: KContext) : + KFuncDecl2(ctx, "stringGe", ctx.mkBoolSort(), ctx.mkStringSort(), ctx.mkStringSort()) { + override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkStringGeNoSimplify(arg0, arg1) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index bba138513..d53359b87 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -3,10 +3,12 @@ package io.ksmt.expr import io.ksmt.KContext import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual -import io.ksmt.decl.* +import io.ksmt.decl.KDecl +import io.ksmt.decl.KRegexKleeneClosureDecl +import io.ksmt.decl.KRegexLiteralDecl +import io.ksmt.decl.KRegexKleeneCrossDecl import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KRegexSort -import io.ksmt.sort.KStringSort class KRegexLiteralExpr internal constructor( ctx: KContext, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index a9a9901ef..c5cabd40e 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -3,9 +3,21 @@ package io.ksmt.expr import io.ksmt.KContext import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual -import io.ksmt.decl.* +import io.ksmt.decl.KDecl +import io.ksmt.decl.KStringLenDecl +import io.ksmt.decl.KStringLiteralDecl +import io.ksmt.decl.KStringLtDecl +import io.ksmt.decl.KStringLeDecl +import io.ksmt.decl.KStringGtDecl +import io.ksmt.decl.KStringGeDecl +import io.ksmt.decl.KStringToRegexDecl +import io.ksmt.decl.KStringInRegexDecl import io.ksmt.expr.transformer.KTransformerBase -import io.ksmt.sort.* +import io.ksmt.sort.KSort +import io.ksmt.sort.KBoolSort +import io.ksmt.sort.KIntSort +import io.ksmt.sort.KRegexSort +import io.ksmt.sort.KStringSort import io.ksmt.utils.cast class KStringLiteralExpr internal constructor( @@ -97,7 +109,7 @@ class KStringInRegexExpr internal constructor( override val args: List> get() = listOf(arg0.cast(), arg1.cast()) - override val decl: KDecl + override val decl: KStringInRegexDecl get() = ctx.mkStringInRegexDecl() override fun accept(transformer: KTransformerBase): KExpr { @@ -149,3 +161,87 @@ class KPrefixOfExpr internal constructor( override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } + +class KStringLtExpr internal constructor( + ctx: KContext, + val lhs: KExpr, + val rhs: KExpr +) : KApp(ctx) { + override val sort: KBoolSort = ctx.boolSort + + override val decl: KStringLtDecl + get() = ctx.mkStringLtDecl() + + override val args: List> + get() = listOf(lhs, rhs) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(lhs, rhs) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) +} + +class KStringLeExpr internal constructor( + ctx: KContext, + val lhs: KExpr, + val rhs: KExpr +) : KApp(ctx) { + override val sort: KBoolSort = ctx.boolSort + + override val decl: KStringLeDecl + get() = ctx.mkStringLeDecl() + + override val args: List> + get() = listOf(lhs, rhs) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(lhs, rhs) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) +} + +class KStringGtExpr internal constructor( + ctx: KContext, + val lhs: KExpr, + val rhs: KExpr +) : KApp(ctx) { + override val sort: KBoolSort = ctx.boolSort + + override val decl: KStringGtDecl + get() = ctx.mkStringGtDecl() + + override val args: List> + get() = listOf(lhs, rhs) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(lhs, rhs) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) +} + +class KStringGeExpr internal constructor( + ctx: KContext, + val lhs: KExpr, + val rhs: KExpr +) : KApp(ctx) { + override val sort: KBoolSort = ctx.boolSort + + override val decl: KStringGeDecl + get() = ctx.mkStringGeDecl() + + override val args: List> + get() = listOf(lhs, rhs) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(lhs, rhs) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) +} From d771e78dc124139118c6df1cc582c8972529c9fd Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 4 Dec 2024 04:10:51 +0300 Subject: [PATCH 17/84] Implement regular expression complement operation --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 20 ++++++++++++++++++ .../src/main/kotlin/io/ksmt/decl/Regex.kt | 6 ++++++ .../src/main/kotlin/io/ksmt/expr/Regex.kt | 21 +++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index d07ed3e9c..7b0a1623b 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -147,6 +147,7 @@ import io.ksmt.decl.KRegexIntersectionDecl import io.ksmt.decl.KRegexKleeneClosureDecl import io.ksmt.decl.KRegexKleeneCrossDecl import io.ksmt.decl.KRegexDifferenceDecl +import io.ksmt.decl.KRegexComplementDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl import io.ksmt.decl.KOrDecl @@ -308,6 +309,7 @@ import io.ksmt.expr.KRegexIntersectionExpr import io.ksmt.expr.KRegexKleeneClosureExpr import io.ksmt.expr.KRegexKleeneCrossExpr import io.ksmt.expr.KRegexDifferenceExpr +import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr import io.ksmt.expr.KLtArithExpr @@ -2213,6 +2215,22 @@ open class KContext( KRegexDifferenceExpr(this, arg0, arg1) } + private val regexComplementExprCache = mkAstInterner() + + /** + * Create regular expression's complement. + * */ + open fun mkRegexComplement(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkRegexComplementNoSimplify, ::mkRegexComplementNoSimplify) // Add simplified version + + /** + * Create regular expression's complement. + * */ + open fun mkRegexComplementNoSimplify(arg: KExpr): KRegexComplementExpr = regexComplementExprCache.createIfContextActive { + ensureContextMatch(arg) + KRegexComplementExpr(this, arg) + } + // bitvectors private val bv1Cache = mkAstInterner() private val bv8Cache = mkAstInterner() @@ -4850,6 +4868,8 @@ open class KContext( fun mkRegexDifferenceDecl(): KRegexDifferenceDecl = KRegexDifferenceDecl(this) + fun mkRegexComplementDecl(): KRegexComplementDecl = KRegexComplementDecl(this) + // Bit vectors fun mkBvDecl(value: Boolean): KDecl = KBitVec1ValueDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index 6a338fcf6..d6d83a0d9 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -95,3 +95,9 @@ class KRegexDifferenceDecl internal constructor( ): KApp = mkRegexDifferenceNoSimplify(arg0, arg1) } +class KRegexComplementDecl internal constructor( + ctx: KContext +) : KFuncDecl1(ctx, "comp", ctx.mkRegexSort(), ctx.mkRegexSort()) { + override fun KContext.apply(arg: KExpr): KApp = mkRegexComplementNoSimplify(arg) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index d53359b87..b0c52e738 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -7,6 +7,7 @@ import io.ksmt.decl.KDecl import io.ksmt.decl.KRegexKleeneClosureDecl import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KRegexKleeneCrossDecl +import io.ksmt.decl.KRegexComplementDecl import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KRegexSort @@ -151,3 +152,23 @@ class KRegexDifferenceExpr internal constructor( override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } + +class KRegexComplementExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KRegexSort = ctx.regexSort + + override val decl: KRegexComplementDecl + get() = ctx.mkRegexComplementDecl() + + override val args: List> + get() = listOf(arg) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} From c8cb6bf3fa58279a2f93bc409768b7b1130d076b Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 4 Dec 2024 18:32:00 +0300 Subject: [PATCH 18/84] Fix imports --- .../kotlin/io/ksmt/utils/DefaultValueSampler.kt | 16 +++++++++++++++- .../io/ksmt/utils/KExprTheoryRequirement.kt | 17 ++++++++++++++++- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt index 932285b88..df98dffcf 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt @@ -2,7 +2,21 @@ package io.ksmt.utils import io.ksmt.KContext import io.ksmt.expr.KExpr -import io.ksmt.sort.* +import io.ksmt.sort.KSortVisitor +import io.ksmt.sort.KSort +import io.ksmt.sort.KBoolSort +import io.ksmt.sort.KIntSort +import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort +import io.ksmt.sort.KBvSort +import io.ksmt.sort.KFpSort +import io.ksmt.sort.KFpRoundingModeSort +import io.ksmt.sort.KArraySort +import io.ksmt.sort.KArray2Sort +import io.ksmt.sort.KArray3Sort +import io.ksmt.sort.KArrayNSort +import io.ksmt.sort.KUninterpretedSort open class DefaultValueSampler(val ctx: KContext) : KSortVisitor> { override fun visit(sort: KBoolSort): KExpr<*> = diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt index c033d4d02..ae88d2b7d 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt @@ -18,7 +18,22 @@ import io.ksmt.solver.KTheory.LRA import io.ksmt.solver.KTheory.NIA import io.ksmt.solver.KTheory.NRA import io.ksmt.solver.KTheory.UF -import io.ksmt.sort.* +import io.ksmt.sort.KSortVisitor +import io.ksmt.sort.KSort +import io.ksmt.sort.KBoolSort +import io.ksmt.sort.KArithSort +import io.ksmt.sort.KIntSort +import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort +import io.ksmt.sort.KBvSort +import io.ksmt.sort.KFpSort +import io.ksmt.sort.KFpRoundingModeSort +import io.ksmt.sort.KArraySort +import io.ksmt.sort.KArray2Sort +import io.ksmt.sort.KArray3Sort +import io.ksmt.sort.KArrayNSort +import io.ksmt.sort.KUninterpretedSort class KExprTheoryRequirement(ctx: KContext) : KNonRecursiveTransformer(ctx) { val usedTheories = hashSetOf() From 844db5939d4acab4ef3d1c1c5dbd883ab7ab0171 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 4 Dec 2024 18:59:24 +0300 Subject: [PATCH 19/84] Add regular expression constants --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 35 ++++++++++++++ .../src/main/kotlin/io/ksmt/decl/Regex.kt | 21 +++++++++ .../src/main/kotlin/io/ksmt/expr/Regex.kt | 47 ++++++++++++++++++- 3 files changed, 102 insertions(+), 1 deletion(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 7b0a1623b..cf4efa5a6 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -140,6 +140,9 @@ import io.ksmt.decl.KStringLtDecl import io.ksmt.decl.KStringLeDecl import io.ksmt.decl.KStringGtDecl import io.ksmt.decl.KStringGeDecl +import io.ksmt.decl.KEpsilonDecl +import io.ksmt.decl.KAllDecl +import io.ksmt.decl.KAllCharDecl import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KRegexConcatDecl import io.ksmt.decl.KRegexUnionDecl @@ -302,6 +305,9 @@ import io.ksmt.expr.KStringLtExpr import io.ksmt.expr.KStringLeExpr import io.ksmt.expr.KStringGtExpr import io.ksmt.expr.KStringGeExpr +import io.ksmt.expr.KEpsilon +import io.ksmt.expr.KAll +import io.ksmt.expr.KAllChar import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr @@ -2231,6 +2237,28 @@ open class KContext( KRegexComplementExpr(this, arg) } + val epsilonExpr: KEpsilon = KEpsilon(this) + + /** + * Create regex Epsilon constant. + * Epsilon regular expression denoting the empty set of strings. + * */ + fun mkEpsilon(): KEpsilon = epsilonExpr + + val allExpr: KAll = KAll(this) + + /** + * Create regex constant denoting the set of all strings. + * */ + fun mkAll(): KAll = allExpr + + val allCharExpr: KAllChar = KAllChar(this) + + /** + * Create regex constant denoting the set of all strings of length 1. + * */ + fun mkAllChar(): KAllChar = allCharExpr + // bitvectors private val bv1Cache = mkAstInterner() private val bv8Cache = mkAstInterner() @@ -4854,6 +4882,7 @@ open class KContext( fun mkStringGeDecl(): KStringGeDecl = KStringGeDecl(this) // regex + fun mkRegexLiteralDecl(value: String): KRegexLiteralDecl = KRegexLiteralDecl(this, value) fun mkRegexConcatDecl(): KRegexConcatDecl = KRegexConcatDecl(this) @@ -4870,6 +4899,12 @@ open class KContext( fun mkRegexComplementDecl(): KRegexComplementDecl = KRegexComplementDecl(this) + fun mkEpsilonDecl(): KEpsilonDecl = KEpsilonDecl(this) + + fun mkAllDecl(): KAllDecl = KAllDecl(this) + + fun mkAllCharDecl(): KAllCharDecl = KAllCharDecl(this) + // Bit vectors fun mkBvDecl(value: Boolean): KDecl = KBitVec1ValueDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index d6d83a0d9..51f004a47 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -101,3 +101,24 @@ class KRegexComplementDecl internal constructor( override fun KContext.apply(arg: KExpr): KApp = mkRegexComplementNoSimplify(arg) override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } + +class KEpsilonDecl internal constructor( + ctx: KContext +) : KConstDecl(ctx, "eps", ctx.mkRegexSort()) { + override fun apply(args: List>): KApp = ctx.mkEpsilon() + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} + +class KAllDecl internal constructor( + ctx: KContext +) : KConstDecl(ctx, "all", ctx.mkRegexSort()) { + override fun apply(args: List>): KApp = ctx.mkAll() + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} + +class KAllCharDecl internal constructor( + ctx: KContext +) : KConstDecl(ctx, "all_char", ctx.mkRegexSort()) { + override fun apply(args: List>): KApp = ctx.mkAllChar() + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index b0c52e738..51587d19a 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -5,9 +5,12 @@ import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual import io.ksmt.decl.KDecl import io.ksmt.decl.KRegexKleeneClosureDecl -import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KRegexKleeneCrossDecl +import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KRegexComplementDecl +import io.ksmt.decl.KEpsilonDecl +import io.ksmt.decl.KAllDecl +import io.ksmt.decl.KAllCharDecl import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KRegexSort @@ -172,3 +175,45 @@ class KRegexComplementExpr internal constructor( override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } } + +class KEpsilon(ctx: KContext) : KInterpretedValue(ctx) { + override val sort: KRegexSort = ctx.regexSort + + override val decl: KEpsilonDecl + get() = ctx.mkEpsilonDecl() + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash() + override fun internEquals(other: Any): Boolean = structurallyEqual(other) +} + +class KAll(ctx: KContext) : KInterpretedValue(ctx) { + override val sort: KRegexSort = ctx.regexSort + + override val decl: KAllDecl + get() = ctx.mkAllDecl() + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash() + override fun internEquals(other: Any): Boolean = structurallyEqual(other) +} + +class KAllChar(ctx: KContext) : KInterpretedValue(ctx) { + override val sort: KRegexSort = ctx.regexSort + + override val decl: KAllCharDecl + get() = ctx.mkAllCharDecl() + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash() + override fun internEquals(other: Any): Boolean = structurallyEqual(other) +} From 4182e5a8e7f94041dbf2f477c77926f6cd69ad22 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 4 Dec 2024 19:18:38 +0300 Subject: [PATCH 20/84] Implement operation to make regex optional --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 22 +++++++++++++++++++ .../src/main/kotlin/io/ksmt/decl/Regex.kt | 7 ++++++ .../src/main/kotlin/io/ksmt/expr/Regex.kt | 22 +++++++++++++++++++ 3 files changed, 51 insertions(+) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index cf4efa5a6..86764ee62 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -151,6 +151,7 @@ import io.ksmt.decl.KRegexKleeneClosureDecl import io.ksmt.decl.KRegexKleeneCrossDecl import io.ksmt.decl.KRegexDifferenceDecl import io.ksmt.decl.KRegexComplementDecl +import io.ksmt.decl.KRegexOptionDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl import io.ksmt.decl.KOrDecl @@ -316,6 +317,7 @@ import io.ksmt.expr.KRegexKleeneClosureExpr import io.ksmt.expr.KRegexKleeneCrossExpr import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr +import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr import io.ksmt.expr.KLtArithExpr @@ -2237,6 +2239,24 @@ open class KContext( KRegexComplementExpr(this, arg) } + private val regexOptionExprCache = mkAstInterner() + + /** + * Make regular expression optional. + * Equivalent to concatenating a regular expression with the empty string. + * */ + open fun mkRegexOption(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkRegexOptionNoSimplify, ::mkRegexOptionNoSimplify) // Add simplified version + + /** + * Make regular expression optional. + * Equivalent to concatenating a regular expression with the empty string. + * */ + open fun mkRegexOptionNoSimplify(arg: KExpr): KRegexOptionExpr = regexOptionExprCache.createIfContextActive { + ensureContextMatch(arg) + KRegexOptionExpr(this, arg) + } + val epsilonExpr: KEpsilon = KEpsilon(this) /** @@ -4899,6 +4919,8 @@ open class KContext( fun mkRegexComplementDecl(): KRegexComplementDecl = KRegexComplementDecl(this) + fun mkRegexOptionDecl(): KRegexOptionDecl = KRegexOptionDecl(this) + fun mkEpsilonDecl(): KEpsilonDecl = KEpsilonDecl(this) fun mkAllDecl(): KAllDecl = KAllDecl(this) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index 51f004a47..41876c234 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -102,6 +102,13 @@ class KRegexComplementDecl internal constructor( override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } +class KRegexOptionDecl internal constructor( + ctx: KContext +) : KFuncDecl1(ctx, "opt", ctx.mkRegexSort(), ctx.mkRegexSort()) { + override fun KContext.apply(arg: KExpr): KApp = mkRegexOptionNoSimplify(arg) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} + class KEpsilonDecl internal constructor( ctx: KContext ) : KConstDecl(ctx, "eps", ctx.mkRegexSort()) { diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index 51587d19a..b8661aed8 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -8,6 +8,7 @@ import io.ksmt.decl.KRegexKleeneClosureDecl import io.ksmt.decl.KRegexKleeneCrossDecl import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KRegexComplementDecl +import io.ksmt.decl.KRegexOptionDecl import io.ksmt.decl.KEpsilonDecl import io.ksmt.decl.KAllDecl import io.ksmt.decl.KAllCharDecl @@ -176,6 +177,27 @@ class KRegexComplementExpr internal constructor( override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } } +class KRegexOptionExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KRegexSort = ctx.regexSort + + override val decl: KRegexOptionDecl + get() = ctx.mkRegexOptionDecl() + + override val args: List> + get() = listOf(arg) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} + + class KEpsilon(ctx: KContext) : KInterpretedValue(ctx) { override val sort: KRegexSort = ctx.regexSort From 79b6f20362a8f8fade7faf20669ae031c4e9d2de Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 4 Dec 2024 19:27:17 +0300 Subject: [PATCH 21/84] Implement strings' contains operation --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 30 +++++++++++++++---- .../src/main/kotlin/io/ksmt/decl/String.kt | 6 ++++ .../src/main/kotlin/io/ksmt/expr/String.kt | 22 ++++++++++++++ 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 86764ee62..f6b8d9a05 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -140,6 +140,7 @@ import io.ksmt.decl.KStringLtDecl import io.ksmt.decl.KStringLeDecl import io.ksmt.decl.KStringGtDecl import io.ksmt.decl.KStringGeDecl +import io.ksmt.decl.KStringContainsDecl import io.ksmt.decl.KEpsilonDecl import io.ksmt.decl.KAllDecl import io.ksmt.decl.KAllCharDecl @@ -306,6 +307,7 @@ import io.ksmt.expr.KStringLtExpr import io.ksmt.expr.KStringLeExpr import io.ksmt.expr.KStringGtExpr import io.ksmt.expr.KStringGeExpr +import io.ksmt.expr.KStringContainsExpr import io.ksmt.expr.KEpsilon import io.ksmt.expr.KAll import io.ksmt.expr.KAllChar @@ -2019,7 +2021,7 @@ open class KContext( * Create a lexicographic ordering (`<` (less)) expression. * */ open fun mkStringLt(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::mkStringLtNoSimplify, ::mkStringLtNoSimplify) + mkSimplified(lhs, rhs, KContext::mkStringLtNoSimplify, ::mkStringLtNoSimplify) // Add simplified version /** * Create a lexicographic ordering (`<` (less)) expression. @@ -2036,7 +2038,7 @@ open class KContext( * Create a lexicographic ordering reflexive closure (`<=` (less or equal)) expression. * */ open fun mkStringLe(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::mkStringLeNoSimplify, ::mkStringLeNoSimplify) + mkSimplified(lhs, rhs, KContext::mkStringLeNoSimplify, ::mkStringLeNoSimplify) // Add simplified version /** * Create a lexicographic ordering reflexive closure (`<=` (less or equal)) expression. @@ -2053,7 +2055,7 @@ open class KContext( * Create a lexicographic ordering (`>` (greater)) expression. * */ open fun mkStringGt(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::mkStringGtNoSimplify, ::mkStringGtNoSimplify) + mkSimplified(lhs, rhs, KContext::mkStringGtNoSimplify, ::mkStringGtNoSimplify) // Add simplified version /** * Create a lexicographic ordering (`>` (greater)) expression. @@ -2070,7 +2072,7 @@ open class KContext( * Create a lexicographic ordering reflexive closure (`>=` (greater or equal)) expression. * */ open fun mkStringGe(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::mkStringGeNoSimplify, ::mkStringGeNoSimplify) + mkSimplified(lhs, rhs, KContext::mkStringGeNoSimplify, ::mkStringGeNoSimplify) // Add simplified version /** * Create a lexicographic ordering reflexive closure (`>=` (greater or equal)) expression. @@ -2081,6 +2083,23 @@ open class KContext( KStringGeExpr(this, lhs, rhs) } + private val stringContainsCache = mkAstInterner() + + /** + * Check if first string contains second one. + * */ + open fun mkStringContains(lhs: KExpr, rhs: KExpr): KExpr = + mkSimplified(lhs, rhs, KContext::mkStringContainsNoSimplify, ::mkStringContainsNoSimplify) // Add simplified version + + /** + * Check if first string contains second one. + * */ + open fun mkStringContainsNoSimplify(lhs: KExpr, rhs: KExpr): KStringContainsExpr = + stringContainsCache.createIfContextActive { + ensureContextMatch(lhs, rhs) + KStringContainsExpr(this, lhs, rhs) + } + private val stringToRegexExprCache = mkAstInterner() /** @@ -4901,8 +4920,9 @@ open class KContext( fun mkStringGeDecl(): KStringGeDecl = KStringGeDecl(this) - // regex + fun mkStringContainsDecl(): KStringContainsDecl = KStringContainsDecl(this) + // regex fun mkRegexLiteralDecl(value: String): KRegexLiteralDecl = KRegexLiteralDecl(this, value) fun mkRegexConcatDecl(): KRegexConcatDecl = KRegexConcatDecl(this) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index f40d3ad98..bde2f02bb 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -121,3 +121,9 @@ class KStringGeDecl internal constructor(ctx: KContext) : override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkStringGeNoSimplify(arg0, arg1) override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } + +class KStringContainsDecl internal constructor(ctx: KContext) : + KFuncDecl2(ctx, "contains", ctx.mkBoolSort(), ctx.mkStringSort(), ctx.mkStringSort()) { + override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkStringContainsNoSimplify(arg0, arg1) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index c5cabd40e..630eb5777 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -12,6 +12,7 @@ import io.ksmt.decl.KStringGtDecl import io.ksmt.decl.KStringGeDecl import io.ksmt.decl.KStringToRegexDecl import io.ksmt.decl.KStringInRegexDecl +import io.ksmt.decl.KStringContainsDecl import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KSort import io.ksmt.sort.KBoolSort @@ -245,3 +246,24 @@ class KStringGeExpr internal constructor( override fun internHashCode(): Int = hash(lhs, rhs) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) } + +class KStringContainsExpr internal constructor( + ctx: KContext, + val lhs: KExpr, + val rhs: KExpr +) : KApp(ctx) { + override val sort: KBoolSort = ctx.boolSort + + override val decl: KStringContainsDecl + get() = ctx.mkStringContainsDecl() + + override val args: List> + get() = listOf(lhs, rhs) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(lhs, rhs) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) +} From 0837aa92f8ee6c8570dfccd5988e34f096279ee5 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sun, 8 Dec 2024 21:08:09 +0300 Subject: [PATCH 22/84] Describe operations on strings and regex that have not yet been implemented --- .../src/main/kotlin/io/ksmt/decl/Regex.kt | 6 +++++ .../src/main/kotlin/io/ksmt/decl/String.kt | 24 +++++++++++++++++++ .../src/main/kotlin/io/ksmt/expr/Regex.kt | 6 +++++ .../src/main/kotlin/io/ksmt/expr/String.kt | 24 +++++++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index 41876c234..4ffba5f46 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -129,3 +129,9 @@ class KAllCharDecl internal constructor( override fun apply(args: List>): KApp = ctx.mkAllChar() override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } + +class KRangeDecl : RuntimeException("Not yet implemented") + +class KRegexReplaceDecl : RuntimeException("Not yet implemented") + +class KRegexReplaceAllDecl : RuntimeException("Not yet implemented") diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index bde2f02bb..e9aa11edb 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -127,3 +127,27 @@ class KStringContainsDecl internal constructor(ctx: KContext) : override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkStringContainsNoSimplify(arg0, arg1) override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } + +class KSingletonSubstringDecl : RuntimeException("Not yet implemented") + +class KSubstringDecl : RuntimeException("Not yet implemented") + +class KIndexOfDecl : RuntimeException("Not yet implemented") + +class KStringReplaceDecl : RuntimeException("Not yet implemented") + +class KStringReplaceAllDecl : RuntimeException("Not yet implemented") + +/* + Maps to and from integers. + */ + +class KIsDigitDecl : RuntimeException("Not yet implemented") + +class KToCodeDecl : RuntimeException("Not yet implemented") + +class KFromCodeDecl : RuntimeException("Not yet implemented") + +class KToIntDecl : RuntimeException("Not yet implemented") + +class KFromIntDecl : RuntimeException("Not yet implemented") diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index b8661aed8..06a4081ef 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -239,3 +239,9 @@ class KAllChar(ctx: KContext) : KInterpretedValue(ctx) { override fun internHashCode(): Int = hash() override fun internEquals(other: Any): Boolean = structurallyEqual(other) } + +class KRangeExpr : RuntimeException("Not yet implemented") + +class KRegexReplaceExpr : RuntimeException("Not yet implemented") + +class KRegexReplaceAllExpr : RuntimeException("Not yet implemented") diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index 630eb5777..bd3b9c5e8 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -267,3 +267,27 @@ class KStringContainsExpr internal constructor( override fun internHashCode(): Int = hash(lhs, rhs) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) } + +class KSingletonSubstringExpr : RuntimeException("Not yet implemented") + +class KSubstringExpr : RuntimeException("Not yet implemented") + +class KIndexOfExpr : RuntimeException("Not yet implemented") + +class KStringReplaceExpr : RuntimeException("Not yet implemented") + +class KStringReplaceAllExpr : RuntimeException("Not yet implemented") + +/* + Maps to and from integers. + */ + +class KIsDigitExpr : RuntimeException("Not yet implemented") + +class KToCodeExpr : RuntimeException("Not yet implemented") + +class KFromCodeExpr : RuntimeException("Not yet implemented") + +class KToIntExpr : RuntimeException("Not yet implemented") + +class KFromIntExpr : RuntimeException("Not yet implemented") From 45bd8015c08710f60660fbf9fd5176550138626c Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sun, 8 Dec 2024 21:31:50 +0300 Subject: [PATCH 23/84] Syntactic sugar for comparing string expressions --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index f6b8d9a05..e764e7012 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -2032,6 +2032,12 @@ open class KContext( KStringLtExpr(this, lhs, rhs) } + /** + * Create a lexicographic ordering (`<` (less)) expression. + * */ + @JvmName("stringLt") + infix fun KExpr.lt(other: KExpr) = mkStringLt(this, other) + private val stringLeCache = mkAstInterner() /** @@ -2049,6 +2055,12 @@ open class KContext( KStringLeExpr(this, lhs, rhs) } + /** + * Create a lexicographic ordering reflexive closure (`<=` (less or equal)) expression. + * */ + @JvmName("stringLe") + infix fun KExpr.le(other: KExpr) = mkStringLe(this, other) + private val stringGtCache = mkAstInterner() /** @@ -2066,6 +2078,12 @@ open class KContext( KStringGtExpr(this, lhs, rhs) } + /** + * Create a lexicographic ordering (`>` (greater)) expression. + * */ + @JvmName("stringGt") + infix fun KExpr.gt(other: KExpr) = mkStringGt(this, other) + private val stringGeCache = mkAstInterner() /** @@ -2083,6 +2101,12 @@ open class KContext( KStringGeExpr(this, lhs, rhs) } + /** + * Create a lexicographic ordering reflexive closure (`>=` (greater or equal)) expression. + * */ + @JvmName("stringGe") + infix fun KExpr.ge(other: KExpr) = mkStringGe(this, other) + private val stringContainsCache = mkAstInterner() /** From f9da6a611e1bfe3304f8c1ace917b8a5230dc817 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sun, 8 Dec 2024 21:41:59 +0300 Subject: [PATCH 24/84] Syntactic sugar for strings and regex concatenation --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 18 +++++++++++++++--- .../src/main/kotlin/io/ksmt/decl/Regex.kt | 2 +- .../src/main/kotlin/io/ksmt/decl/String.kt | 4 ++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index e764e7012..285d68406 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -1953,18 +1953,24 @@ open class KContext( /** * Create String concatenation (`concat`) expression. * */ - open fun mkStringConcatExpr(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkStringConcatExprNoSimplify, ::mkStringConcatExprNoSimplify) // Add simplified version + open fun mkStringConcat(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkStringConcatNoSimplify, ::mkStringConcatNoSimplify) // Add simplified version /** * Create String concatenation (`concat`) expression. * */ - open fun mkStringConcatExprNoSimplify(arg0: KExpr, arg1: KExpr): KStringConcatExpr = + open fun mkStringConcatNoSimplify(arg0: KExpr, arg1: KExpr): KStringConcatExpr = stringConcatExprCache.createIfContextActive { ensureContextMatch(arg0, arg1) KStringConcatExpr(this, arg0, arg1) } + /** + * Create String concatenation (`concat`) expression. + * */ + @JvmName("stringConcat") + operator fun KExpr.plus(other: KExpr) = mkStringConcat(this, other) + private val stringLenExprCache = mkAstInterner() /** @@ -2183,6 +2189,12 @@ open class KContext( KRegexConcatExpr(this, arg0, arg1) } + /** + * Create Regex concatenation (`concat`) expression. + * */ + @JvmName("regexConcat") + operator fun KExpr.plus(other: KExpr) = mkRegexConcat(this, other) + private val regexUnionExprCache = mkAstInterner() /** diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index 4ffba5f46..33aba66bd 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -17,7 +17,7 @@ class KRegexConcatDecl internal constructor( ctx: KContext, ) : KFuncDecl2( ctx, - name = "concat", + name = "regex_concat", resultSort = ctx.mkRegexSort(), ctx.mkRegexSort(), ctx.mkRegexSort() diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index e9aa11edb..6f6421b16 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -20,7 +20,7 @@ class KStringConcatDecl internal constructor( ctx: KContext, ) : KFuncDecl2( ctx, - name = "concat", + name = "str_concat", resultSort = ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkStringSort() @@ -30,7 +30,7 @@ class KStringConcatDecl internal constructor( override fun KContext.apply( arg0: KExpr, arg1: KExpr - ): KApp = mkStringConcatExprNoSimplify(arg0, arg1) + ): KApp = mkStringConcatNoSimplify(arg0, arg1) } class KStringLenDecl internal constructor( From ee0ff54729c1ac908b2fe2fb7bdd78f4f69b1c5d Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sun, 8 Dec 2024 21:55:35 +0300 Subject: [PATCH 25/84] Syntactic sugar for strings literals and length expr --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 285d68406..204e94daf 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -1948,6 +1948,9 @@ open class KContext( KStringLiteralExpr(this, value) } + val String.expr + get() = mkStringLiteral(this) + private val stringConcatExprCache = mkAstInterner() /** @@ -1987,6 +1990,12 @@ open class KContext( KStringLenExpr(this, arg) } + val KExpr.len + get() = mkStringLen(this) + + val String.len + get() = mkStringLen(this.expr) + private val suffixOfExprCache = mkAstInterner() /** From eb068cc3d19c2a100d4a8c5cab2117fadc58b19c Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sun, 8 Dec 2024 22:04:36 +0300 Subject: [PATCH 26/84] Syntactic sugar for suffixOf, prefixOf, contains operations --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 204e94daf..66f98deb1 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -2013,6 +2013,11 @@ open class KContext( KSuffixOfExpr(this, arg0, arg1) } + /** + * Check if first string is a suffix of second. + * */ + infix fun KExpr.isSuffixOf(other: KExpr) = mkSuffixOf(this, other) + private val prefixOfExprCache = mkAstInterner() /** @@ -2030,6 +2035,11 @@ open class KContext( KPrefixOfExpr(this, arg0, arg1) } + /** + * Check if first string is a prefix of second. + * */ + infix fun KExpr.isPrefixOf(other: KExpr) = mkPrefixOf(this, other) + private val stringLtCache = mkAstInterner() /** @@ -2139,6 +2149,11 @@ open class KContext( KStringContainsExpr(this, lhs, rhs) } + /** + * Check if first string contains second one. + * */ + infix fun KExpr.contains(other: KExpr) = mkStringContains(this, other) + private val stringToRegexExprCache = mkAstInterner() /** From 1b38d128b33cda20a86cf46f49f9c836ea1b193b Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sun, 8 Dec 2024 22:44:13 +0300 Subject: [PATCH 27/84] Syntactic sugar for inRegex, toRegex operations --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 66f98deb1..86f3f8728 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -2152,6 +2152,7 @@ open class KContext( /** * Check if first string contains second one. * */ + @JvmName("strContains") infix fun KExpr.contains(other: KExpr) = mkStringContains(this, other) private val stringToRegexExprCache = mkAstInterner() @@ -2170,6 +2171,16 @@ open class KContext( KStringToRegexExpr(this, arg) } + /** + * Create a regular expression based on a string expression. + * */ + fun KExpr.toRegex() = mkStringToRegex(this) + + /** + * Create a regular expression based on a string expression. + * */ + fun String.toRegex() = mkStringToRegex(this.expr) + private val stringInRegexExprCache = mkAstInterner() /** @@ -2187,6 +2198,22 @@ open class KContext( KStringInRegexExpr(this, arg0, arg1) } + /** + * Check if a string belongs to the language defined by the regular expression. + * */ + infix fun KExpr.inRegex(other: KExpr) = mkStringInRegex(this, other) + + /** + * Check if a string belongs to the language defined by the regular expression. + * */ + infix fun String.inRegex(other: KExpr) = mkStringInRegex(this.expr, other) + + /** + * Check if a string belongs to the language defined by the regular expression. + * */ + @JvmName("regexContains") + infix fun KExpr.contains(other: KExpr) = mkStringInRegex(other, this) + private val regexLiteralCache = mkAstInterner() /** From f42d7ebd5ffb17d6a37a06cbe3eed1f0f687fbe8 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sun, 8 Dec 2024 23:33:56 +0300 Subject: [PATCH 28/84] Implement replace operations for strings --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 48 +++++++++++++++++++ .../src/main/kotlin/io/ksmt/decl/String.kt | 38 ++++++++++++++- .../src/main/kotlin/io/ksmt/expr/String.kt | 46 +++++++++++++++++- 3 files changed, 128 insertions(+), 4 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 86f3f8728..050022cc7 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -141,6 +141,8 @@ import io.ksmt.decl.KStringLeDecl import io.ksmt.decl.KStringGtDecl import io.ksmt.decl.KStringGeDecl import io.ksmt.decl.KStringContainsDecl +import io.ksmt.decl.KStringReplaceDecl +import io.ksmt.decl.KStringReplaceAllDecl import io.ksmt.decl.KEpsilonDecl import io.ksmt.decl.KAllDecl import io.ksmt.decl.KAllCharDecl @@ -308,6 +310,8 @@ import io.ksmt.expr.KStringLeExpr import io.ksmt.expr.KStringGtExpr import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KStringContainsExpr +import io.ksmt.expr.KStringReplaceExpr +import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KEpsilon import io.ksmt.expr.KAll import io.ksmt.expr.KAllChar @@ -2155,6 +2159,46 @@ open class KContext( @JvmName("strContains") infix fun KExpr.contains(other: KExpr) = mkStringContains(this, other) + private val stringReplaceCache = mkAstInterner() + + /** + * Replace the first occurrence of the second string in the first string with the third, + * if there are such occurrences, otherwise return the first string. + * If the second line is empty, then the third is inserted at the beginning of the first. + * */ + open fun mkStringReplace(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = + mkSimplified(arg0, arg1, arg2, KContext::mkStringReplaceNoSimplify, ::mkStringReplaceNoSimplify) // Add simplified version + + /** + * Replace the first occurrence of the second string in the first string with the third, + * if there are such occurrences, otherwise return the first string. + * If the second line is empty, then the third is inserted at the beginning of the first. + * */ + open fun mkStringReplaceNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringReplaceExpr = + stringReplaceCache.createIfContextActive { + ensureContextMatch(arg0, arg1, arg2) + KStringReplaceExpr(this, arg0, arg1, arg2) + } + + private val stringReplaceAllCache = mkAstInterner() + + /** + * Replace the all occurrences of the second string in the first string with the third, + * if there are such occurrences, otherwise return the first string. + * */ + open fun mkStringReplaceAll(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = + mkSimplified(arg0, arg1, arg2, KContext::mkStringReplaceAllNoSimplify, ::mkStringReplaceAllNoSimplify) // Add simplified version + + /** + * Replace the all occurrences of the second string in the first string with the third, + * if there are such occurrences, otherwise return the first string. + * */ + open fun mkStringReplaceAllNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringReplaceAllExpr = + stringReplaceAllCache.createIfContextActive { + ensureContextMatch(arg0, arg1, arg2) + KStringReplaceAllExpr(this, arg0, arg1, arg2) + } + private val stringToRegexExprCache = mkAstInterner() /** @@ -5009,6 +5053,10 @@ open class KContext( fun mkStringContainsDecl(): KStringContainsDecl = KStringContainsDecl(this) + fun mkStringReplaceDecl(): KStringReplaceDecl = KStringReplaceDecl(this) + + fun mkStringReplaceAllDecl(): KStringReplaceAllDecl = KStringReplaceAllDecl(this) + // regex fun mkRegexLiteralDecl(value: String): KRegexLiteralDecl = KRegexLiteralDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index 6f6421b16..34a6b96ea 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -134,9 +134,43 @@ class KSubstringDecl : RuntimeException("Not yet implemented") class KIndexOfDecl : RuntimeException("Not yet implemented") -class KStringReplaceDecl : RuntimeException("Not yet implemented") +class KStringReplaceDecl internal constructor( + ctx: KContext, +) : KFuncDecl3( + ctx, + name = "str_replace", + resultSort = ctx.mkStringSort(), + ctx.mkStringSort(), + ctx.mkStringSort(), + ctx.mkStringSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KApp = mkStringReplaceNoSimplify(arg0, arg1, arg2) +} -class KStringReplaceAllDecl : RuntimeException("Not yet implemented") +class KStringReplaceAllDecl internal constructor( + ctx: KContext, +) : KFuncDecl3( + ctx, + name = "str_replace_all", + resultSort = ctx.mkStringSort(), + ctx.mkStringSort(), + ctx.mkStringSort(), + ctx.mkStringSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KApp = mkStringReplaceNoSimplify(arg0, arg1, arg2) +} /* Maps to and from integers. diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index bd3b9c5e8..160c56bd0 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -13,6 +13,8 @@ import io.ksmt.decl.KStringGeDecl import io.ksmt.decl.KStringToRegexDecl import io.ksmt.decl.KStringInRegexDecl import io.ksmt.decl.KStringContainsDecl +import io.ksmt.decl.KStringReplaceDecl +import io.ksmt.decl.KStringReplaceAllDecl import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KSort import io.ksmt.sort.KBoolSort @@ -274,9 +276,49 @@ class KSubstringExpr : RuntimeException("Not yet implemented") class KIndexOfExpr : RuntimeException("Not yet implemented") -class KStringReplaceExpr : RuntimeException("Not yet implemented") +class KStringReplaceExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr, + val arg2: KExpr +) : KApp(ctx) { + override val sort: KStringSort = ctx.stringSort + + override val decl: KStringReplaceDecl + get() = ctx.mkStringReplaceDecl() + + override val args: List> + get() = listOf(arg0, arg1, arg2) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg0, arg1, arg2) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) +} -class KStringReplaceAllExpr : RuntimeException("Not yet implemented") +class KStringReplaceAllExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr, + val arg2: KExpr +) : KApp(ctx) { + override val sort: KStringSort = ctx.stringSort + + override val decl: KStringReplaceAllDecl + get() = ctx.mkStringReplaceAllDecl() + + override val args: List> + get() = listOf(arg0, arg1, arg2) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg0, arg1, arg2) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) +} /* Maps to and from integers. From 01a57efd73f4d09df0f035877fd33321f80a6f76 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sun, 8 Dec 2024 23:45:07 +0300 Subject: [PATCH 29/84] Implement regex range operation --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 29 +++++++++++++++++-- .../src/main/kotlin/io/ksmt/decl/Regex.kt | 18 +++++++++++- .../src/main/kotlin/io/ksmt/expr/Regex.kt | 22 +++++++++++++- 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 050022cc7..bc24aafdb 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -155,6 +155,7 @@ import io.ksmt.decl.KRegexKleeneCrossDecl import io.ksmt.decl.KRegexDifferenceDecl import io.ksmt.decl.KRegexComplementDecl import io.ksmt.decl.KRegexOptionDecl +import io.ksmt.decl.KRangeDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl import io.ksmt.decl.KOrDecl @@ -324,6 +325,7 @@ import io.ksmt.expr.KRegexKleeneCrossExpr import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr +import io.ksmt.expr.KRangeExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr import io.ksmt.expr.KLtArithExpr @@ -2359,13 +2361,13 @@ open class KContext( private val regexDifferenceExprCache = mkAstInterner() /** - * Create Regex difference (`intersect`) expression. + * Create Regex difference (`diff`) expression. * */ open fun mkRegexDifference(arg0: KExpr, arg1: KExpr): KExpr = mkSimplified(arg0, arg1, KContext::mkRegexDifferenceNoSimplify, ::mkRegexDifferenceNoSimplify) // Add simplified version /** - * Create Regex difference (`intersect`) expression. + * Create Regex difference (`diff`) expression. * */ open fun mkRegexDifferenceNoSimplify(arg0: KExpr, arg1: KExpr): KRegexDifferenceExpr = regexDifferenceExprCache.createIfContextActive { @@ -2407,6 +2409,27 @@ open class KContext( KRegexOptionExpr(this, arg) } + private val rangeExprCache = mkAstInterner() + + /** + * Return the set of all singleton strings in the range + * between the first and second string that are also singletons. + * Otherwise the empty set. + * */ + open fun mkRange(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkRangeNoSimplify, ::mkRangeNoSimplify) // Add simplified version + + /** + * Return the set of all singleton strings in the range + * between the first and second string that are also singletons. + * Otherwise the empty set. + * */ + open fun mkRangeNoSimplify(arg0: KExpr, arg1: KExpr): KRangeExpr = + rangeExprCache.createIfContextActive { + ensureContextMatch(arg0, arg1) + KRangeExpr(this, arg0, arg1) + } + val epsilonExpr: KEpsilon = KEpsilon(this) /** @@ -5076,6 +5099,8 @@ open class KContext( fun mkRegexOptionDecl(): KRegexOptionDecl = KRegexOptionDecl(this) + fun mkRangeDecl(): KRangeDecl = KRangeDecl(this) + fun mkEpsilonDecl(): KEpsilonDecl = KEpsilonDecl(this) fun mkAllDecl(): KAllDecl = KAllDecl(this) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index 33aba66bd..82e644be4 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -4,6 +4,7 @@ import io.ksmt.KContext import io.ksmt.expr.KApp import io.ksmt.expr.KExpr import io.ksmt.sort.KRegexSort +import io.ksmt.sort.KStringSort class KRegexLiteralDecl internal constructor( ctx: KContext, @@ -130,7 +131,22 @@ class KAllCharDecl internal constructor( override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } -class KRangeDecl : RuntimeException("Not yet implemented") +class KRangeDecl internal constructor( + ctx: KContext, +) : KFuncDecl2( + ctx, + name = "range", + resultSort = ctx.mkRegexSort(), + ctx.mkStringSort(), + ctx.mkStringSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkRangeNoSimplify(arg0, arg1) +} class KRegexReplaceDecl : RuntimeException("Not yet implemented") diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index 06a4081ef..034f63c3c 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -14,6 +14,7 @@ import io.ksmt.decl.KAllDecl import io.ksmt.decl.KAllCharDecl import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KRegexSort +import io.ksmt.sort.KStringSort class KRegexLiteralExpr internal constructor( ctx: KContext, @@ -240,7 +241,26 @@ class KAllChar(ctx: KContext) : KInterpretedValue(ctx) { override fun internEquals(other: Any): Boolean = structurallyEqual(other) } -class KRangeExpr : RuntimeException("Not yet implemented") +class KRangeExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr +) : KApp(ctx) { + override val args: List> + get() = listOf(arg0, arg1) + + override val decl: KDecl + get() = ctx.mkRangeDecl() + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override val sort: KRegexSort = ctx.mkRegexSort() + + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) +} class KRegexReplaceExpr : RuntimeException("Not yet implemented") From 1d2222585b10a15739c481cbeb30fab6254b686a Mon Sep 17 00:00:00 2001 From: raf-nr Date: Mon, 9 Dec 2024 00:28:01 +0300 Subject: [PATCH 30/84] Implement operations, that maps strings to and from integers --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 113 ++++++++++++++++++ .../src/main/kotlin/io/ksmt/decl/String.kt | 37 +++++- .../src/main/kotlin/io/ksmt/expr/String.kt | 105 +++++++++++++++- 3 files changed, 244 insertions(+), 11 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index bc24aafdb..2ea3a4aad 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -143,6 +143,11 @@ import io.ksmt.decl.KStringGeDecl import io.ksmt.decl.KStringContainsDecl import io.ksmt.decl.KStringReplaceDecl import io.ksmt.decl.KStringReplaceAllDecl +import io.ksmt.decl.KStringIsDigitDecl +import io.ksmt.decl.KStringToCodeDecl +import io.ksmt.decl.KStringFromCodeDecl +import io.ksmt.decl.KStringToIntDecl +import io.ksmt.decl.KStringFromIntDecl import io.ksmt.decl.KEpsilonDecl import io.ksmt.decl.KAllDecl import io.ksmt.decl.KAllCharDecl @@ -313,6 +318,11 @@ import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KStringContainsExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr +import io.ksmt.expr.KStringIsDigitExpr +import io.ksmt.expr.KStringToCodeExpr +import io.ksmt.expr.KStringFromCodeExpr +import io.ksmt.expr.KStringToIntExpr +import io.ksmt.expr.KStringFromIntExpr import io.ksmt.expr.KEpsilon import io.ksmt.expr.KAll import io.ksmt.expr.KAllChar @@ -2201,6 +2211,99 @@ open class KContext( KStringReplaceAllExpr(this, arg0, arg1, arg2) } + private val stringIsDigitCache = mkAstInterner() + + /** + * Check that the string contains only decimal digit characters. + * */ + open fun mkStringIsDigit(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkStringIsDigitNoSimplify, ::mkStringIsDigitNoSimplify) // Add simplified version + + /** + * Check that the string contains only decimal digit characters. + * */ + open fun mkStringIsDigitNoSimplify(arg: KExpr): KStringIsDigitExpr = + stringIsDigitCache.createIfContextActive { + ensureContextMatch(arg) + KStringIsDigitExpr(this, arg) + } + + private val stringToCodeCache = mkAstInterner() + + /** + * Returns the code point of the only character in the string if the string is a singleton. + * Otherwise, returns -1. + * */ + open fun mkStringToCode(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkStringToCodeNoSimplify, ::mkStringToCodeNoSimplify) // Add simplified version + + /** + * Returns the code point of the only character in the string if the string is a singleton. + * Otherwise, returns -1. + * */ + open fun mkStringToCodeNoSimplify(arg: KExpr): KStringToCodeExpr = + stringToCodeCache.createIfContextActive { + ensureContextMatch(arg) + KStringToCodeExpr(this, arg) + } + + private val stringFromCodeCache = mkAstInterner() + + /** + * Returns a singleton string consisting of a character, with the given code point. + * If codepoint not in range [0, 196607], returns empty string. + * */ + open fun mkStringFromCode(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkStringFromCodeNoSimplify, ::mkStringFromCodeNoSimplify) // Add simplified version + + /** + * Returns a singleton string consisting of a character, with the given code point. + * If codepoint not in range [0, 196607], returns empty string. + * */ + open fun mkStringFromCodeNoSimplify(arg: KExpr): KStringFromCodeExpr = + stringFromCodeCache.createIfContextActive { + ensureContextMatch(arg) + KStringFromCodeExpr(this, arg) + } + + private val stringToIntCache = mkAstInterner() + + /** + * Converts a string containing only decimal digits to a positive integer. + * Otherwise, if the string contains a character that is not a decimal number, then returns -1. + * */ + open fun mkStringToInt(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkStringToIntNoSimplify, ::mkStringToIntNoSimplify) // Add simplified version + + /** + * Converts a string containing only decimal digits to a positive integer. + * Otherwise, if the string contains a character that is not a decimal number, then returns -1. + * */ + open fun mkStringToIntNoSimplify(arg: KExpr): KStringToIntExpr = + stringToIntCache.createIfContextActive { + ensureContextMatch(arg) + KStringToIntExpr(this, arg) + } + + private val stringFromIntCache = mkAstInterner() + + /** + * Converts a positive integer to a string consisting of the decimal digits of that number, with no leading zeros. + * If the number is negative, it returns an empty string. + * */ + open fun mkStringFromInt(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkStringFromIntNoSimplify, ::mkStringFromIntNoSimplify) // Add simplified version + + /** + * Converts a positive integer to a string consisting of the decimal digits of that number, with no leading zeros. + * If the number is negative, it returns an empty string. + * */ + open fun mkStringFromIntNoSimplify(arg: KExpr): KStringFromIntExpr = + stringFromIntCache.createIfContextActive { + ensureContextMatch(arg) + KStringFromIntExpr(this, arg) + } + private val stringToRegexExprCache = mkAstInterner() /** @@ -5080,6 +5183,16 @@ open class KContext( fun mkStringReplaceAllDecl(): KStringReplaceAllDecl = KStringReplaceAllDecl(this) + fun mkStringIsDigitDecl(): KStringIsDigitDecl = KStringIsDigitDecl(this) + + fun mkStringToCodeDecl(): KStringToCodeDecl = KStringToCodeDecl(this) + + fun mkStringFromCodeDecl(): KStringFromCodeDecl = KStringFromCodeDecl(this) + + fun mkStringToIntDecl(): KStringToIntDecl = KStringToIntDecl(this) + + fun mkStringFromIntDecl(): KStringFromIntDecl = KStringFromIntDecl(this) + // regex fun mkRegexLiteralDecl(value: String): KRegexLiteralDecl = KRegexLiteralDecl(this, value) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index 34a6b96ea..13e2d10e5 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -169,19 +169,44 @@ class KStringReplaceAllDecl internal constructor( arg0: KExpr, arg1: KExpr, arg2: KExpr - ): KApp = mkStringReplaceNoSimplify(arg0, arg1, arg2) + ): KApp = mkStringReplaceAllNoSimplify(arg0, arg1, arg2) } /* Maps to and from integers. */ -class KIsDigitDecl : RuntimeException("Not yet implemented") +class KStringIsDigitDecl internal constructor( + ctx: KContext +) : KFuncDecl1(ctx, "is_digit", ctx.mkBoolSort(), ctx.mkStringSort()) { + override fun KContext.apply(arg: KExpr): KApp = mkStringIsDigitNoSimplify(arg) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} -class KToCodeDecl : RuntimeException("Not yet implemented") +class KStringToCodeDecl internal constructor( + ctx: KContext +) : KFuncDecl1(ctx, "to_code", ctx.mkIntSort(), ctx.mkStringSort()) { + override fun KContext.apply(arg: KExpr): KApp = mkStringToCodeNoSimplify(arg) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} -class KFromCodeDecl : RuntimeException("Not yet implemented") +class KStringFromCodeDecl internal constructor( + ctx: KContext +) : KFuncDecl1(ctx, "from_code", ctx.mkStringSort(), ctx.mkIntSort()) { + override fun KContext.apply(arg: KExpr): KApp = mkStringFromCodeNoSimplify(arg) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} -class KToIntDecl : RuntimeException("Not yet implemented") +class KStringToIntDecl internal constructor( + ctx: KContext +) : KFuncDecl1(ctx, "to_int", ctx.mkIntSort(), ctx.mkStringSort()) { + override fun KContext.apply(arg: KExpr): KApp = mkStringToIntNoSimplify(arg) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} -class KFromIntDecl : RuntimeException("Not yet implemented") +class KStringFromIntDecl internal constructor( + ctx: KContext +) : KFuncDecl1(ctx, "from_int", ctx.mkStringSort(), ctx.mkIntSort()) { + override fun KContext.apply(arg: KExpr): KApp = mkStringFromIntNoSimplify(arg) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index 160c56bd0..3d2a53d7d 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -15,6 +15,11 @@ import io.ksmt.decl.KStringInRegexDecl import io.ksmt.decl.KStringContainsDecl import io.ksmt.decl.KStringReplaceDecl import io.ksmt.decl.KStringReplaceAllDecl +import io.ksmt.decl.KStringIsDigitDecl +import io.ksmt.decl.KStringToCodeDecl +import io.ksmt.decl.KStringFromCodeDecl +import io.ksmt.decl.KStringToIntDecl +import io.ksmt.decl.KStringFromIntDecl import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KSort import io.ksmt.sort.KBoolSort @@ -324,12 +329,102 @@ class KStringReplaceAllExpr internal constructor( Maps to and from integers. */ -class KIsDigitExpr : RuntimeException("Not yet implemented") +class KStringIsDigitExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KBoolSort = ctx.boolSort + + override val decl: KStringIsDigitDecl + get() = ctx.mkStringIsDigitDecl() + + override val args: List> + get() = listOf(arg) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} + +class KStringToCodeExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KIntSort = ctx.intSort + + override val decl: KStringToCodeDecl + get() = ctx.mkStringToCodeDecl() + + override val args: List> + get() = listOf(arg) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} + +class KStringFromCodeExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KStringSort = ctx.stringSort + + override val decl: KStringFromCodeDecl + get() = ctx.mkStringFromCodeDecl() -class KToCodeExpr : RuntimeException("Not yet implemented") + override val args: List> + get() = listOf(arg) -class KFromCodeExpr : RuntimeException("Not yet implemented") + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } -class KToIntExpr : RuntimeException("Not yet implemented") + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} -class KFromIntExpr : RuntimeException("Not yet implemented") +class KStringToIntExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KIntSort = ctx.intSort + + override val decl: KStringToIntDecl + get() = ctx.mkStringToIntDecl() + + override val args: List> + get() = listOf(arg) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} + +class KStringFromIntExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KStringSort = ctx.stringSort + + override val decl: KStringFromIntDecl + get() = ctx.mkStringFromIntDecl() + + override val args: List> + get() = listOf(arg) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} From 4363af94d9537c5ddfdea7579c8951e49fb4c6fa Mon Sep 17 00:00:00 2001 From: raf-nr Date: Mon, 9 Dec 2024 01:31:45 +0300 Subject: [PATCH 31/84] Implement strings' replace operations based on regex --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 44 ++++++++++++++++++ .../src/main/kotlin/io/ksmt/decl/String.kt | 42 ++++++++++++++++- .../src/main/kotlin/io/ksmt/expr/Regex.kt | 4 -- .../src/main/kotlin/io/ksmt/expr/String.kt | 46 +++++++++++++++++++ 4 files changed, 130 insertions(+), 6 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 2ea3a4aad..572c2ba27 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -143,6 +143,8 @@ import io.ksmt.decl.KStringGeDecl import io.ksmt.decl.KStringContainsDecl import io.ksmt.decl.KStringReplaceDecl import io.ksmt.decl.KStringReplaceAllDecl +import io.ksmt.decl.KStringReplaceWithRegexDecl +import io.ksmt.decl.KStringReplaceAllWithRegexDecl import io.ksmt.decl.KStringIsDigitDecl import io.ksmt.decl.KStringToCodeDecl import io.ksmt.decl.KStringFromCodeDecl @@ -318,6 +320,8 @@ import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KStringContainsExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr +import io.ksmt.expr.KStringReplaceWithRegexExpr +import io.ksmt.expr.KStringReplaceAllWithRegexExpr import io.ksmt.expr.KStringIsDigitExpr import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr @@ -2211,6 +2215,42 @@ open class KContext( KStringReplaceAllExpr(this, arg0, arg1, arg2) } + private val stringReplaceWithRegexCache = mkAstInterner() + + /** + * Replace the shortest leftmost match of regex in first string, if any, by second string. + * If the language of r contains the empty string, the result is to prepend second string to first one. + * */ + open fun mkStringReplaceWithRegex(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = + mkSimplified(arg0, arg1, arg2, KContext::mkStringReplaceWithRegexNoSimplify, ::mkStringReplaceWithRegexNoSimplify) // Add simplified version + + /** + * Replace the shortest leftmost match of regex in first string, if any, by second string. + * If the language of r contains the empty string, the result is to prepend second string to first one. + * */ + open fun mkStringReplaceWithRegexNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringReplaceWithRegexExpr = + stringReplaceWithRegexCache.createIfContextActive { + ensureContextMatch(arg0, arg1, arg2) + KStringReplaceWithRegexExpr(this, arg0, arg1, arg2) + } + + private val stringReplaceAllWithRegexCache = mkAstInterner() + + /** + * Replace left-to right, each shortest non-empty match of regex in first string by seconds. + * */ + open fun mkStringReplaceAllWithRegex(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = + mkSimplified(arg0, arg1, arg2, KContext::mkStringReplaceAllWithRegexNoSimplify, ::mkStringReplaceAllWithRegexNoSimplify) // Add simplified version + + /** + * Replace left-to right, each shortest non-empty match of regex in first string by seconds. + * */ + open fun mkStringReplaceAllWithRegexNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringReplaceAllWithRegexExpr = + stringReplaceAllWithRegexCache.createIfContextActive { + ensureContextMatch(arg0, arg1, arg2) + KStringReplaceAllWithRegexExpr(this, arg0, arg1, arg2) + } + private val stringIsDigitCache = mkAstInterner() /** @@ -5183,6 +5223,10 @@ open class KContext( fun mkStringReplaceAllDecl(): KStringReplaceAllDecl = KStringReplaceAllDecl(this) + fun mkStringReplaceWithRegexDecl(): KStringReplaceWithRegexDecl = KStringReplaceWithRegexDecl(this) + + fun mkStringReplaceAllWithRegexDecl(): KStringReplaceAllWithRegexDecl = KStringReplaceAllWithRegexDecl(this) + fun mkStringIsDigitDecl(): KStringIsDigitDecl = KStringIsDigitDecl(this) fun mkStringToCodeDecl(): KStringToCodeDecl = KStringToCodeDecl(this) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index 13e2d10e5..dafeb8910 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -138,7 +138,7 @@ class KStringReplaceDecl internal constructor( ctx: KContext, ) : KFuncDecl3( ctx, - name = "str_replace", + name = "replace", resultSort = ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkStringSort(), @@ -157,7 +157,7 @@ class KStringReplaceAllDecl internal constructor( ctx: KContext, ) : KFuncDecl3( ctx, - name = "str_replace_all", + name = "replace_all", resultSort = ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkStringSort(), @@ -172,6 +172,44 @@ class KStringReplaceAllDecl internal constructor( ): KApp = mkStringReplaceAllNoSimplify(arg0, arg1, arg2) } +class KStringReplaceWithRegexDecl internal constructor( + ctx: KContext, +) : KFuncDecl3( + ctx, + name = "replace_with_regex", + resultSort = ctx.mkStringSort(), + ctx.mkStringSort(), + ctx.mkRegexSort(), + ctx.mkStringSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KApp = mkStringReplaceWithRegexNoSimplify(arg0, arg1, arg2) +} + +class KStringReplaceAllWithRegexDecl internal constructor( + ctx: KContext, +) : KFuncDecl3( + ctx, + name = "replace_all_with_regex", + resultSort = ctx.mkStringSort(), + ctx.mkStringSort(), + ctx.mkRegexSort(), + ctx.mkStringSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KApp = mkStringReplaceAllWithRegexNoSimplify(arg0, arg1, arg2) +} + /* Maps to and from integers. */ diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index 034f63c3c..0233547c4 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -261,7 +261,3 @@ class KRangeExpr internal constructor( override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } - -class KRegexReplaceExpr : RuntimeException("Not yet implemented") - -class KRegexReplaceAllExpr : RuntimeException("Not yet implemented") diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index 3d2a53d7d..403fe1f3e 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -15,6 +15,8 @@ import io.ksmt.decl.KStringInRegexDecl import io.ksmt.decl.KStringContainsDecl import io.ksmt.decl.KStringReplaceDecl import io.ksmt.decl.KStringReplaceAllDecl +import io.ksmt.decl.KStringReplaceWithRegexDecl +import io.ksmt.decl.KStringReplaceAllWithRegexDecl import io.ksmt.decl.KStringIsDigitDecl import io.ksmt.decl.KStringToCodeDecl import io.ksmt.decl.KStringFromCodeDecl @@ -325,6 +327,50 @@ class KStringReplaceAllExpr internal constructor( override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) } +class KStringReplaceWithRegexExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr, + val arg2: KExpr +) : KApp(ctx) { + override val sort: KStringSort = ctx.stringSort + + override val decl: KStringReplaceWithRegexDecl + get() = ctx.mkStringReplaceWithRegexDecl() + + override val args: List> + get() = listOf(arg0.cast(), arg1.cast(), arg2.cast()) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg0, arg1, arg2) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) +} + +class KStringReplaceAllWithRegexExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr, + val arg2: KExpr +) : KApp(ctx) { + override val sort: KStringSort = ctx.stringSort + + override val decl: KStringReplaceAllWithRegexDecl + get() = ctx.mkStringReplaceAllWithRegexDecl() + + override val args: List> + get() = listOf(arg0.cast(), arg1.cast(), arg2.cast()) + + override fun accept(transformer: KTransformerBase): KExpr { + TODO("Not yet implemented") + } + + override fun internHashCode(): Int = hash(arg0, arg1, arg2) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) +} + /* Maps to and from integers. */ From 7cfad2e418890b475eefec3270bf828009d2a689 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Mon, 9 Dec 2024 21:48:28 +0300 Subject: [PATCH 32/84] Implement remaining operations on strings and transformers for strings --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 75 +++++++++ .../src/main/kotlin/io/ksmt/decl/String.kt | 44 +++++- .../src/main/kotlin/io/ksmt/expr/String.kt | 147 ++++++++++-------- .../transformer/KNonRecursiveTransformer.kt | 142 +++++++++++++++++ .../expr/transformer/KNonRecursiveVisitor.kt | 93 +++++++++++ .../io/ksmt/expr/transformer/KTransformer.kt | 52 +++++++ .../ksmt/expr/transformer/KTransformerBase.kt | 53 ++++++- .../io/ksmt/expr/transformer/KVisitor.kt | 77 +++++++++ 8 files changed, 612 insertions(+), 71 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 572c2ba27..194c22b89 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -141,6 +141,9 @@ import io.ksmt.decl.KStringLeDecl import io.ksmt.decl.KStringGtDecl import io.ksmt.decl.KStringGeDecl import io.ksmt.decl.KStringContainsDecl +import io.ksmt.decl.KSingletonSubstringDecl +import io.ksmt.decl.KSubstringDecl +import io.ksmt.decl.KIndexOfDecl import io.ksmt.decl.KStringReplaceDecl import io.ksmt.decl.KStringReplaceAllDecl import io.ksmt.decl.KStringReplaceWithRegexDecl @@ -318,6 +321,9 @@ import io.ksmt.expr.KStringLeExpr import io.ksmt.expr.KStringGtExpr import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KStringContainsExpr +import io.ksmt.expr.KSingletonSubstringExpr +import io.ksmt.expr.KSubstringExpr +import io.ksmt.expr.KIndexOfExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr @@ -2175,6 +2181,69 @@ open class KContext( @JvmName("strContains") infix fun KExpr.contains(other: KExpr) = mkStringContains(this, other) + private val singletonSubstringCache = mkAstInterner() + + /** + * Returns singleton string containing a character at given position. + * If position is out of range (less than 0, or grater than (string length - 1)), then returns empty string. + * */ + open fun mkSingletonSubstring(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkSingletonSubstringNoSimplify, ::mkSingletonSubstringNoSimplify) // Add simplified version + + /** + * Returns singleton string containing a character at given position. + * If position is out of range (less than 0, or grater than (string length - 1)), then returns empty string. + * */ + open fun mkSingletonSubstringNoSimplify(arg0: KExpr, arg1: KExpr): KSingletonSubstringExpr = + singletonSubstringCache.createIfContextActive { + ensureContextMatch(arg0, arg1) + KSingletonSubstringExpr(this, arg0, arg1) + } + + private val substringCache = mkAstInterner() + + /** + * Evaluates the longest substring from the input string, starting at the specified position + * and extending up to the given length. Returns an empty string if the given length is negative + * or the given position is out of bounds. + */ + open fun mkSubstring(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = + mkSimplified(arg0, arg1, arg2, KContext::mkSubstringNoSimplify, ::mkSubstringNoSimplify) // Add simplified version + + /** + * Evaluates the longest substring from the input string, starting at the specified position + * and extending up to the given length. Returns an empty string if the given length is negative + * or the given position is out of bounds. + */ + open fun mkSubstringNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KSubstringExpr = + substringCache.createIfContextActive { + ensureContextMatch(arg0, arg1) + KSubstringExpr(this, arg0, arg1, arg2) + } + + private val indexOfCache = mkAstInterner() + + /** + * Find the index of the first occurrence of the second string in the first string, + * starting at the specified position. Returns -1 if not found + * or if the position is out of bounds. + * Returns the position if the second string is empty. + */ + open fun mkIndexOf(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = + mkSimplified(arg0, arg1, arg2, KContext::mkIndexOfNoSimplify, ::mkIndexOfNoSimplify) // Add simplified version + + /** + * Find the index of the first occurrence of the second string in the first string, + * starting at the specified position. Returns -1 if not found + * or if the position is out of bounds. + * Returns the position if the second string is empty. + */ + open fun mkIndexOfNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KIndexOfExpr = + indexOfCache.createIfContextActive { + ensureContextMatch(arg0, arg1) + KIndexOfExpr(this, arg0, arg1, arg2) + } + private val stringReplaceCache = mkAstInterner() /** @@ -5219,6 +5288,12 @@ open class KContext( fun mkStringContainsDecl(): KStringContainsDecl = KStringContainsDecl(this) + fun mkSingletonSubstringDecl(): KSingletonSubstringDecl = KSingletonSubstringDecl(this) + + fun mkSubstringDecl(): KSubstringDecl = KSubstringDecl(this) + + fun mkIndexOfDecl(): KIndexOfDecl = KIndexOfDecl(this) + fun mkStringReplaceDecl(): KStringReplaceDecl = KStringReplaceDecl(this) fun mkStringReplaceAllDecl(): KStringReplaceAllDecl = KStringReplaceAllDecl(this) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index dafeb8910..95ffed3b6 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -128,11 +128,49 @@ class KStringContainsDecl internal constructor(ctx: KContext) : override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } -class KSingletonSubstringDecl : RuntimeException("Not yet implemented") +class KSingletonSubstringDecl internal constructor(ctx: KContext) : + KFuncDecl2(ctx, "singleton_substr", ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkIntSort()) { + override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkSingletonSubstringNoSimplify(arg0, arg1) + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) +} + +class KSubstringDecl internal constructor( + ctx: KContext, +) : KFuncDecl3( + ctx, + name = "substr", + resultSort = ctx.mkStringSort(), + ctx.mkStringSort(), + ctx.mkIntSort(), + ctx.mkIntSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) -class KSubstringDecl : RuntimeException("Not yet implemented") + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KApp = mkSubstringNoSimplify(arg0, arg1, arg2) +} -class KIndexOfDecl : RuntimeException("Not yet implemented") +class KIndexOfDecl internal constructor( + ctx: KContext, +) : KFuncDecl3( + ctx, + name = "index_of", + resultSort = ctx.mkIntSort(), + ctx.mkStringSort(), + ctx.mkStringSort(), + ctx.mkIntSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KApp = mkIndexOfNoSimplify(arg0, arg1, arg2) +} class KStringReplaceDecl internal constructor( ctx: KContext, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index 403fe1f3e..e4e7409ed 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -13,6 +13,9 @@ import io.ksmt.decl.KStringGeDecl import io.ksmt.decl.KStringToRegexDecl import io.ksmt.decl.KStringInRegexDecl import io.ksmt.decl.KStringContainsDecl +import io.ksmt.decl.KSingletonSubstringDecl +import io.ksmt.decl.KSubstringDecl +import io.ksmt.decl.KIndexOfDecl import io.ksmt.decl.KStringReplaceDecl import io.ksmt.decl.KStringReplaceAllDecl import io.ksmt.decl.KStringReplaceWithRegexDecl @@ -40,9 +43,7 @@ class KStringLiteralExpr internal constructor( override val decl: KStringLiteralDecl get() = ctx.mkStringLiteralDecl(value) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(value) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { value } @@ -59,9 +60,7 @@ class KStringConcatExpr internal constructor( override val decl: KDecl get() = ctx.mkStringConcatDecl() - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override val sort: KStringSort = ctx.mkStringSort() @@ -81,9 +80,7 @@ class KStringLenExpr internal constructor( override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -101,9 +98,7 @@ class KStringToRegexExpr internal constructor( override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -122,9 +117,7 @@ class KStringInRegexExpr internal constructor( override val decl: KStringInRegexDecl get() = ctx.mkStringInRegexDecl() - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) @@ -143,9 +136,7 @@ class KSuffixOfExpr internal constructor( override val decl: KDecl get() = ctx.mkSuffixOfDecl() - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) @@ -164,9 +155,7 @@ class KPrefixOfExpr internal constructor( override val decl: KDecl get() = ctx.mkPrefixOfDecl() - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) @@ -185,9 +174,7 @@ class KStringLtExpr internal constructor( override val args: List> get() = listOf(lhs, rhs) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(lhs, rhs) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) @@ -206,9 +193,7 @@ class KStringLeExpr internal constructor( override val args: List> get() = listOf(lhs, rhs) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(lhs, rhs) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) @@ -227,9 +212,7 @@ class KStringGtExpr internal constructor( override val args: List> get() = listOf(lhs, rhs) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(lhs, rhs) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) @@ -248,9 +231,7 @@ class KStringGeExpr internal constructor( override val args: List> get() = listOf(lhs, rhs) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(lhs, rhs) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) @@ -269,19 +250,70 @@ class KStringContainsExpr internal constructor( override val args: List> get() = listOf(lhs, rhs) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(lhs, rhs) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) } -class KSingletonSubstringExpr : RuntimeException("Not yet implemented") +class KSingletonSubstringExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr +) : KApp(ctx) { + override val sort: KStringSort = ctx.stringSort + + override val decl: KSingletonSubstringDecl + get() = ctx.mkSingletonSubstringDecl() + + override val args: List> + get() = listOf(arg0.cast(), arg1.cast()) + + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) +} + +class KSubstringExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr, + val arg2: KExpr +) : KApp(ctx) { + override val sort: KStringSort = ctx.stringSort + + override val decl: KSubstringDecl + get() = ctx.mkSubstringDecl() + + override val args: List> + get() = listOf(arg0.cast(), arg1.cast(), arg2.cast()) + + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + + override fun internHashCode(): Int = hash(arg0, arg1, arg2) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) +} + +class KIndexOfExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr, + val arg2: KExpr +) : KApp(ctx) { + override val sort: KIntSort = ctx.intSort + + override val decl: KIndexOfDecl + get() = ctx.mkIndexOfDecl() + + override val args: List> + get() = listOf(arg0.cast(), arg1.cast(), arg2.cast()) -class KSubstringExpr : RuntimeException("Not yet implemented") + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) -class KIndexOfExpr : RuntimeException("Not yet implemented") + override fun internHashCode(): Int = hash(arg0, arg1, arg2) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) +} class KStringReplaceExpr internal constructor( ctx: KContext, @@ -297,9 +329,7 @@ class KStringReplaceExpr internal constructor( override val args: List> get() = listOf(arg0, arg1, arg2) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1, arg2) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) @@ -319,9 +349,7 @@ class KStringReplaceAllExpr internal constructor( override val args: List> get() = listOf(arg0, arg1, arg2) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1, arg2) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) @@ -341,9 +369,7 @@ class KStringReplaceWithRegexExpr internal constructor( override val args: List> get() = listOf(arg0.cast(), arg1.cast(), arg2.cast()) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1, arg2) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) @@ -363,9 +389,7 @@ class KStringReplaceAllWithRegexExpr internal constructor( override val args: List> get() = listOf(arg0.cast(), arg1.cast(), arg2.cast()) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1, arg2) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) @@ -387,9 +411,7 @@ class KStringIsDigitExpr internal constructor( override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -407,9 +429,7 @@ class KStringToCodeExpr internal constructor( override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -427,9 +447,7 @@ class KStringFromCodeExpr internal constructor( override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -447,9 +465,7 @@ class KStringToIntExpr internal constructor( override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -467,10 +483,7 @@ class KStringFromIntExpr internal constructor( override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } - + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } } diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt index 5d5b1a272..e20ea240f 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt @@ -124,6 +124,30 @@ import io.ksmt.expr.KToRealIntExpr import io.ksmt.expr.KUnaryMinusArithExpr import io.ksmt.expr.KUniversalQuantifier import io.ksmt.expr.KXorExpr +import io.ksmt.expr.KStringConcatExpr +import io.ksmt.expr.KStringLenExpr +import io.ksmt.expr.KStringToRegexExpr +import io.ksmt.expr.KStringInRegexExpr +import io.ksmt.expr.KSuffixOfExpr +import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringLtExpr +import io.ksmt.expr.KStringLeExpr +import io.ksmt.expr.KStringGtExpr +import io.ksmt.expr.KStringGeExpr +import io.ksmt.expr.KStringContainsExpr +import io.ksmt.expr.KSingletonSubstringExpr +import io.ksmt.expr.KSubstringExpr +import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringReplaceExpr +import io.ksmt.expr.KStringReplaceAllExpr +import io.ksmt.expr.KStringReplaceWithRegexExpr +import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringIsDigitExpr +import io.ksmt.expr.KStringToCodeExpr +import io.ksmt.expr.KStringFromCodeExpr +import io.ksmt.expr.KStringToIntExpr +import io.ksmt.expr.KStringFromIntExpr +import io.ksmt.expr.KStringLiteralExpr import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -136,6 +160,8 @@ import io.ksmt.sort.KBvSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.utils.uncheckedCast @@ -661,6 +687,122 @@ abstract class KNonRecursiveTransformer(override val ctx: KContext) : KNonRecurs override fun transform(expr: KIsIntRealExpr): KExpr = transformExprAfterTransformedDefault(expr, expr.arg, ::transformApp, KContext::mkRealIsInt) + // string transformers + override fun transform(expr: KStringConcatExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkStringConcat + ) + + override fun transform(expr: KStringLenExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkStringLen + ) + + override fun transform(expr: KStringToRegexExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkStringToRegex + ) + + override fun transform(expr: KStringInRegexExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkStringInRegex + ) + + override fun transform(expr: KSuffixOfExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkSuffixOf + ) + + override fun transform(expr: KPrefixOfExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkPrefixOf + ) + + override fun transform(expr: KStringLtExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.lhs, expr.rhs, ::transformApp, KContext::mkStringLt + ) + + override fun transform(expr: KStringLeExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.lhs, expr.rhs, ::transformApp, KContext::mkStringLe + ) + + override fun transform(expr: KStringGtExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.lhs, expr.rhs, ::transformApp, KContext::mkStringGt + ) + + override fun transform(expr: KStringGeExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.lhs, expr.rhs, ::transformApp, KContext::mkStringGe + ) + + override fun transform(expr: KStringContainsExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.lhs, expr.rhs, ::transformApp, KContext::mkStringContains + ) + + override fun transform(expr: KSingletonSubstringExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkSingletonSubstring + ) + + override fun transform(expr: KSubstringExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkSubstring + ) + + override fun transform(expr: KIndexOfExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkIndexOf + ) + + override fun transform(expr: KStringReplaceExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkStringReplace + ) + + override fun transform(expr: KStringReplaceAllExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkStringReplaceAll + ) + + override fun transform(expr: KStringReplaceWithRegexExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkStringReplaceWithRegex + ) + + override fun transform(expr: KStringReplaceAllWithRegexExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkStringReplaceAllWithRegex + ) + + override fun transform(expr: KStringIsDigitExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkStringIsDigit + ) + + override fun transform(expr: KStringToCodeExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkStringToCode + ) + + override fun transform(expr: KStringFromCodeExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkStringFromCode + ) + + override fun transform(expr: KStringToIntExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkStringToCode + ) + + override fun transform(expr: KStringFromIntExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkStringFromCode + ) + // quantified expressions override fun transform(expr: KExistentialQuantifier): KExpr = transformExprAfterTransformedDefault(expr, expr.body, ::transformExpr) { body -> diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt index 35bd4d57b..1f809897d 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt @@ -124,6 +124,29 @@ import io.ksmt.expr.KToRealIntExpr import io.ksmt.expr.KUnaryMinusArithExpr import io.ksmt.expr.KUniversalQuantifier import io.ksmt.expr.KXorExpr +import io.ksmt.expr.KStringConcatExpr +import io.ksmt.expr.KStringLenExpr +import io.ksmt.expr.KStringToRegexExpr +import io.ksmt.expr.KStringInRegexExpr +import io.ksmt.expr.KSuffixOfExpr +import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringLtExpr +import io.ksmt.expr.KStringLeExpr +import io.ksmt.expr.KStringGtExpr +import io.ksmt.expr.KStringGeExpr +import io.ksmt.expr.KStringContainsExpr +import io.ksmt.expr.KSingletonSubstringExpr +import io.ksmt.expr.KSubstringExpr +import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringReplaceExpr +import io.ksmt.expr.KStringReplaceAllExpr +import io.ksmt.expr.KStringReplaceWithRegexExpr +import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringIsDigitExpr +import io.ksmt.expr.KStringToCodeExpr +import io.ksmt.expr.KStringFromCodeExpr +import io.ksmt.expr.KStringToIntExpr +import io.ksmt.expr.KStringFromIntExpr import io.ksmt.sort.KArithSort import io.ksmt.sort.KArraySortBase import io.ksmt.sort.KBvSort @@ -629,6 +652,76 @@ abstract class KNonRecursiveVisitor( override fun visit(expr: KIsIntRealExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + // string visitors + override fun visit(expr: KStringConcatExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) + + override fun visit(expr: KStringLenExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + + override fun visit(expr: KStringToRegexExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + + override fun visit(expr: KStringInRegexExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) + + override fun visit(expr: KSuffixOfExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) + + override fun visit(expr: KPrefixOfExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) + + override fun visit(expr: KStringLtExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.lhs, expr.rhs, ::visitApp) + + override fun visit(expr: KStringLeExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.lhs, expr.rhs, ::visitApp) + + override fun visit(expr: KStringGtExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.lhs, expr.rhs, ::visitApp) + + override fun visit(expr: KStringGeExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.lhs, expr.rhs, ::visitApp) + + override fun visit(expr: KStringContainsExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.lhs, expr.rhs, ::visitApp) + + override fun visit(expr: KSingletonSubstringExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) + + override fun visit(expr: KSubstringExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, expr.arg2, ::visitApp) + + override fun visit(expr: KIndexOfExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, expr.arg2, ::visitApp) + + override fun visit(expr: KStringReplaceExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, expr.arg2, ::visitApp) + + override fun visit(expr: KStringReplaceAllExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, expr.arg2, ::visitApp) + + override fun visit(expr: KStringReplaceWithRegexExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, expr.arg2, ::visitApp) + + override fun visit(expr: KStringReplaceAllWithRegexExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, expr.arg2, ::visitApp) + + override fun visit(expr: KStringIsDigitExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + + override fun visit(expr: KStringToCodeExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + + override fun visit(expr: KStringFromCodeExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + + override fun visit(expr: KStringToIntExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + + override fun visit(expr: KStringFromIntExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + // quantified expressions override fun visit(expr: KExistentialQuantifier): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.body, ::visitExpr) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt index dc68dd567..ad82ae6bf 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt @@ -150,6 +150,30 @@ import io.ksmt.expr.KUnaryMinusArithExpr import io.ksmt.expr.KUninterpretedSortValue import io.ksmt.expr.KUniversalQuantifier import io.ksmt.expr.KXorExpr +import io.ksmt.expr.KStringConcatExpr +import io.ksmt.expr.KStringLenExpr +import io.ksmt.expr.KStringToRegexExpr +import io.ksmt.expr.KStringInRegexExpr +import io.ksmt.expr.KSuffixOfExpr +import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringLtExpr +import io.ksmt.expr.KStringLeExpr +import io.ksmt.expr.KStringGtExpr +import io.ksmt.expr.KStringGeExpr +import io.ksmt.expr.KStringContainsExpr +import io.ksmt.expr.KSingletonSubstringExpr +import io.ksmt.expr.KSubstringExpr +import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringReplaceExpr +import io.ksmt.expr.KStringReplaceAllExpr +import io.ksmt.expr.KStringReplaceWithRegexExpr +import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringIsDigitExpr +import io.ksmt.expr.KStringToCodeExpr +import io.ksmt.expr.KStringFromCodeExpr +import io.ksmt.expr.KStringToIntExpr +import io.ksmt.expr.KStringFromIntExpr +import io.ksmt.expr.KStringLiteralExpr import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -171,6 +195,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KUninterpretedSort @@ -412,6 +438,32 @@ interface KTransformer : KTransformerBase { override fun transform(expr: KIsIntRealExpr): KExpr = transformApp(expr) override fun transform(expr: KRealNumExpr): KExpr = transformValue(expr) + // string transformers + override fun transform(expr: KStringConcatExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringLenExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringToRegexExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringInRegexExpr): KExpr = transformApp(expr) + override fun transform(expr: KSuffixOfExpr): KExpr = transformApp(expr) + override fun transform(expr: KPrefixOfExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringLtExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringLeExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringGtExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringGeExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringContainsExpr): KExpr = transformApp(expr) + override fun transform(expr: KSingletonSubstringExpr): KExpr = transformApp(expr) + override fun transform(expr: KSubstringExpr): KExpr = transformApp(expr) + override fun transform(expr: KIndexOfExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringReplaceExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringReplaceAllExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringReplaceWithRegexExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringReplaceAllWithRegexExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringIsDigitExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringToCodeExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringFromCodeExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringToIntExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringFromIntExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringLiteralExpr): KExpr = transformValue(expr) + // quantifier transformers override fun transform(expr: KExistentialQuantifier): KExpr = with(ctx) { val body = expr.body.accept(this@KTransformer) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt index 8178548b6..5f2eb694f 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt @@ -141,6 +141,30 @@ import io.ksmt.expr.KUnaryMinusArithExpr import io.ksmt.expr.KUninterpretedSortValue import io.ksmt.expr.KUniversalQuantifier import io.ksmt.expr.KXorExpr +import io.ksmt.expr.KStringConcatExpr +import io.ksmt.expr.KStringLenExpr +import io.ksmt.expr.KStringToRegexExpr +import io.ksmt.expr.KStringInRegexExpr +import io.ksmt.expr.KSuffixOfExpr +import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringLtExpr +import io.ksmt.expr.KStringLeExpr +import io.ksmt.expr.KStringGtExpr +import io.ksmt.expr.KStringGeExpr +import io.ksmt.expr.KStringContainsExpr +import io.ksmt.expr.KSingletonSubstringExpr +import io.ksmt.expr.KSubstringExpr +import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringReplaceExpr +import io.ksmt.expr.KStringReplaceAllExpr +import io.ksmt.expr.KStringReplaceWithRegexExpr +import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringIsDigitExpr +import io.ksmt.expr.KStringToCodeExpr +import io.ksmt.expr.KStringFromCodeExpr +import io.ksmt.expr.KStringToIntExpr +import io.ksmt.expr.KStringFromIntExpr +import io.ksmt.expr.KStringLiteralExpr import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -162,10 +186,11 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KUninterpretedSort - interface KTransformerBase { fun apply(expr: KExpr): KExpr = expr.accept(this) @@ -341,6 +366,32 @@ interface KTransformerBase { fun transform(expr: KIsIntRealExpr): KExpr fun transform(expr: KRealNumExpr): KExpr + // string transformers + fun transform(expr: KStringConcatExpr): KExpr + fun transform(expr: KStringLenExpr): KExpr + fun transform(expr: KStringToRegexExpr): KExpr + fun transform(expr: KStringInRegexExpr): KExpr + fun transform(expr: KSuffixOfExpr): KExpr + fun transform(expr: KPrefixOfExpr): KExpr + fun transform(expr: KStringLtExpr): KExpr + fun transform(expr: KStringLeExpr): KExpr + fun transform(expr: KStringGtExpr): KExpr + fun transform(expr: KStringGeExpr): KExpr + fun transform(expr: KStringContainsExpr): KExpr + fun transform(expr: KSingletonSubstringExpr): KExpr + fun transform(expr: KSubstringExpr): KExpr + fun transform(expr: KIndexOfExpr): KExpr + fun transform(expr: KStringReplaceExpr): KExpr + fun transform(expr: KStringReplaceAllExpr): KExpr + fun transform(expr: KStringReplaceWithRegexExpr): KExpr + fun transform(expr: KStringReplaceAllWithRegexExpr): KExpr + fun transform(expr: KStringIsDigitExpr): KExpr + fun transform(expr: KStringToCodeExpr): KExpr + fun transform(expr: KStringFromCodeExpr): KExpr + fun transform(expr: KStringToIntExpr): KExpr + fun transform(expr: KStringFromIntExpr): KExpr + fun transform(expr: KStringLiteralExpr): KExpr + // quantifier transformers fun transform(expr: KExistentialQuantifier): KExpr fun transform(expr: KUniversalQuantifier): KExpr diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt index 3f114a9e1..b215b360f 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt @@ -149,6 +149,30 @@ import io.ksmt.expr.KUnaryMinusArithExpr import io.ksmt.expr.KUninterpretedSortValue import io.ksmt.expr.KUniversalQuantifier import io.ksmt.expr.KXorExpr +import io.ksmt.expr.KStringConcatExpr +import io.ksmt.expr.KStringLenExpr +import io.ksmt.expr.KStringToRegexExpr +import io.ksmt.expr.KStringInRegexExpr +import io.ksmt.expr.KSuffixOfExpr +import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringLtExpr +import io.ksmt.expr.KStringLeExpr +import io.ksmt.expr.KStringGtExpr +import io.ksmt.expr.KStringGeExpr +import io.ksmt.expr.KStringContainsExpr +import io.ksmt.expr.KSingletonSubstringExpr +import io.ksmt.expr.KSubstringExpr +import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringReplaceExpr +import io.ksmt.expr.KStringReplaceAllExpr +import io.ksmt.expr.KStringReplaceWithRegexExpr +import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringIsDigitExpr +import io.ksmt.expr.KStringToCodeExpr +import io.ksmt.expr.KStringFromCodeExpr +import io.ksmt.expr.KStringToIntExpr +import io.ksmt.expr.KStringFromIntExpr +import io.ksmt.expr.KStringLiteralExpr import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -170,6 +194,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KUninterpretedSort @@ -614,6 +640,57 @@ interface KVisitor : KTransformer { override fun transform(expr: KIsIntRealExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KRealNumExpr): KExpr = visitExpr(expr, ::visit) + // string visitors + fun visit(expr: KStringConcatExpr): V = visitApp(expr) + fun visit(expr: KStringLenExpr): V = visitApp(expr) + fun visit(expr: KStringToRegexExpr): V = visitApp(expr) + fun visit(expr: KStringInRegexExpr): V = visitApp(expr) + fun visit(expr: KSuffixOfExpr): V = visitApp(expr) + fun visit(expr: KPrefixOfExpr): V = visitApp(expr) + fun visit(expr: KStringLtExpr): V = visitApp(expr) + fun visit(expr: KStringLeExpr): V = visitApp(expr) + fun visit(expr: KStringGtExpr): V = visitApp(expr) + fun visit(expr: KStringGeExpr): V = visitApp(expr) + fun visit(expr: KStringContainsExpr): V = visitApp(expr) + fun visit(expr: KSingletonSubstringExpr): V = visitApp(expr) + fun visit(expr: KSubstringExpr): V = visitApp(expr) + fun visit(expr: KIndexOfExpr): V = visitApp(expr) + fun visit(expr: KStringReplaceExpr): V = visitApp(expr) + fun visit(expr: KStringReplaceAllExpr): V = visitApp(expr) + fun visit(expr: KStringReplaceWithRegexExpr): V = visitApp(expr) + fun visit(expr: KStringReplaceAllWithRegexExpr): V = visitApp(expr) + fun visit(expr: KStringIsDigitExpr): V = visitApp(expr) + fun visit(expr: KStringToCodeExpr): V = visitApp(expr) + fun visit(expr: KStringFromCodeExpr): V = visitApp(expr) + fun visit(expr: KStringToIntExpr): V = visitApp(expr) + fun visit(expr: KStringFromIntExpr): V = visitApp(expr) + fun visit(expr: KStringLiteralExpr): V = visitValue(expr) + + override fun transform(expr: KStringConcatExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringLenExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringToRegexExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringInRegexExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KSuffixOfExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KPrefixOfExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringLtExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringLeExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringGtExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringGeExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringContainsExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KSingletonSubstringExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KSubstringExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KIndexOfExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringReplaceExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringReplaceAllExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringReplaceWithRegexExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringReplaceAllWithRegexExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringIsDigitExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringToCodeExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringFromCodeExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringToIntExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringFromIntExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringLiteralExpr): KExpr = visitExpr(expr, ::visit) + // quantifier visitors fun visit(expr: KExistentialQuantifier): V = visitExpr(expr) fun visit(expr: KUniversalQuantifier): V = visitExpr(expr) From 98f82c90a70e82d445ab6674c76b9ccd2d5e76d9 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Mon, 9 Dec 2024 22:41:00 +0300 Subject: [PATCH 33/84] Describe and implement transformers interfaces for regex --- .../src/main/kotlin/io/ksmt/expr/Regex.kt | 52 +++++------------ .../transformer/KNonRecursiveTransformer.kt | 56 ++++++++++++++++++- .../expr/transformer/KNonRecursiveVisitor.kt | 37 ++++++++++++ .../io/ksmt/expr/transformer/KTransformer.kt | 28 ++++++++++ .../ksmt/expr/transformer/KTransformerBase.kt | 28 ++++++++++ .../io/ksmt/expr/transformer/KVisitor.kt | 42 ++++++++++++++ 6 files changed, 203 insertions(+), 40 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index 0233547c4..027e46357 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -26,9 +26,7 @@ class KRegexLiteralExpr internal constructor( override val decl: KRegexLiteralDecl get() = ctx.mkRegexLiteralDecl(value) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(value) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { value } @@ -45,9 +43,7 @@ class KRegexConcatExpr internal constructor( override val decl: KDecl get() = ctx.mkRegexConcatDecl() - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override val sort: KRegexSort = ctx.mkRegexSort() @@ -66,9 +62,7 @@ class KRegexUnionExpr internal constructor( override val decl: KDecl get() = ctx.mkRegexUnionDecl() - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override val sort: KRegexSort = ctx.mkRegexSort() @@ -87,9 +81,7 @@ class KRegexIntersectionExpr internal constructor( override val decl: KDecl get() = ctx.mkRegexIntersectionDecl() - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override val sort: KRegexSort = ctx.mkRegexSort() @@ -109,9 +101,7 @@ class KRegexKleeneClosureExpr internal constructor( override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -129,9 +119,7 @@ class KRegexKleeneCrossExpr internal constructor( override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -148,9 +136,7 @@ class KRegexDifferenceExpr internal constructor( override val decl: KDecl get() = ctx.mkRegexDifferenceDecl() - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override val sort: KRegexSort = ctx.mkRegexSort() @@ -170,9 +156,7 @@ class KRegexComplementExpr internal constructor( override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -190,9 +174,7 @@ class KRegexOptionExpr internal constructor( override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -205,9 +187,7 @@ class KEpsilon(ctx: KContext) : KInterpretedValue(ctx) { override val decl: KEpsilonDecl get() = ctx.mkEpsilonDecl() - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash() override fun internEquals(other: Any): Boolean = structurallyEqual(other) @@ -219,9 +199,7 @@ class KAll(ctx: KContext) : KInterpretedValue(ctx) { override val decl: KAllDecl get() = ctx.mkAllDecl() - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash() override fun internEquals(other: Any): Boolean = structurallyEqual(other) @@ -233,9 +211,7 @@ class KAllChar(ctx: KContext) : KInterpretedValue(ctx) { override val decl: KAllCharDecl get() = ctx.mkAllCharDecl() - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash() override fun internEquals(other: Any): Boolean = structurallyEqual(other) @@ -252,9 +228,7 @@ class KRangeExpr internal constructor( override val decl: KDecl get() = ctx.mkRangeDecl() - override fun accept(transformer: KTransformerBase): KExpr { - TODO("Not yet implemented") - } + override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override val sort: KRegexSort = ctx.mkRegexSort() diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt index e20ea240f..ea19bac06 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt @@ -147,7 +147,15 @@ import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr import io.ksmt.expr.KStringToIntExpr import io.ksmt.expr.KStringFromIntExpr -import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.KRegexConcatExpr +import io.ksmt.expr.KRegexUnionExpr +import io.ksmt.expr.KRegexIntersectionExpr +import io.ksmt.expr.KRegexKleeneClosureExpr +import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexDifferenceExpr +import io.ksmt.expr.KRegexComplementExpr +import io.ksmt.expr.KRegexOptionExpr +import io.ksmt.expr.KRangeExpr import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -803,6 +811,52 @@ abstract class KNonRecursiveTransformer(override val ctx: KContext) : KNonRecurs expr, expr.arg, ::transformApp, KContext::mkStringFromCode ) + // regex transformers + override fun transform(expr: KRegexConcatExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkRegexConcat + ) + + override fun transform(expr: KRegexUnionExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkRegexUnion + ) + + override fun transform(expr: KRegexIntersectionExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkRegexIntersection + ) + + override fun transform(expr: KRegexKleeneClosureExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkRegexKleeneClosure + ) + + override fun transform(expr: KRegexKleeneCrossExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkRegexKleeneCross + ) + + override fun transform(expr: KRegexDifferenceExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkRegexDifference + ) + + override fun transform(expr: KRegexComplementExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkRegexComplement + ) + + override fun transform(expr: KRegexOptionExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkRegexOption + ) + + override fun transform(expr: KRangeExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkRange + ) + // quantified expressions override fun transform(expr: KExistentialQuantifier): KExpr = transformExprAfterTransformedDefault(expr, expr.body, ::transformExpr) { body -> diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt index 1f809897d..8bd71a93a 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt @@ -147,6 +147,15 @@ import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr import io.ksmt.expr.KStringToIntExpr import io.ksmt.expr.KStringFromIntExpr +import io.ksmt.expr.KRegexConcatExpr +import io.ksmt.expr.KRegexUnionExpr +import io.ksmt.expr.KRegexIntersectionExpr +import io.ksmt.expr.KRegexKleeneClosureExpr +import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexDifferenceExpr +import io.ksmt.expr.KRegexComplementExpr +import io.ksmt.expr.KRegexOptionExpr +import io.ksmt.expr.KRangeExpr import io.ksmt.sort.KArithSort import io.ksmt.sort.KArraySortBase import io.ksmt.sort.KBvSort @@ -722,6 +731,34 @@ abstract class KNonRecursiveVisitor( override fun visit(expr: KStringFromIntExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + // regex visitors + override fun visit(expr: KRegexConcatExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) + + override fun visit(expr: KRegexUnionExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) + + override fun visit(expr: KRegexIntersectionExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) + + override fun visit(expr: KRegexKleeneClosureExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + + override fun visit(expr: KRegexKleeneCrossExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + + override fun visit(expr: KRegexDifferenceExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) + + override fun visit(expr: KRegexComplementExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + + override fun visit(expr: KRegexOptionExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + + override fun visit(expr: KRangeExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) + // quantified expressions override fun visit(expr: KExistentialQuantifier): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.body, ::visitExpr) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt index ad82ae6bf..4e2739a8e 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt @@ -174,6 +174,19 @@ import io.ksmt.expr.KStringFromCodeExpr import io.ksmt.expr.KStringToIntExpr import io.ksmt.expr.KStringFromIntExpr import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.KRegexConcatExpr +import io.ksmt.expr.KRegexUnionExpr +import io.ksmt.expr.KRegexIntersectionExpr +import io.ksmt.expr.KRegexKleeneClosureExpr +import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexDifferenceExpr +import io.ksmt.expr.KRegexComplementExpr +import io.ksmt.expr.KRegexOptionExpr +import io.ksmt.expr.KRangeExpr +import io.ksmt.expr.KRegexLiteralExpr +import io.ksmt.expr.KEpsilon +import io.ksmt.expr.KAll +import io.ksmt.expr.KAllChar import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -464,6 +477,21 @@ interface KTransformer : KTransformerBase { override fun transform(expr: KStringFromIntExpr): KExpr = transformApp(expr) override fun transform(expr: KStringLiteralExpr): KExpr = transformValue(expr) + // regex transformers + override fun transform(expr: KRegexConcatExpr): KExpr = transformApp(expr) + override fun transform(expr: KRegexUnionExpr): KExpr = transformApp(expr) + override fun transform(expr: KRegexIntersectionExpr): KExpr = transformApp(expr) + override fun transform(expr: KRegexKleeneClosureExpr): KExpr = transformApp(expr) + override fun transform(expr: KRegexKleeneCrossExpr): KExpr = transformApp(expr) + override fun transform(expr: KRegexDifferenceExpr): KExpr = transformApp(expr) + override fun transform(expr: KRegexComplementExpr): KExpr = transformApp(expr) + override fun transform(expr: KRegexOptionExpr): KExpr = transformApp(expr) + override fun transform(expr: KRangeExpr): KExpr = transformApp(expr) + override fun transform(expr: KRegexLiteralExpr): KExpr = transformValue(expr) + override fun transform(expr: KEpsilon): KExpr = transformValue(expr) + override fun transform(expr: KAll): KExpr = transformValue(expr) + override fun transform(expr: KAllChar): KExpr = transformValue(expr) + // quantifier transformers override fun transform(expr: KExistentialQuantifier): KExpr = with(ctx) { val body = expr.body.accept(this@KTransformer) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt index 5f2eb694f..ace65fd42 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt @@ -165,6 +165,19 @@ import io.ksmt.expr.KStringFromCodeExpr import io.ksmt.expr.KStringToIntExpr import io.ksmt.expr.KStringFromIntExpr import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.KRegexConcatExpr +import io.ksmt.expr.KRegexUnionExpr +import io.ksmt.expr.KRegexIntersectionExpr +import io.ksmt.expr.KRegexKleeneClosureExpr +import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexDifferenceExpr +import io.ksmt.expr.KRegexComplementExpr +import io.ksmt.expr.KRegexOptionExpr +import io.ksmt.expr.KRangeExpr +import io.ksmt.expr.KRegexLiteralExpr +import io.ksmt.expr.KEpsilon +import io.ksmt.expr.KAll +import io.ksmt.expr.KAllChar import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -392,6 +405,21 @@ interface KTransformerBase { fun transform(expr: KStringFromIntExpr): KExpr fun transform(expr: KStringLiteralExpr): KExpr + // regex transformers + fun transform(expr: KRegexConcatExpr): KExpr + fun transform(expr: KRegexUnionExpr): KExpr + fun transform(expr: KRegexIntersectionExpr): KExpr + fun transform(expr: KRegexKleeneClosureExpr): KExpr + fun transform(expr: KRegexKleeneCrossExpr): KExpr + fun transform(expr: KRegexDifferenceExpr): KExpr + fun transform(expr: KRegexComplementExpr): KExpr + fun transform(expr: KRegexOptionExpr): KExpr + fun transform(expr: KRangeExpr): KExpr + fun transform(expr: KRegexLiteralExpr): KExpr + fun transform(expr: KEpsilon): KExpr + fun transform(expr: KAll): KExpr + fun transform(expr: KAllChar): KExpr + // quantifier transformers fun transform(expr: KExistentialQuantifier): KExpr fun transform(expr: KUniversalQuantifier): KExpr diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt index b215b360f..286d4fb3c 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt @@ -173,6 +173,19 @@ import io.ksmt.expr.KStringFromCodeExpr import io.ksmt.expr.KStringToIntExpr import io.ksmt.expr.KStringFromIntExpr import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.KRegexConcatExpr +import io.ksmt.expr.KRegexUnionExpr +import io.ksmt.expr.KRegexIntersectionExpr +import io.ksmt.expr.KRegexKleeneClosureExpr +import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexDifferenceExpr +import io.ksmt.expr.KRegexComplementExpr +import io.ksmt.expr.KRegexOptionExpr +import io.ksmt.expr.KRangeExpr +import io.ksmt.expr.KRegexLiteralExpr +import io.ksmt.expr.KEpsilon +import io.ksmt.expr.KAll +import io.ksmt.expr.KAllChar import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -691,6 +704,35 @@ interface KVisitor : KTransformer { override fun transform(expr: KStringFromIntExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringLiteralExpr): KExpr = visitExpr(expr, ::visit) + // regex visitors + fun visit(expr: KRegexConcatExpr): V = visitApp(expr) + fun visit(expr: KRegexUnionExpr): V = visitApp(expr) + fun visit(expr: KRegexIntersectionExpr): V = visitApp(expr) + fun visit(expr: KRegexKleeneClosureExpr): V = visitApp(expr) + fun visit(expr: KRegexKleeneCrossExpr): V = visitApp(expr) + fun visit(expr: KRegexDifferenceExpr): V = visitApp(expr) + fun visit(expr: KRegexComplementExpr): V = visitApp(expr) + fun visit(expr: KRegexOptionExpr): V = visitApp(expr) + fun visit(expr: KRangeExpr): V = visitApp(expr) + fun visit(expr: KRegexLiteralExpr): V = visitValue(expr) + fun visit(expr: KEpsilon): V = visitValue(expr) + fun visit(expr: KAll): V = visitValue(expr) + fun visit(expr: KAllChar): V = visitValue(expr) + + override fun transform(expr: KRegexConcatExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexUnionExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexIntersectionExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexKleeneClosureExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexKleeneCrossExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexDifferenceExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexComplementExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexOptionExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRangeExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexLiteralExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KEpsilon): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KAll): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KAllChar): KExpr = visitExpr(expr, ::visit) + // quantifier visitors fun visit(expr: KExistentialQuantifier): V = visitExpr(expr) fun visit(expr: KUniversalQuantifier): V = visitExpr(expr) From 8e0fafb06e089748312e01c3e8fdc421171c6114 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Mon, 9 Dec 2024 23:00:16 +0300 Subject: [PATCH 34/84] Add string and regex declarations in visitor --- .../main/kotlin/io/ksmt/decl/KDeclVisitor.kt | 41 +++++++++++++++++++ .../src/main/kotlin/io/ksmt/decl/Regex.kt | 38 ++++++++--------- 2 files changed, 58 insertions(+), 21 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt index 2f162efdd..b90a38454 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt @@ -15,6 +15,8 @@ import io.ksmt.sort.KBv8Sort import io.ksmt.sort.KBvSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort interface KDeclVisitor { @@ -131,4 +133,43 @@ interface KDeclVisitor { fun visit(decl: KBvNegNoOverflowDecl): T = visit(decl as KFuncDecl) fun visit(decl: KBvMulNoOverflowDecl): T = visit(decl as KFuncDecl) fun visit(decl: KBvMulNoUnderflowDecl): T = visit(decl as KFuncDecl) + + fun visit(decl: KStringConcatDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringLenDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringToRegexDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringInRegexDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KSuffixOfDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KPrefixOfDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringLtDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringLeDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringGtDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringGeDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringContainsDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KSingletonSubstringDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KSubstringDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KIndexOfDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringReplaceDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringReplaceAllDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringReplaceWithRegexDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringReplaceAllWithRegexDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringIsDigitDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringToCodeDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringFromCodeDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringToIntDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringFromIntDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringLiteralDecl): T = visit(decl as KConstDecl) + + fun visit(decl: KRegexConcatDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRegexUnionDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRegexIntersectionDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRegexKleeneClosureDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRegexKleeneCrossDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRegexDifferenceDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRegexComplementDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRegexOptionDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRangeDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRegexLiteralDecl): T = visit(decl as KConstDecl) + fun visit(decl: KEpsilonDecl): T = visit(decl as KConstDecl) + fun visit(decl: KAllDecl): T = visit(decl as KConstDecl) + fun visit(decl: KAllCharDecl): T = visit(decl as KConstDecl) } diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index 82e644be4..fc9faa920 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -110,6 +110,23 @@ class KRegexOptionDecl internal constructor( override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } +class KRangeDecl internal constructor( + ctx: KContext, +) : KFuncDecl2( + ctx, + name = "range", + resultSort = ctx.mkRegexSort(), + ctx.mkStringSort(), + ctx.mkStringSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkRangeNoSimplify(arg0, arg1) +} + class KEpsilonDecl internal constructor( ctx: KContext ) : KConstDecl(ctx, "eps", ctx.mkRegexSort()) { @@ -130,24 +147,3 @@ class KAllCharDecl internal constructor( override fun apply(args: List>): KApp = ctx.mkAllChar() override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) } - -class KRangeDecl internal constructor( - ctx: KContext, -) : KFuncDecl2( - ctx, - name = "range", - resultSort = ctx.mkRegexSort(), - ctx.mkStringSort(), - ctx.mkStringSort() -) { - override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) - - override fun KContext.apply( - arg0: KExpr, - arg1: KExpr - ): KApp = mkRangeNoSimplify(arg0, arg1) -} - -class KRegexReplaceDecl : RuntimeException("Not yet implemented") - -class KRegexReplaceAllDecl : RuntimeException("Not yet implemented") From 889642f2eaed33474fbb765af73af5333e543f57 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Mon, 9 Dec 2024 23:33:31 +0300 Subject: [PATCH 35/84] Add exceptions that Bitwuzla does not support string theory --- .../ksmt/solver/bitwuzla/KBitwuzlaContext.kt | 9 + .../bitwuzla/KBitwuzlaExprInternalizer.kt | 197 +++++++++++++++++- 2 files changed, 205 insertions(+), 1 deletion(-) diff --git a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaContext.kt b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaContext.kt index 5fb618e35..91cd8148f 100644 --- a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaContext.kt +++ b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaContext.kt @@ -18,6 +18,7 @@ import io.ksmt.expr.KFunctionAsArray import io.ksmt.expr.KUniversalQuantifier import io.ksmt.expr.transformer.KNonRecursiveTransformer import io.ksmt.solver.KSolverException +import io.ksmt.solver.KSolverUnsupportedFeatureException import org.ksmt.solver.bitwuzla.bindings.BitwuzlaNativeException import org.ksmt.solver.bitwuzla.bindings.BitwuzlaSort import org.ksmt.solver.bitwuzla.bindings.BitwuzlaTerm @@ -34,6 +35,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KSortVisitor import io.ksmt.sort.KUninterpretedSort @@ -362,6 +365,12 @@ open class KBitwuzlaContext(val ctx: KContext) : AutoCloseable { override fun visit(sort: KRealSort) { } + override fun visit(sort: KStringSort) { + } + + override fun visit(sort: KRegexSort) { + } + override fun visit(sort: S) { } diff --git a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt index 322d90569..08091d5c6 100644 --- a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt +++ b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt @@ -151,6 +151,43 @@ import io.ksmt.expr.KUnaryMinusArithExpr import io.ksmt.expr.KUninterpretedSortValue import io.ksmt.expr.KUniversalQuantifier import io.ksmt.expr.KXorExpr +import io.ksmt.expr.KStringConcatExpr +import io.ksmt.expr.KStringLenExpr +import io.ksmt.expr.KStringToRegexExpr +import io.ksmt.expr.KStringInRegexExpr +import io.ksmt.expr.KSuffixOfExpr +import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringLtExpr +import io.ksmt.expr.KStringLeExpr +import io.ksmt.expr.KStringGtExpr +import io.ksmt.expr.KStringGeExpr +import io.ksmt.expr.KStringContainsExpr +import io.ksmt.expr.KSingletonSubstringExpr +import io.ksmt.expr.KSubstringExpr +import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringReplaceExpr +import io.ksmt.expr.KStringReplaceAllExpr +import io.ksmt.expr.KStringReplaceWithRegexExpr +import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringIsDigitExpr +import io.ksmt.expr.KStringToCodeExpr +import io.ksmt.expr.KStringFromCodeExpr +import io.ksmt.expr.KStringToIntExpr +import io.ksmt.expr.KStringFromIntExpr +import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.KRegexConcatExpr +import io.ksmt.expr.KRegexUnionExpr +import io.ksmt.expr.KRegexIntersectionExpr +import io.ksmt.expr.KRegexKleeneClosureExpr +import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexDifferenceExpr +import io.ksmt.expr.KRegexComplementExpr +import io.ksmt.expr.KRegexOptionExpr +import io.ksmt.expr.KRangeExpr +import io.ksmt.expr.KRegexLiteralExpr +import io.ksmt.expr.KEpsilon +import io.ksmt.expr.KAll +import io.ksmt.expr.KAllChar import io.ksmt.expr.rewrite.simplify.rewriteBvAddNoUnderflowExpr import io.ksmt.expr.rewrite.simplify.rewriteBvMulNoUnderflowExpr import io.ksmt.expr.rewrite.simplify.rewriteBvNegNoOverflowExpr @@ -183,6 +220,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KSortVisitor import io.ksmt.sort.KUninterpretedSort @@ -1405,6 +1444,154 @@ open class KBitwuzlaExprInternalizer(val bitwuzlaCtx: KBitwuzlaContext) : KExprL ) } + override fun transform(expr: KStringConcatExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringLenExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringToRegexExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringInRegexExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KSuffixOfExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KPrefixOfExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringLtExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringLeExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringGtExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringGeExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringContainsExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KSingletonSubstringExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KSubstringExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KIndexOfExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringReplaceExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringReplaceAllExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringReplaceWithRegexExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringReplaceAllWithRegexExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringIsDigitExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringToCodeExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringFromCodeExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringToIntExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringFromIntExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringLiteralExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KRegexConcatExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KRegexUnionExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KRegexIntersectionExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KRegexKleeneClosureExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KRegexKleeneCrossExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KRegexDifferenceExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KRegexComplementExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KRegexOptionExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KRangeExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KRegexLiteralExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KEpsilon): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KAll): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KAllChar): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + private inline fun T.internalizeQuantifier( crossinline mkQuantifierTerm: (LongArray) -> BitwuzlaTerm ): T { @@ -1554,7 +1741,7 @@ open class KBitwuzlaExprInternalizer(val bitwuzlaCtx: KBitwuzlaContext) : KExprL } /** - * Bitwuzla doesn't support integers and reals. + * Bitwuzla doesn't support strings, regular expressions, integers and reals. * */ override fun visit(sort: KIntSort) = throw KSolverUnsupportedFeatureException("Unsupported sort $sort") @@ -1562,6 +1749,12 @@ open class KBitwuzlaExprInternalizer(val bitwuzlaCtx: KBitwuzlaContext) : KExprL override fun visit(sort: KRealSort) = throw KSolverUnsupportedFeatureException("Unsupported sort $sort") + override fun visit(sort: KStringSort) = + throw KSolverUnsupportedFeatureException("Unsupported sort $sort") + + override fun visit(sort: KRegexSort) = + throw KSolverUnsupportedFeatureException("Unsupported sort $sort") + /** * Replace Uninterpreted sorts with (BitVec 32). * The sort universe size is limited by 2^32 values which should be enough. @@ -1704,6 +1897,8 @@ open class KBitwuzlaExprInternalizer(val bitwuzlaCtx: KBitwuzlaContext) : KExprL override fun visit(sort: KBoolSort): Boolean = false override fun visit(sort: KIntSort): Boolean = false override fun visit(sort: KRealSort): Boolean = false + override fun visit(sort: KStringSort): Boolean = false + override fun visit(sort: KRegexSort): Boolean = false override fun visit(sort: S): Boolean = false override fun visit(sort: S): Boolean = false override fun visit(sort: KFpRoundingModeSort): Boolean = false From c8958dc38e90230daa2f3521b970ce3ec54019a9 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Mon, 9 Dec 2024 23:37:49 +0300 Subject: [PATCH 36/84] Add string theory to KTheory class --- .../ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt | 3 ++- ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt index 3b6edfc6e..0cf375684 100644 --- a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt +++ b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt @@ -9,6 +9,7 @@ import io.ksmt.solver.KTheory.LIA import io.ksmt.solver.KTheory.LRA import io.ksmt.solver.KTheory.NIA import io.ksmt.solver.KTheory.NRA +import io.ksmt.solver.KTheory.STR import org.ksmt.solver.bitwuzla.bindings.Bitwuzla import org.ksmt.solver.bitwuzla.bindings.BitwuzlaOption import org.ksmt.solver.bitwuzla.bindings.Native @@ -52,7 +53,7 @@ class KBitwuzlaSolverConfigurationImpl(private val bitwuzla: Bitwuzla) : KBitwuz override fun optimizeForTheories(theories: Set?, quantifiersAllowed: Boolean) { if (theories.isNullOrEmpty()) return - if (setOf(LIA, LRA, NIA, NRA).intersect(theories).isNotEmpty()) { + if (setOf(LIA, LRA, NIA, NRA, STR).intersect(theories).isNotEmpty()) { throw KSolverUnsupportedFeatureException("Unsupported theories $theories") } } diff --git a/ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt b/ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt index bee24e454..3e7af4deb 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt @@ -14,7 +14,8 @@ import io.ksmt.solver.KTheory.UF * */ enum class KTheory { UF, BV, FP, Array, - LIA, NIA, LRA, NRA + LIA, NIA, LRA, NRA, + STR } @Suppress("ComplexMethod", "ComplexCondition") @@ -76,4 +77,8 @@ fun Set?.smtLib2String(quantifiersAllowed: Boolean = false): String = b append("A") } + + if (KTheory.STR in theories) { + append("STR") + } } From c5b9f7ea8729fe7e75fc3fb4d0cc80c03f96418f Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 10 Dec 2024 01:04:34 +0300 Subject: [PATCH 37/84] Fix str name in KTheory class --- .../solver/bitwuzla/KBitwuzlaSolverConfiguration.kt | 4 ++-- ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt index 0cf375684..4f0387072 100644 --- a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt +++ b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt @@ -9,7 +9,7 @@ import io.ksmt.solver.KTheory.LIA import io.ksmt.solver.KTheory.LRA import io.ksmt.solver.KTheory.NIA import io.ksmt.solver.KTheory.NRA -import io.ksmt.solver.KTheory.STR +import io.ksmt.solver.KTheory.Str import org.ksmt.solver.bitwuzla.bindings.Bitwuzla import org.ksmt.solver.bitwuzla.bindings.BitwuzlaOption import org.ksmt.solver.bitwuzla.bindings.Native @@ -53,7 +53,7 @@ class KBitwuzlaSolverConfigurationImpl(private val bitwuzla: Bitwuzla) : KBitwuz override fun optimizeForTheories(theories: Set?, quantifiersAllowed: Boolean) { if (theories.isNullOrEmpty()) return - if (setOf(LIA, LRA, NIA, NRA, STR).intersect(theories).isNotEmpty()) { + if (setOf(LIA, LRA, NIA, NRA, Str).intersect(theories).isNotEmpty()) { throw KSolverUnsupportedFeatureException("Unsupported theories $theories") } } diff --git a/ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt b/ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt index 3e7af4deb..73fd885df 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt @@ -8,6 +8,7 @@ import io.ksmt.solver.KTheory.LRA import io.ksmt.solver.KTheory.NIA import io.ksmt.solver.KTheory.NRA import io.ksmt.solver.KTheory.UF +import io.ksmt.solver.KTheory.Str /** * SMT theory @@ -15,7 +16,7 @@ import io.ksmt.solver.KTheory.UF enum class KTheory { UF, BV, FP, Array, LIA, NIA, LRA, NRA, - STR + Str } @Suppress("ComplexMethod", "ComplexCondition") @@ -56,6 +57,10 @@ fun Set?.smtLib2String(quantifiersAllowed: Boolean = false): String = b append("FP") } + if (Str in theories) { + append("S") + } + if (LIA in theories || NIA in theories || LRA in theories || NRA in theories) { val hasNonLinear = NIA in theories || NRA in theories val hasReal = LRA in theories || NRA in theories @@ -78,7 +83,4 @@ fun Set?.smtLib2String(quantifiersAllowed: Boolean = false): String = b append("A") } - if (KTheory.STR in theories) { - append("STR") - } } From 2e2286da18f2f6ca27c8fc590c2e94c3da769994 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 10 Dec 2024 01:08:10 +0300 Subject: [PATCH 38/84] Implement string and regex sorts cvc5 internalizer --- .../io/ksmt/solver/cvc5/KCvc5SortInternalizer.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5SortInternalizer.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5SortInternalizer.kt index 88a5a8e66..43a93d5f3 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5SortInternalizer.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5SortInternalizer.kt @@ -11,6 +11,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KSortVisitor import io.ksmt.sort.KUninterpretedSort @@ -33,6 +35,14 @@ open class KCvc5SortInternalizer( tm.builder { realSort } } + override fun visit(sort: KStringSort): Sort = cvc5Ctx.internalizeSort(sort) { + tm.builder { stringSort } + } + + override fun visit(sort: KRegexSort): Sort = cvc5Ctx.internalizeSort(sort) { + tm.builder { regExpSort } + } + override fun visit(sort: KArraySort): Sort = cvc5Ctx.internalizeSort(sort) { val domain = sort.domain.internalizeCvc5Sort() From eac27d5135b4a35f089932bb0ad51540bd6f141c Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 10 Dec 2024 21:11:05 +0300 Subject: [PATCH 39/84] Add string and regex expressions internalizer for cvc5 --- .../ksmt/solver/cvc5/KCvc5ExprInternalizer.kt | 250 ++++++++++++++++++ 1 file changed, 250 insertions(+) diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt index 39dae685d..39ba6e262 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt @@ -155,6 +155,43 @@ import io.ksmt.expr.KUnaryMinusArithExpr import io.ksmt.expr.KUninterpretedSortValue import io.ksmt.expr.KUniversalQuantifier import io.ksmt.expr.KXorExpr +import io.ksmt.expr.KStringConcatExpr +import io.ksmt.expr.KStringLenExpr +import io.ksmt.expr.KStringToRegexExpr +import io.ksmt.expr.KStringInRegexExpr +import io.ksmt.expr.KSuffixOfExpr +import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringLtExpr +import io.ksmt.expr.KStringLeExpr +import io.ksmt.expr.KStringGtExpr +import io.ksmt.expr.KStringGeExpr +import io.ksmt.expr.KStringContainsExpr +import io.ksmt.expr.KSingletonSubstringExpr +import io.ksmt.expr.KSubstringExpr +import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringReplaceExpr +import io.ksmt.expr.KStringReplaceAllExpr +import io.ksmt.expr.KStringReplaceWithRegexExpr +import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringIsDigitExpr +import io.ksmt.expr.KStringToCodeExpr +import io.ksmt.expr.KStringFromCodeExpr +import io.ksmt.expr.KStringToIntExpr +import io.ksmt.expr.KStringFromIntExpr +import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.KRegexConcatExpr +import io.ksmt.expr.KRegexUnionExpr +import io.ksmt.expr.KRegexIntersectionExpr +import io.ksmt.expr.KRegexKleeneClosureExpr +import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexDifferenceExpr +import io.ksmt.expr.KRegexComplementExpr +import io.ksmt.expr.KRegexOptionExpr +import io.ksmt.expr.KRangeExpr +import io.ksmt.expr.KRegexLiteralExpr +import io.ksmt.expr.KEpsilon +import io.ksmt.expr.KAll +import io.ksmt.expr.KAllChar import io.ksmt.expr.rewrite.simplify.rewriteBvAddNoOverflowExpr import io.ksmt.expr.rewrite.simplify.rewriteBvAddNoUnderflowExpr import io.ksmt.expr.rewrite.simplify.rewriteBvDivNoOverflowExpr @@ -181,6 +218,8 @@ import io.ksmt.sort.KFp64Sort import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KUninterpretedSort import io.ksmt.utils.powerOfTwo @@ -1141,6 +1180,217 @@ class KCvc5ExprInternalizer( } } + // strings + override fun transform(expr: KStringConcatExpr) = with(expr) { + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.STRING_CONCAT, arg0, arg1) + } + } + + override fun transform(expr: KStringLenExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.STRING_LENGTH, arg) + } + } + + override fun transform(expr: KStringToRegexExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.STRING_TO_REGEXP, arg) + } + } + + override fun transform(expr: KStringInRegexExpr) = with(expr) { + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.STRING_IN_REGEXP, arg0, arg1) + } + } + + override fun transform(expr: KSuffixOfExpr) = with(expr) { + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.STRING_SUFFIX, arg0, arg1) + } + } + + override fun transform(expr: KPrefixOfExpr) = with(expr) { + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.STRING_PREFIX, arg0, arg1) + } + } + + override fun transform(expr: KStringLtExpr) = with(expr) { + transform(lhs, rhs) { lhs: Term, rhs: Term -> + tm.mkTerm(Kind.STRING_LT, lhs, rhs) + } + } + + override fun transform(expr: KStringLeExpr) = with(expr) { + transform(lhs, rhs) { lhs: Term, rhs: Term -> + tm.mkTerm(Kind.STRING_LEQ, lhs, rhs) + } + } + + override fun transform(expr: KStringGtExpr) = with(expr) { + transform(lhs, rhs) { lhs: Term, rhs: Term -> + tm.mkTerm(Kind.STRING_LT, rhs, lhs) + } + } + + override fun transform(expr: KStringGeExpr) = with(expr) { + transform(lhs, rhs) { lhs: Term, rhs: Term -> + tm.mkTerm(Kind.STRING_LEQ, rhs, lhs) + } + } + + override fun transform(expr: KStringContainsExpr) = with(expr) { + transform(lhs, rhs) { lhs: Term, rhs: Term -> + tm.mkTerm(Kind.STRING_CONTAINS, rhs, lhs) + } + } + + override fun transform(expr: KSingletonSubstringExpr) = with(expr) { + TODO("Not yet implemented") + } + + override fun transform(expr: KSubstringExpr) = with(expr) { + TODO("Not yet implemented") + } + + override fun transform(expr: KIndexOfExpr) = with(expr) { + TODO("Not yet implemented") + } + + override fun transform(expr: KStringReplaceExpr) = with(expr) { + transform(arg0, arg1, arg2) { arg0: Term, arg1: Term, arg2: Term -> + tm.mkTerm(Kind.STRING_REPLACE, arg0, arg1, arg2) + } + } + + override fun transform(expr: KStringReplaceAllExpr) = with(expr) { + transform(arg0, arg1, arg2) { arg0: Term, arg1: Term, arg2: Term -> + tm.mkTerm(Kind.STRING_REPLACE_ALL, arg0, arg1, arg2) + } + } + + override fun transform(expr: KStringReplaceWithRegexExpr) = with(expr) { + transform(arg0, arg1, arg2) { arg0: Term, arg1: Term, arg2: Term -> + tm.mkTerm(Kind.STRING_REPLACE_RE, arg0, arg1, arg2) + } + } + + override fun transform(expr: KStringReplaceAllWithRegexExpr) = with(expr) { + transform(arg0, arg1, arg2) { arg0: Term, arg1: Term, arg2: Term -> + tm.mkTerm(Kind.STRING_REPLACE_RE_ALL, arg0, arg1, arg2) + } + } + + override fun transform(expr: KStringIsDigitExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.STRING_IS_DIGIT, arg) + } + } + + override fun transform(expr: KStringToCodeExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.STRING_TO_CODE, arg) + } + } + + override fun transform(expr: KStringFromCodeExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.STRING_FROM_CODE, arg) + } + } + + override fun transform(expr: KStringToIntExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.STRING_TO_INT, arg) + } + } + + override fun transform(expr: KStringFromIntExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.STRING_FROM_INT, arg) + } + } + + override fun transform(expr: KStringLiteralExpr) = with(expr) { + transform { tm.builder { mkString(expr.value) } } + } + + // regex + override fun transform(expr: KRegexConcatExpr) = with(expr) { + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.REGEXP_CONCAT, arg0, arg1) + } + } + + override fun transform(expr: KRegexUnionExpr) = with(expr) { + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.REGEXP_UNION, arg0, arg1) + } + } + + override fun transform(expr: KRegexIntersectionExpr) = with(expr) { + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.REGEXP_INTER, arg0, arg1) + } + } + + override fun transform(expr: KRegexKleeneClosureExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.REGEXP_STAR, arg) + } + } + + override fun transform(expr: KRegexKleeneCrossExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.REGEXP_PLUS, arg) + } + } + + override fun transform(expr: KRegexDifferenceExpr) = with(expr) { + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.REGEXP_DIFF, arg0, arg1) + } + } + + override fun transform(expr: KRegexComplementExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.REGEXP_COMPLEMENT, arg) + } + } + + override fun transform(expr: KRegexOptionExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.REGEXP_OPT, arg) + } + } + + override fun transform(expr: KRangeExpr) = with(expr) { + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.REGEXP_RANGE, arg0, arg1) + } + } + + override fun transform(expr: KEpsilon) = with(expr) { + transform { tm.mkTerm(Kind.REGEXP_NONE) } + } + + override fun transform(expr: KAll) = with(expr) { + transform { tm.mkTerm(Kind.REGEXP_ALL) } + } + + override fun transform(expr: KAllChar) = with(expr) { + transform { tm.mkTerm(Kind.REGEXP_ALLCHAR) } + } + + override fun transform(expr: KRegexLiteralExpr) = with(expr) { + transform(ctx.mkStringLiteral(value)) { str: Term -> // Reconsider. + tm.mkTerm(Kind.STRING_TO_REGEXP, str) + } + } + + // Quantifiers override fun transform(expr: KExistentialQuantifier) = expr.transformQuantifiedExpression(expr.bounds, expr.body, isUniversal = false) From 3dc16f858e5884ce32ea6eb8d0f3fd052ecf0317 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 10 Dec 2024 22:55:03 +0300 Subject: [PATCH 40/84] Add cvc5 internalizer for substrings and indexOf expressions --- .../io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt index 39ba6e262..c9be9ee5a 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt @@ -1248,15 +1248,21 @@ class KCvc5ExprInternalizer( } override fun transform(expr: KSingletonSubstringExpr) = with(expr) { - TODO("Not yet implemented") + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.STRING_CHARAT, arg0, arg1) + } } override fun transform(expr: KSubstringExpr) = with(expr) { - TODO("Not yet implemented") + transform(arg0, arg1, arg2) { arg0: Term, arg1: Term, arg2: Term -> + tm.mkTerm(Kind.STRING_SUBSTR, arg0, arg1, arg2) + } } override fun transform(expr: KIndexOfExpr) = with(expr) { - TODO("Not yet implemented") + transform(arg0, arg1, arg2) { arg0: Term, arg1: Term, arg2: Term -> + tm.mkTerm(Kind.STRING_INDEXOF, arg0, arg1, arg2) + } } override fun transform(expr: KStringReplaceExpr) = with(expr) { From 62b1a6aba170097ce55d65aabbf6646d3650d6a9 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 10 Dec 2024 23:06:02 +0300 Subject: [PATCH 41/84] Implement converter from cvc5 to ksmt --- .../io/ksmt/solver/cvc5/KCvc5ExprConverter.kt | 110 +++++++++++------- 1 file changed, 65 insertions(+), 45 deletions(-) diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt index 0084e0686..341355b8c 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt @@ -82,6 +82,7 @@ open class KCvc5ExprConverter( Kind.CONST_ARRAY -> convertNativeConstArrayExpr(expr) Kind.CONST_INTEGER -> convertNativeConstIntegerExpr(expr) Kind.CONST_RATIONAL -> convertNativeConstRealExpr(expr) + Kind.CONST_STRING -> convertNativeConstStringExpr(expr) Kind.CONSTANT -> convert { expr.convertDecl().apply(emptyList()) } Kind.UNINTERPRETED_SORT_VALUE -> convert { model ?: error("Uninterpreted value without model") @@ -378,6 +379,64 @@ open class KCvc5ExprConverter( Kind.SELECT -> convertNativeArraySelect(expr) Kind.STORE -> convertNativeArrayStore(expr) + // strings + Kind.STRING_CONCAT -> expr.convert(::mkStringConcat) + Kind.STRING_LENGTH -> expr.convert(::mkStringLen) + Kind.STRING_TO_REGEXP -> expr.convert(::mkStringToRegex) + Kind.STRING_IN_REGEXP -> expr.convert(::mkStringInRegex) + Kind.STRING_SUFFIX -> expr.convert(::mkSuffixOf) + Kind.STRING_PREFIX -> expr.convert(::mkPrefixOf) + Kind.STRING_LT -> expr.convert(::mkStringLt) + Kind.STRING_LEQ -> expr.convert(::mkStringLe) + Kind.STRING_CONTAINS -> expr.convert(::mkStringContains) + Kind.STRING_CHARAT -> expr.convert(::mkSingletonSubstring) + Kind.STRING_SUBSTR -> expr.convert(::mkSubstring) + Kind.STRING_INDEXOF -> expr.convert(::mkIndexOf) + Kind.STRING_REPLACE -> expr.convert(::mkStringReplace) + Kind.STRING_REPLACE_ALL -> expr.convert(::mkStringReplaceAll) + Kind.STRING_REPLACE_RE -> expr.convert(::mkStringReplaceWithRegex) + Kind.STRING_REPLACE_RE_ALL -> expr.convert(::mkStringReplaceAllWithRegex) + Kind.STRING_IS_DIGIT -> expr.convert(::mkStringIsDigit) + Kind.STRING_TO_CODE -> expr.convert(::mkStringToCode) + Kind.STRING_FROM_CODE -> expr.convert(::mkStringFromCode) + Kind.STRING_TO_INT -> expr.convert(::mkStringToInt) + Kind.STRING_FROM_INT -> expr.convert(::mkStringFromInt) + Kind.STRING_UPDATE -> throw KSolverUnsupportedFeatureException( + "No direct mapping of ${Kind.STRING_UPDATE} in ksmt" + ) + Kind.STRING_INDEXOF_RE -> throw KSolverUnsupportedFeatureException( + "No direct mapping of ${Kind.STRING_INDEXOF_RE} in ksmt" + ) + Kind.STRING_TO_LOWER -> throw KSolverUnsupportedFeatureException( + "No direct mapping of ${Kind.STRING_TO_LOWER} in ksmt" + ) + Kind.STRING_TO_UPPER -> throw KSolverUnsupportedFeatureException( + "No direct mapping of ${Kind.STRING_TO_UPPER} in ksmt" + ) + Kind.STRING_REV -> throw KSolverUnsupportedFeatureException( + "No direct mapping of ${Kind.STRING_REV} in ksmt" + ) + + // regex + Kind.REGEXP_CONCAT -> expr.convert(::mkRegexConcat) + Kind.REGEXP_UNION -> expr.convert(::mkRegexUnion) + Kind.REGEXP_INTER -> expr.convert(::mkRegexIntersection) + Kind.REGEXP_STAR -> expr.convert(::mkRegexKleeneClosure) + Kind.REGEXP_PLUS -> expr.convert(::mkRegexKleeneCross) + Kind.REGEXP_DIFF -> expr.convert(::mkRegexDifference) + Kind.REGEXP_COMPLEMENT -> expr.convert(::mkRegexComplement) + Kind.REGEXP_OPT -> expr.convert(::mkRegexOption) + Kind.REGEXP_NONE -> convert { mkEpsilon() } + Kind.REGEXP_ALL -> convert { mkAll() } + Kind.REGEXP_ALLCHAR -> convert { mkAllChar() } + Kind.REGEXP_RANGE -> expr.convert(::mkRange) + Kind.REGEXP_REPEAT -> throw KSolverUnsupportedFeatureException( + "No direct mapping of ${Kind.STRING_REV} in ksmt" + ) + Kind.REGEXP_LOOP -> throw KSolverUnsupportedFeatureException( + "No direct mapping of ${Kind.STRING_REV} in ksmt" + ) + Kind.EQ_RANGE -> throw KSolverUnsupportedFeatureException("EQ_RANGE is not supported") Kind.APPLY_CONSTRUCTOR, @@ -452,51 +511,6 @@ open class KCvc5ExprConverter( Kind.TABLE_JOIN, Kind.TABLE_GROUP -> throw KSolverUnsupportedFeatureException("currently ksmt does not support tables") - Kind.STRING_CONCAT, - Kind.STRING_IN_REGEXP, - Kind.STRING_LENGTH, - Kind.STRING_SUBSTR, - Kind.STRING_UPDATE, - Kind.STRING_CHARAT, - Kind.STRING_CONTAINS, - Kind.STRING_INDEXOF, - Kind.STRING_INDEXOF_RE, - Kind.STRING_REPLACE, - Kind.STRING_REPLACE_ALL, - Kind.STRING_REPLACE_RE, - Kind.STRING_REPLACE_RE_ALL, - Kind.STRING_TO_LOWER, - Kind.STRING_TO_UPPER, - Kind.STRING_REV, - Kind.STRING_TO_CODE, - Kind.STRING_FROM_CODE, - Kind.STRING_LT, - Kind.STRING_LEQ, - Kind.STRING_PREFIX, - Kind.STRING_SUFFIX, - Kind.STRING_IS_DIGIT, - Kind.STRING_FROM_INT, - Kind.STRING_TO_INT, - Kind.CONST_STRING, - Kind.STRING_TO_REGEXP -> throw KSolverUnsupportedFeatureException("currently ksmt does not support strings") - - Kind.REGEXP_CONCAT, - Kind.REGEXP_UNION, - Kind.REGEXP_INTER, - Kind.REGEXP_DIFF, - Kind.REGEXP_STAR, - Kind.REGEXP_PLUS, - Kind.REGEXP_OPT, - Kind.REGEXP_RANGE, - Kind.REGEXP_REPEAT, - Kind.REGEXP_LOOP, - Kind.REGEXP_NONE, - Kind.REGEXP_ALL, - Kind.REGEXP_ALLCHAR, - Kind.REGEXP_COMPLEMENT -> throw KSolverUnsupportedFeatureException( - "currently ksmt does not support regular expressions" - ) - Kind.SEQ_CONCAT, Kind.SEQ_LENGTH, Kind.SEQ_EXTRACT, @@ -710,6 +724,12 @@ open class KCvc5ExprConverter( } } + private fun convertNativeConstStringExpr(expr: Term): ExprConversionResult = with(ctx) { + convert { + mkStringLiteral(expr.stringValue) + } + } + private fun convertNativeBitvectorConstExpr(expr: Term): ExprConversionResult = with(ctx) { convert { mkBv(expr.bitVectorValue, expr.bitVectorValue.length.toUInt()) } } From 811d531a8d06c33d5c544c04d0dece264bfd833b Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 10 Dec 2024 23:30:42 +0300 Subject: [PATCH 42/84] Implement string/regex methods for cvc5 uninterpreted sort collector --- .../src/main/kotlin/io/ksmt/solver/cvc5/KCvc5Context.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5Context.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5Context.kt index 124227a45..b91f348e4 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5Context.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5Context.kt @@ -27,6 +27,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KSortVisitor import io.ksmt.sort.KUninterpretedSort @@ -373,6 +375,10 @@ class KCvc5Context( override fun visit(sort: KRealSort) = Unit + override fun visit(sort: KStringSort) = Unit + + override fun visit(sort: KRegexSort) = Unit + override fun visit(sort: S) = Unit override fun visit(sort: S) = Unit From 97bead4df8163f05833e5a0a141e1f4e01764129 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 10 Dec 2024 23:31:28 +0300 Subject: [PATCH 43/84] Add exceptions that Yices does not support string theory --- .../solver/yices/KYicesExprInternalizer.kt | 187 ++++++++++++++++++ .../io/ksmt/solver/yices/KYicesModel.kt | 4 + .../solver/yices/KYicesSortInternalizer.kt | 14 +- 3 files changed, 201 insertions(+), 4 deletions(-) diff --git a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt index 64c23a232..b5c8ec3f8 100644 --- a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt +++ b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt @@ -145,6 +145,43 @@ import io.ksmt.expr.KUnaryMinusArithExpr import io.ksmt.expr.KUninterpretedSortValue import io.ksmt.expr.KUniversalQuantifier import io.ksmt.expr.KXorExpr +import io.ksmt.expr.KStringConcatExpr +import io.ksmt.expr.KStringLenExpr +import io.ksmt.expr.KStringToRegexExpr +import io.ksmt.expr.KStringInRegexExpr +import io.ksmt.expr.KSuffixOfExpr +import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringLtExpr +import io.ksmt.expr.KStringLeExpr +import io.ksmt.expr.KStringGtExpr +import io.ksmt.expr.KStringGeExpr +import io.ksmt.expr.KStringContainsExpr +import io.ksmt.expr.KSingletonSubstringExpr +import io.ksmt.expr.KSubstringExpr +import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringReplaceExpr +import io.ksmt.expr.KStringReplaceAllExpr +import io.ksmt.expr.KStringReplaceWithRegexExpr +import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringIsDigitExpr +import io.ksmt.expr.KStringToCodeExpr +import io.ksmt.expr.KStringFromCodeExpr +import io.ksmt.expr.KStringToIntExpr +import io.ksmt.expr.KStringFromIntExpr +import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.KRegexConcatExpr +import io.ksmt.expr.KRegexUnionExpr +import io.ksmt.expr.KRegexIntersectionExpr +import io.ksmt.expr.KRegexKleeneClosureExpr +import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexDifferenceExpr +import io.ksmt.expr.KRegexComplementExpr +import io.ksmt.expr.KRegexOptionExpr +import io.ksmt.expr.KRangeExpr +import io.ksmt.expr.KRegexLiteralExpr +import io.ksmt.expr.KEpsilon +import io.ksmt.expr.KAll +import io.ksmt.expr.KAllChar import io.ksmt.expr.rewrite.simplify.rewriteBvAddNoOverflowExpr import io.ksmt.expr.rewrite.simplify.rewriteBvAddNoUnderflowExpr import io.ksmt.expr.rewrite.simplify.rewriteBvDivNoOverflowExpr @@ -176,6 +213,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KUninterpretedSort import java.math.BigInteger @@ -964,6 +1003,154 @@ open class KYicesExprInternalizer( } } + override fun transform(expr: KStringConcatExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KStringLenExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + } + + override fun transform(expr: KStringToRegexExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KStringInRegexExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KSuffixOfExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KPrefixOfExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KStringLtExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KStringLeExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KStringGtExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KStringGeExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KStringContainsExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KSingletonSubstringExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KSubstringExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KIndexOfExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + } + + override fun transform(expr: KStringReplaceExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KStringReplaceAllExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KStringReplaceWithRegexExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KStringReplaceAllWithRegexExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KStringIsDigitExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + } + + override fun transform(expr: KStringToCodeExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + } + + override fun transform(expr: KStringFromCodeExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + } + + override fun transform(expr: KStringToIntExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + } + + override fun transform(expr: KStringFromIntExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + } + + override fun transform(expr: KStringLiteralExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KRegexConcatExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KRegexUnionExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KRegexIntersectionExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KRegexKleeneClosureExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KRegexKleeneCrossExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KRegexDifferenceExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KRegexComplementExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KRegexOptionExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KRangeExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KRegexLiteralExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KEpsilon): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KAll): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KAllChar): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + private inline fun > E.internalizeQuantifiedBody( quantifiedDecls: List>, quantifierBody: KExpr<*>, diff --git a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesModel.kt b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesModel.kt index 9e968796b..66ff311c3 100644 --- a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesModel.kt +++ b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesModel.kt @@ -26,6 +26,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KSortVisitor import io.ksmt.sort.KUninterpretedSort @@ -228,6 +230,8 @@ class KYicesModel( override fun visit(sort: KBoolSort) = Unit override fun visit(sort: KIntSort) = Unit override fun visit(sort: KRealSort) = Unit + override fun visit(sort: KStringSort) = Unit + override fun visit(sort: KRegexSort) = Unit override fun visit(sort: S) = Unit override fun visit(sort: S) = Unit override fun visit(sort: KFpRoundingModeSort) = Unit diff --git a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesSortInternalizer.kt b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesSortInternalizer.kt index fddfbf1f4..9bcc868ea 100644 --- a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesSortInternalizer.kt +++ b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesSortInternalizer.kt @@ -12,6 +12,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KSortVisitor import io.ksmt.sort.KUninterpretedSort @@ -74,13 +76,17 @@ open class KYicesSortInternalizer( internalizedSort = yicesCtx.newUninterpretedType(sort.name) } - override fun visit(sort: S) { + override fun visit(sort: S) = throw KSolverUnsupportedFeatureException("Unsupported sort $sort") - } - override fun visit(sort: KFpRoundingModeSort) { + override fun visit(sort: KFpRoundingModeSort) = + throw KSolverUnsupportedFeatureException("Unsupported sort $sort") + + override fun visit(sort: KStringSort) = + throw KSolverUnsupportedFeatureException("Unsupported sort $sort") + + override fun visit(sort: KRegexSort) = throw KSolverUnsupportedFeatureException("Unsupported sort $sort") - } fun internalizeYicesSort(sort: KSort): YicesSort = yicesCtx.internalizeSort(sort) { sort.accept(this) From b3ecd8a11390e373db7ab58f7e1e6542245797cf Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 11 Dec 2024 00:45:40 +0300 Subject: [PATCH 44/84] Fix typo in exceptions' messages --- .../io/ksmt/solver/yices/KYicesExprInternalizer.kt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt index b5c8ec3f8..9149eed78 100644 --- a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt +++ b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt @@ -1008,7 +1008,7 @@ open class KYicesExprInternalizer( } override fun transform(expr: KStringLenExpr): KExpr { - throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } override fun transform(expr: KStringToRegexExpr): KExpr { @@ -1056,7 +1056,7 @@ open class KYicesExprInternalizer( } override fun transform(expr: KIndexOfExpr): KExpr { - throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } override fun transform(expr: KStringReplaceExpr): KExpr { @@ -1076,23 +1076,23 @@ open class KYicesExprInternalizer( } override fun transform(expr: KStringIsDigitExpr): KExpr { - throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } override fun transform(expr: KStringToCodeExpr): KExpr { - throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } override fun transform(expr: KStringFromCodeExpr): KExpr { - throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } override fun transform(expr: KStringToIntExpr): KExpr { - throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } override fun transform(expr: KStringFromIntExpr): KExpr { - throw KSolverUnsupportedFeatureException("string and int theory is not supported in Yices") + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } override fun transform(expr: KStringLiteralExpr): KExpr { From 81ac05fbc97532ddb97f8308ee2d41f54e460b44 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 11 Dec 2024 23:22:36 +0300 Subject: [PATCH 45/84] Fix yices solver configuration after adding string theory --- .../kotlin/io/ksmt/solver/yices/KYicesSolverConfiguration.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesSolverConfiguration.kt b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesSolverConfiguration.kt index 669a56a4b..88e1b3d80 100644 --- a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesSolverConfiguration.kt +++ b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesSolverConfiguration.kt @@ -7,6 +7,7 @@ import io.ksmt.solver.KSolverUnsupportedFeatureException import io.ksmt.solver.KSolverUnsupportedParameterException import io.ksmt.solver.KTheory import io.ksmt.solver.KTheory.FP +import io.ksmt.solver.KTheory.Str import io.ksmt.solver.KTheory.LIA import io.ksmt.solver.KTheory.LRA import io.ksmt.solver.KTheory.NIA @@ -41,6 +42,10 @@ class KYicesSolverConfigurationImpl(private val config: Config) : KYicesSolverCo throw KSolverUnsupportedFeatureException("Unsupported theory $FP") } + if (Str in theories) { + throw KSolverUnsupportedFeatureException("Unsupported theory $Str") + } + // Yices requires MCSAT for the arithmetic theories if (setOf(LIA, LRA, NIA, NRA).intersect(theories).isNotEmpty()) { return From ca8bff6846d7549c2bb02cb9074046c2d3fece9c Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 11 Dec 2024 23:25:22 +0300 Subject: [PATCH 46/84] Delete regex literal expression --- .../bitwuzla/KBitwuzlaExprInternalizer.kt | 5 ----- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 13 ------------- .../main/kotlin/io/ksmt/decl/KDeclVisitor.kt | 1 - ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt | 8 -------- ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt | 17 ----------------- .../io/ksmt/expr/transformer/KTransformer.kt | 2 -- .../ksmt/expr/transformer/KTransformerBase.kt | 2 -- .../kotlin/io/ksmt/expr/transformer/KVisitor.kt | 3 --- .../ksmt/solver/cvc5/KCvc5ExprInternalizer.kt | 7 ------- .../ksmt/solver/yices/KYicesExprInternalizer.kt | 5 ----- 10 files changed, 63 deletions(-) diff --git a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt index 08091d5c6..285af863f 100644 --- a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt +++ b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt @@ -184,7 +184,6 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRangeExpr -import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KEpsilon import io.ksmt.expr.KAll import io.ksmt.expr.KAllChar @@ -1576,10 +1575,6 @@ open class KBitwuzlaExprInternalizer(val bitwuzlaCtx: KBitwuzlaContext) : KExprL throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } - override fun transform(expr: KRegexLiteralExpr): KExpr { - throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") - } - override fun transform(expr: KEpsilon): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 194c22b89..f1bbba3fa 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -156,7 +156,6 @@ import io.ksmt.decl.KStringFromIntDecl import io.ksmt.decl.KEpsilonDecl import io.ksmt.decl.KAllDecl import io.ksmt.decl.KAllCharDecl -import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KRegexConcatDecl import io.ksmt.decl.KRegexUnionDecl import io.ksmt.decl.KRegexIntersectionDecl @@ -336,7 +335,6 @@ import io.ksmt.expr.KStringFromIntExpr import io.ksmt.expr.KEpsilon import io.ksmt.expr.KAll import io.ksmt.expr.KAllChar -import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr import io.ksmt.expr.KRegexIntersectionExpr @@ -2472,15 +2470,6 @@ open class KContext( @JvmName("regexContains") infix fun KExpr.contains(other: KExpr) = mkStringInRegex(other, this) - private val regexLiteralCache = mkAstInterner() - - /** - * Create a Regex value. - * */ - fun mkRegexLiteral(value: String): KRegexLiteralExpr = regexLiteralCache.createIfContextActive { - KRegexLiteralExpr(this, value) - } - private val regexConcatExprCache = mkAstInterner() /** @@ -5313,8 +5302,6 @@ open class KContext( fun mkStringFromIntDecl(): KStringFromIntDecl = KStringFromIntDecl(this) // regex - fun mkRegexLiteralDecl(value: String): KRegexLiteralDecl = KRegexLiteralDecl(this, value) - fun mkRegexConcatDecl(): KRegexConcatDecl = KRegexConcatDecl(this) fun mkRegexUnionDecl(): KRegexUnionDecl = KRegexUnionDecl(this) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt index b90a38454..41680c676 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt @@ -168,7 +168,6 @@ interface KDeclVisitor { fun visit(decl: KRegexComplementDecl): T = visit(decl as KFuncDecl) fun visit(decl: KRegexOptionDecl): T = visit(decl as KFuncDecl) fun visit(decl: KRangeDecl): T = visit(decl as KFuncDecl) - fun visit(decl: KRegexLiteralDecl): T = visit(decl as KConstDecl) fun visit(decl: KEpsilonDecl): T = visit(decl as KConstDecl) fun visit(decl: KAllDecl): T = visit(decl as KConstDecl) fun visit(decl: KAllCharDecl): T = visit(decl as KConstDecl) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index fc9faa920..df893e53c 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -6,14 +6,6 @@ import io.ksmt.expr.KExpr import io.ksmt.sort.KRegexSort import io.ksmt.sort.KStringSort -class KRegexLiteralDecl internal constructor( - ctx: KContext, - val value: String -) : KConstDecl(ctx, value, ctx.mkRegexSort()) { - override fun apply(args: List>): KApp = ctx.mkRegexLiteral(value) - override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) -} - class KRegexConcatDecl internal constructor( ctx: KContext, ) : KFuncDecl2( diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index 027e46357..b076b3b0e 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -6,7 +6,6 @@ import io.ksmt.cache.structurallyEqual import io.ksmt.decl.KDecl import io.ksmt.decl.KRegexKleeneClosureDecl import io.ksmt.decl.KRegexKleeneCrossDecl -import io.ksmt.decl.KRegexLiteralDecl import io.ksmt.decl.KRegexComplementDecl import io.ksmt.decl.KRegexOptionDecl import io.ksmt.decl.KEpsilonDecl @@ -16,22 +15,6 @@ import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KRegexSort import io.ksmt.sort.KStringSort -class KRegexLiteralExpr internal constructor( - ctx: KContext, - val value: String -) : KInterpretedValue(ctx) { - override val sort: KRegexSort - get() = ctx.regexSort - - override val decl: KRegexLiteralDecl - get() = ctx.mkRegexLiteralDecl(value) - - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) - - override fun internHashCode(): Int = hash(value) - override fun internEquals(other: Any): Boolean = structurallyEqual(other) { value } -} - class KRegexConcatExpr internal constructor( ctx: KContext, val arg0: KExpr, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt index 4e2739a8e..95c317a54 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt @@ -183,7 +183,6 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRangeExpr -import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KEpsilon import io.ksmt.expr.KAll import io.ksmt.expr.KAllChar @@ -487,7 +486,6 @@ interface KTransformer : KTransformerBase { override fun transform(expr: KRegexComplementExpr): KExpr = transformApp(expr) override fun transform(expr: KRegexOptionExpr): KExpr = transformApp(expr) override fun transform(expr: KRangeExpr): KExpr = transformApp(expr) - override fun transform(expr: KRegexLiteralExpr): KExpr = transformValue(expr) override fun transform(expr: KEpsilon): KExpr = transformValue(expr) override fun transform(expr: KAll): KExpr = transformValue(expr) override fun transform(expr: KAllChar): KExpr = transformValue(expr) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt index ace65fd42..557e69211 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt @@ -174,7 +174,6 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRangeExpr -import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KEpsilon import io.ksmt.expr.KAll import io.ksmt.expr.KAllChar @@ -415,7 +414,6 @@ interface KTransformerBase { fun transform(expr: KRegexComplementExpr): KExpr fun transform(expr: KRegexOptionExpr): KExpr fun transform(expr: KRangeExpr): KExpr - fun transform(expr: KRegexLiteralExpr): KExpr fun transform(expr: KEpsilon): KExpr fun transform(expr: KAll): KExpr fun transform(expr: KAllChar): KExpr diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt index 286d4fb3c..75aa2dedd 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt @@ -182,7 +182,6 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRangeExpr -import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KEpsilon import io.ksmt.expr.KAll import io.ksmt.expr.KAllChar @@ -714,7 +713,6 @@ interface KVisitor : KTransformer { fun visit(expr: KRegexComplementExpr): V = visitApp(expr) fun visit(expr: KRegexOptionExpr): V = visitApp(expr) fun visit(expr: KRangeExpr): V = visitApp(expr) - fun visit(expr: KRegexLiteralExpr): V = visitValue(expr) fun visit(expr: KEpsilon): V = visitValue(expr) fun visit(expr: KAll): V = visitValue(expr) fun visit(expr: KAllChar): V = visitValue(expr) @@ -728,7 +726,6 @@ interface KVisitor : KTransformer { override fun transform(expr: KRegexComplementExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KRegexOptionExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KRangeExpr): KExpr = visitExpr(expr, ::visit) - override fun transform(expr: KRegexLiteralExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KEpsilon): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KAll): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KAllChar): KExpr = visitExpr(expr, ::visit) diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt index c9be9ee5a..4d8f94cd4 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt @@ -188,7 +188,6 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRangeExpr -import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KEpsilon import io.ksmt.expr.KAll import io.ksmt.expr.KAllChar @@ -1390,12 +1389,6 @@ class KCvc5ExprInternalizer( transform { tm.mkTerm(Kind.REGEXP_ALLCHAR) } } - override fun transform(expr: KRegexLiteralExpr) = with(expr) { - transform(ctx.mkStringLiteral(value)) { str: Term -> // Reconsider. - tm.mkTerm(Kind.STRING_TO_REGEXP, str) - } - } - // Quantifiers override fun transform(expr: KExistentialQuantifier) = expr.transformQuantifiedExpression(expr.bounds, expr.body, isUniversal = false) diff --git a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt index 9149eed78..34547ea05 100644 --- a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt +++ b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt @@ -178,7 +178,6 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRangeExpr -import io.ksmt.expr.KRegexLiteralExpr import io.ksmt.expr.KEpsilon import io.ksmt.expr.KAll import io.ksmt.expr.KAllChar @@ -1135,10 +1134,6 @@ open class KYicesExprInternalizer( throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } - override fun transform(expr: KRegexLiteralExpr): KExpr { - throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") - } - override fun transform(expr: KEpsilon): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } From b54264f5c85ed66a7e8fcd9880feb1e70857c66e Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 11 Dec 2024 23:29:01 +0300 Subject: [PATCH 47/84] Fix string theory name in KTheory class --- .../io/ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt | 4 ++-- ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt | 6 +++--- .../io/ksmt/solver/yices/KYicesSolverConfiguration.kt | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt index 4f0387072..64f4fe2fb 100644 --- a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt +++ b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaSolverConfiguration.kt @@ -9,7 +9,7 @@ import io.ksmt.solver.KTheory.LIA import io.ksmt.solver.KTheory.LRA import io.ksmt.solver.KTheory.NIA import io.ksmt.solver.KTheory.NRA -import io.ksmt.solver.KTheory.Str +import io.ksmt.solver.KTheory.S import org.ksmt.solver.bitwuzla.bindings.Bitwuzla import org.ksmt.solver.bitwuzla.bindings.BitwuzlaOption import org.ksmt.solver.bitwuzla.bindings.Native @@ -53,7 +53,7 @@ class KBitwuzlaSolverConfigurationImpl(private val bitwuzla: Bitwuzla) : KBitwuz override fun optimizeForTheories(theories: Set?, quantifiersAllowed: Boolean) { if (theories.isNullOrEmpty()) return - if (setOf(LIA, LRA, NIA, NRA, Str).intersect(theories).isNotEmpty()) { + if (setOf(LIA, LRA, NIA, NRA, S).intersect(theories).isNotEmpty()) { throw KSolverUnsupportedFeatureException("Unsupported theories $theories") } } diff --git a/ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt b/ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt index 73fd885df..679348a25 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/solver/KTheory.kt @@ -8,7 +8,7 @@ import io.ksmt.solver.KTheory.LRA import io.ksmt.solver.KTheory.NIA import io.ksmt.solver.KTheory.NRA import io.ksmt.solver.KTheory.UF -import io.ksmt.solver.KTheory.Str +import io.ksmt.solver.KTheory.S /** * SMT theory @@ -16,7 +16,7 @@ import io.ksmt.solver.KTheory.Str enum class KTheory { UF, BV, FP, Array, LIA, NIA, LRA, NRA, - Str + S } @Suppress("ComplexMethod", "ComplexCondition") @@ -57,7 +57,7 @@ fun Set?.smtLib2String(quantifiersAllowed: Boolean = false): String = b append("FP") } - if (Str in theories) { + if (S in theories) { append("S") } diff --git a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesSolverConfiguration.kt b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesSolverConfiguration.kt index 88e1b3d80..793dc72e9 100644 --- a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesSolverConfiguration.kt +++ b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesSolverConfiguration.kt @@ -7,7 +7,7 @@ import io.ksmt.solver.KSolverUnsupportedFeatureException import io.ksmt.solver.KSolverUnsupportedParameterException import io.ksmt.solver.KTheory import io.ksmt.solver.KTheory.FP -import io.ksmt.solver.KTheory.Str +import io.ksmt.solver.KTheory.S import io.ksmt.solver.KTheory.LIA import io.ksmt.solver.KTheory.LRA import io.ksmt.solver.KTheory.NIA @@ -42,8 +42,8 @@ class KYicesSolverConfigurationImpl(private val config: Config) : KYicesSolverCo throw KSolverUnsupportedFeatureException("Unsupported theory $FP") } - if (Str in theories) { - throw KSolverUnsupportedFeatureException("Unsupported theory $Str") + if (S in theories) { + throw KSolverUnsupportedFeatureException("Unsupported theory $S") } // Yices requires MCSAT for the arithmetic theories From 6daeecc01407dc086799ce346ab7495fbcf27ca8 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Thu, 12 Dec 2024 03:37:20 +0300 Subject: [PATCH 48/84] Change the names of classes and methods, do the code formatting --- .../bitwuzla/KBitwuzlaExprInternalizer.kt | 44 +-- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 226 +++++------ .../main/kotlin/io/ksmt/decl/KDeclVisitor.kt | 22 +- .../src/main/kotlin/io/ksmt/decl/Regex.kt | 115 ++++-- .../src/main/kotlin/io/ksmt/decl/String.kt | 250 ++++++++---- .../src/main/kotlin/io/ksmt/expr/Regex.kt | 167 ++++---- .../src/main/kotlin/io/ksmt/expr/String.kt | 358 ++++++++++-------- .../transformer/KNonRecursiveTransformer.kt | 58 +-- .../expr/transformer/KNonRecursiveVisitor.kt | 42 +- .../io/ksmt/expr/transformer/KTransformer.kt | 44 +-- .../ksmt/expr/transformer/KTransformerBase.kt | 44 +-- .../io/ksmt/expr/transformer/KVisitor.kt | 66 ++-- .../io/ksmt/solver/cvc5/KCvc5ExprConverter.kt | 22 +- .../ksmt/solver/cvc5/KCvc5ExprInternalizer.kt | 64 ++-- .../solver/yices/KYicesExprInternalizer.kt | 44 +-- 15 files changed, 889 insertions(+), 677 deletions(-) diff --git a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt index 285af863f..d883f6472 100644 --- a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt +++ b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt @@ -155,16 +155,16 @@ import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KStringInRegexExpr -import io.ksmt.expr.KSuffixOfExpr -import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringSuffixOfExpr +import io.ksmt.expr.KStringPrefixOfExpr import io.ksmt.expr.KStringLtExpr import io.ksmt.expr.KStringLeExpr import io.ksmt.expr.KStringGtExpr import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KStringContainsExpr -import io.ksmt.expr.KSingletonSubstringExpr -import io.ksmt.expr.KSubstringExpr -import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringSingletonSubExpr +import io.ksmt.expr.KStringSubExpr +import io.ksmt.expr.KStringIndexOfExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr @@ -178,15 +178,15 @@ import io.ksmt.expr.KStringLiteralExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr import io.ksmt.expr.KRegexIntersectionExpr -import io.ksmt.expr.KRegexKleeneClosureExpr -import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexStarExpr +import io.ksmt.expr.KRegexCrossExpr import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr -import io.ksmt.expr.KRangeExpr -import io.ksmt.expr.KEpsilon -import io.ksmt.expr.KAll -import io.ksmt.expr.KAllChar +import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexEpsilon +import io.ksmt.expr.KRegexAll +import io.ksmt.expr.KRegexAllChar import io.ksmt.expr.rewrite.simplify.rewriteBvAddNoUnderflowExpr import io.ksmt.expr.rewrite.simplify.rewriteBvMulNoUnderflowExpr import io.ksmt.expr.rewrite.simplify.rewriteBvNegNoOverflowExpr @@ -1459,11 +1459,11 @@ open class KBitwuzlaExprInternalizer(val bitwuzlaCtx: KBitwuzlaContext) : KExprL throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } - override fun transform(expr: KSuffixOfExpr): KExpr { + override fun transform(expr: KStringSuffixOfExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } - override fun transform(expr: KPrefixOfExpr): KExpr { + override fun transform(expr: KStringPrefixOfExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } @@ -1487,15 +1487,15 @@ open class KBitwuzlaExprInternalizer(val bitwuzlaCtx: KBitwuzlaContext) : KExprL throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } - override fun transform(expr: KSingletonSubstringExpr): KExpr { + override fun transform(expr: KStringSingletonSubExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } - override fun transform(expr: KSubstringExpr): KExpr { + override fun transform(expr: KStringSubExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } - override fun transform(expr: KIndexOfExpr): KExpr { + override fun transform(expr: KStringIndexOfExpr): KExpr { throw KSolverUnsupportedFeatureException("string and int theory is not supported in Bitwuzla") } @@ -1551,11 +1551,11 @@ open class KBitwuzlaExprInternalizer(val bitwuzlaCtx: KBitwuzlaContext) : KExprL throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } - override fun transform(expr: KRegexKleeneClosureExpr): KExpr { + override fun transform(expr: KRegexStarExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } - override fun transform(expr: KRegexKleeneCrossExpr): KExpr { + override fun transform(expr: KRegexCrossExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } @@ -1571,19 +1571,19 @@ open class KBitwuzlaExprInternalizer(val bitwuzlaCtx: KBitwuzlaContext) : KExprL throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } - override fun transform(expr: KRangeExpr): KExpr { + override fun transform(expr: KRegexRangeExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } - override fun transform(expr: KEpsilon): KExpr { + override fun transform(expr: KRegexEpsilon): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } - override fun transform(expr: KAll): KExpr { + override fun transform(expr: KRegexAll): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } - override fun transform(expr: KAllChar): KExpr { + override fun transform(expr: KRegexAllChar): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index f1bbba3fa..b9ddf2241 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -134,16 +134,16 @@ import io.ksmt.decl.KStringConcatDecl import io.ksmt.decl.KStringLenDecl import io.ksmt.decl.KStringToRegexDecl import io.ksmt.decl.KStringInRegexDecl -import io.ksmt.decl.KSuffixOfDecl -import io.ksmt.decl.KPrefixOfDecl +import io.ksmt.decl.KStringSuffixOfDecl +import io.ksmt.decl.KStringPrefixOfDecl import io.ksmt.decl.KStringLtDecl import io.ksmt.decl.KStringLeDecl import io.ksmt.decl.KStringGtDecl import io.ksmt.decl.KStringGeDecl import io.ksmt.decl.KStringContainsDecl -import io.ksmt.decl.KSingletonSubstringDecl -import io.ksmt.decl.KSubstringDecl -import io.ksmt.decl.KIndexOfDecl +import io.ksmt.decl.KStringSingletonSubDecl +import io.ksmt.decl.KStringSubDecl +import io.ksmt.decl.KStringIndexOfDecl import io.ksmt.decl.KStringReplaceDecl import io.ksmt.decl.KStringReplaceAllDecl import io.ksmt.decl.KStringReplaceWithRegexDecl @@ -153,18 +153,18 @@ import io.ksmt.decl.KStringToCodeDecl import io.ksmt.decl.KStringFromCodeDecl import io.ksmt.decl.KStringToIntDecl import io.ksmt.decl.KStringFromIntDecl -import io.ksmt.decl.KEpsilonDecl -import io.ksmt.decl.KAllDecl -import io.ksmt.decl.KAllCharDecl +import io.ksmt.decl.KRegexEpsilonDecl +import io.ksmt.decl.KRegexAllDecl +import io.ksmt.decl.KRegexAllCharDecl import io.ksmt.decl.KRegexConcatDecl import io.ksmt.decl.KRegexUnionDecl import io.ksmt.decl.KRegexIntersectionDecl -import io.ksmt.decl.KRegexKleeneClosureDecl -import io.ksmt.decl.KRegexKleeneCrossDecl +import io.ksmt.decl.KRegexStarDecl +import io.ksmt.decl.KRegexCrossDecl import io.ksmt.decl.KRegexDifferenceDecl import io.ksmt.decl.KRegexComplementDecl import io.ksmt.decl.KRegexOptionDecl -import io.ksmt.decl.KRangeDecl +import io.ksmt.decl.KRegexRangeDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl import io.ksmt.decl.KOrDecl @@ -313,16 +313,16 @@ import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KStringInRegexExpr -import io.ksmt.expr.KSuffixOfExpr -import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringSuffixOfExpr +import io.ksmt.expr.KStringPrefixOfExpr import io.ksmt.expr.KStringLtExpr import io.ksmt.expr.KStringLeExpr import io.ksmt.expr.KStringGtExpr import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KStringContainsExpr -import io.ksmt.expr.KSingletonSubstringExpr -import io.ksmt.expr.KSubstringExpr -import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringSingletonSubExpr +import io.ksmt.expr.KStringSubExpr +import io.ksmt.expr.KStringIndexOfExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr @@ -332,18 +332,18 @@ import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr import io.ksmt.expr.KStringToIntExpr import io.ksmt.expr.KStringFromIntExpr -import io.ksmt.expr.KEpsilon -import io.ksmt.expr.KAll -import io.ksmt.expr.KAllChar +import io.ksmt.expr.KRegexEpsilon +import io.ksmt.expr.KRegexAll +import io.ksmt.expr.KRegexAllChar import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr import io.ksmt.expr.KRegexIntersectionExpr -import io.ksmt.expr.KRegexKleeneClosureExpr -import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexStarExpr +import io.ksmt.expr.KRegexCrossExpr import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr -import io.ksmt.expr.KRangeExpr +import io.ksmt.expr.KRegexRangeExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr import io.ksmt.expr.KLtArithExpr @@ -1972,6 +1972,9 @@ open class KContext( KStringLiteralExpr(this, value) } + /** + * Create a String value. + * */ val String.expr get() = mkStringLiteral(this) @@ -2020,49 +2023,43 @@ open class KContext( val String.len get() = mkStringLen(this.expr) - private val suffixOfExprCache = mkAstInterner() + private val stringSuffixOfExprCache = mkAstInterner() /** * Check if first string is a suffix of second. * */ - open fun mkSuffixOf(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkSuffixOfNoSimplify, ::mkSuffixOfNoSimplify) // Add simplified version + open fun mkStringSuffixOf(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkStringSuffixOfNoSimplify, ::mkStringSuffixOfNoSimplify) // Add simplified version /** * Check if first string is a suffix of second. * */ - open fun mkSuffixOfNoSimplify(arg0: KExpr, arg1: KExpr): KSuffixOfExpr = - suffixOfExprCache.createIfContextActive { + open fun mkStringSuffixOfNoSimplify(arg0: KExpr, arg1: KExpr): KStringSuffixOfExpr = + stringSuffixOfExprCache.createIfContextActive { ensureContextMatch(arg0, arg1) - KSuffixOfExpr(this, arg0, arg1) + KStringSuffixOfExpr(this, arg0, arg1) } - /** - * Check if first string is a suffix of second. - * */ - infix fun KExpr.isSuffixOf(other: KExpr) = mkSuffixOf(this, other) + infix fun KExpr.isSuffixOf(other: KExpr) = mkStringSuffixOf(this, other) - private val prefixOfExprCache = mkAstInterner() + private val stringPrefixOfExprCache = mkAstInterner() /** * Check if first string is a prefix of second. * */ - open fun mkPrefixOf(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkPrefixOfNoSimplify, ::mkPrefixOfNoSimplify) // Add simplified version + open fun mkStringPrefixOf(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkStringPrefixOfNoSimplify, ::mkStringPrefixOfNoSimplify) // Add simplified version /** * Check if first string is a prefix of second. * */ - open fun mkPrefixOfNoSimplify(arg0: KExpr, arg1: KExpr): KPrefixOfExpr = - prefixOfExprCache.createIfContextActive { + open fun mkStringPrefixOfNoSimplify(arg0: KExpr, arg1: KExpr): KStringPrefixOfExpr = + stringPrefixOfExprCache.createIfContextActive { ensureContextMatch(arg0, arg1) - KPrefixOfExpr(this, arg0, arg1) + KStringPrefixOfExpr(this, arg0, arg1) } - /** - * Check if first string is a prefix of second. - * */ - infix fun KExpr.isPrefixOf(other: KExpr) = mkPrefixOf(this, other) + infix fun KExpr.isPrefixOf(other: KExpr) = mkStringPrefixOf(this, other) private val stringLtCache = mkAstInterner() @@ -2081,9 +2078,6 @@ open class KContext( KStringLtExpr(this, lhs, rhs) } - /** - * Create a lexicographic ordering (`<` (less)) expression. - * */ @JvmName("stringLt") infix fun KExpr.lt(other: KExpr) = mkStringLt(this, other) @@ -2104,9 +2098,6 @@ open class KContext( KStringLeExpr(this, lhs, rhs) } - /** - * Create a lexicographic ordering reflexive closure (`<=` (less or equal)) expression. - * */ @JvmName("stringLe") infix fun KExpr.le(other: KExpr) = mkStringLe(this, other) @@ -2127,9 +2118,6 @@ open class KContext( KStringGtExpr(this, lhs, rhs) } - /** - * Create a lexicographic ordering (`>` (greater)) expression. - * */ @JvmName("stringGt") infix fun KExpr.gt(other: KExpr) = mkStringGt(this, other) @@ -2150,9 +2138,6 @@ open class KContext( KStringGeExpr(this, lhs, rhs) } - /** - * Create a lexicographic ordering reflexive closure (`>=` (greater or equal)) expression. - * */ @JvmName("stringGe") infix fun KExpr.ge(other: KExpr) = mkStringGe(this, other) @@ -2173,53 +2158,50 @@ open class KContext( KStringContainsExpr(this, lhs, rhs) } - /** - * Check if first string contains second one. - * */ @JvmName("strContains") infix fun KExpr.contains(other: KExpr) = mkStringContains(this, other) - private val singletonSubstringCache = mkAstInterner() + private val stringSingletonSubCache = mkAstInterner() /** * Returns singleton string containing a character at given position. * If position is out of range (less than 0, or grater than (string length - 1)), then returns empty string. * */ - open fun mkSingletonSubstring(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkSingletonSubstringNoSimplify, ::mkSingletonSubstringNoSimplify) // Add simplified version + open fun mkStringSingletonSub(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkStringSingletonSubNoSimplify, ::mkStringSingletonSubNoSimplify) // Add simplified version /** * Returns singleton string containing a character at given position. * If position is out of range (less than 0, or grater than (string length - 1)), then returns empty string. * */ - open fun mkSingletonSubstringNoSimplify(arg0: KExpr, arg1: KExpr): KSingletonSubstringExpr = - singletonSubstringCache.createIfContextActive { + open fun mkStringSingletonSubNoSimplify(arg0: KExpr, arg1: KExpr): KStringSingletonSubExpr = + stringSingletonSubCache.createIfContextActive { ensureContextMatch(arg0, arg1) - KSingletonSubstringExpr(this, arg0, arg1) + KStringSingletonSubExpr(this, arg0, arg1) } - private val substringCache = mkAstInterner() + private val stringSubCache = mkAstInterner() /** * Evaluates the longest substring from the input string, starting at the specified position * and extending up to the given length. Returns an empty string if the given length is negative * or the given position is out of bounds. */ - open fun mkSubstring(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::mkSubstringNoSimplify, ::mkSubstringNoSimplify) // Add simplified version + open fun mkStringSub(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = + mkSimplified(arg0, arg1, arg2, KContext::mkStringSubNoSimplify, ::mkStringSubNoSimplify) // Add simplified version /** * Evaluates the longest substring from the input string, starting at the specified position * and extending up to the given length. Returns an empty string if the given length is negative * or the given position is out of bounds. */ - open fun mkSubstringNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KSubstringExpr = - substringCache.createIfContextActive { + open fun mkStringSubNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringSubExpr = + stringSubCache.createIfContextActive { ensureContextMatch(arg0, arg1) - KSubstringExpr(this, arg0, arg1, arg2) + KStringSubExpr(this, arg0, arg1, arg2) } - private val indexOfCache = mkAstInterner() + private val stringIndexOfCache = mkAstInterner() /** * Find the index of the first occurrence of the second string in the first string, @@ -2227,8 +2209,8 @@ open class KContext( * or if the position is out of bounds. * Returns the position if the second string is empty. */ - open fun mkIndexOf(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::mkIndexOfNoSimplify, ::mkIndexOfNoSimplify) // Add simplified version + open fun mkStringIndexOf(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = + mkSimplified(arg0, arg1, arg2, KContext::mkStringIndexOfNoSimplify, ::mkStringIndexOfNoSimplify) // Add simplified version /** * Find the index of the first occurrence of the second string in the first string, @@ -2236,10 +2218,10 @@ open class KContext( * or if the position is out of bounds. * Returns the position if the second string is empty. */ - open fun mkIndexOfNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KIndexOfExpr = - indexOfCache.createIfContextActive { + open fun mkStringIndexOfNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringIndexOfExpr = + stringIndexOfCache.createIfContextActive { ensureContextMatch(arg0, arg1) - KIndexOfExpr(this, arg0, arg1, arg2) + KStringIndexOfExpr(this, arg0, arg1, arg2) } private val stringReplaceCache = mkAstInterner() @@ -2427,14 +2409,8 @@ open class KContext( KStringToRegexExpr(this, arg) } - /** - * Create a regular expression based on a string expression. - * */ fun KExpr.toRegex() = mkStringToRegex(this) - /** - * Create a regular expression based on a string expression. - * */ fun String.toRegex() = mkStringToRegex(this.expr) private val stringInRegexExprCache = mkAstInterner() @@ -2454,19 +2430,10 @@ open class KContext( KStringInRegexExpr(this, arg0, arg1) } - /** - * Check if a string belongs to the language defined by the regular expression. - * */ infix fun KExpr.inRegex(other: KExpr) = mkStringInRegex(this, other) - /** - * Check if a string belongs to the language defined by the regular expression. - * */ infix fun String.inRegex(other: KExpr) = mkStringInRegex(this.expr, other) - /** - * Check if a string belongs to the language defined by the regular expression. - * */ @JvmName("regexContains") infix fun KExpr.contains(other: KExpr) = mkStringInRegex(other, this) @@ -2487,9 +2454,6 @@ open class KContext( KRegexConcatExpr(this, arg0, arg1) } - /** - * Create Regex concatenation (`concat`) expression. - * */ @JvmName("regexConcat") operator fun KExpr.plus(other: KExpr) = mkRegexConcat(this, other) @@ -2527,37 +2491,39 @@ open class KContext( KRegexIntersectionExpr(this, arg0, arg1) } - private val regexKleeneClosureExprCache = mkAstInterner() + private val regexStarExprCache = mkAstInterner() /** * Create regular expression's Kleene closure. * */ - open fun mkRegexKleeneClosure(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkRegexKleeneClosureNoSimplify, ::mkRegexKleeneClosureNoSimplify) // Add simplified version + open fun mkRegexStar(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkRegexStarNoSimplify, ::mkRegexStarNoSimplify) // Add simplified version /** * Create regular expression's Kleene closure. * */ - open fun mkRegexKleeneClosureNoSimplify(arg: KExpr): KRegexKleeneClosureExpr = regexKleeneClosureExprCache.createIfContextActive { - ensureContextMatch(arg) - KRegexKleeneClosureExpr(this, arg) - } + open fun mkRegexStarNoSimplify(arg: KExpr): KRegexStarExpr = + regexStarExprCache.createIfContextActive { + ensureContextMatch(arg) + KRegexStarExpr(this, arg) + } - private val regexKleeneCrossExprCache = mkAstInterner() + private val regexCrossExprCache = mkAstInterner() /** * Create regular expression's Kleene cross. * */ - open fun mkRegexKleeneCross(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkRegexKleeneCrossNoSimplify, ::mkRegexKleeneCrossNoSimplify) // Add simplified version + open fun mkRegexCross(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkRegexCrossNoSimplify, ::mkRegexCrossNoSimplify) // Add simplified version /** * Create regular expression's Kleene cross. * */ - open fun mkRegexKleeneCrossNoSimplify(arg: KExpr): KRegexKleeneCrossExpr = regexKleeneCrossExprCache.createIfContextActive { - ensureContextMatch(arg) - KRegexKleeneCrossExpr(this, arg) - } + open fun mkRegexCrossNoSimplify(arg: KExpr): KRegexCrossExpr = + regexCrossExprCache.createIfContextActive { + ensureContextMatch(arg) + KRegexCrossExpr(this, arg) + } private val regexDifferenceExprCache = mkAstInterner() @@ -2610,48 +2576,48 @@ open class KContext( KRegexOptionExpr(this, arg) } - private val rangeExprCache = mkAstInterner() + private val regexRangeExprCache = mkAstInterner() /** * Return the set of all singleton strings in the range * between the first and second string that are also singletons. * Otherwise the empty set. * */ - open fun mkRange(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkRangeNoSimplify, ::mkRangeNoSimplify) // Add simplified version + open fun mkRegexRange(arg0: KExpr, arg1: KExpr): KExpr = + mkSimplified(arg0, arg1, KContext::mkRegexRangeNoSimplify, ::mkRegexRangeNoSimplify) // Add simplified version /** * Return the set of all singleton strings in the range * between the first and second string that are also singletons. * Otherwise the empty set. * */ - open fun mkRangeNoSimplify(arg0: KExpr, arg1: KExpr): KRangeExpr = - rangeExprCache.createIfContextActive { + open fun mkRegexRangeNoSimplify(arg0: KExpr, arg1: KExpr): KRegexRangeExpr = + regexRangeExprCache.createIfContextActive { ensureContextMatch(arg0, arg1) - KRangeExpr(this, arg0, arg1) + KRegexRangeExpr(this, arg0, arg1) } - val epsilonExpr: KEpsilon = KEpsilon(this) + val regexEpsilonExpr: KRegexEpsilon = KRegexEpsilon(this) /** * Create regex Epsilon constant. * Epsilon regular expression denoting the empty set of strings. * */ - fun mkEpsilon(): KEpsilon = epsilonExpr + fun mkRegexEpsilon(): KRegexEpsilon = regexEpsilonExpr - val allExpr: KAll = KAll(this) + val regexAllExpr: KRegexAll = KRegexAll(this) /** * Create regex constant denoting the set of all strings. * */ - fun mkAll(): KAll = allExpr + fun mkRegexAll(): KRegexAll = regexAllExpr - val allCharExpr: KAllChar = KAllChar(this) + val regexAllCharExpr: KRegexAllChar = KRegexAllChar(this) /** * Create regex constant denoting the set of all strings of length 1. * */ - fun mkAllChar(): KAllChar = allCharExpr + fun mkRegexAllChar(): KRegexAllChar = regexAllCharExpr // bitvectors private val bv1Cache = mkAstInterner() @@ -5263,9 +5229,9 @@ open class KContext( fun mkStringInRegexDecl(): KStringInRegexDecl = KStringInRegexDecl(this) - fun mkSuffixOfDecl(): KSuffixOfDecl = KSuffixOfDecl(this) + fun mkStringSuffixOfDecl(): KStringSuffixOfDecl = KStringSuffixOfDecl(this) - fun mkPrefixOfDecl(): KPrefixOfDecl = KPrefixOfDecl(this) + fun mkStringPrefixOfDecl(): KStringPrefixOfDecl = KStringPrefixOfDecl(this) fun mkStringLtDecl(): KStringLtDecl = KStringLtDecl(this) @@ -5277,11 +5243,11 @@ open class KContext( fun mkStringContainsDecl(): KStringContainsDecl = KStringContainsDecl(this) - fun mkSingletonSubstringDecl(): KSingletonSubstringDecl = KSingletonSubstringDecl(this) + fun mkStringSingletonSubDecl(): KStringSingletonSubDecl = KStringSingletonSubDecl(this) - fun mkSubstringDecl(): KSubstringDecl = KSubstringDecl(this) + fun mkStringSubDecl(): KStringSubDecl = KStringSubDecl(this) - fun mkIndexOfDecl(): KIndexOfDecl = KIndexOfDecl(this) + fun mkStringIndexOfDecl(): KStringIndexOfDecl = KStringIndexOfDecl(this) fun mkStringReplaceDecl(): KStringReplaceDecl = KStringReplaceDecl(this) @@ -5308,9 +5274,9 @@ open class KContext( fun mkRegexIntersectionDecl(): KRegexIntersectionDecl = KRegexIntersectionDecl(this) - fun mkRegexKleeneClosureDecl(): KRegexKleeneClosureDecl = KRegexKleeneClosureDecl(this) + fun mkRegexStarDecl(): KRegexStarDecl = KRegexStarDecl(this) - fun mkRegexKleeneCrossDecl(): KRegexKleeneCrossDecl = KRegexKleeneCrossDecl(this) + fun mkRegexCrossDecl(): KRegexCrossDecl = KRegexCrossDecl(this) fun mkRegexDifferenceDecl(): KRegexDifferenceDecl = KRegexDifferenceDecl(this) @@ -5318,13 +5284,13 @@ open class KContext( fun mkRegexOptionDecl(): KRegexOptionDecl = KRegexOptionDecl(this) - fun mkRangeDecl(): KRangeDecl = KRangeDecl(this) + fun mkRegexRangeDecl(): KRegexRangeDecl = KRegexRangeDecl(this) - fun mkEpsilonDecl(): KEpsilonDecl = KEpsilonDecl(this) + fun mkRegexEpsilonDecl(): KRegexEpsilonDecl = KRegexEpsilonDecl(this) - fun mkAllDecl(): KAllDecl = KAllDecl(this) + fun mkRegexAllDecl(): KRegexAllDecl = KRegexAllDecl(this) - fun mkAllCharDecl(): KAllCharDecl = KAllCharDecl(this) + fun mkRegexAllCharDecl(): KRegexAllCharDecl = KRegexAllCharDecl(this) // Bit vectors fun mkBvDecl(value: Boolean): KDecl = diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt index 41680c676..d86452ebf 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt @@ -138,16 +138,16 @@ interface KDeclVisitor { fun visit(decl: KStringLenDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringToRegexDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringInRegexDecl): T = visit(decl as KFuncDecl) - fun visit(decl: KSuffixOfDecl): T = visit(decl as KFuncDecl) - fun visit(decl: KPrefixOfDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringSuffixOfDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringPrefixOfDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringLtDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringLeDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringGtDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringGeDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringContainsDecl): T = visit(decl as KFuncDecl) - fun visit(decl: KSingletonSubstringDecl): T = visit(decl as KFuncDecl) - fun visit(decl: KSubstringDecl): T = visit(decl as KFuncDecl) - fun visit(decl: KIndexOfDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringSingletonSubDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringSubDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringIndexOfDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringReplaceDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringReplaceAllDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringReplaceWithRegexDecl): T = visit(decl as KFuncDecl) @@ -162,13 +162,13 @@ interface KDeclVisitor { fun visit(decl: KRegexConcatDecl): T = visit(decl as KFuncDecl) fun visit(decl: KRegexUnionDecl): T = visit(decl as KFuncDecl) fun visit(decl: KRegexIntersectionDecl): T = visit(decl as KFuncDecl) - fun visit(decl: KRegexKleeneClosureDecl): T = visit(decl as KFuncDecl) - fun visit(decl: KRegexKleeneCrossDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRegexStarDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRegexCrossDecl): T = visit(decl as KFuncDecl) fun visit(decl: KRegexDifferenceDecl): T = visit(decl as KFuncDecl) fun visit(decl: KRegexComplementDecl): T = visit(decl as KFuncDecl) fun visit(decl: KRegexOptionDecl): T = visit(decl as KFuncDecl) - fun visit(decl: KRangeDecl): T = visit(decl as KFuncDecl) - fun visit(decl: KEpsilonDecl): T = visit(decl as KConstDecl) - fun visit(decl: KAllDecl): T = visit(decl as KConstDecl) - fun visit(decl: KAllCharDecl): T = visit(decl as KConstDecl) + fun visit(decl: KRegexRangeDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRegexEpsilonDecl): T = visit(decl as KConstDecl) + fun visit(decl: KRegexAllDecl): T = visit(decl as KConstDecl) + fun visit(decl: KRegexAllCharDecl): T = visit(decl as KConstDecl) } diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index df893e53c..9411f08d9 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -10,8 +10,8 @@ class KRegexConcatDecl internal constructor( ctx: KContext, ) : KFuncDecl2( ctx, - name = "regex_concat", - resultSort = ctx.mkRegexSort(), + "regex_concat", + ctx.mkRegexSort(), ctx.mkRegexSort(), ctx.mkRegexSort() ) { @@ -27,8 +27,8 @@ class KRegexUnionDecl internal constructor( ctx: KContext, ) : KFuncDecl2( ctx, - name = "union", - resultSort = ctx.mkRegexSort(), + "regex_union", + ctx.mkRegexSort(), ctx.mkRegexSort(), ctx.mkRegexSort() ) { @@ -44,8 +44,8 @@ class KRegexIntersectionDecl internal constructor( ctx: KContext, ) : KFuncDecl2( ctx, - name = "intersect", - resultSort = ctx.mkRegexSort(), + "regex_intersect", + ctx.mkRegexSort(), ctx.mkRegexSort(), ctx.mkRegexSort() ) { @@ -57,26 +57,42 @@ class KRegexIntersectionDecl internal constructor( ): KApp = mkRegexIntersectionNoSimplify(arg0, arg1) } -class KRegexKleeneClosureDecl internal constructor( +class KRegexStarDecl internal constructor( ctx: KContext -) : KFuncDecl1(ctx, "closure", ctx.mkRegexSort(), ctx.mkRegexSort()) { - override fun KContext.apply(arg: KExpr): KApp = mkRegexKleeneClosureNoSimplify(arg) +) : KFuncDecl1( + ctx, + "regex_star", + ctx.mkRegexSort(), + ctx.mkRegexSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg: KExpr + ): KApp = mkRegexStarNoSimplify(arg) } -class KRegexKleeneCrossDecl internal constructor( +class KRegexCrossDecl internal constructor( ctx: KContext -) : KFuncDecl1(ctx, "kleene_cross", ctx.mkRegexSort(), ctx.mkRegexSort()) { - override fun KContext.apply(arg: KExpr): KApp = mkRegexKleeneCrossNoSimplify(arg) +) : KFuncDecl1( + ctx, + "regex_cross", + ctx.mkRegexSort(), + ctx.mkRegexSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg: KExpr + ): KApp = mkRegexCrossNoSimplify(arg) } class KRegexDifferenceDecl internal constructor( ctx: KContext, ) : KFuncDecl2( ctx, - name = "diff", - resultSort = ctx.mkRegexSort(), + "regex_diff", + ctx.mkRegexSort(), ctx.mkRegexSort(), ctx.mkRegexSort() ) { @@ -90,24 +106,40 @@ class KRegexDifferenceDecl internal constructor( class KRegexComplementDecl internal constructor( ctx: KContext -) : KFuncDecl1(ctx, "comp", ctx.mkRegexSort(), ctx.mkRegexSort()) { - override fun KContext.apply(arg: KExpr): KApp = mkRegexComplementNoSimplify(arg) +) : KFuncDecl1( + ctx, + "regex_comp", + ctx.mkRegexSort(), + ctx.mkRegexSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg: KExpr + ): KApp = mkRegexComplementNoSimplify(arg) } class KRegexOptionDecl internal constructor( ctx: KContext -) : KFuncDecl1(ctx, "opt", ctx.mkRegexSort(), ctx.mkRegexSort()) { - override fun KContext.apply(arg: KExpr): KApp = mkRegexOptionNoSimplify(arg) +) : KFuncDecl1( + ctx, + "regex_opt", + ctx.mkRegexSort(), + ctx.mkRegexSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg: KExpr + ): KApp = mkRegexOptionNoSimplify(arg) } -class KRangeDecl internal constructor( +class KRegexRangeDecl internal constructor( ctx: KContext, ) : KFuncDecl2( ctx, - name = "range", - resultSort = ctx.mkRegexSort(), + "regex_range", + ctx.mkRegexSort(), ctx.mkStringSort(), ctx.mkStringSort() ) { @@ -116,26 +148,47 @@ class KRangeDecl internal constructor( override fun KContext.apply( arg0: KExpr, arg1: KExpr - ): KApp = mkRangeNoSimplify(arg0, arg1) + ): KApp = mkRegexRangeNoSimplify(arg0, arg1) } -class KEpsilonDecl internal constructor( +class KRegexEpsilonDecl internal constructor( ctx: KContext -) : KConstDecl(ctx, "eps", ctx.mkRegexSort()) { - override fun apply(args: List>): KApp = ctx.mkEpsilon() +) : KConstDecl( + ctx, + "regex_eps", + ctx.mkRegexSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun apply( + args: List> + ): KApp = ctx.mkRegexEpsilon() } -class KAllDecl internal constructor( +class KRegexAllDecl internal constructor( ctx: KContext -) : KConstDecl(ctx, "all", ctx.mkRegexSort()) { - override fun apply(args: List>): KApp = ctx.mkAll() +) : KConstDecl( + ctx, + "regex_all", + ctx.mkRegexSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun apply( + args: List> + ): KApp = ctx.mkRegexAll() } -class KAllCharDecl internal constructor( +class KRegexAllCharDecl internal constructor( ctx: KContext -) : KConstDecl(ctx, "all_char", ctx.mkRegexSort()) { - override fun apply(args: List>): KApp = ctx.mkAllChar() +) : KConstDecl( + ctx, + "regex_all_char", + ctx.mkRegexSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun apply( + args: List> + ): KApp = ctx.mkRegexAllChar() } diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index 95ffed3b6..ec8e06de1 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -8,20 +8,12 @@ import io.ksmt.sort.KIntSort import io.ksmt.sort.KRegexSort import io.ksmt.sort.KStringSort -class KStringLiteralDecl internal constructor( - ctx: KContext, - val value: String -) : KConstDecl(ctx, value, ctx.mkStringSort()) { - override fun apply(args: List>): KApp = ctx.mkStringLiteral(value) - override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) -} - class KStringConcatDecl internal constructor( ctx: KContext, ) : KFuncDecl2( ctx, - name = "str_concat", - resultSort = ctx.mkStringSort(), + "str_concat", + ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkStringSort() ) { @@ -35,24 +27,40 @@ class KStringConcatDecl internal constructor( class KStringLenDecl internal constructor( ctx: KContext -) : KFuncDecl1(ctx, "len", ctx.mkIntSort(), ctx.mkStringSort()) { - override fun KContext.apply(arg: KExpr): KApp = mkStringLenNoSimplify(arg) +) : KFuncDecl1( + ctx, + "str_len", + ctx.mkIntSort(), + ctx.mkStringSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg: KExpr + ): KApp = mkStringLenNoSimplify(arg) } class KStringToRegexDecl internal constructor( ctx: KContext -) : KFuncDecl1(ctx, "to_regex", ctx.mkRegexSort(), ctx.mkStringSort()) { - override fun KContext.apply(arg: KExpr): KApp = mkStringToRegexNoSimplify(arg) +) : KFuncDecl1( + ctx, + "str_to_regex", + ctx.mkRegexSort(), + ctx.mkStringSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg: KExpr + ): KApp = mkStringToRegexNoSimplify(arg) } class KStringInRegexDecl internal constructor( ctx: KContext, ) : KFuncDecl2( ctx, - name = "in_regex", - resultSort = ctx.mkBoolSort(), + "str_in_regex", + ctx.mkBoolSort(), ctx.mkStringSort(), ctx.mkRegexSort() ) { @@ -64,12 +72,12 @@ class KStringInRegexDecl internal constructor( ): KApp = mkStringInRegexNoSimplify(arg0, arg1) } -class KSuffixOfDecl internal constructor( +class KStringSuffixOfDecl internal constructor( ctx: KContext, ) : KFuncDecl2( ctx, - name = "suffix_of", - resultSort = ctx.mkBoolSort(), + "str_suffix_of", + ctx.mkBoolSort(), ctx.mkStringSort(), ctx.mkStringSort() ) { @@ -78,15 +86,15 @@ class KSuffixOfDecl internal constructor( override fun KContext.apply( arg0: KExpr, arg1: KExpr - ): KApp = mkSuffixOfNoSimplify(arg0, arg1) + ): KApp = mkStringSuffixOfNoSimplify(arg0, arg1) } -class KPrefixOfDecl internal constructor( +class KStringPrefixOfDecl internal constructor( ctx: KContext, ) : KFuncDecl2( ctx, - name = "prefix_of", - resultSort = ctx.mkBoolSort(), + "str_prefix_of", + ctx.mkBoolSort(), ctx.mkStringSort(), ctx.mkStringSort() ) { @@ -95,51 +103,116 @@ class KPrefixOfDecl internal constructor( override fun KContext.apply( arg0: KExpr, arg1: KExpr - ): KApp = mkPrefixOfNoSimplify(arg0, arg1) + ): KApp = mkStringPrefixOfNoSimplify(arg0, arg1) } -class KStringLtDecl internal constructor(ctx: KContext) : - KFuncDecl2(ctx, "stringLt", ctx.mkBoolSort(), ctx.mkStringSort(), ctx.mkStringSort()) { - override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkStringLtNoSimplify(arg0, arg1) +class KStringLtDecl internal constructor( + ctx: KContext +) : KFuncDecl2( + ctx, + "str_lt", + ctx.mkBoolSort(), + ctx.mkStringSort(), + ctx.mkStringSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkStringLtNoSimplify(arg0, arg1) } -class KStringLeDecl internal constructor(ctx: KContext) : - KFuncDecl2(ctx, "stringLe", ctx.mkBoolSort(), ctx.mkStringSort(), ctx.mkStringSort()) { - override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkStringLeNoSimplify(arg0, arg1) +class KStringLeDecl internal constructor( + ctx: KContext +) : KFuncDecl2( + ctx, + "str_le", + ctx.mkBoolSort(), + ctx.mkStringSort(), + ctx.mkStringSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkStringLeNoSimplify(arg0, arg1) } -class KStringGtDecl internal constructor(ctx: KContext) : - KFuncDecl2(ctx, "stringGt", ctx.mkBoolSort(), ctx.mkStringSort(), ctx.mkStringSort()) { - override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkStringGtNoSimplify(arg0, arg1) +class KStringGtDecl internal constructor( + ctx: KContext +) : KFuncDecl2( + ctx, + "str_gt", + ctx.mkBoolSort(), + ctx.mkStringSort(), + ctx.mkStringSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkStringGtNoSimplify(arg0, arg1) } -class KStringGeDecl internal constructor(ctx: KContext) : - KFuncDecl2(ctx, "stringGe", ctx.mkBoolSort(), ctx.mkStringSort(), ctx.mkStringSort()) { - override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkStringGeNoSimplify(arg0, arg1) +class KStringGeDecl internal constructor( + ctx: KContext +) : KFuncDecl2( + ctx, + "str_ge", + ctx.mkBoolSort(), + ctx.mkStringSort(), + ctx.mkStringSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkStringGeNoSimplify(arg0, arg1) } -class KStringContainsDecl internal constructor(ctx: KContext) : - KFuncDecl2(ctx, "contains", ctx.mkBoolSort(), ctx.mkStringSort(), ctx.mkStringSort()) { - override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkStringContainsNoSimplify(arg0, arg1) +class KStringContainsDecl internal constructor( + ctx: KContext +) : KFuncDecl2( + ctx, + "str_contains", + ctx.mkBoolSort(), + ctx.mkStringSort(), + ctx.mkStringSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkStringContainsNoSimplify(arg0, arg1) } -class KSingletonSubstringDecl internal constructor(ctx: KContext) : - KFuncDecl2(ctx, "singleton_substr", ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkIntSort()) { - override fun KContext.apply(arg0: KExpr, arg1: KExpr): KApp = mkSingletonSubstringNoSimplify(arg0, arg1) +class KStringSingletonSubDecl internal constructor( + ctx: KContext +) : KFuncDecl2( + ctx, + "str_singleton_sub", + ctx.mkStringSort(), + ctx.mkStringSort(), + ctx.mkIntSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr + ): KApp = mkStringSingletonSubNoSimplify(arg0, arg1) } -class KSubstringDecl internal constructor( +class KStringSubDecl internal constructor( ctx: KContext, ) : KFuncDecl3( ctx, - name = "substr", - resultSort = ctx.mkStringSort(), + "str_sub", + ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkIntSort(), ctx.mkIntSort() @@ -150,15 +223,15 @@ class KSubstringDecl internal constructor( arg0: KExpr, arg1: KExpr, arg2: KExpr - ): KApp = mkSubstringNoSimplify(arg0, arg1, arg2) + ): KApp = mkStringSubNoSimplify(arg0, arg1, arg2) } -class KIndexOfDecl internal constructor( +class KStringIndexOfDecl internal constructor( ctx: KContext, ) : KFuncDecl3( ctx, - name = "index_of", - resultSort = ctx.mkIntSort(), + "str_index_of", + ctx.mkIntSort(), ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkIntSort() @@ -169,15 +242,15 @@ class KIndexOfDecl internal constructor( arg0: KExpr, arg1: KExpr, arg2: KExpr - ): KApp = mkIndexOfNoSimplify(arg0, arg1, arg2) + ): KApp = mkStringIndexOfNoSimplify(arg0, arg1, arg2) } class KStringReplaceDecl internal constructor( ctx: KContext, ) : KFuncDecl3( ctx, - name = "replace", - resultSort = ctx.mkStringSort(), + "str_replace", + ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkStringSort() @@ -195,8 +268,8 @@ class KStringReplaceAllDecl internal constructor( ctx: KContext, ) : KFuncDecl3( ctx, - name = "replace_all", - resultSort = ctx.mkStringSort(), + "str_replace_all", + ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkStringSort() @@ -214,8 +287,8 @@ class KStringReplaceWithRegexDecl internal constructor( ctx: KContext, ) : KFuncDecl3( ctx, - name = "replace_with_regex", - resultSort = ctx.mkStringSort(), + "str_replace_with_regex", + ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkRegexSort(), ctx.mkStringSort() @@ -233,8 +306,8 @@ class KStringReplaceAllWithRegexDecl internal constructor( ctx: KContext, ) : KFuncDecl3( ctx, - name = "replace_all_with_regex", - resultSort = ctx.mkStringSort(), + "str_replace_all_with_regex", + ctx.mkStringSort(), ctx.mkStringSort(), ctx.mkRegexSort(), ctx.mkStringSort() @@ -254,35 +327,78 @@ class KStringReplaceAllWithRegexDecl internal constructor( class KStringIsDigitDecl internal constructor( ctx: KContext -) : KFuncDecl1(ctx, "is_digit", ctx.mkBoolSort(), ctx.mkStringSort()) { - override fun KContext.apply(arg: KExpr): KApp = mkStringIsDigitNoSimplify(arg) +) : KFuncDecl1( + ctx, + "str_is_digit", + ctx.mkBoolSort(), + ctx.mkStringSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply(arg: KExpr): KApp = mkStringIsDigitNoSimplify(arg) } class KStringToCodeDecl internal constructor( ctx: KContext -) : KFuncDecl1(ctx, "to_code", ctx.mkIntSort(), ctx.mkStringSort()) { - override fun KContext.apply(arg: KExpr): KApp = mkStringToCodeNoSimplify(arg) +) : KFuncDecl1( + ctx, + "str_to_code", + ctx.mkIntSort(), + ctx.mkStringSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply(arg: KExpr): KApp = mkStringToCodeNoSimplify(arg) } class KStringFromCodeDecl internal constructor( ctx: KContext -) : KFuncDecl1(ctx, "from_code", ctx.mkStringSort(), ctx.mkIntSort()) { - override fun KContext.apply(arg: KExpr): KApp = mkStringFromCodeNoSimplify(arg) +) : KFuncDecl1( + ctx, + "str_from_code", + ctx.mkStringSort(), + ctx.mkIntSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply(arg: KExpr): KApp = mkStringFromCodeNoSimplify(arg) } class KStringToIntDecl internal constructor( ctx: KContext -) : KFuncDecl1(ctx, "to_int", ctx.mkIntSort(), ctx.mkStringSort()) { - override fun KContext.apply(arg: KExpr): KApp = mkStringToIntNoSimplify(arg) +) : KFuncDecl1( + ctx, + "str_to_int", + ctx.mkIntSort(), + ctx.mkStringSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply(arg: KExpr): KApp = mkStringToIntNoSimplify(arg) } class KStringFromIntDecl internal constructor( ctx: KContext -) : KFuncDecl1(ctx, "from_int", ctx.mkStringSort(), ctx.mkIntSort()) { +) : KFuncDecl1( + ctx, + "str_from_int", + ctx.mkStringSort(), + ctx.mkIntSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + override fun KContext.apply(arg: KExpr): KApp = mkStringFromIntNoSimplify(arg) +} + +class KStringLiteralDecl internal constructor( + ctx: KContext, + val value: String +) : KConstDecl( + ctx, + value, + ctx.mkStringSort() +) { override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun apply(args: List>): KApp = ctx.mkStringLiteral(value) } diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index b076b3b0e..8a3bc1c6a 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -3,14 +3,18 @@ package io.ksmt.expr import io.ksmt.KContext import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual -import io.ksmt.decl.KDecl -import io.ksmt.decl.KRegexKleeneClosureDecl -import io.ksmt.decl.KRegexKleeneCrossDecl +import io.ksmt.decl.KRegexConcatDecl +import io.ksmt.decl.KRegexUnionDecl +import io.ksmt.decl.KRegexIntersectionDecl +import io.ksmt.decl.KRegexStarDecl +import io.ksmt.decl.KRegexCrossDecl +import io.ksmt.decl.KRegexDifferenceDecl import io.ksmt.decl.KRegexComplementDecl import io.ksmt.decl.KRegexOptionDecl -import io.ksmt.decl.KEpsilonDecl -import io.ksmt.decl.KAllDecl -import io.ksmt.decl.KAllCharDecl +import io.ksmt.decl.KRegexRangeDecl +import io.ksmt.decl.KRegexEpsilonDecl +import io.ksmt.decl.KRegexAllDecl +import io.ksmt.decl.KRegexAllCharDecl import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KRegexSort import io.ksmt.sort.KStringSort @@ -20,15 +24,17 @@ class KRegexConcatExpr internal constructor( val arg0: KExpr, val arg1: KExpr ) : KApp(ctx) { - override val args: List> - get() = listOf(arg0, arg1) + override val sort: KRegexSort + get() = ctx.mkRegexSort() - override val decl: KDecl + override val decl: KRegexConcatDecl get() = ctx.mkRegexConcatDecl() - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val args: List> + get() = listOf(arg0, arg1) - override val sort: KRegexSort = ctx.mkRegexSort() + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) @@ -39,15 +45,17 @@ class KRegexUnionExpr internal constructor( val arg0: KExpr, val arg1: KExpr ) : KApp(ctx) { - override val args: List> - get() = listOf(arg0, arg1) + override val sort: KRegexSort + get() = ctx.mkRegexSort() - override val decl: KDecl + override val decl: KRegexUnionDecl get() = ctx.mkRegexUnionDecl() - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val args: List> + get() = listOf(arg0, arg1) - override val sort: KRegexSort = ctx.mkRegexSort() + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) @@ -58,51 +66,57 @@ class KRegexIntersectionExpr internal constructor( val arg0: KExpr, val arg1: KExpr ) : KApp(ctx) { - override val args: List> - get() = listOf(arg0, arg1) + override val sort: KRegexSort + get() = ctx.mkRegexSort() - override val decl: KDecl + override val decl: KRegexIntersectionDecl get() = ctx.mkRegexIntersectionDecl() - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val args: List> + get() = listOf(arg0, arg1) - override val sort: KRegexSort = ctx.mkRegexSort() + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } -class KRegexKleeneClosureExpr internal constructor( +class KRegexStarExpr internal constructor( ctx: KContext, val arg: KExpr ) : KApp(ctx) { - override val sort: KRegexSort = ctx.regexSort + override val sort: KRegexSort + get() = ctx.regexSort - override val decl: KRegexKleeneClosureDecl - get() = ctx.mkRegexKleeneClosureDecl() + override val decl: KRegexStarDecl + get() = ctx.mkRegexStarDecl() override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } } -class KRegexKleeneCrossExpr internal constructor( +class KRegexCrossExpr internal constructor( ctx: KContext, val arg: KExpr ) : KApp(ctx) { - override val sort: KRegexSort = ctx.regexSort + override val sort: KRegexSort + get() = ctx.regexSort - override val decl: KRegexKleeneCrossDecl - get() = ctx.mkRegexKleeneCrossDecl() + override val decl: KRegexCrossDecl + get() = ctx.mkRegexCrossDecl() override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -113,15 +127,17 @@ class KRegexDifferenceExpr internal constructor( val arg0: KExpr, val arg1: KExpr ) : KApp(ctx) { + override val sort: KRegexSort + get() = ctx.mkRegexSort() + override val args: List> get() = listOf(arg0, arg1) - override val decl: KDecl + override val decl: KRegexDifferenceDecl get() = ctx.mkRegexDifferenceDecl() - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) - - override val sort: KRegexSort = ctx.mkRegexSort() + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) @@ -131,7 +147,8 @@ class KRegexComplementExpr internal constructor( ctx: KContext, val arg: KExpr ) : KApp(ctx) { - override val sort: KRegexSort = ctx.regexSort + override val sort: KRegexSort + get() = ctx.regexSort override val decl: KRegexComplementDecl get() = ctx.mkRegexComplementDecl() @@ -139,7 +156,8 @@ class KRegexComplementExpr internal constructor( override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -149,7 +167,8 @@ class KRegexOptionExpr internal constructor( ctx: KContext, val arg: KExpr ) : KApp(ctx) { - override val sort: KRegexSort = ctx.regexSort + override val sort: KRegexSort + get() = ctx.regexSort override val decl: KRegexOptionDecl get() = ctx.mkRegexOptionDecl() @@ -157,64 +176,72 @@ class KRegexOptionExpr internal constructor( override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } } +class KRegexRangeExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr +) : KApp(ctx) { + override val sort: KRegexSort + get() = ctx.mkRegexSort() -class KEpsilon(ctx: KContext) : KInterpretedValue(ctx) { - override val sort: KRegexSort = ctx.regexSort + override val args: List> + get() = listOf(arg0, arg1) - override val decl: KEpsilonDecl - get() = ctx.mkEpsilonDecl() + override val decl: KRegexRangeDecl + get() = ctx.mkRegexRangeDecl() - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) - override fun internHashCode(): Int = hash() - override fun internEquals(other: Any): Boolean = structurallyEqual(other) + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } -class KAll(ctx: KContext) : KInterpretedValue(ctx) { - override val sort: KRegexSort = ctx.regexSort +class KRegexEpsilon(ctx: KContext) : KInterpretedValue(ctx) { + override val sort: KRegexSort + get() = ctx.regexSort - override val decl: KAllDecl - get() = ctx.mkAllDecl() + override val decl: KRegexEpsilonDecl + get() = ctx.mkRegexEpsilonDecl() - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash() override fun internEquals(other: Any): Boolean = structurallyEqual(other) } -class KAllChar(ctx: KContext) : KInterpretedValue(ctx) { - override val sort: KRegexSort = ctx.regexSort +class KRegexAll(ctx: KContext) : KInterpretedValue(ctx) { + override val sort: KRegexSort + get() = ctx.regexSort - override val decl: KAllCharDecl - get() = ctx.mkAllCharDecl() + override val decl: KRegexAllDecl + get() = ctx.mkRegexAllDecl() - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash() override fun internEquals(other: Any): Boolean = structurallyEqual(other) } -class KRangeExpr internal constructor( - ctx: KContext, - val arg0: KExpr, - val arg1: KExpr -) : KApp(ctx) { - override val args: List> - get() = listOf(arg0, arg1) - - override val decl: KDecl - get() = ctx.mkRangeDecl() +class KRegexAllChar(ctx: KContext) : KInterpretedValue(ctx) { + override val sort: KRegexSort + get() = ctx.regexSort - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KRegexAllCharDecl + get() = ctx.mkRegexAllCharDecl() - override val sort: KRegexSort = ctx.mkRegexSort() + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) - override fun internHashCode(): Int = hash(arg0, arg1) - override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) + override fun internHashCode(): Int = hash() + override fun internEquals(other: Any): Boolean = structurallyEqual(other) } diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index e4e7409ed..4451d670a 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -3,9 +3,10 @@ package io.ksmt.expr import io.ksmt.KContext import io.ksmt.cache.hash import io.ksmt.cache.structurallyEqual -import io.ksmt.decl.KDecl +import io.ksmt.decl.KStringConcatDecl import io.ksmt.decl.KStringLenDecl -import io.ksmt.decl.KStringLiteralDecl +import io.ksmt.decl.KStringSuffixOfDecl +import io.ksmt.decl.KStringPrefixOfDecl import io.ksmt.decl.KStringLtDecl import io.ksmt.decl.KStringLeDecl import io.ksmt.decl.KStringGtDecl @@ -13,9 +14,9 @@ import io.ksmt.decl.KStringGeDecl import io.ksmt.decl.KStringToRegexDecl import io.ksmt.decl.KStringInRegexDecl import io.ksmt.decl.KStringContainsDecl -import io.ksmt.decl.KSingletonSubstringDecl -import io.ksmt.decl.KSubstringDecl -import io.ksmt.decl.KIndexOfDecl +import io.ksmt.decl.KStringSingletonSubDecl +import io.ksmt.decl.KStringSubDecl +import io.ksmt.decl.KStringIndexOfDecl import io.ksmt.decl.KStringReplaceDecl import io.ksmt.decl.KStringReplaceAllDecl import io.ksmt.decl.KStringReplaceWithRegexDecl @@ -25,6 +26,7 @@ import io.ksmt.decl.KStringToCodeDecl import io.ksmt.decl.KStringFromCodeDecl import io.ksmt.decl.KStringToIntDecl import io.ksmt.decl.KStringFromIntDecl +import io.ksmt.decl.KStringLiteralDecl import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KSort import io.ksmt.sort.KBoolSort @@ -33,36 +35,22 @@ import io.ksmt.sort.KRegexSort import io.ksmt.sort.KStringSort import io.ksmt.utils.cast -class KStringLiteralExpr internal constructor( - ctx: KContext, - val value: String -) : KInterpretedValue(ctx) { - override val sort: KStringSort - get() = ctx.stringSort - - override val decl: KStringLiteralDecl - get() = ctx.mkStringLiteralDecl(value) - - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) - - override fun internHashCode(): Int = hash(value) - override fun internEquals(other: Any): Boolean = structurallyEqual(other) { value } -} - class KStringConcatExpr internal constructor( ctx: KContext, val arg0: KExpr, val arg1: KExpr ) : KApp(ctx) { + override val sort: KStringSort + get() = ctx.mkStringSort() + override val args: List> get() = listOf(arg0, arg1) - override val decl: KDecl + override val decl: KStringConcatDecl get() = ctx.mkStringConcatDecl() - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) - - override val sort: KStringSort = ctx.mkStringSort() + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) @@ -72,15 +60,17 @@ class KStringLenExpr internal constructor( ctx: KContext, val arg: KExpr ) : KApp(ctx) { - override val sort: KIntSort = ctx.intSort - - override val decl: KStringLenDecl - get() = ctx.mkStringLenDecl() + override val sort: KIntSort + get() = ctx.intSort override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KStringLenDecl + get() = ctx.mkStringLenDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -90,15 +80,17 @@ class KStringToRegexExpr internal constructor( ctx: KContext, val arg: KExpr ) : KApp(ctx) { - override val sort: KRegexSort = ctx.regexSort - - override val decl: KStringToRegexDecl - get() = ctx.mkStringToRegexDecl() + override val sort: KRegexSort + get() = ctx.regexSort override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KStringToRegexDecl + get() = ctx.mkStringToRegexDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -109,7 +101,8 @@ class KStringInRegexExpr internal constructor( val arg0: KExpr, val arg1: KExpr ) : KApp(ctx) { - override val sort: KBoolSort = ctx.mkBoolSort() + override val sort: KBoolSort + get() = ctx.boolSort override val args: List> get() = listOf(arg0.cast(), arg1.cast()) @@ -117,45 +110,50 @@ class KStringInRegexExpr internal constructor( override val decl: KStringInRegexDecl get() = ctx.mkStringInRegexDecl() - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } -class KSuffixOfExpr internal constructor( +class KStringSuffixOfExpr internal constructor( ctx: KContext, val arg0: KExpr, val arg1: KExpr ) : KApp(ctx) { - override val sort: KBoolSort = ctx.mkBoolSort() + override val sort: KBoolSort + get() = ctx.boolSort override val args: List> get() = listOf(arg0, arg1) - override val decl: KDecl - get() = ctx.mkSuffixOfDecl() + override val decl: KStringSuffixOfDecl + get() = ctx.mkStringSuffixOfDecl() - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } -class KPrefixOfExpr internal constructor( +class KStringPrefixOfExpr internal constructor( ctx: KContext, val arg0: KExpr, val arg1: KExpr ) : KApp(ctx) { - override val sort: KBoolSort = ctx.mkBoolSort() + override val sort: KBoolSort + get() = ctx.boolSort override val args: List> get() = listOf(arg0, arg1) - override val decl: KDecl - get() = ctx.mkPrefixOfDecl() + override val decl: KStringPrefixOfDecl + get() = ctx.mkStringPrefixOfDecl() - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) @@ -163,153 +161,169 @@ class KPrefixOfExpr internal constructor( class KStringLtExpr internal constructor( ctx: KContext, - val lhs: KExpr, - val rhs: KExpr + val arg0: KExpr, + val arg1: KExpr ) : KApp(ctx) { - override val sort: KBoolSort = ctx.boolSort + override val sort: KBoolSort + get() = ctx.boolSort + + override val args: List> + get() = listOf(arg0, arg1) override val decl: KStringLtDecl get() = ctx.mkStringLtDecl() - override val args: List> - get() = listOf(lhs, rhs) - - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) - override fun internHashCode(): Int = hash(lhs, rhs) - override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } class KStringLeExpr internal constructor( ctx: KContext, - val lhs: KExpr, - val rhs: KExpr + val arg0: KExpr, + val arg1: KExpr ) : KApp(ctx) { - override val sort: KBoolSort = ctx.boolSort + override val sort: KBoolSort + get() = ctx.boolSort + + override val args: List> + get() = listOf(arg0, arg1) override val decl: KStringLeDecl get() = ctx.mkStringLeDecl() - override val args: List> - get() = listOf(lhs, rhs) - - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) - override fun internHashCode(): Int = hash(lhs, rhs) - override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } class KStringGtExpr internal constructor( ctx: KContext, - val lhs: KExpr, - val rhs: KExpr + val arg0: KExpr, + val arg1: KExpr ) : KApp(ctx) { - override val sort: KBoolSort = ctx.boolSort + override val sort: KBoolSort + get() = ctx.boolSort + + override val args: List> + get() = listOf(arg0, arg1) override val decl: KStringGtDecl get() = ctx.mkStringGtDecl() - override val args: List> - get() = listOf(lhs, rhs) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) - - override fun internHashCode(): Int = hash(lhs, rhs) - override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } class KStringGeExpr internal constructor( ctx: KContext, - val lhs: KExpr, - val rhs: KExpr + val arg0: KExpr, + val arg1: KExpr ) : KApp(ctx) { - override val sort: KBoolSort = ctx.boolSort + override val sort: KBoolSort + get() = ctx.boolSort + + override val args: List> + get() = listOf(arg0, arg1) override val decl: KStringGeDecl get() = ctx.mkStringGeDecl() - override val args: List> - get() = listOf(lhs, rhs) - - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) - override fun internHashCode(): Int = hash(lhs, rhs) - override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } class KStringContainsExpr internal constructor( ctx: KContext, - val lhs: KExpr, - val rhs: KExpr + val arg0: KExpr, + val arg1: KExpr ) : KApp(ctx) { - override val sort: KBoolSort = ctx.boolSort + override val sort: KBoolSort + get() = ctx.boolSort + + override val args: List> + get() = listOf(arg0, arg1) override val decl: KStringContainsDecl get() = ctx.mkStringContainsDecl() - override val args: List> - get() = listOf(lhs, rhs) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) - - override fun internHashCode(): Int = hash(lhs, rhs) - override fun internEquals(other: Any): Boolean = structurallyEqual(other, { lhs }, { rhs }) + override fun internHashCode(): Int = hash(arg0, arg1) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } -class KSingletonSubstringExpr internal constructor( +class KStringSingletonSubExpr internal constructor( ctx: KContext, val arg0: KExpr, val arg1: KExpr ) : KApp(ctx) { - override val sort: KStringSort = ctx.stringSort - - override val decl: KSingletonSubstringDecl - get() = ctx.mkSingletonSubstringDecl() + override val sort: KStringSort + get() = ctx.stringSort override val args: List> get() = listOf(arg0.cast(), arg1.cast()) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KStringSingletonSubDecl + get() = ctx.mkStringSingletonSubDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } -class KSubstringExpr internal constructor( +class KStringSubExpr internal constructor( ctx: KContext, val arg0: KExpr, val arg1: KExpr, val arg2: KExpr ) : KApp(ctx) { - override val sort: KStringSort = ctx.stringSort - - override val decl: KSubstringDecl - get() = ctx.mkSubstringDecl() + override val sort: KStringSort + get() = ctx.stringSort override val args: List> get() = listOf(arg0.cast(), arg1.cast(), arg2.cast()) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KStringSubDecl + get() = ctx.mkStringSubDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1, arg2) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) } -class KIndexOfExpr internal constructor( +class KStringIndexOfExpr internal constructor( ctx: KContext, val arg0: KExpr, val arg1: KExpr, val arg2: KExpr ) : KApp(ctx) { - override val sort: KIntSort = ctx.intSort - - override val decl: KIndexOfDecl - get() = ctx.mkIndexOfDecl() + override val sort: KIntSort + get() = ctx.intSort override val args: List> get() = listOf(arg0.cast(), arg1.cast(), arg2.cast()) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KStringIndexOfDecl + get() = ctx.mkStringIndexOfDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1, arg2) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) @@ -321,15 +335,17 @@ class KStringReplaceExpr internal constructor( val arg1: KExpr, val arg2: KExpr ) : KApp(ctx) { - override val sort: KStringSort = ctx.stringSort - - override val decl: KStringReplaceDecl - get() = ctx.mkStringReplaceDecl() + override val sort: KStringSort + get() = ctx.stringSort override val args: List> get() = listOf(arg0, arg1, arg2) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KStringReplaceDecl + get() = ctx.mkStringReplaceDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1, arg2) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) @@ -341,15 +357,17 @@ class KStringReplaceAllExpr internal constructor( val arg1: KExpr, val arg2: KExpr ) : KApp(ctx) { - override val sort: KStringSort = ctx.stringSort - - override val decl: KStringReplaceAllDecl - get() = ctx.mkStringReplaceAllDecl() + override val sort: KStringSort + get() = ctx.stringSort override val args: List> get() = listOf(arg0, arg1, arg2) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KStringReplaceAllDecl + get() = ctx.mkStringReplaceAllDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1, arg2) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) @@ -361,15 +379,17 @@ class KStringReplaceWithRegexExpr internal constructor( val arg1: KExpr, val arg2: KExpr ) : KApp(ctx) { - override val sort: KStringSort = ctx.stringSort - - override val decl: KStringReplaceWithRegexDecl - get() = ctx.mkStringReplaceWithRegexDecl() + override val sort: KStringSort + get() = ctx.stringSort override val args: List> get() = listOf(arg0.cast(), arg1.cast(), arg2.cast()) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KStringReplaceWithRegexDecl + get() = ctx.mkStringReplaceWithRegexDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1, arg2) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) @@ -381,15 +401,17 @@ class KStringReplaceAllWithRegexExpr internal constructor( val arg1: KExpr, val arg2: KExpr ) : KApp(ctx) { - override val sort: KStringSort = ctx.stringSort - - override val decl: KStringReplaceAllWithRegexDecl - get() = ctx.mkStringReplaceAllWithRegexDecl() + override val sort: KStringSort + get() = ctx.stringSort override val args: List> get() = listOf(arg0.cast(), arg1.cast(), arg2.cast()) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KStringReplaceAllWithRegexDecl + get() = ctx.mkStringReplaceAllWithRegexDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg0, arg1, arg2) override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) @@ -403,15 +425,17 @@ class KStringIsDigitExpr internal constructor( ctx: KContext, val arg: KExpr ) : KApp(ctx) { - override val sort: KBoolSort = ctx.boolSort - - override val decl: KStringIsDigitDecl - get() = ctx.mkStringIsDigitDecl() + override val sort: KBoolSort + get() = ctx.boolSort override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KStringIsDigitDecl + get() = ctx.mkStringIsDigitDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -421,15 +445,17 @@ class KStringToCodeExpr internal constructor( ctx: KContext, val arg: KExpr ) : KApp(ctx) { - override val sort: KIntSort = ctx.intSort - - override val decl: KStringToCodeDecl - get() = ctx.mkStringToCodeDecl() + override val sort: KIntSort + get() = ctx.intSort override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KStringToCodeDecl + get() = ctx.mkStringToCodeDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -439,15 +465,17 @@ class KStringFromCodeExpr internal constructor( ctx: KContext, val arg: KExpr ) : KApp(ctx) { - override val sort: KStringSort = ctx.stringSort - - override val decl: KStringFromCodeDecl - get() = ctx.mkStringFromCodeDecl() + override val sort: KStringSort + get() = ctx.stringSort override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KStringFromCodeDecl + get() = ctx.mkStringFromCodeDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -457,15 +485,17 @@ class KStringToIntExpr internal constructor( ctx: KContext, val arg: KExpr ) : KApp(ctx) { - override val sort: KIntSort = ctx.intSort - - override val decl: KStringToIntDecl - get() = ctx.mkStringToIntDecl() + override val sort: KIntSort + get() = ctx.intSort override val args: List> get() = listOf(arg) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override val decl: KStringToIntDecl + get() = ctx.mkStringToIntDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } @@ -475,15 +505,35 @@ class KStringFromIntExpr internal constructor( ctx: KContext, val arg: KExpr ) : KApp(ctx) { - override val sort: KStringSort = ctx.stringSort + override val sort: KStringSort + get() = ctx.stringSort + + override val args: List> + get() = listOf(arg) override val decl: KStringFromIntDecl get() = ctx.mkStringFromIntDecl() - override val args: List> - get() = listOf(arg) + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) - override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) override fun internHashCode(): Int = hash(arg) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } } + +class KStringLiteralExpr internal constructor( + ctx: KContext, + val value: String +) : KInterpretedValue(ctx) { + override val sort: KStringSort + get() = ctx.stringSort + + override val decl: KStringLiteralDecl + get() = ctx.mkStringLiteralDecl(value) + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) + + override fun internHashCode(): Int = hash(value) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { value } +} diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt index ea19bac06..f654fcdd2 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt @@ -128,16 +128,16 @@ import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KStringInRegexExpr -import io.ksmt.expr.KSuffixOfExpr -import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringSuffixOfExpr +import io.ksmt.expr.KStringPrefixOfExpr import io.ksmt.expr.KStringLtExpr import io.ksmt.expr.KStringLeExpr import io.ksmt.expr.KStringGtExpr import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KStringContainsExpr -import io.ksmt.expr.KSingletonSubstringExpr -import io.ksmt.expr.KSubstringExpr -import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringSingletonSubExpr +import io.ksmt.expr.KStringSubExpr +import io.ksmt.expr.KStringIndexOfExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr @@ -150,12 +150,12 @@ import io.ksmt.expr.KStringFromIntExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr import io.ksmt.expr.KRegexIntersectionExpr -import io.ksmt.expr.KRegexKleeneClosureExpr -import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexStarExpr +import io.ksmt.expr.KRegexCrossExpr import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr -import io.ksmt.expr.KRangeExpr +import io.ksmt.expr.KRegexRangeExpr import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -716,54 +716,54 @@ abstract class KNonRecursiveTransformer(override val ctx: KContext) : KNonRecurs expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkStringInRegex ) - override fun transform(expr: KSuffixOfExpr): KExpr = + override fun transform(expr: KStringSuffixOfExpr): KExpr = transformExprAfterTransformedDefault( - expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkSuffixOf + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkStringSuffixOf ) - override fun transform(expr: KPrefixOfExpr): KExpr = + override fun transform(expr: KStringPrefixOfExpr): KExpr = transformExprAfterTransformedDefault( - expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkPrefixOf + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkStringPrefixOf ) override fun transform(expr: KStringLtExpr): KExpr = transformExprAfterTransformedDefault( - expr, expr.lhs, expr.rhs, ::transformApp, KContext::mkStringLt + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkStringLt ) override fun transform(expr: KStringLeExpr): KExpr = transformExprAfterTransformedDefault( - expr, expr.lhs, expr.rhs, ::transformApp, KContext::mkStringLe + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkStringLe ) override fun transform(expr: KStringGtExpr): KExpr = transformExprAfterTransformedDefault( - expr, expr.lhs, expr.rhs, ::transformApp, KContext::mkStringGt + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkStringGt ) override fun transform(expr: KStringGeExpr): KExpr = transformExprAfterTransformedDefault( - expr, expr.lhs, expr.rhs, ::transformApp, KContext::mkStringGe + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkStringGe ) override fun transform(expr: KStringContainsExpr): KExpr = transformExprAfterTransformedDefault( - expr, expr.lhs, expr.rhs, ::transformApp, KContext::mkStringContains + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkStringContains ) - override fun transform(expr: KSingletonSubstringExpr): KExpr = + override fun transform(expr: KStringSingletonSubExpr): KExpr = transformExprAfterTransformedDefault( - expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkSingletonSubstring + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkStringSingletonSub ) - override fun transform(expr: KSubstringExpr): KExpr = + override fun transform(expr: KStringSubExpr): KExpr = transformExprAfterTransformedDefault( - expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkSubstring + expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkStringSub ) - override fun transform(expr: KIndexOfExpr): KExpr = + override fun transform(expr: KStringIndexOfExpr): KExpr = transformExprAfterTransformedDefault( - expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkIndexOf + expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkStringIndexOf ) override fun transform(expr: KStringReplaceExpr): KExpr = @@ -827,14 +827,14 @@ abstract class KNonRecursiveTransformer(override val ctx: KContext) : KNonRecurs expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkRegexIntersection ) - override fun transform(expr: KRegexKleeneClosureExpr): KExpr = + override fun transform(expr: KRegexStarExpr): KExpr = transformExprAfterTransformedDefault( - expr, expr.arg, ::transformApp, KContext::mkRegexKleeneClosure + expr, expr.arg, ::transformApp, KContext::mkRegexStar ) - override fun transform(expr: KRegexKleeneCrossExpr): KExpr = + override fun transform(expr: KRegexCrossExpr): KExpr = transformExprAfterTransformedDefault( - expr, expr.arg, ::transformApp, KContext::mkRegexKleeneCross + expr, expr.arg, ::transformApp, KContext::mkRegexCross ) override fun transform(expr: KRegexDifferenceExpr): KExpr = @@ -852,9 +852,9 @@ abstract class KNonRecursiveTransformer(override val ctx: KContext) : KNonRecurs expr, expr.arg, ::transformApp, KContext::mkRegexOption ) - override fun transform(expr: KRangeExpr): KExpr = + override fun transform(expr: KRegexRangeExpr): KExpr = transformExprAfterTransformedDefault( - expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkRange + expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkRegexRange ) // quantified expressions diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt index 8bd71a93a..40684b9c3 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt @@ -128,16 +128,16 @@ import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KStringInRegexExpr -import io.ksmt.expr.KSuffixOfExpr -import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringSuffixOfExpr +import io.ksmt.expr.KStringPrefixOfExpr import io.ksmt.expr.KStringLtExpr import io.ksmt.expr.KStringLeExpr import io.ksmt.expr.KStringGtExpr import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KStringContainsExpr -import io.ksmt.expr.KSingletonSubstringExpr -import io.ksmt.expr.KSubstringExpr -import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringSingletonSubExpr +import io.ksmt.expr.KStringSubExpr +import io.ksmt.expr.KStringIndexOfExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr @@ -150,12 +150,12 @@ import io.ksmt.expr.KStringFromIntExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr import io.ksmt.expr.KRegexIntersectionExpr -import io.ksmt.expr.KRegexKleeneClosureExpr -import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexStarExpr +import io.ksmt.expr.KRegexCrossExpr import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr -import io.ksmt.expr.KRangeExpr +import io.ksmt.expr.KRegexRangeExpr import io.ksmt.sort.KArithSort import io.ksmt.sort.KArraySortBase import io.ksmt.sort.KBvSort @@ -674,34 +674,34 @@ abstract class KNonRecursiveVisitor( override fun visit(expr: KStringInRegexExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) - override fun visit(expr: KSuffixOfExpr): KExprVisitResult = + override fun visit(expr: KStringSuffixOfExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) - override fun visit(expr: KPrefixOfExpr): KExprVisitResult = + override fun visit(expr: KStringPrefixOfExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) override fun visit(expr: KStringLtExpr): KExprVisitResult = - visitExprAfterVisitedDefault(expr, expr.lhs, expr.rhs, ::visitApp) + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) override fun visit(expr: KStringLeExpr): KExprVisitResult = - visitExprAfterVisitedDefault(expr, expr.lhs, expr.rhs, ::visitApp) + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) override fun visit(expr: KStringGtExpr): KExprVisitResult = - visitExprAfterVisitedDefault(expr, expr.lhs, expr.rhs, ::visitApp) + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) override fun visit(expr: KStringGeExpr): KExprVisitResult = - visitExprAfterVisitedDefault(expr, expr.lhs, expr.rhs, ::visitApp) + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) override fun visit(expr: KStringContainsExpr): KExprVisitResult = - visitExprAfterVisitedDefault(expr, expr.lhs, expr.rhs, ::visitApp) + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) - override fun visit(expr: KSingletonSubstringExpr): KExprVisitResult = + override fun visit(expr: KStringSingletonSubExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) - override fun visit(expr: KSubstringExpr): KExprVisitResult = + override fun visit(expr: KStringSubExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, expr.arg2, ::visitApp) - override fun visit(expr: KIndexOfExpr): KExprVisitResult = + override fun visit(expr: KStringIndexOfExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, expr.arg2, ::visitApp) override fun visit(expr: KStringReplaceExpr): KExprVisitResult = @@ -741,10 +741,10 @@ abstract class KNonRecursiveVisitor( override fun visit(expr: KRegexIntersectionExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) - override fun visit(expr: KRegexKleeneClosureExpr): KExprVisitResult = + override fun visit(expr: KRegexStarExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) - override fun visit(expr: KRegexKleeneCrossExpr): KExprVisitResult = + override fun visit(expr: KRegexCrossExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) override fun visit(expr: KRegexDifferenceExpr): KExprVisitResult = @@ -756,7 +756,7 @@ abstract class KNonRecursiveVisitor( override fun visit(expr: KRegexOptionExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) - override fun visit(expr: KRangeExpr): KExprVisitResult = + override fun visit(expr: KRegexRangeExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) // quantified expressions diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt index 95c317a54..aae8df22b 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt @@ -154,16 +154,16 @@ import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KStringInRegexExpr -import io.ksmt.expr.KSuffixOfExpr -import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringSuffixOfExpr +import io.ksmt.expr.KStringPrefixOfExpr import io.ksmt.expr.KStringLtExpr import io.ksmt.expr.KStringLeExpr import io.ksmt.expr.KStringGtExpr import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KStringContainsExpr -import io.ksmt.expr.KSingletonSubstringExpr -import io.ksmt.expr.KSubstringExpr -import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringSingletonSubExpr +import io.ksmt.expr.KStringSubExpr +import io.ksmt.expr.KStringIndexOfExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr @@ -177,15 +177,15 @@ import io.ksmt.expr.KStringLiteralExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr import io.ksmt.expr.KRegexIntersectionExpr -import io.ksmt.expr.KRegexKleeneClosureExpr -import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexStarExpr +import io.ksmt.expr.KRegexCrossExpr import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr -import io.ksmt.expr.KRangeExpr -import io.ksmt.expr.KEpsilon -import io.ksmt.expr.KAll -import io.ksmt.expr.KAllChar +import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexEpsilon +import io.ksmt.expr.KRegexAll +import io.ksmt.expr.KRegexAllChar import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -455,16 +455,16 @@ interface KTransformer : KTransformerBase { override fun transform(expr: KStringLenExpr): KExpr = transformApp(expr) override fun transform(expr: KStringToRegexExpr): KExpr = transformApp(expr) override fun transform(expr: KStringInRegexExpr): KExpr = transformApp(expr) - override fun transform(expr: KSuffixOfExpr): KExpr = transformApp(expr) - override fun transform(expr: KPrefixOfExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringSuffixOfExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringPrefixOfExpr): KExpr = transformApp(expr) override fun transform(expr: KStringLtExpr): KExpr = transformApp(expr) override fun transform(expr: KStringLeExpr): KExpr = transformApp(expr) override fun transform(expr: KStringGtExpr): KExpr = transformApp(expr) override fun transform(expr: KStringGeExpr): KExpr = transformApp(expr) override fun transform(expr: KStringContainsExpr): KExpr = transformApp(expr) - override fun transform(expr: KSingletonSubstringExpr): KExpr = transformApp(expr) - override fun transform(expr: KSubstringExpr): KExpr = transformApp(expr) - override fun transform(expr: KIndexOfExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringSingletonSubExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringSubExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringIndexOfExpr): KExpr = transformApp(expr) override fun transform(expr: KStringReplaceExpr): KExpr = transformApp(expr) override fun transform(expr: KStringReplaceAllExpr): KExpr = transformApp(expr) override fun transform(expr: KStringReplaceWithRegexExpr): KExpr = transformApp(expr) @@ -480,15 +480,15 @@ interface KTransformer : KTransformerBase { override fun transform(expr: KRegexConcatExpr): KExpr = transformApp(expr) override fun transform(expr: KRegexUnionExpr): KExpr = transformApp(expr) override fun transform(expr: KRegexIntersectionExpr): KExpr = transformApp(expr) - override fun transform(expr: KRegexKleeneClosureExpr): KExpr = transformApp(expr) - override fun transform(expr: KRegexKleeneCrossExpr): KExpr = transformApp(expr) + override fun transform(expr: KRegexStarExpr): KExpr = transformApp(expr) + override fun transform(expr: KRegexCrossExpr): KExpr = transformApp(expr) override fun transform(expr: KRegexDifferenceExpr): KExpr = transformApp(expr) override fun transform(expr: KRegexComplementExpr): KExpr = transformApp(expr) override fun transform(expr: KRegexOptionExpr): KExpr = transformApp(expr) - override fun transform(expr: KRangeExpr): KExpr = transformApp(expr) - override fun transform(expr: KEpsilon): KExpr = transformValue(expr) - override fun transform(expr: KAll): KExpr = transformValue(expr) - override fun transform(expr: KAllChar): KExpr = transformValue(expr) + override fun transform(expr: KRegexRangeExpr): KExpr = transformApp(expr) + override fun transform(expr: KRegexEpsilon): KExpr = transformValue(expr) + override fun transform(expr: KRegexAll): KExpr = transformValue(expr) + override fun transform(expr: KRegexAllChar): KExpr = transformValue(expr) // quantifier transformers override fun transform(expr: KExistentialQuantifier): KExpr = with(ctx) { diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt index 557e69211..8eae656be 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt @@ -145,16 +145,16 @@ import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KStringInRegexExpr -import io.ksmt.expr.KSuffixOfExpr -import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringSuffixOfExpr +import io.ksmt.expr.KStringPrefixOfExpr import io.ksmt.expr.KStringLtExpr import io.ksmt.expr.KStringLeExpr import io.ksmt.expr.KStringGtExpr import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KStringContainsExpr -import io.ksmt.expr.KSingletonSubstringExpr -import io.ksmt.expr.KSubstringExpr -import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringSingletonSubExpr +import io.ksmt.expr.KStringSubExpr +import io.ksmt.expr.KStringIndexOfExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr @@ -168,15 +168,15 @@ import io.ksmt.expr.KStringLiteralExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr import io.ksmt.expr.KRegexIntersectionExpr -import io.ksmt.expr.KRegexKleeneClosureExpr -import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexStarExpr +import io.ksmt.expr.KRegexCrossExpr import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr -import io.ksmt.expr.KRangeExpr -import io.ksmt.expr.KEpsilon -import io.ksmt.expr.KAll -import io.ksmt.expr.KAllChar +import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexEpsilon +import io.ksmt.expr.KRegexAll +import io.ksmt.expr.KRegexAllChar import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -383,16 +383,16 @@ interface KTransformerBase { fun transform(expr: KStringLenExpr): KExpr fun transform(expr: KStringToRegexExpr): KExpr fun transform(expr: KStringInRegexExpr): KExpr - fun transform(expr: KSuffixOfExpr): KExpr - fun transform(expr: KPrefixOfExpr): KExpr + fun transform(expr: KStringSuffixOfExpr): KExpr + fun transform(expr: KStringPrefixOfExpr): KExpr fun transform(expr: KStringLtExpr): KExpr fun transform(expr: KStringLeExpr): KExpr fun transform(expr: KStringGtExpr): KExpr fun transform(expr: KStringGeExpr): KExpr fun transform(expr: KStringContainsExpr): KExpr - fun transform(expr: KSingletonSubstringExpr): KExpr - fun transform(expr: KSubstringExpr): KExpr - fun transform(expr: KIndexOfExpr): KExpr + fun transform(expr: KStringSingletonSubExpr): KExpr + fun transform(expr: KStringSubExpr): KExpr + fun transform(expr: KStringIndexOfExpr): KExpr fun transform(expr: KStringReplaceExpr): KExpr fun transform(expr: KStringReplaceAllExpr): KExpr fun transform(expr: KStringReplaceWithRegexExpr): KExpr @@ -408,15 +408,15 @@ interface KTransformerBase { fun transform(expr: KRegexConcatExpr): KExpr fun transform(expr: KRegexUnionExpr): KExpr fun transform(expr: KRegexIntersectionExpr): KExpr - fun transform(expr: KRegexKleeneClosureExpr): KExpr - fun transform(expr: KRegexKleeneCrossExpr): KExpr + fun transform(expr: KRegexStarExpr): KExpr + fun transform(expr: KRegexCrossExpr): KExpr fun transform(expr: KRegexDifferenceExpr): KExpr fun transform(expr: KRegexComplementExpr): KExpr fun transform(expr: KRegexOptionExpr): KExpr - fun transform(expr: KRangeExpr): KExpr - fun transform(expr: KEpsilon): KExpr - fun transform(expr: KAll): KExpr - fun transform(expr: KAllChar): KExpr + fun transform(expr: KRegexRangeExpr): KExpr + fun transform(expr: KRegexEpsilon): KExpr + fun transform(expr: KRegexAll): KExpr + fun transform(expr: KRegexAllChar): KExpr // quantifier transformers fun transform(expr: KExistentialQuantifier): KExpr diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt index 75aa2dedd..bae50fb0a 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt @@ -153,16 +153,16 @@ import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KStringInRegexExpr -import io.ksmt.expr.KSuffixOfExpr -import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringSuffixOfExpr +import io.ksmt.expr.KStringPrefixOfExpr import io.ksmt.expr.KStringLtExpr import io.ksmt.expr.KStringLeExpr import io.ksmt.expr.KStringGtExpr import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KStringContainsExpr -import io.ksmt.expr.KSingletonSubstringExpr -import io.ksmt.expr.KSubstringExpr -import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringSingletonSubExpr +import io.ksmt.expr.KStringSubExpr +import io.ksmt.expr.KStringIndexOfExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr @@ -176,15 +176,15 @@ import io.ksmt.expr.KStringLiteralExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr import io.ksmt.expr.KRegexIntersectionExpr -import io.ksmt.expr.KRegexKleeneClosureExpr -import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexStarExpr +import io.ksmt.expr.KRegexCrossExpr import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr -import io.ksmt.expr.KRangeExpr -import io.ksmt.expr.KEpsilon -import io.ksmt.expr.KAll -import io.ksmt.expr.KAllChar +import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexEpsilon +import io.ksmt.expr.KRegexAll +import io.ksmt.expr.KRegexAllChar import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -657,16 +657,16 @@ interface KVisitor : KTransformer { fun visit(expr: KStringLenExpr): V = visitApp(expr) fun visit(expr: KStringToRegexExpr): V = visitApp(expr) fun visit(expr: KStringInRegexExpr): V = visitApp(expr) - fun visit(expr: KSuffixOfExpr): V = visitApp(expr) - fun visit(expr: KPrefixOfExpr): V = visitApp(expr) + fun visit(expr: KStringSuffixOfExpr): V = visitApp(expr) + fun visit(expr: KStringPrefixOfExpr): V = visitApp(expr) fun visit(expr: KStringLtExpr): V = visitApp(expr) fun visit(expr: KStringLeExpr): V = visitApp(expr) fun visit(expr: KStringGtExpr): V = visitApp(expr) fun visit(expr: KStringGeExpr): V = visitApp(expr) fun visit(expr: KStringContainsExpr): V = visitApp(expr) - fun visit(expr: KSingletonSubstringExpr): V = visitApp(expr) - fun visit(expr: KSubstringExpr): V = visitApp(expr) - fun visit(expr: KIndexOfExpr): V = visitApp(expr) + fun visit(expr: KStringSingletonSubExpr): V = visitApp(expr) + fun visit(expr: KStringSubExpr): V = visitApp(expr) + fun visit(expr: KStringIndexOfExpr): V = visitApp(expr) fun visit(expr: KStringReplaceExpr): V = visitApp(expr) fun visit(expr: KStringReplaceAllExpr): V = visitApp(expr) fun visit(expr: KStringReplaceWithRegexExpr): V = visitApp(expr) @@ -682,16 +682,16 @@ interface KVisitor : KTransformer { override fun transform(expr: KStringLenExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringToRegexExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringInRegexExpr): KExpr = visitExpr(expr, ::visit) - override fun transform(expr: KSuffixOfExpr): KExpr = visitExpr(expr, ::visit) - override fun transform(expr: KPrefixOfExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringSuffixOfExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringPrefixOfExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringLtExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringLeExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringGtExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringGeExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringContainsExpr): KExpr = visitExpr(expr, ::visit) - override fun transform(expr: KSingletonSubstringExpr): KExpr = visitExpr(expr, ::visit) - override fun transform(expr: KSubstringExpr): KExpr = visitExpr(expr, ::visit) - override fun transform(expr: KIndexOfExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringSingletonSubExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringSubExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringIndexOfExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringReplaceExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringReplaceAllExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringReplaceWithRegexExpr): KExpr = visitExpr(expr, ::visit) @@ -707,28 +707,28 @@ interface KVisitor : KTransformer { fun visit(expr: KRegexConcatExpr): V = visitApp(expr) fun visit(expr: KRegexUnionExpr): V = visitApp(expr) fun visit(expr: KRegexIntersectionExpr): V = visitApp(expr) - fun visit(expr: KRegexKleeneClosureExpr): V = visitApp(expr) - fun visit(expr: KRegexKleeneCrossExpr): V = visitApp(expr) + fun visit(expr: KRegexStarExpr): V = visitApp(expr) + fun visit(expr: KRegexCrossExpr): V = visitApp(expr) fun visit(expr: KRegexDifferenceExpr): V = visitApp(expr) fun visit(expr: KRegexComplementExpr): V = visitApp(expr) fun visit(expr: KRegexOptionExpr): V = visitApp(expr) - fun visit(expr: KRangeExpr): V = visitApp(expr) - fun visit(expr: KEpsilon): V = visitValue(expr) - fun visit(expr: KAll): V = visitValue(expr) - fun visit(expr: KAllChar): V = visitValue(expr) + fun visit(expr: KRegexRangeExpr): V = visitApp(expr) + fun visit(expr: KRegexEpsilon): V = visitValue(expr) + fun visit(expr: KRegexAll): V = visitValue(expr) + fun visit(expr: KRegexAllChar): V = visitValue(expr) override fun transform(expr: KRegexConcatExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KRegexUnionExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KRegexIntersectionExpr): KExpr = visitExpr(expr, ::visit) - override fun transform(expr: KRegexKleeneClosureExpr): KExpr = visitExpr(expr, ::visit) - override fun transform(expr: KRegexKleeneCrossExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexStarExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexCrossExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KRegexDifferenceExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KRegexComplementExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KRegexOptionExpr): KExpr = visitExpr(expr, ::visit) - override fun transform(expr: KRangeExpr): KExpr = visitExpr(expr, ::visit) - override fun transform(expr: KEpsilon): KExpr = visitExpr(expr, ::visit) - override fun transform(expr: KAll): KExpr = visitExpr(expr, ::visit) - override fun transform(expr: KAllChar): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexRangeExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexEpsilon): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexAll): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexAllChar): KExpr = visitExpr(expr, ::visit) // quantifier visitors fun visit(expr: KExistentialQuantifier): V = visitExpr(expr) diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt index 341355b8c..d0d2c9e98 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt @@ -384,14 +384,14 @@ open class KCvc5ExprConverter( Kind.STRING_LENGTH -> expr.convert(::mkStringLen) Kind.STRING_TO_REGEXP -> expr.convert(::mkStringToRegex) Kind.STRING_IN_REGEXP -> expr.convert(::mkStringInRegex) - Kind.STRING_SUFFIX -> expr.convert(::mkSuffixOf) - Kind.STRING_PREFIX -> expr.convert(::mkPrefixOf) + Kind.STRING_SUFFIX -> expr.convert(::mkStringSuffixOf) + Kind.STRING_PREFIX -> expr.convert(::mkStringPrefixOf) Kind.STRING_LT -> expr.convert(::mkStringLt) Kind.STRING_LEQ -> expr.convert(::mkStringLe) Kind.STRING_CONTAINS -> expr.convert(::mkStringContains) - Kind.STRING_CHARAT -> expr.convert(::mkSingletonSubstring) - Kind.STRING_SUBSTR -> expr.convert(::mkSubstring) - Kind.STRING_INDEXOF -> expr.convert(::mkIndexOf) + Kind.STRING_CHARAT -> expr.convert(::mkStringSingletonSub) + Kind.STRING_SUBSTR -> expr.convert(::mkStringSub) + Kind.STRING_INDEXOF -> expr.convert(::mkStringIndexOf) Kind.STRING_REPLACE -> expr.convert(::mkStringReplace) Kind.STRING_REPLACE_ALL -> expr.convert(::mkStringReplaceAll) Kind.STRING_REPLACE_RE -> expr.convert(::mkStringReplaceWithRegex) @@ -421,15 +421,15 @@ open class KCvc5ExprConverter( Kind.REGEXP_CONCAT -> expr.convert(::mkRegexConcat) Kind.REGEXP_UNION -> expr.convert(::mkRegexUnion) Kind.REGEXP_INTER -> expr.convert(::mkRegexIntersection) - Kind.REGEXP_STAR -> expr.convert(::mkRegexKleeneClosure) - Kind.REGEXP_PLUS -> expr.convert(::mkRegexKleeneCross) + Kind.REGEXP_STAR -> expr.convert(::mkRegexStar) + Kind.REGEXP_PLUS -> expr.convert(::mkRegexCross) Kind.REGEXP_DIFF -> expr.convert(::mkRegexDifference) Kind.REGEXP_COMPLEMENT -> expr.convert(::mkRegexComplement) Kind.REGEXP_OPT -> expr.convert(::mkRegexOption) - Kind.REGEXP_NONE -> convert { mkEpsilon() } - Kind.REGEXP_ALL -> convert { mkAll() } - Kind.REGEXP_ALLCHAR -> convert { mkAllChar() } - Kind.REGEXP_RANGE -> expr.convert(::mkRange) + Kind.REGEXP_NONE -> convert { mkRegexEpsilon() } + Kind.REGEXP_ALL -> convert { mkRegexAll() } + Kind.REGEXP_ALLCHAR -> convert { mkRegexAllChar() } + Kind.REGEXP_RANGE -> expr.convert(::mkRegexRange) Kind.REGEXP_REPEAT -> throw KSolverUnsupportedFeatureException( "No direct mapping of ${Kind.STRING_REV} in ksmt" ) diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt index 4d8f94cd4..4d58cbdea 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt @@ -159,16 +159,16 @@ import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KStringInRegexExpr -import io.ksmt.expr.KSuffixOfExpr -import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringSuffixOfExpr +import io.ksmt.expr.KStringPrefixOfExpr import io.ksmt.expr.KStringLtExpr import io.ksmt.expr.KStringLeExpr import io.ksmt.expr.KStringGtExpr import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KStringContainsExpr -import io.ksmt.expr.KSingletonSubstringExpr -import io.ksmt.expr.KSubstringExpr -import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringSingletonSubExpr +import io.ksmt.expr.KStringSubExpr +import io.ksmt.expr.KStringIndexOfExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr @@ -182,15 +182,15 @@ import io.ksmt.expr.KStringLiteralExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr import io.ksmt.expr.KRegexIntersectionExpr -import io.ksmt.expr.KRegexKleeneClosureExpr -import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexStarExpr +import io.ksmt.expr.KRegexCrossExpr import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr -import io.ksmt.expr.KRangeExpr -import io.ksmt.expr.KEpsilon -import io.ksmt.expr.KAll -import io.ksmt.expr.KAllChar +import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexEpsilon +import io.ksmt.expr.KRegexAll +import io.ksmt.expr.KRegexAllChar import io.ksmt.expr.rewrite.simplify.rewriteBvAddNoOverflowExpr import io.ksmt.expr.rewrite.simplify.rewriteBvAddNoUnderflowExpr import io.ksmt.expr.rewrite.simplify.rewriteBvDivNoOverflowExpr @@ -1204,61 +1204,61 @@ class KCvc5ExprInternalizer( } } - override fun transform(expr: KSuffixOfExpr) = with(expr) { + override fun transform(expr: KStringSuffixOfExpr) = with(expr) { transform(arg0, arg1) { arg0: Term, arg1: Term -> tm.mkTerm(Kind.STRING_SUFFIX, arg0, arg1) } } - override fun transform(expr: KPrefixOfExpr) = with(expr) { + override fun transform(expr: KStringPrefixOfExpr) = with(expr) { transform(arg0, arg1) { arg0: Term, arg1: Term -> tm.mkTerm(Kind.STRING_PREFIX, arg0, arg1) } } override fun transform(expr: KStringLtExpr) = with(expr) { - transform(lhs, rhs) { lhs: Term, rhs: Term -> - tm.mkTerm(Kind.STRING_LT, lhs, rhs) + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.STRING_LT, arg0, arg1) } } override fun transform(expr: KStringLeExpr) = with(expr) { - transform(lhs, rhs) { lhs: Term, rhs: Term -> - tm.mkTerm(Kind.STRING_LEQ, lhs, rhs) + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.STRING_LEQ, arg0, arg1) } } override fun transform(expr: KStringGtExpr) = with(expr) { - transform(lhs, rhs) { lhs: Term, rhs: Term -> - tm.mkTerm(Kind.STRING_LT, rhs, lhs) + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.STRING_LT, arg1, arg0) } } override fun transform(expr: KStringGeExpr) = with(expr) { - transform(lhs, rhs) { lhs: Term, rhs: Term -> - tm.mkTerm(Kind.STRING_LEQ, rhs, lhs) + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.STRING_LEQ, arg1, arg0) } } override fun transform(expr: KStringContainsExpr) = with(expr) { - transform(lhs, rhs) { lhs: Term, rhs: Term -> - tm.mkTerm(Kind.STRING_CONTAINS, rhs, lhs) + transform(arg0, arg1) { arg0: Term, arg1: Term -> + tm.mkTerm(Kind.STRING_CONTAINS, arg0, arg1) } } - override fun transform(expr: KSingletonSubstringExpr) = with(expr) { + override fun transform(expr: KStringSingletonSubExpr) = with(expr) { transform(arg0, arg1) { arg0: Term, arg1: Term -> tm.mkTerm(Kind.STRING_CHARAT, arg0, arg1) } } - override fun transform(expr: KSubstringExpr) = with(expr) { + override fun transform(expr: KStringSubExpr) = with(expr) { transform(arg0, arg1, arg2) { arg0: Term, arg1: Term, arg2: Term -> tm.mkTerm(Kind.STRING_SUBSTR, arg0, arg1, arg2) } } - override fun transform(expr: KIndexOfExpr) = with(expr) { + override fun transform(expr: KStringIndexOfExpr) = with(expr) { transform(arg0, arg1, arg2) { arg0: Term, arg1: Term, arg2: Term -> tm.mkTerm(Kind.STRING_INDEXOF, arg0, arg1, arg2) } @@ -1341,13 +1341,13 @@ class KCvc5ExprInternalizer( } } - override fun transform(expr: KRegexKleeneClosureExpr) = with(expr) { + override fun transform(expr: KRegexStarExpr) = with(expr) { transform(arg) { arg: Term -> tm.mkTerm(Kind.REGEXP_STAR, arg) } } - override fun transform(expr: KRegexKleeneCrossExpr) = with(expr) { + override fun transform(expr: KRegexCrossExpr) = with(expr) { transform(arg) { arg: Term -> tm.mkTerm(Kind.REGEXP_PLUS, arg) } @@ -1371,21 +1371,21 @@ class KCvc5ExprInternalizer( } } - override fun transform(expr: KRangeExpr) = with(expr) { + override fun transform(expr: KRegexRangeExpr) = with(expr) { transform(arg0, arg1) { arg0: Term, arg1: Term -> tm.mkTerm(Kind.REGEXP_RANGE, arg0, arg1) } } - override fun transform(expr: KEpsilon) = with(expr) { + override fun transform(expr: KRegexEpsilon) = with(expr) { transform { tm.mkTerm(Kind.REGEXP_NONE) } } - override fun transform(expr: KAll) = with(expr) { + override fun transform(expr: KRegexAll) = with(expr) { transform { tm.mkTerm(Kind.REGEXP_ALL) } } - override fun transform(expr: KAllChar) = with(expr) { + override fun transform(expr: KRegexAllChar) = with(expr) { transform { tm.mkTerm(Kind.REGEXP_ALLCHAR) } } diff --git a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt index 34547ea05..86a8a7963 100644 --- a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt +++ b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt @@ -149,16 +149,16 @@ import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLenExpr import io.ksmt.expr.KStringToRegexExpr import io.ksmt.expr.KStringInRegexExpr -import io.ksmt.expr.KSuffixOfExpr -import io.ksmt.expr.KPrefixOfExpr +import io.ksmt.expr.KStringSuffixOfExpr +import io.ksmt.expr.KStringPrefixOfExpr import io.ksmt.expr.KStringLtExpr import io.ksmt.expr.KStringLeExpr import io.ksmt.expr.KStringGtExpr import io.ksmt.expr.KStringGeExpr import io.ksmt.expr.KStringContainsExpr -import io.ksmt.expr.KSingletonSubstringExpr -import io.ksmt.expr.KSubstringExpr -import io.ksmt.expr.KIndexOfExpr +import io.ksmt.expr.KStringSingletonSubExpr +import io.ksmt.expr.KStringSubExpr +import io.ksmt.expr.KStringIndexOfExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr @@ -172,15 +172,15 @@ import io.ksmt.expr.KStringLiteralExpr import io.ksmt.expr.KRegexConcatExpr import io.ksmt.expr.KRegexUnionExpr import io.ksmt.expr.KRegexIntersectionExpr -import io.ksmt.expr.KRegexKleeneClosureExpr -import io.ksmt.expr.KRegexKleeneCrossExpr +import io.ksmt.expr.KRegexStarExpr +import io.ksmt.expr.KRegexCrossExpr import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr -import io.ksmt.expr.KRangeExpr -import io.ksmt.expr.KEpsilon -import io.ksmt.expr.KAll -import io.ksmt.expr.KAllChar +import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexEpsilon +import io.ksmt.expr.KRegexAll +import io.ksmt.expr.KRegexAllChar import io.ksmt.expr.rewrite.simplify.rewriteBvAddNoOverflowExpr import io.ksmt.expr.rewrite.simplify.rewriteBvAddNoUnderflowExpr import io.ksmt.expr.rewrite.simplify.rewriteBvDivNoOverflowExpr @@ -1018,11 +1018,11 @@ open class KYicesExprInternalizer( throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } - override fun transform(expr: KSuffixOfExpr): KExpr { + override fun transform(expr: KStringSuffixOfExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } - override fun transform(expr: KPrefixOfExpr): KExpr { + override fun transform(expr: KStringPrefixOfExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } @@ -1046,15 +1046,15 @@ open class KYicesExprInternalizer( throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } - override fun transform(expr: KSingletonSubstringExpr): KExpr { + override fun transform(expr: KStringSingletonSubExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } - override fun transform(expr: KSubstringExpr): KExpr { + override fun transform(expr: KStringSubExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } - override fun transform(expr: KIndexOfExpr): KExpr { + override fun transform(expr: KStringIndexOfExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } @@ -1110,11 +1110,11 @@ open class KYicesExprInternalizer( throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } - override fun transform(expr: KRegexKleeneClosureExpr): KExpr { + override fun transform(expr: KRegexStarExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } - override fun transform(expr: KRegexKleeneCrossExpr): KExpr { + override fun transform(expr: KRegexCrossExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } @@ -1130,19 +1130,19 @@ open class KYicesExprInternalizer( throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } - override fun transform(expr: KRangeExpr): KExpr { + override fun transform(expr: KRegexRangeExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } - override fun transform(expr: KEpsilon): KExpr { + override fun transform(expr: KRegexEpsilon): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } - override fun transform(expr: KAll): KExpr { + override fun transform(expr: KRegexAll): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } - override fun transform(expr: KAllChar): KExpr { + override fun transform(expr: KRegexAllChar): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } From ce195266902cf740a67c18a88ecd160b6c763d14 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Thu, 12 Dec 2024 03:47:59 +0300 Subject: [PATCH 49/84] Update sort visitor implementation for theory requirement --- .../src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt index ae88d2b7d..c9bd6ccc5 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/KExprTheoryRequirement.kt @@ -18,6 +18,7 @@ import io.ksmt.solver.KTheory.LRA import io.ksmt.solver.KTheory.NIA import io.ksmt.solver.KTheory.NRA import io.ksmt.solver.KTheory.UF +import io.ksmt.solver.KTheory.S import io.ksmt.sort.KSortVisitor import io.ksmt.sort.KSort import io.ksmt.sort.KBoolSort @@ -93,11 +94,11 @@ class KExprTheoryRequirement(ctx: KContext) : KNonRecursiveTransformer(ctx) { } override fun visit(sort: KStringSort) { - TODO("Not yet implemented") + usedTheories += S } override fun visit(sort: KRegexSort) { - TODO("Not yet implemented") + usedTheories += S } override fun visit(sort: S) { From c9e2e19d053e3e250106790c7b5e6694429187d2 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Thu, 12 Dec 2024 04:16:26 +0300 Subject: [PATCH 50/84] Add string and regex sorts to z3 sort internalizer --- .../kotlin/io/ksmt/solver/z3/KZ3SortInternalizer.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3SortInternalizer.kt b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3SortInternalizer.kt index 614cb8225..bbfc72248 100644 --- a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3SortInternalizer.kt +++ b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3SortInternalizer.kt @@ -17,6 +17,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KSortVisitor import io.ksmt.sort.KUninterpretedSort @@ -40,6 +42,14 @@ open class KZ3SortInternalizer( internalizedSort = Native.mkRealSort(nCtx) } + override fun visit(sort: KStringSort) { + internalizedSort = Native.mkStringSort(nCtx) + } + + override fun visit(sort: KRegexSort) { + internalizedSort = Native.mkReSort(nCtx, Native.mkStringSort(nCtx)) + } + override fun visit(sort: KArraySort) { val domain = internalizeZ3Sort(sort.domain) val range = internalizeZ3Sort(sort.range) From 07bdf4b749ff3cfefeb878d3adf7408a66bf34b7 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Thu, 12 Dec 2024 04:26:06 +0300 Subject: [PATCH 51/84] Implement z3 internalizer some methods for strings --- .../io/ksmt/solver/z3/KZ3ExprInternalizer.kt | 246 ++++++++++++++++++ 1 file changed, 246 insertions(+) diff --git a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt index 75cdfc558..2a648d4d8 100644 --- a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt +++ b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt @@ -149,6 +149,42 @@ import io.ksmt.expr.KUnaryMinusArithExpr import io.ksmt.expr.KUninterpretedSortValue import io.ksmt.expr.KUniversalQuantifier import io.ksmt.expr.KXorExpr +import io.ksmt.expr.KStringConcatExpr +import io.ksmt.expr.KStringLenExpr +import io.ksmt.expr.KStringToRegexExpr +import io.ksmt.expr.KStringInRegexExpr +import io.ksmt.expr.KStringSuffixOfExpr +import io.ksmt.expr.KStringPrefixOfExpr +import io.ksmt.expr.KStringLtExpr +import io.ksmt.expr.KStringLeExpr +import io.ksmt.expr.KStringGtExpr +import io.ksmt.expr.KStringGeExpr +import io.ksmt.expr.KStringContainsExpr +import io.ksmt.expr.KStringSingletonSubExpr +import io.ksmt.expr.KStringSubExpr +import io.ksmt.expr.KStringIndexOfExpr +import io.ksmt.expr.KStringReplaceExpr +import io.ksmt.expr.KStringReplaceAllExpr +import io.ksmt.expr.KStringReplaceWithRegexExpr +import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringIsDigitExpr +import io.ksmt.expr.KStringToCodeExpr +import io.ksmt.expr.KStringFromCodeExpr +import io.ksmt.expr.KStringToIntExpr +import io.ksmt.expr.KStringFromIntExpr +import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.KRegexConcatExpr +import io.ksmt.expr.KRegexUnionExpr +import io.ksmt.expr.KRegexIntersectionExpr +import io.ksmt.expr.KRegexStarExpr +import io.ksmt.expr.KRegexCrossExpr +import io.ksmt.expr.KRegexDifferenceExpr +import io.ksmt.expr.KRegexComplementExpr +import io.ksmt.expr.KRegexOptionExpr +import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexEpsilon +import io.ksmt.expr.KRegexAll +import io.ksmt.expr.KRegexAllChar import io.ksmt.solver.util.KExprLongInternalizerBase import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort @@ -825,6 +861,216 @@ open class KZ3ExprInternalizer( } } + // strings + override fun transform(expr: KStringConcatExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkSeqConcat(nCtx, 2, longArrayOf(arg0, arg1)) + } + } + + override fun transform(expr: KStringLenExpr) = with(expr) { + transform(arg) { arg -> + Native.mkSeqLength(nCtx, arg) + } + } + + override fun transform(expr: KStringToRegexExpr) = with(expr) { + transform(arg) { arg -> + Native.mkSeqToRe(nCtx, arg) + } + } + + override fun transform(expr: KStringInRegexExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkSeqInRe(nCtx, arg0, arg1) + } + } + + override fun transform(expr: KStringSuffixOfExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkSeqSuffix(nCtx, arg0, arg1) + } + } + + override fun transform(expr: KStringPrefixOfExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkSeqPrefix(nCtx, arg0, arg1) + } + } + + override fun transform(expr: KStringLtExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkStrLt(nCtx, arg0, arg1) + } + } + + override fun transform(expr: KStringLeExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkStrLe(nCtx, arg0, arg1) + } + } + + override fun transform(expr: KStringGtExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkStrLt(nCtx, arg1, arg0) + } + } + + override fun transform(expr: KStringGeExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkStrLe(nCtx, arg1, arg0) + } + } + + override fun transform(expr: KStringContainsExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkSeqContains(nCtx, arg0, arg1) + } + } + + override fun transform(expr: KStringSingletonSubExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkSeqAt(nCtx, arg0, arg1) + } + } + + override fun transform(expr: KStringSubExpr) = with(expr) { + transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> + TODO("Not yet implemented") + } + } + + override fun transform(expr: KStringIndexOfExpr) = with(expr) { + transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> + Native.mkSeqIndex(nCtx, arg0, arg1, arg2) + } + } + + override fun transform(expr: KStringReplaceExpr) = with(expr) { + transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> + TODO("Not yet implemented") + } + } + + override fun transform(expr: KStringReplaceAllExpr) = with(expr) { + transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> + TODO("Not yet implemented") + } + } + + override fun transform(expr: KStringReplaceWithRegexExpr) = with(expr) { + transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> + TODO("Not yet implemented") + } + } + + override fun transform(expr: KStringReplaceAllWithRegexExpr) = with(expr) { + transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> + TODO("Not yet implemented") + } + } + + override fun transform(expr: KStringIsDigitExpr) = with(expr) { + transform(arg) { arg -> + TODO("Not yet implemented") + } + } + + override fun transform(expr: KStringToCodeExpr) = with(expr) { + transform(arg) { arg -> + Native.mkStringToCode(nCtx, arg) + } + } + + override fun transform(expr: KStringFromCodeExpr) = with(expr) { + transform(arg) { arg -> + Native.mkStringFromCode(nCtx, arg) + } + } + + override fun transform(expr: KStringToIntExpr) = with(expr) { + transform(arg) { arg -> + Native.mkStrToInt(nCtx, arg) + } + } + + override fun transform(expr: KStringFromIntExpr) = with(expr) { + transform(arg) { arg -> + Native.mkIntToStr(nCtx, arg) + } + } + + override fun transform(expr: KStringLiteralExpr) = with(expr) { + transform { Native.mkString(nCtx, value) } + } + + // regex + override fun transform(expr: KRegexConcatExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkReConcat(nCtx, 2, longArrayOf(arg0, arg1)) + } + } + + override fun transform(expr: KRegexUnionExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkReUnion(nCtx, 2, longArrayOf(arg0, arg1)) + } + } + + override fun transform(expr: KRegexIntersectionExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkReIntersect(nCtx, 2, longArrayOf(arg0, arg1)) + } + } + + override fun transform(expr: KRegexStarExpr) = with(expr) { + transform(arg) { arg -> + Native.mkReStar(nCtx, arg) + } + } + + override fun transform(expr: KRegexCrossExpr) = with(expr) { + transform(arg) { arg -> + Native.mkRePlus(nCtx, arg) + } + } + + override fun transform(expr: KRegexDifferenceExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkReDiff(nCtx, arg0, arg1) + } + } + + override fun transform(expr: KRegexComplementExpr) = with(expr) { + transform(arg) { arg -> + Native.mkReComplement(nCtx, arg) + } + } + + override fun transform(expr: KRegexOptionExpr) = with(expr) { + transform(arg) { arg -> + Native.mkReOption(nCtx, arg) + } + } + + override fun transform(expr: KRegexRangeExpr) = with(expr) { + transform(arg0, arg1) { arg0, arg1 -> + Native.mkReRange(nCtx, arg0, arg1) + } + } + + override fun transform(expr: KRegexEpsilon) = with(expr) { + TODO("Not yet implemented") + } + + override fun transform(expr: KRegexAll) = with(expr) { + TODO("Not yet implemented") + } + + override fun transform(expr: KRegexAllChar) = with(expr) { + TODO("Not yet implemented") + } + private fun transformQuantifier(expr: KQuantifier, isUniversal: Boolean) = with(expr) { val boundConstants = bounds.map { ctx.mkConstApp(it) } transformArray(boundConstants + body) { args -> From 18d690da18db2ee393059abe1fb22efd11d4ff04 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Thu, 12 Dec 2024 17:16:28 +0300 Subject: [PATCH 52/84] Add string literals printer with quotes --- ksmt-core/src/main/kotlin/io/ksmt/decl/KDecl.kt | 7 ++++++- ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt | 3 +++ .../main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/KDecl.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/KDecl.kt index f309d187a..147162fb7 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/KDecl.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/KDecl.kt @@ -18,7 +18,12 @@ abstract class KDecl( override fun print(builder: StringBuilder): Unit = with(builder) { append('(') - append(name) + + if (this@KDecl is KStringLiteralDecl) { + append("\"$name\"") + } else { + append(name) + } if (this@KDecl is KParameterizedFuncDecl) { append(parameters.joinToString(separator = " ", prefix = " [", postfix = "]")) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index 4451d670a..5f45e6d0b 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -27,6 +27,7 @@ import io.ksmt.decl.KStringFromCodeDecl import io.ksmt.decl.KStringToIntDecl import io.ksmt.decl.KStringFromIntDecl import io.ksmt.decl.KStringLiteralDecl +import io.ksmt.expr.printer.ExpressionPrinter import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KSort import io.ksmt.sort.KBoolSort @@ -534,6 +535,8 @@ class KStringLiteralExpr internal constructor( override fun accept(transformer: KTransformerBase): KExpr = transformer.transform(this) + override fun print(printer: ExpressionPrinter) = with(printer) { append("\"$value\"") } + override fun internHashCode(): Int = hash(value) override fun internEquals(other: Any): Boolean = structurallyEqual(other) { value } } diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt index d0d2c9e98..40408da25 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt @@ -431,10 +431,10 @@ open class KCvc5ExprConverter( Kind.REGEXP_ALLCHAR -> convert { mkRegexAllChar() } Kind.REGEXP_RANGE -> expr.convert(::mkRegexRange) Kind.REGEXP_REPEAT -> throw KSolverUnsupportedFeatureException( - "No direct mapping of ${Kind.STRING_REV} in ksmt" + "No direct mapping of ${Kind.REGEXP_REPEAT} in ksmt" ) Kind.REGEXP_LOOP -> throw KSolverUnsupportedFeatureException( - "No direct mapping of ${Kind.STRING_REV} in ksmt" + "No direct mapping of ${Kind.REGEXP_LOOP} in ksmt" ) Kind.EQ_RANGE -> throw KSolverUnsupportedFeatureException("EQ_RANGE is not supported") From 3e7f8bd27b32f0090a06f510a9fa77bcc86378d5 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Fri, 13 Dec 2024 00:43:59 +0300 Subject: [PATCH 53/84] Implement toLower, toUpper and reverse string operations --- .../bitwuzla/KBitwuzlaExprInternalizer.kt | 20 +++++ ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 88 ++++++++++++++++++ .../main/kotlin/io/ksmt/decl/KDeclVisitor.kt | 4 + .../src/main/kotlin/io/ksmt/decl/String.kt | 68 ++++++++++++++ .../src/main/kotlin/io/ksmt/expr/String.kt | 90 +++++++++++++++++++ .../transformer/KNonRecursiveTransformer.kt | 24 +++++ .../expr/transformer/KNonRecursiveVisitor.kt | 16 ++++ .../io/ksmt/expr/transformer/KTransformer.kt | 8 ++ .../ksmt/expr/transformer/KTransformerBase.kt | 8 ++ .../io/ksmt/expr/transformer/KVisitor.kt | 12 +++ .../io/ksmt/solver/cvc5/KCvc5ExprConverter.kt | 16 +--- .../ksmt/solver/cvc5/KCvc5ExprInternalizer.kt | 28 ++++++ .../solver/yices/KYicesExprInternalizer.kt | 20 +++++ .../io/ksmt/solver/z3/KZ3ExprInternalizer.kt | 28 ++++++ 14 files changed, 418 insertions(+), 12 deletions(-) diff --git a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt index d883f6472..f21f2013d 100644 --- a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt +++ b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt @@ -165,10 +165,14 @@ import io.ksmt.expr.KStringContainsExpr import io.ksmt.expr.KStringSingletonSubExpr import io.ksmt.expr.KStringSubExpr import io.ksmt.expr.KStringIndexOfExpr +import io.ksmt.expr.KStringIndexOfRegexExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringToLowerExpr +import io.ksmt.expr.KStringToUpperExpr +import io.ksmt.expr.KStringReverseExpr import io.ksmt.expr.KStringIsDigitExpr import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr @@ -1499,6 +1503,10 @@ open class KBitwuzlaExprInternalizer(val bitwuzlaCtx: KBitwuzlaContext) : KExprL throw KSolverUnsupportedFeatureException("string and int theory is not supported in Bitwuzla") } + override fun transform(expr: KStringIndexOfRegexExpr): KExpr { + throw KSolverUnsupportedFeatureException("string and int theory is not supported in Bitwuzla") + } + override fun transform(expr: KStringReplaceExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } @@ -1515,6 +1523,18 @@ open class KBitwuzlaExprInternalizer(val bitwuzlaCtx: KBitwuzlaContext) : KExprL throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } + override fun transform(expr: KStringToLowerExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringToUpperExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KStringReverseExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + override fun transform(expr: KStringIsDigitExpr): KExpr { throw KSolverUnsupportedFeatureException("string and int theory is not supported in Bitwuzla") } diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index b9ddf2241..31e323c5a 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -144,10 +144,14 @@ import io.ksmt.decl.KStringContainsDecl import io.ksmt.decl.KStringSingletonSubDecl import io.ksmt.decl.KStringSubDecl import io.ksmt.decl.KStringIndexOfDecl +import io.ksmt.decl.KStringIndexOfRegexDecl import io.ksmt.decl.KStringReplaceDecl import io.ksmt.decl.KStringReplaceAllDecl import io.ksmt.decl.KStringReplaceWithRegexDecl import io.ksmt.decl.KStringReplaceAllWithRegexDecl +import io.ksmt.decl.KStringToLowerDecl +import io.ksmt.decl.KStringToUpperDecl +import io.ksmt.decl.KStringReverseDecl import io.ksmt.decl.KStringIsDigitDecl import io.ksmt.decl.KStringToCodeDecl import io.ksmt.decl.KStringFromCodeDecl @@ -323,10 +327,14 @@ import io.ksmt.expr.KStringContainsExpr import io.ksmt.expr.KStringSingletonSubExpr import io.ksmt.expr.KStringSubExpr import io.ksmt.expr.KStringIndexOfExpr +import io.ksmt.expr.KStringIndexOfRegexExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringToLowerExpr +import io.ksmt.expr.KStringToUpperExpr +import io.ksmt.expr.KStringReverseExpr import io.ksmt.expr.KStringIsDigitExpr import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr @@ -2224,6 +2232,27 @@ open class KContext( KStringIndexOfExpr(this, arg0, arg1, arg2) } + private val stringIndexOfRegexCache = mkAstInterner() + + /** + * Find the index of the first match of a regular expression in the string, + * starting at the specified position. Returns -1 if not found + * or if the position is out of bounds. + */ + open fun mkStringIndexOfRegex(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = + mkSimplified(arg0, arg1, arg2, KContext::mkStringIndexOfRegexNoSimplify, ::mkStringIndexOfRegexNoSimplify) // Add simplified version + + /** + * Find the index of the first match of a regular expression in the string, + * starting at the specified position. Returns -1 if not found + * or if the position is out of bounds. + */ + open fun mkStringIndexOfRegexNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringIndexOfRegexExpr = + stringIndexOfRegexCache.createIfContextActive { + ensureContextMatch(arg0, arg1) + KStringIndexOfRegexExpr(this, arg0, arg1, arg2) + } + private val stringReplaceCache = mkAstInterner() /** @@ -2300,6 +2329,57 @@ open class KContext( KStringReplaceAllWithRegexExpr(this, arg0, arg1, arg2) } + private val stringToLowerExprCache = mkAstInterner() + + /** + * Convert string to lower case. + * */ + open fun mkStringToLower(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkStringToLowerNoSimplify, ::mkStringToLowerNoSimplify) // Add simplified version + + /** + * Convert string to lower case. + * */ + open fun mkStringToLowerNoSimplify(arg: KExpr): KStringToLowerExpr = + stringToLowerExprCache.createIfContextActive { + ensureContextMatch(arg) + KStringToLowerExpr(this, arg) + } + + private val stringToUpperExprCache = mkAstInterner() + + /** + * Convert string to upper case. + * */ + open fun mkStringToUpper(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkStringToUpperNoSimplify, ::mkStringToUpperNoSimplify) // Add simplified version + + /** + * Convert string to upper case. + * */ + open fun mkStringToUpperNoSimplify(arg: KExpr): KStringToUpperExpr = + stringToUpperExprCache.createIfContextActive { + ensureContextMatch(arg) + KStringToUpperExpr(this, arg) + } + + private val stringReverseExprCache = mkAstInterner() + + /** + * Reverse string. + * */ + open fun mkStringReverse(arg: KExpr): KExpr = + mkSimplified(arg, KContext::mkStringReverseNoSimplify, ::mkStringReverseNoSimplify) // Add simplified version + + /** + * Reverse string. + * */ + open fun mkStringReverseNoSimplify(arg: KExpr): KStringReverseExpr = + stringReverseExprCache.createIfContextActive { + ensureContextMatch(arg) + KStringReverseExpr(this, arg) + } + private val stringIsDigitCache = mkAstInterner() /** @@ -5249,6 +5329,8 @@ open class KContext( fun mkStringIndexOfDecl(): KStringIndexOfDecl = KStringIndexOfDecl(this) + fun mkStringIndexOfRegexDecl(): KStringIndexOfRegexDecl = KStringIndexOfRegexDecl(this) + fun mkStringReplaceDecl(): KStringReplaceDecl = KStringReplaceDecl(this) fun mkStringReplaceAllDecl(): KStringReplaceAllDecl = KStringReplaceAllDecl(this) @@ -5257,6 +5339,12 @@ open class KContext( fun mkStringReplaceAllWithRegexDecl(): KStringReplaceAllWithRegexDecl = KStringReplaceAllWithRegexDecl(this) + fun mkStringToLowerDecl(): KStringToLowerDecl = KStringToLowerDecl(this) + + fun mkStringToUpperDecl(): KStringToUpperDecl = KStringToUpperDecl(this) + + fun mkStringReverseDecl(): KStringReverseDecl = KStringReverseDecl(this) + fun mkStringIsDigitDecl(): KStringIsDigitDecl = KStringIsDigitDecl(this) fun mkStringToCodeDecl(): KStringToCodeDecl = KStringToCodeDecl(this) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt index d86452ebf..3f5c45b64 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt @@ -148,10 +148,14 @@ interface KDeclVisitor { fun visit(decl: KStringSingletonSubDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringSubDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringIndexOfDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringIndexOfRegexDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringReplaceDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringReplaceAllDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringReplaceWithRegexDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringReplaceAllWithRegexDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringToLowerDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringToUpperDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KStringReverseDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringIsDigitDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringToCodeDecl): T = visit(decl as KFuncDecl) fun visit(decl: KStringFromCodeDecl): T = visit(decl as KFuncDecl) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt index ec8e06de1..8304d96af 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt @@ -245,6 +245,25 @@ class KStringIndexOfDecl internal constructor( ): KApp = mkStringIndexOfNoSimplify(arg0, arg1, arg2) } +class KStringIndexOfRegexDecl internal constructor( + ctx: KContext, +) : KFuncDecl3( + ctx, + "str_index_of_regex", + ctx.mkIntSort(), + ctx.mkStringSort(), + ctx.mkRegexSort(), + ctx.mkIntSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KApp = mkStringIndexOfRegexNoSimplify(arg0, arg1, arg2) +} + class KStringReplaceDecl internal constructor( ctx: KContext, ) : KFuncDecl3( @@ -321,6 +340,51 @@ class KStringReplaceAllWithRegexDecl internal constructor( ): KApp = mkStringReplaceAllWithRegexNoSimplify(arg0, arg1, arg2) } +class KStringToLowerDecl internal constructor( + ctx: KContext +) : KFuncDecl1( + ctx, + "str_to_lower", + ctx.mkStringSort(), + ctx.mkStringSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg: KExpr + ): KApp = mkStringToLowerNoSimplify(arg) +} + +class KStringToUpperDecl internal constructor( + ctx: KContext +) : KFuncDecl1( + ctx, + "str_to_upper", + ctx.mkStringSort(), + ctx.mkStringSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg: KExpr + ): KApp = mkStringToUpperNoSimplify(arg) +} + +class KStringReverseDecl internal constructor( + ctx: KContext +) : KFuncDecl1( + ctx, + "str_rev", + ctx.mkStringSort(), + ctx.mkStringSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg: KExpr + ): KApp = mkStringReverseNoSimplify(arg) +} + /* Maps to and from integers. */ @@ -390,6 +454,10 @@ class KStringFromIntDecl internal constructor( override fun KContext.apply(arg: KExpr): KApp = mkStringFromIntNoSimplify(arg) } +/* + Literals + */ + class KStringLiteralDecl internal constructor( ctx: KContext, val value: String diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt index 5f45e6d0b..1f96a4b65 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt @@ -17,10 +17,14 @@ import io.ksmt.decl.KStringContainsDecl import io.ksmt.decl.KStringSingletonSubDecl import io.ksmt.decl.KStringSubDecl import io.ksmt.decl.KStringIndexOfDecl +import io.ksmt.decl.KStringIndexOfRegexDecl import io.ksmt.decl.KStringReplaceDecl import io.ksmt.decl.KStringReplaceAllDecl import io.ksmt.decl.KStringReplaceWithRegexDecl import io.ksmt.decl.KStringReplaceAllWithRegexDecl +import io.ksmt.decl.KStringToLowerDecl +import io.ksmt.decl.KStringToUpperDecl +import io.ksmt.decl.KStringReverseDecl import io.ksmt.decl.KStringIsDigitDecl import io.ksmt.decl.KStringToCodeDecl import io.ksmt.decl.KStringFromCodeDecl @@ -330,6 +334,28 @@ class KStringIndexOfExpr internal constructor( override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) } +class KStringIndexOfRegexExpr internal constructor( + ctx: KContext, + val arg0: KExpr, + val arg1: KExpr, + val arg2: KExpr +) : KApp(ctx) { + override val sort: KIntSort + get() = ctx.intSort + + override val args: List> + get() = listOf(arg0.cast(), arg1.cast(), arg2.cast()) + + override val decl: KStringIndexOfRegexDecl + get() = ctx.mkStringIndexOfRegexDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) + + override fun internHashCode(): Int = hash(arg0, arg1, arg2) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) +} + class KStringReplaceExpr internal constructor( ctx: KContext, val arg0: KExpr, @@ -418,6 +444,66 @@ class KStringReplaceAllWithRegexExpr internal constructor( override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }, { arg2 }) } +class KStringToLowerExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KStringSort + get() = ctx.stringSort + + override val args: List> + get() = listOf(arg) + + override val decl: KStringToLowerDecl + get() = ctx.mkStringToLowerDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) + + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} + +class KStringToUpperExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KStringSort + get() = ctx.stringSort + + override val args: List> + get() = listOf(arg) + + override val decl: KStringToUpperDecl + get() = ctx.mkStringToUpperDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) + + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} + +class KStringReverseExpr internal constructor( + ctx: KContext, + val arg: KExpr +) : KApp(ctx) { + override val sort: KStringSort + get() = ctx.stringSort + + override val args: List> + get() = listOf(arg) + + override val decl: KStringReverseDecl + get() = ctx.mkStringReverseDecl() + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) + + override fun internHashCode(): Int = hash(arg) + override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } +} + /* Maps to and from integers. */ @@ -522,6 +608,10 @@ class KStringFromIntExpr internal constructor( override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg } } +/* + Literals + */ + class KStringLiteralExpr internal constructor( ctx: KContext, val value: String diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt index f654fcdd2..2c09c771f 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt @@ -138,10 +138,14 @@ import io.ksmt.expr.KStringContainsExpr import io.ksmt.expr.KStringSingletonSubExpr import io.ksmt.expr.KStringSubExpr import io.ksmt.expr.KStringIndexOfExpr +import io.ksmt.expr.KStringIndexOfRegexExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringToLowerExpr +import io.ksmt.expr.KStringToUpperExpr +import io.ksmt.expr.KStringReverseExpr import io.ksmt.expr.KStringIsDigitExpr import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr @@ -766,6 +770,11 @@ abstract class KNonRecursiveTransformer(override val ctx: KContext) : KNonRecurs expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkStringIndexOf ) + override fun transform(expr: KStringIndexOfRegexExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkStringIndexOfRegex + ) + override fun transform(expr: KStringReplaceExpr): KExpr = transformExprAfterTransformedDefault( expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkStringReplace @@ -786,6 +795,21 @@ abstract class KNonRecursiveTransformer(override val ctx: KContext) : KNonRecurs expr, expr.arg0, expr.arg1, expr.arg2, ::transformApp, KContext::mkStringReplaceAllWithRegex ) + override fun transform(expr: KStringToLowerExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkStringToLower + ) + + override fun transform(expr: KStringToUpperExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkStringToUpper + ) + + override fun transform(expr: KStringReverseExpr): KExpr = + transformExprAfterTransformedDefault( + expr, expr.arg, ::transformApp, KContext::mkStringReverse + ) + override fun transform(expr: KStringIsDigitExpr): KExpr = transformExprAfterTransformedDefault( expr, expr.arg, ::transformApp, KContext::mkStringIsDigit diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt index 40684b9c3..8d64be26e 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt @@ -138,10 +138,14 @@ import io.ksmt.expr.KStringContainsExpr import io.ksmt.expr.KStringSingletonSubExpr import io.ksmt.expr.KStringSubExpr import io.ksmt.expr.KStringIndexOfExpr +import io.ksmt.expr.KStringIndexOfRegexExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringToLowerExpr +import io.ksmt.expr.KStringToUpperExpr +import io.ksmt.expr.KStringReverseExpr import io.ksmt.expr.KStringIsDigitExpr import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr @@ -704,6 +708,9 @@ abstract class KNonRecursiveVisitor( override fun visit(expr: KStringIndexOfExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, expr.arg2, ::visitApp) + override fun visit(expr: KStringIndexOfRegexExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, expr.arg2, ::visitApp) + override fun visit(expr: KStringReplaceExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, expr.arg2, ::visitApp) @@ -716,6 +723,15 @@ abstract class KNonRecursiveVisitor( override fun visit(expr: KStringReplaceAllWithRegexExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, expr.arg2, ::visitApp) + override fun visit(expr: KStringToLowerExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + + override fun visit(expr: KStringToUpperExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + + override fun visit(expr: KStringReverseExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + override fun visit(expr: KStringIsDigitExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt index aae8df22b..22e01501a 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt @@ -164,10 +164,14 @@ import io.ksmt.expr.KStringContainsExpr import io.ksmt.expr.KStringSingletonSubExpr import io.ksmt.expr.KStringSubExpr import io.ksmt.expr.KStringIndexOfExpr +import io.ksmt.expr.KStringIndexOfRegexExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringToLowerExpr +import io.ksmt.expr.KStringToUpperExpr +import io.ksmt.expr.KStringReverseExpr import io.ksmt.expr.KStringIsDigitExpr import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr @@ -465,10 +469,14 @@ interface KTransformer : KTransformerBase { override fun transform(expr: KStringSingletonSubExpr): KExpr = transformApp(expr) override fun transform(expr: KStringSubExpr): KExpr = transformApp(expr) override fun transform(expr: KStringIndexOfExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringIndexOfRegexExpr): KExpr = transformApp(expr) override fun transform(expr: KStringReplaceExpr): KExpr = transformApp(expr) override fun transform(expr: KStringReplaceAllExpr): KExpr = transformApp(expr) override fun transform(expr: KStringReplaceWithRegexExpr): KExpr = transformApp(expr) override fun transform(expr: KStringReplaceAllWithRegexExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringToLowerExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringToUpperExpr): KExpr = transformApp(expr) + override fun transform(expr: KStringReverseExpr): KExpr = transformApp(expr) override fun transform(expr: KStringIsDigitExpr): KExpr = transformApp(expr) override fun transform(expr: KStringToCodeExpr): KExpr = transformApp(expr) override fun transform(expr: KStringFromCodeExpr): KExpr = transformApp(expr) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt index 8eae656be..a5a867859 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt @@ -155,10 +155,14 @@ import io.ksmt.expr.KStringContainsExpr import io.ksmt.expr.KStringSingletonSubExpr import io.ksmt.expr.KStringSubExpr import io.ksmt.expr.KStringIndexOfExpr +import io.ksmt.expr.KStringIndexOfRegexExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringToLowerExpr +import io.ksmt.expr.KStringToUpperExpr +import io.ksmt.expr.KStringReverseExpr import io.ksmt.expr.KStringIsDigitExpr import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr @@ -393,10 +397,14 @@ interface KTransformerBase { fun transform(expr: KStringSingletonSubExpr): KExpr fun transform(expr: KStringSubExpr): KExpr fun transform(expr: KStringIndexOfExpr): KExpr + fun transform(expr: KStringIndexOfRegexExpr): KExpr fun transform(expr: KStringReplaceExpr): KExpr fun transform(expr: KStringReplaceAllExpr): KExpr fun transform(expr: KStringReplaceWithRegexExpr): KExpr fun transform(expr: KStringReplaceAllWithRegexExpr): KExpr + fun transform(expr: KStringToLowerExpr): KExpr + fun transform(expr: KStringToUpperExpr): KExpr + fun transform(expr: KStringReverseExpr): KExpr fun transform(expr: KStringIsDigitExpr): KExpr fun transform(expr: KStringToCodeExpr): KExpr fun transform(expr: KStringFromCodeExpr): KExpr diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt index bae50fb0a..47af60183 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt @@ -163,10 +163,14 @@ import io.ksmt.expr.KStringContainsExpr import io.ksmt.expr.KStringSingletonSubExpr import io.ksmt.expr.KStringSubExpr import io.ksmt.expr.KStringIndexOfExpr +import io.ksmt.expr.KStringIndexOfRegexExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringToLowerExpr +import io.ksmt.expr.KStringToUpperExpr +import io.ksmt.expr.KStringReverseExpr import io.ksmt.expr.KStringIsDigitExpr import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr @@ -667,10 +671,14 @@ interface KVisitor : KTransformer { fun visit(expr: KStringSingletonSubExpr): V = visitApp(expr) fun visit(expr: KStringSubExpr): V = visitApp(expr) fun visit(expr: KStringIndexOfExpr): V = visitApp(expr) + fun visit(expr: KStringIndexOfRegexExpr): V = visitApp(expr) fun visit(expr: KStringReplaceExpr): V = visitApp(expr) fun visit(expr: KStringReplaceAllExpr): V = visitApp(expr) fun visit(expr: KStringReplaceWithRegexExpr): V = visitApp(expr) fun visit(expr: KStringReplaceAllWithRegexExpr): V = visitApp(expr) + fun visit(expr: KStringToLowerExpr): V = visitApp(expr) + fun visit(expr: KStringToUpperExpr): V = visitApp(expr) + fun visit(expr: KStringReverseExpr): V = visitApp(expr) fun visit(expr: KStringIsDigitExpr): V = visitApp(expr) fun visit(expr: KStringToCodeExpr): V = visitApp(expr) fun visit(expr: KStringFromCodeExpr): V = visitApp(expr) @@ -692,10 +700,14 @@ interface KVisitor : KTransformer { override fun transform(expr: KStringSingletonSubExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringSubExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringIndexOfExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringIndexOfRegexExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringReplaceExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringReplaceAllExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringReplaceWithRegexExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringReplaceAllWithRegexExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringToLowerExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringToUpperExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KStringReverseExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringIsDigitExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringToCodeExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KStringFromCodeExpr): KExpr = visitExpr(expr, ::visit) diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt index 40408da25..19c6f99e4 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt @@ -401,21 +401,13 @@ open class KCvc5ExprConverter( Kind.STRING_FROM_CODE -> expr.convert(::mkStringFromCode) Kind.STRING_TO_INT -> expr.convert(::mkStringToInt) Kind.STRING_FROM_INT -> expr.convert(::mkStringFromInt) + Kind.STRING_INDEXOF_RE -> expr.convert(::mkStringIndexOfRegex) + Kind.STRING_TO_LOWER -> expr.convert(::mkStringToLower) + Kind.STRING_TO_UPPER -> expr.convert(::mkStringToUpper) + Kind.STRING_REV -> expr.convert(::mkStringReverse) Kind.STRING_UPDATE -> throw KSolverUnsupportedFeatureException( "No direct mapping of ${Kind.STRING_UPDATE} in ksmt" ) - Kind.STRING_INDEXOF_RE -> throw KSolverUnsupportedFeatureException( - "No direct mapping of ${Kind.STRING_INDEXOF_RE} in ksmt" - ) - Kind.STRING_TO_LOWER -> throw KSolverUnsupportedFeatureException( - "No direct mapping of ${Kind.STRING_TO_LOWER} in ksmt" - ) - Kind.STRING_TO_UPPER -> throw KSolverUnsupportedFeatureException( - "No direct mapping of ${Kind.STRING_TO_UPPER} in ksmt" - ) - Kind.STRING_REV -> throw KSolverUnsupportedFeatureException( - "No direct mapping of ${Kind.STRING_REV} in ksmt" - ) // regex Kind.REGEXP_CONCAT -> expr.convert(::mkRegexConcat) diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt index 4d58cbdea..216e8b77b 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt @@ -169,10 +169,14 @@ import io.ksmt.expr.KStringContainsExpr import io.ksmt.expr.KStringSingletonSubExpr import io.ksmt.expr.KStringSubExpr import io.ksmt.expr.KStringIndexOfExpr +import io.ksmt.expr.KStringIndexOfRegexExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringToLowerExpr +import io.ksmt.expr.KStringToUpperExpr +import io.ksmt.expr.KStringReverseExpr import io.ksmt.expr.KStringIsDigitExpr import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr @@ -1264,6 +1268,12 @@ class KCvc5ExprInternalizer( } } + override fun transform(expr: KStringIndexOfRegexExpr) = with(expr) { + transform(arg0, arg1, arg2) { arg0: Term, arg1: Term, arg2: Term -> + tm.mkTerm(Kind.STRING_INDEXOF_RE, arg0, arg1, arg2) + } + } + override fun transform(expr: KStringReplaceExpr) = with(expr) { transform(arg0, arg1, arg2) { arg0: Term, arg1: Term, arg2: Term -> tm.mkTerm(Kind.STRING_REPLACE, arg0, arg1, arg2) @@ -1288,6 +1298,24 @@ class KCvc5ExprInternalizer( } } + override fun transform(expr: KStringToLowerExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.STRING_TO_LOWER, arg) + } + } + + override fun transform(expr: KStringToUpperExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.STRING_TO_UPPER, arg) + } + } + + override fun transform(expr: KStringReverseExpr) = with(expr) { + transform(arg) { arg: Term -> + tm.mkTerm(Kind.STRING_REV, arg) + } + } + override fun transform(expr: KStringIsDigitExpr) = with(expr) { transform(arg) { arg: Term -> tm.mkTerm(Kind.STRING_IS_DIGIT, arg) diff --git a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt index 86a8a7963..71906e422 100644 --- a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt +++ b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt @@ -159,10 +159,14 @@ import io.ksmt.expr.KStringContainsExpr import io.ksmt.expr.KStringSingletonSubExpr import io.ksmt.expr.KStringSubExpr import io.ksmt.expr.KStringIndexOfExpr +import io.ksmt.expr.KStringIndexOfRegexExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringToLowerExpr +import io.ksmt.expr.KStringToUpperExpr +import io.ksmt.expr.KStringReverseExpr import io.ksmt.expr.KStringIsDigitExpr import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr @@ -1058,6 +1062,10 @@ open class KYicesExprInternalizer( throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } + override fun transform(expr: KStringIndexOfRegexExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + override fun transform(expr: KStringReplaceExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } @@ -1074,6 +1082,18 @@ open class KYicesExprInternalizer( throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } + override fun transform(expr: KStringToLowerExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KStringToUpperExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KStringReverseExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + override fun transform(expr: KStringIsDigitExpr): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } diff --git a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt index 2a648d4d8..04c5d1c70 100644 --- a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt +++ b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt @@ -163,10 +163,14 @@ import io.ksmt.expr.KStringContainsExpr import io.ksmt.expr.KStringSingletonSubExpr import io.ksmt.expr.KStringSubExpr import io.ksmt.expr.KStringIndexOfExpr +import io.ksmt.expr.KStringIndexOfRegexExpr import io.ksmt.expr.KStringReplaceExpr import io.ksmt.expr.KStringReplaceAllExpr import io.ksmt.expr.KStringReplaceWithRegexExpr import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringToLowerExpr +import io.ksmt.expr.KStringToUpperExpr +import io.ksmt.expr.KStringReverseExpr import io.ksmt.expr.KStringIsDigitExpr import io.ksmt.expr.KStringToCodeExpr import io.ksmt.expr.KStringFromCodeExpr @@ -946,6 +950,12 @@ open class KZ3ExprInternalizer( } } + override fun transform(expr: KStringIndexOfExpr) = with(expr) { + transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> + TODO("Not yet implemented") + } + } + override fun transform(expr: KStringReplaceExpr) = with(expr) { transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> TODO("Not yet implemented") @@ -970,6 +980,24 @@ open class KZ3ExprInternalizer( } } + override fun transform(expr: KStringToLowerExpr) = with(expr) { + transform(arg) { arg -> + TODO("Not yet implemented") + } + } + + override fun transform(expr: KStringToUpperExpr) = with(expr) { + transform(arg) { arg -> + TODO("Not yet implemented") + } + } + + override fun transform(expr: KStringReverseExpr) = with(expr) { + transform(arg) { arg -> + TODO("Not yet implemented") + } + } + override fun transform(expr: KStringIsDigitExpr) = with(expr) { transform(arg) { arg -> TODO("Not yet implemented") From a124b8b0742793e6f8aac51cc574e35d5c5e40f6 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sat, 14 Dec 2024 18:36:55 +0300 Subject: [PATCH 54/84] Add string and regex default values --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 4 ++++ .../main/kotlin/io/ksmt/utils/DefaultValueSampler.kt | 10 ++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index 31e323c5a..b80dc794e 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -5136,6 +5136,10 @@ open class KContext( open fun realSortDefaultValue(): KExpr = mkRealNum(0) + open fun stringSortDefaultValue(): KExpr = mkStringLiteral("") + + open fun regexSortDefaultValue(): KExpr = mkRegexEpsilon() + open fun bvSortDefaultValue(sort: S): KExpr = mkBv(0, sort) open fun fpSortDefaultValue(sort: S): KExpr = mkFpZero(signBit = false, sort) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt index df98dffcf..e17464256 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/DefaultValueSampler.kt @@ -28,13 +28,11 @@ open class DefaultValueSampler(val ctx: KContext) : KSortVisitor> { override fun visit(sort: KRealSort): KExpr<*> = ctx.realSortDefaultValue() - override fun visit(sort: KStringSort): KExpr<*> { - TODO("Not yet implemented") - } + override fun visit(sort: KStringSort): KExpr<*> = + ctx.stringSortDefaultValue() - override fun visit(sort: KRegexSort): KExpr<*> { - TODO("Not yet implemented") - } + override fun visit(sort: KRegexSort): KExpr<*> = + ctx.regexSortDefaultValue() override fun visit(sort: S): KExpr<*> = ctx.bvSortDefaultValue(sort) From ceb95a2bd25beebc6bb849840c797ddc90af3f36 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sat, 14 Dec 2024 18:38:19 +0300 Subject: [PATCH 55/84] Fix bug with regex constants in cvc5 --- .../io/ksmt/solver/cvc5/KCvc5DeclInternalizer.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5DeclInternalizer.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5DeclInternalizer.kt index 38c765b58..5364120c6 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5DeclInternalizer.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5DeclInternalizer.kt @@ -3,8 +3,11 @@ package io.ksmt.solver.cvc5 import io.github.cvc5.Solver import io.github.cvc5.Term import io.ksmt.decl.KConstDecl +import io.ksmt.decl.KDecl import io.ksmt.decl.KDeclVisitor import io.ksmt.decl.KFuncDecl +import io.ksmt.solver.KSolverUnsupportedFeatureException +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort open class KCvc5DeclInternalizer( @@ -29,9 +32,16 @@ open class KCvc5DeclInternalizer( } override fun visit(decl: KConstDecl): Term = cvc5Ctx.internalizeDecl(decl) { + checkConstDeclSort(decl) cvc5Ctx.addDeclaration(decl) val sort = decl.sort.accept(sortInternalizer) tm.builder { mkConst(sort, decl.name) } } + + private fun checkConstDeclSort(decl: KDecl) { + if (decl.sort is KRegexSort) { + throw KSolverUnsupportedFeatureException("Regex constants unsupported in cvc5") + } + } } From 9c2e89b57948c435fc4bbe2460fc165e28b37733 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 17 Dec 2024 18:06:46 +0300 Subject: [PATCH 56/84] Add string and regex sorts serializer and deserializer --- .../io/ksmt/runner/serializer/AstDeserializer.kt | 2 ++ .../kotlin/io/ksmt/runner/serializer/AstSerializer.kt | 10 ++++++++++ .../main/kotlin/io/ksmt/runner/serializer/SortKind.kt | 3 ++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt index 722c62d79..239990e2d 100644 --- a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt +++ b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt @@ -92,6 +92,8 @@ class AstDeserializer( SortKind.Bool -> boolSort SortKind.Int -> intSort SortKind.Real -> realSort + SortKind.String -> stringSort + SortKind.Regex -> regexSort SortKind.FpRM -> mkFpRoundingModeSort() SortKind.Bv -> mkBvSort(readUInt()) SortKind.Fp -> mkFpSort(readUInt(), readUInt()) diff --git a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstSerializer.kt b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstSerializer.kt index c17d79e3c..f699b8a75 100644 --- a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstSerializer.kt +++ b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstSerializer.kt @@ -164,6 +164,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KSortVisitor import io.ksmt.sort.KUninterpretedSort @@ -230,6 +232,14 @@ class AstSerializer( serializeSort(sort, SortKind.Real) {} } + override fun visit(sort: KStringSort) { + serializeSort(sort, SortKind.String) {} + } + + override fun visit(sort: KRegexSort) { + serializeSort(sort, SortKind.Regex) {} + } + override fun visit(sort: S) { serializeSort(sort, SortKind.Bv) { writeUInt(sort.sizeBits) diff --git a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/SortKind.kt b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/SortKind.kt index cdfac3d24..a24f38c70 100644 --- a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/SortKind.kt +++ b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/SortKind.kt @@ -1,5 +1,6 @@ package io.ksmt.runner.serializer enum class SortKind { - Bool, Int, Real, Bv, Fp, Array, Array2, Array3, ArrayN, FpRM, Uninterpreted + Bool, Int, Real, Bv, Fp, Array, Array2, Array3, ArrayN, FpRM, Uninterpreted, + String, Regex } From 1e31092c39e83b9c2b99532f4e4d3f8542bebfe2 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 17 Dec 2024 18:22:29 +0300 Subject: [PATCH 57/84] Add string and regex expressions serializer/deserializer --- .../ksmt/runner/serializer/AstDeserializer.kt | 41 ++++ .../ksmt/runner/serializer/AstSerializer.kt | 202 ++++++++++++++++++ .../io/ksmt/runner/serializer/ExprKind.kt | 40 ++++ .../ksmt/runner/serializer/ExprKindMapper.kt | 162 ++++++++++++++ 4 files changed, 445 insertions(+) diff --git a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt index 239990e2d..5de3fe7bc 100644 --- a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt +++ b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt @@ -87,6 +87,7 @@ class AstDeserializer( mkFreshFuncDecl(name, sort, argSorts as List) } + @Suppress("ComplexMethod") private fun AbstractBuffer.deserializeSort(sortKind: SortKind): KSort = with(serializationCtx.ctx) { when (sortKind) { SortKind.Bool -> boolSort @@ -278,6 +279,46 @@ class AstDeserializer( ExprKind.ToIntRealExpr -> deserialize(::mkRealToIntNoSimplify) ExprKind.IsIntRealExpr -> deserialize(::mkRealIsIntNoSimplify) ExprKind.RealNumExpr -> mkRealNum(readExpr() as KIntNumExpr, readExpr() as KIntNumExpr) + ExprKind.StringConcatExpr -> deserialize(::mkStringConcatNoSimplify) + ExprKind.StringLenExpr -> deserialize(::mkStringLenNoSimplify) + ExprKind.StringToRegexExpr -> deserialize(::mkStringToRegexNoSimplify) + ExprKind.StringInRegexExpr -> deserialize(::mkStringInRegexNoSimplify) + ExprKind.StringSuffixOfExpr -> deserialize(::mkStringSuffixOfNoSimplify) + ExprKind.StringPrefixOfExpr -> deserialize(::mkStringPrefixOfNoSimplify) + ExprKind.StringLtExpr -> deserialize(::mkStringLtNoSimplify) + ExprKind.StringLeExpr -> deserialize(::mkStringLeNoSimplify) + ExprKind.StringGtExpr -> deserialize(::mkStringGtNoSimplify) + ExprKind.StringGeExpr -> deserialize(::mkStringGeNoSimplify) + ExprKind.StringContainsExpr -> deserialize(::mkStringContainsNoSimplify) + ExprKind.StringSingletonSubExpr -> deserialize(::mkStringSingletonSubNoSimplify) + ExprKind.StringSubExpr -> deserialize(::mkStringSubNoSimplify) + ExprKind.StringIndexOfExpr -> deserialize(::mkStringIndexOfNoSimplify) + ExprKind.StringIndexOfRegexExpr -> deserialize(::mkStringIndexOfRegexNoSimplify) + ExprKind.StringReplaceExpr -> deserialize(::mkStringReplaceNoSimplify) + ExprKind.StringReplaceAllExpr -> deserialize(::mkStringReplaceAllNoSimplify) + ExprKind.StringReplaceWithRegexExpr -> deserialize(::mkStringReplaceWithRegexNoSimplify) + ExprKind.StringReplaceAllWithRegexExpr -> deserialize(::mkStringReplaceAllWithRegexNoSimplify) + ExprKind.StringToLowerExpr -> deserialize(::mkStringToLowerNoSimplify) + ExprKind.StringToUpperExpr -> deserialize(::mkStringToUpperNoSimplify) + ExprKind.StringReverseExpr -> deserialize(::mkStringReverseNoSimplify) + ExprKind.StringIsDigitExpr -> deserialize(::mkStringIsDigitNoSimplify) + ExprKind.StringToCodeExpr -> deserialize(::mkStringToCodeNoSimplify) + ExprKind.StringFromCodeExpr -> deserialize(::mkStringFromCodeNoSimplify) + ExprKind.StringToIntExpr -> deserialize(::mkStringToIntNoSimplify) + ExprKind.StringFromIntExpr -> deserialize(::mkStringFromIntNoSimplify) + ExprKind.StringLiteralExpr -> mkStringLiteral(readString()) + ExprKind.RegexConcatExpr -> deserialize(::mkRegexConcatNoSimplify) + ExprKind.RegexUnionExpr -> deserialize(::mkRegexUnionNoSimplify) + ExprKind.RegexIntersectionExpr -> deserialize(::mkRegexIntersectionNoSimplify) + ExprKind.RegexStarExpr -> deserialize(::mkRegexStarNoSimplify) + ExprKind.RegexCrossExpr -> deserialize(::mkRegexCrossNoSimplify) + ExprKind.RegexDifferenceExpr -> deserialize(::mkRegexDifferenceNoSimplify) + ExprKind.RegexComplementExpr -> deserialize(::mkRegexComplementNoSimplify) + ExprKind.RegexOptionExpr -> deserialize(::mkRegexOptionNoSimplify) + ExprKind.RegexRangeExpr -> deserialize(::mkRegexRangeNoSimplify) + ExprKind.RegexEpsilonExpr -> mkRegexEpsilon() + ExprKind.RegexAllExpr -> mkRegexAll() + ExprKind.RegexAllCharExpr -> mkRegexAllChar() ExprKind.ExistentialQuantifier -> { val bounds = readAstArray() mkExistentialQuantifier(readExpr(), bounds as List>) diff --git a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstSerializer.kt b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstSerializer.kt index f699b8a75..d5afe93e4 100644 --- a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstSerializer.kt +++ b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstSerializer.kt @@ -147,6 +147,46 @@ import io.ksmt.expr.KUnaryMinusArithExpr import io.ksmt.expr.KUninterpretedSortValue import io.ksmt.expr.KUniversalQuantifier import io.ksmt.expr.KXorExpr +import io.ksmt.expr.KStringConcatExpr +import io.ksmt.expr.KStringLenExpr +import io.ksmt.expr.KStringToRegexExpr +import io.ksmt.expr.KStringInRegexExpr +import io.ksmt.expr.KStringSuffixOfExpr +import io.ksmt.expr.KStringPrefixOfExpr +import io.ksmt.expr.KStringLtExpr +import io.ksmt.expr.KStringLeExpr +import io.ksmt.expr.KStringGtExpr +import io.ksmt.expr.KStringGeExpr +import io.ksmt.expr.KStringContainsExpr +import io.ksmt.expr.KStringSingletonSubExpr +import io.ksmt.expr.KStringSubExpr +import io.ksmt.expr.KStringIndexOfExpr +import io.ksmt.expr.KStringIndexOfRegexExpr +import io.ksmt.expr.KStringReplaceExpr +import io.ksmt.expr.KStringReplaceAllExpr +import io.ksmt.expr.KStringReplaceWithRegexExpr +import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringToLowerExpr +import io.ksmt.expr.KStringToUpperExpr +import io.ksmt.expr.KStringReverseExpr +import io.ksmt.expr.KStringIsDigitExpr +import io.ksmt.expr.KStringToCodeExpr +import io.ksmt.expr.KStringFromCodeExpr +import io.ksmt.expr.KStringToIntExpr +import io.ksmt.expr.KStringFromIntExpr +import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.KRegexConcatExpr +import io.ksmt.expr.KRegexUnionExpr +import io.ksmt.expr.KRegexIntersectionExpr +import io.ksmt.expr.KRegexStarExpr +import io.ksmt.expr.KRegexCrossExpr +import io.ksmt.expr.KRegexDifferenceExpr +import io.ksmt.expr.KRegexComplementExpr +import io.ksmt.expr.KRegexOptionExpr +import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexEpsilon +import io.ksmt.expr.KRegexAll +import io.ksmt.expr.KRegexAllChar import io.ksmt.solver.util.KExprIntInternalizerBase import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort @@ -1108,6 +1148,168 @@ class AstSerializer( serialize(numerator, denominator) } + override fun transform(expr: KStringConcatExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KStringLenExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KStringToRegexExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KStringInRegexExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KStringSuffixOfExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KStringPrefixOfExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KStringLtExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KStringLeExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KStringGtExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KStringGeExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KStringContainsExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KStringSingletonSubExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KStringSubExpr) = with(expr) { + serialize(arg0, arg1, arg2) + } + + override fun transform(expr: KStringIndexOfExpr) = with(expr) { + serialize(arg0, arg1, arg2) + } + + override fun transform(expr: KStringIndexOfRegexExpr) = with(expr) { + serialize(arg0, arg1, arg2) + } + + override fun transform(expr: KStringReplaceExpr) = with(expr) { + serialize(arg0, arg1, arg2) + } + + override fun transform(expr: KStringReplaceAllExpr) = with(expr) { + serialize(arg0, arg1, arg2) + } + + override fun transform(expr: KStringReplaceWithRegexExpr) = with(expr) { + serialize(arg0, arg1, arg2) + } + + override fun transform(expr: KStringReplaceAllWithRegexExpr) = with(expr) { + serialize(arg0, arg1, arg2) + } + + override fun transform(expr: KStringToLowerExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KStringToUpperExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KStringReverseExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KStringIsDigitExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KStringToCodeExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KStringFromCodeExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KStringToIntExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KStringFromIntExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KStringLiteralExpr) = with(expr) { + transform { + writeExpr { writeString(value) } + } + } + + override fun transform(expr: KRegexConcatExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KRegexUnionExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KRegexIntersectionExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KRegexStarExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KRegexCrossExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KRegexDifferenceExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KRegexComplementExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KRegexOptionExpr) = with(expr) { + serialize(arg) + } + + override fun transform(expr: KRegexRangeExpr) = with(expr) { + serialize(arg0, arg1) + } + + override fun transform(expr: KRegexEpsilon) = with(expr) { + serialize() + } + + override fun transform(expr: KRegexAll) = with(expr) { + serialize() + } + + override fun transform(expr: KRegexAllChar) = with(expr) { + serialize() + } + override fun transform(expr: KExistentialQuantifier) = with(expr) { transform(body) { body: Int -> val bounds = bounds.map { it.serializeDecl() } diff --git a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKind.kt b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKind.kt index a284a4f5c..eda73eecb 100644 --- a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKind.kt +++ b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKind.kt @@ -138,6 +138,46 @@ enum class ExprKind { ToIntRealExpr, IsIntRealExpr, RealNumExpr, + StringConcatExpr, + StringLenExpr, + StringToRegexExpr, + StringInRegexExpr, + StringSuffixOfExpr, + StringPrefixOfExpr, + StringLtExpr, + StringLeExpr, + StringGtExpr, + StringGeExpr, + StringContainsExpr, + StringSingletonSubExpr, + StringSubExpr, + StringIndexOfExpr, + StringIndexOfRegexExpr, + StringReplaceExpr, + StringReplaceAllExpr, + StringReplaceWithRegexExpr, + StringReplaceAllWithRegexExpr, + StringToLowerExpr, + StringToUpperExpr, + StringReverseExpr, + StringIsDigitExpr, + StringToCodeExpr, + StringFromCodeExpr, + StringToIntExpr, + StringFromIntExpr, + StringLiteralExpr, + RegexConcatExpr, + RegexUnionExpr, + RegexIntersectionExpr, + RegexStarExpr, + RegexCrossExpr, + RegexDifferenceExpr, + RegexComplementExpr, + RegexOptionExpr, + RegexRangeExpr, + RegexEpsilonExpr, + RegexAllExpr, + RegexAllCharExpr, ExistentialQuantifier, UniversalQuantifier, UninterpretedSortValue, diff --git a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKindMapper.kt b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKindMapper.kt index 555ad49af..60728b102 100644 --- a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKindMapper.kt +++ b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKindMapper.kt @@ -141,6 +141,46 @@ import io.ksmt.expr.KUnaryMinusArithExpr import io.ksmt.expr.KUninterpretedSortValue import io.ksmt.expr.KUniversalQuantifier import io.ksmt.expr.KXorExpr +import io.ksmt.expr.KStringConcatExpr +import io.ksmt.expr.KStringLenExpr +import io.ksmt.expr.KStringToRegexExpr +import io.ksmt.expr.KStringInRegexExpr +import io.ksmt.expr.KStringSuffixOfExpr +import io.ksmt.expr.KStringPrefixOfExpr +import io.ksmt.expr.KStringLtExpr +import io.ksmt.expr.KStringLeExpr +import io.ksmt.expr.KStringGtExpr +import io.ksmt.expr.KStringGeExpr +import io.ksmt.expr.KStringContainsExpr +import io.ksmt.expr.KStringSingletonSubExpr +import io.ksmt.expr.KStringSubExpr +import io.ksmt.expr.KStringIndexOfExpr +import io.ksmt.expr.KStringIndexOfRegexExpr +import io.ksmt.expr.KStringReplaceExpr +import io.ksmt.expr.KStringReplaceAllExpr +import io.ksmt.expr.KStringReplaceWithRegexExpr +import io.ksmt.expr.KStringReplaceAllWithRegexExpr +import io.ksmt.expr.KStringToLowerExpr +import io.ksmt.expr.KStringToUpperExpr +import io.ksmt.expr.KStringReverseExpr +import io.ksmt.expr.KStringIsDigitExpr +import io.ksmt.expr.KStringToCodeExpr +import io.ksmt.expr.KStringFromCodeExpr +import io.ksmt.expr.KStringToIntExpr +import io.ksmt.expr.KStringFromIntExpr +import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.KRegexConcatExpr +import io.ksmt.expr.KRegexUnionExpr +import io.ksmt.expr.KRegexIntersectionExpr +import io.ksmt.expr.KRegexStarExpr +import io.ksmt.expr.KRegexCrossExpr +import io.ksmt.expr.KRegexDifferenceExpr +import io.ksmt.expr.KRegexComplementExpr +import io.ksmt.expr.KRegexOptionExpr +import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexEpsilon +import io.ksmt.expr.KRegexAll +import io.ksmt.expr.KRegexAllChar import io.ksmt.expr.transformer.KTransformerBase import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort @@ -163,6 +203,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KUninterpretedSort @@ -627,6 +669,126 @@ class ExprKindMapper: KTransformerBase { override fun transform(expr: KRealNumExpr): KExpr = expr.kind(ExprKind.RealNumExpr) + override fun transform(expr: KStringConcatExpr): KExpr = expr.kind(ExprKind.StringConcatExpr) + + + override fun transform(expr: KStringLenExpr): KExpr = expr.kind(ExprKind.StringLenExpr) + + + override fun transform(expr: KStringToRegexExpr): KExpr = expr.kind(ExprKind.StringToRegexExpr) + + + override fun transform(expr: KStringInRegexExpr): KExpr = expr.kind(ExprKind.StringInRegexExpr) + + + override fun transform(expr: KStringSuffixOfExpr): KExpr = expr.kind(ExprKind.StringSuffixOfExpr) + + + override fun transform(expr: KStringPrefixOfExpr): KExpr = expr.kind(ExprKind.StringPrefixOfExpr) + + + override fun transform(expr: KStringLtExpr): KExpr = expr.kind(ExprKind.StringLtExpr) + + + override fun transform(expr: KStringLeExpr): KExpr = expr.kind(ExprKind.StringLeExpr) + + + override fun transform(expr: KStringGtExpr): KExpr = expr.kind(ExprKind.StringGtExpr) + + + override fun transform(expr: KStringGeExpr): KExpr = expr.kind(ExprKind.StringGeExpr) + + + override fun transform(expr: KStringContainsExpr): KExpr = expr.kind(ExprKind.StringContainsExpr) + + + override fun transform(expr: KStringSingletonSubExpr): KExpr = expr.kind(ExprKind.StringSingletonSubExpr) + + + override fun transform(expr: KStringSubExpr): KExpr = expr.kind(ExprKind.StringSubExpr) + + + override fun transform(expr: KStringIndexOfExpr): KExpr = expr.kind(ExprKind.StringIndexOfExpr) + + + override fun transform(expr: KStringIndexOfRegexExpr): KExpr = expr.kind(ExprKind.StringIndexOfRegexExpr) + + + override fun transform(expr: KStringReplaceExpr): KExpr = expr.kind(ExprKind.StringReplaceExpr) + + + override fun transform(expr: KStringReplaceAllExpr): KExpr = expr.kind(ExprKind.StringReplaceAllExpr) + + + override fun transform(expr: KStringReplaceWithRegexExpr): KExpr = expr.kind(ExprKind.StringReplaceWithRegexExpr) + + + override fun transform(expr: KStringReplaceAllWithRegexExpr): KExpr = expr.kind(ExprKind.StringReplaceAllWithRegexExpr) + + + override fun transform(expr: KStringToLowerExpr): KExpr = expr.kind(ExprKind.StringToLowerExpr) + + + override fun transform(expr: KStringToUpperExpr): KExpr = expr.kind(ExprKind.StringToUpperExpr) + + + override fun transform(expr: KStringReverseExpr): KExpr = expr.kind(ExprKind.StringReverseExpr) + + + override fun transform(expr: KStringIsDigitExpr): KExpr = expr.kind(ExprKind.StringIsDigitExpr) + + + override fun transform(expr: KStringToCodeExpr): KExpr = expr.kind(ExprKind.StringToCodeExpr) + + + override fun transform(expr: KStringFromCodeExpr): KExpr = expr.kind(ExprKind.StringFromCodeExpr) + + + override fun transform(expr: KStringToIntExpr): KExpr = expr.kind(ExprKind.StringToIntExpr) + + + override fun transform(expr: KStringFromIntExpr): KExpr = expr.kind(ExprKind.StringFromIntExpr) + + + override fun transform(expr: KStringLiteralExpr): KExpr = expr.kind(ExprKind.StringLiteralExpr) + + + override fun transform(expr: KRegexConcatExpr): KExpr = expr.kind(ExprKind.RegexConcatExpr) + + + override fun transform(expr: KRegexUnionExpr): KExpr = expr.kind(ExprKind.RegexUnionExpr) + + + override fun transform(expr: KRegexIntersectionExpr): KExpr = expr.kind(ExprKind.RegexIntersectionExpr) + + + override fun transform(expr: KRegexStarExpr): KExpr = expr.kind(ExprKind.RegexStarExpr) + + + override fun transform(expr: KRegexCrossExpr): KExpr = expr.kind(ExprKind.RegexCrossExpr) + + + override fun transform(expr: KRegexComplementExpr): KExpr = expr.kind(ExprKind.RegexComplementExpr) + + + override fun transform(expr: KRegexDifferenceExpr): KExpr = expr.kind(ExprKind.RegexDifferenceExpr) + + + override fun transform(expr: KRegexOptionExpr): KExpr = expr.kind(ExprKind.RegexOptionExpr) + + + override fun transform(expr: KRegexRangeExpr): KExpr = expr.kind(ExprKind.RegexRangeExpr) + + + override fun transform(expr: KRegexEpsilon): KExpr = expr.kind(ExprKind.RegexEpsilonExpr) + + + override fun transform(expr: KRegexAll): KExpr = expr.kind(ExprKind.RegexAllExpr) + + + override fun transform(expr: KRegexAllChar): KExpr = expr.kind(ExprKind.RegexAllCharExpr) + + override fun transform(expr: KExistentialQuantifier): KExpr = expr.kind(ExprKind.ExistentialQuantifier) From 17d40f55dcbacdd762b3ab3d5e849a9af915ec13 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 18 Dec 2024 01:51:56 +0300 Subject: [PATCH 58/84] Partially implement z3 string internalizer/converter --- .../io/ksmt/solver/z3/KZ3ExprConverter.kt | 14 +++ .../io/ksmt/solver/z3/KZ3ExprInternalizer.kt | 100 +++++++++++------- 2 files changed, 73 insertions(+), 41 deletions(-) diff --git a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt index 1bd9097e7..874f64085 100644 --- a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt +++ b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt @@ -22,6 +22,7 @@ import io.ksmt.expr.KFpRoundingModeExpr import io.ksmt.expr.KIntNumExpr import io.ksmt.expr.KInterpretedValue import io.ksmt.expr.KRealNumExpr +import io.ksmt.expr.KStringLiteralExpr import io.ksmt.expr.rewrite.KExprUninterpretedDeclCollector import io.ksmt.solver.KSolverUnsupportedFeatureException import io.ksmt.solver.util.ExprConversionResult @@ -116,6 +117,9 @@ open class KZ3ExprConverter( Z3_sort_kind.Z3_BOOL_SORT -> boolSort Z3_sort_kind.Z3_INT_SORT -> intSort Z3_sort_kind.Z3_REAL_SORT -> realSort + // Currently, KSMT supports the only type of sequences - strings. + Z3_sort_kind.Z3_SEQ_SORT -> stringSort + Z3_sort_kind.Z3_RE_SORT -> regexSort Z3_sort_kind.Z3_ARRAY_SORT -> convertNativeArraySort(sort) Z3_sort_kind.Z3_BV_SORT -> mkBvSort(Native.getBvSortSize(nCtx, sort).toUInt()) Z3_sort_kind.Z3_FLOATING_POINT_SORT -> @@ -525,6 +529,8 @@ open class KZ3ExprConverter( Z3_sort_kind.Z3_BV_SORT -> convert { convertBvNumeral(expr, sort) } Z3_sort_kind.Z3_ROUNDING_MODE_SORT -> convert { convertFpRmNumeral(expr) } Z3_sort_kind.Z3_FLOATING_POINT_SORT -> convertFpNumeral(expr, sort) + // Currently, KSMT supports the only type of sequences - strings. + Z3_sort_kind.Z3_SEQ_SORT -> convert { convertStringLiteral(expr) } else -> TODO("numerals with ${Native.sortToString(nCtx, sort)} are not supported") } } @@ -547,6 +553,12 @@ open class KZ3ExprConverter( } } + @Suppress("MemberVisibilityCanBePrivate") + fun convertStringLiteral(expr: Long): KStringLiteralExpr = with(ctx) { + val value = Native.getString(nCtx, expr) + mkStringLiteral(value) + } + @Suppress("MemberVisibilityCanBePrivate") fun convertBvNumeral(expr: Long, sort: Long): KBitVecValue<*> = with(ctx) { val sizeBits = Native.getBvSortSize(nCtx, sort).toUInt() @@ -603,6 +615,8 @@ open class KZ3ExprConverter( mkFpToBvExpr(rm, fp, size, isSigned = false) } + "String" -> convertNumeral(expr) + else -> throw KSolverUnsupportedFeatureException("Z3 internal decl $internalDeclName is not supported") } } diff --git a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt index 04c5d1c70..1a13efde3 100644 --- a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt +++ b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt @@ -189,6 +189,7 @@ import io.ksmt.expr.KRegexRangeExpr import io.ksmt.expr.KRegexEpsilon import io.ksmt.expr.KRegexAll import io.ksmt.expr.KRegexAllChar +import io.ksmt.solver.KSolverUnsupportedFeatureException import io.ksmt.solver.util.KExprLongInternalizerBase import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort @@ -940,7 +941,7 @@ open class KZ3ExprInternalizer( override fun transform(expr: KStringSubExpr) = with(expr) { transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> - TODO("Not yet implemented") + Native.mkSeqExtract(nCtx, arg0, arg1, arg2) } } @@ -950,57 +951,50 @@ open class KZ3ExprInternalizer( } } - override fun transform(expr: KStringIndexOfExpr) = with(expr) { - transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> - TODO("Not yet implemented") - } - } + override fun transform(expr: KStringIndexOfRegexExpr) = + throw KSolverUnsupportedFeatureException( + "${expr::class.simpleName} is not supported in z3" + ) override fun transform(expr: KStringReplaceExpr) = with(expr) { transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> - TODO("Not yet implemented") + Native.mkSeqReplace(nCtx, arg0, arg1, arg2) } } - override fun transform(expr: KStringReplaceAllExpr) = with(expr) { - transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> - TODO("Not yet implemented") - } - } + override fun transform(expr: KStringReplaceAllExpr) = + throw KSolverUnsupportedFeatureException( + "${expr::class.simpleName} is not supported in z3" + ) - override fun transform(expr: KStringReplaceWithRegexExpr) = with(expr) { - transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> - TODO("Not yet implemented") - } - } + override fun transform(expr: KStringReplaceWithRegexExpr) = + throw KSolverUnsupportedFeatureException( + "${expr::class.simpleName} is not supported in z3" + ) - override fun transform(expr: KStringReplaceAllWithRegexExpr) = with(expr) { - transform(arg0, arg1, arg2) { arg0, arg1, arg2 -> - TODO("Not yet implemented") - } - } + override fun transform(expr: KStringReplaceAllWithRegexExpr) = + throw KSolverUnsupportedFeatureException( + "${expr::class.simpleName} is not supported in z3" + ) - override fun transform(expr: KStringToLowerExpr) = with(expr) { - transform(arg) { arg -> - TODO("Not yet implemented") - } - } + override fun transform(expr: KStringToLowerExpr) = + throw KSolverUnsupportedFeatureException( + "${expr::class.simpleName} is not supported in z3" + ) - override fun transform(expr: KStringToUpperExpr) = with(expr) { - transform(arg) { arg -> - TODO("Not yet implemented") - } - } + override fun transform(expr: KStringToUpperExpr) = + throw KSolverUnsupportedFeatureException( + "${expr::class.simpleName} is not supported in z3" + ) - override fun transform(expr: KStringReverseExpr) = with(expr) { - transform(arg) { arg -> - TODO("Not yet implemented") - } - } + override fun transform(expr: KStringReverseExpr) = + throw KSolverUnsupportedFeatureException( + "${expr::class.simpleName} is not supported in z3" + ) override fun transform(expr: KStringIsDigitExpr) = with(expr) { transform(arg) { arg -> - TODO("Not yet implemented") + Native.mkCharIsDigit(nCtx, arg) } } @@ -1088,15 +1082,39 @@ open class KZ3ExprInternalizer( } override fun transform(expr: KRegexEpsilon) = with(expr) { - TODO("Not yet implemented") + transform { + Native.mkReEmpty( + nCtx, + Native.mkReSort( + nCtx, + Native.mkStringSort(nCtx) + ) + ) + } } override fun transform(expr: KRegexAll) = with(expr) { - TODO("Not yet implemented") + transform { + Native.mkReFull( + nCtx, + Native.mkReSort( + nCtx, + Native.mkStringSort(nCtx) + ) + ) + } } override fun transform(expr: KRegexAllChar) = with(expr) { - TODO("Not yet implemented") + transform { + Native.mkReAllchar( + nCtx, + Native.mkReSort( + nCtx, + Native.mkStringSort(nCtx) + ) + ) + } } private fun transformQuantifier(expr: KQuantifier, isUniversal: Boolean) = with(expr) { From 8f0921ec2ff8579b4cffd525fb017d1c94291e51 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 18 Dec 2024 22:51:34 +0300 Subject: [PATCH 59/84] Fully implement z3 converter --- .../io/ksmt/solver/z3/KZ3ExprConverter.kt | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt index 874f64085..0e1644679 100644 --- a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt +++ b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt @@ -416,6 +416,47 @@ open class KZ3ExprConverter( throw KSolverUnsupportedFeatureException("Fp $declKind is not supported") } + // Currently, KSMT supports the only type of sequences - strings + Z3_decl_kind.Z3_OP_SEQ_CONCAT -> expr.convert(::mkStringConcat) + Z3_decl_kind.Z3_OP_SEQ_LENGTH -> expr.convert(::mkStringLen) + Z3_decl_kind.Z3_OP_SEQ_TO_RE -> expr.convert(::mkStringToRegex) + Z3_decl_kind.Z3_OP_SEQ_IN_RE -> expr.convert(::mkStringInRegex) + Z3_decl_kind.Z3_OP_SEQ_SUFFIX -> expr.convert(::mkStringSuffixOf) + Z3_decl_kind.Z3_OP_SEQ_PREFIX -> expr.convert(::mkStringPrefixOf) + Z3_decl_kind.Z3_OP_STRING_LT -> expr.convert(::mkStringLt) + Z3_decl_kind.Z3_OP_STRING_LE -> expr.convert(::mkStringLe) + Z3_decl_kind.Z3_OP_SEQ_CONTAINS -> expr.convert(::mkStringContains) + Z3_decl_kind.Z3_OP_SEQ_AT -> expr.convert(::mkStringSingletonSub) + Z3_decl_kind.Z3_OP_SEQ_EXTRACT -> expr.convert(::mkStringSub) + Z3_decl_kind.Z3_OP_SEQ_INDEX -> { + var args = getAppArgs(nCtx, expr) + if (args.size == 2) { + args += Native.mkInt(nCtx, 0, Native.mkIntSort(nCtx)) + } + expr.convert(args, ::mkStringIndexOf) + } + Z3_decl_kind.Z3_OP_SEQ_REPLACE -> expr.convert(::mkStringReplace) + Z3_decl_kind.Z3_OP_SEQ_REPLACE_ALL -> expr.convert(::mkStringReplaceAll) + Z3_decl_kind.Z3_OP_SEQ_REPLACE_RE -> expr.convert(::mkStringReplaceWithRegex) + Z3_decl_kind.Z3_OP_SEQ_REPLACE_RE_ALL -> expr.convert(::mkStringReplaceAllWithRegex) + Z3_decl_kind.Z3_OP_CHAR_IS_DIGIT -> expr.convert(::mkStringIsDigit) + Z3_decl_kind.Z3_OP_STR_TO_CODE -> expr.convert(::mkStringToCode) + Z3_decl_kind.Z3_OP_STR_FROM_CODE -> expr.convert(::mkStringFromCode) + Z3_decl_kind.Z3_OP_STR_TO_INT -> expr.convert(::mkStringToInt) + Z3_decl_kind.Z3_OP_INT_TO_STR -> expr.convert(::mkStringFromInt) + Z3_decl_kind.Z3_OP_RE_CONCAT -> expr.convert(::mkRegexConcat) + Z3_decl_kind.Z3_OP_RE_UNION -> expr.convert(::mkRegexUnion) + Z3_decl_kind.Z3_OP_RE_INTERSECT -> expr.convert(::mkRegexIntersection) + Z3_decl_kind.Z3_OP_RE_STAR -> expr.convert(::mkRegexStar) + Z3_decl_kind.Z3_OP_RE_PLUS -> expr.convert(::mkRegexCross) + Z3_decl_kind.Z3_OP_RE_DIFF -> expr.convert(::mkRegexDifference) + Z3_decl_kind.Z3_OP_RE_COMPLEMENT -> expr.convert(::mkRegexComplement) + Z3_decl_kind.Z3_OP_RE_OPTION -> expr.convert(::mkRegexOption) + Z3_decl_kind.Z3_OP_RE_RANGE -> expr.convert(::mkRegexRange) + Z3_decl_kind.Z3_OP_RE_EMPTY_SET -> ExprConversionResult(mkRegexEpsilon()) + Z3_decl_kind.Z3_OP_RE_FULL_SET -> ExprConversionResult(mkRegexAll()) + Z3_decl_kind.Z3_OP_RE_FULL_CHAR_SET -> ExprConversionResult(mkRegexAllChar()) + Z3_decl_kind.Z3_OP_INTERNAL -> tryConvertInternalAppExpr(expr, decl) Z3_decl_kind.Z3_OP_RECURSIVE -> { @@ -616,6 +657,7 @@ open class KZ3ExprConverter( } "String" -> convertNumeral(expr) + "str.is_digit" -> expr.convert(::mkStringIsDigit) else -> throw KSolverUnsupportedFeatureException("Z3 internal decl $internalDeclName is not supported") } From d16f8d9f6050a142ef1bf7f1c5f01bf88a33407f Mon Sep 17 00:00:00 2001 From: raf-nr Date: Thu, 19 Dec 2024 00:47:43 +0300 Subject: [PATCH 60/84] Implement regex power and loop operations --- .../bitwuzla/KBitwuzlaExprInternalizer.kt | 10 ++++ ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 46 +++++++++++++++++++ .../main/kotlin/io/ksmt/decl/KDeclVisitor.kt | 2 + .../src/main/kotlin/io/ksmt/decl/Regex.kt | 33 +++++++++++++ .../src/main/kotlin/io/ksmt/expr/Regex.kt | 45 ++++++++++++++++++ .../transformer/KNonRecursiveTransformer.kt | 12 +++++ .../expr/transformer/KNonRecursiveVisitor.kt | 8 ++++ .../io/ksmt/expr/transformer/KTransformer.kt | 4 ++ .../ksmt/expr/transformer/KTransformerBase.kt | 4 ++ .../io/ksmt/expr/transformer/KVisitor.kt | 6 +++ .../io/ksmt/solver/cvc5/KCvc5ExprConverter.kt | 37 ++++++++++++--- .../ksmt/solver/cvc5/KCvc5ExprInternalizer.kt | 16 +++++++ .../ksmt/runner/serializer/AstDeserializer.kt | 2 + .../ksmt/runner/serializer/AstSerializer.kt | 21 +++++++++ .../io/ksmt/runner/serializer/ExprKind.kt | 2 + .../ksmt/runner/serializer/ExprKindMapper.kt | 8 ++++ .../solver/yices/KYicesExprInternalizer.kt | 10 ++++ .../io/ksmt/solver/z3/KZ3ExprConverter.kt | 11 +++++ .../io/ksmt/solver/z3/KZ3ExprInternalizer.kt | 14 ++++++ 19 files changed, 285 insertions(+), 6 deletions(-) diff --git a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt index f21f2013d..2e8465893 100644 --- a/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt +++ b/ksmt-bitwuzla/ksmt-bitwuzla-core/src/main/kotlin/io/ksmt/solver/bitwuzla/KBitwuzlaExprInternalizer.kt @@ -188,6 +188,8 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexPowerExpr +import io.ksmt.expr.KRegexLoopExpr import io.ksmt.expr.KRegexEpsilon import io.ksmt.expr.KRegexAll import io.ksmt.expr.KRegexAllChar @@ -1595,6 +1597,14 @@ open class KBitwuzlaExprInternalizer(val bitwuzlaCtx: KBitwuzlaContext) : KExprL throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } + override fun transform(expr: KRegexPowerExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + + override fun transform(expr: KRegexLoopExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") + } + override fun transform(expr: KRegexEpsilon): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Bitwuzla") } diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index b80dc794e..c8d54a0cb 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -169,6 +169,8 @@ import io.ksmt.decl.KRegexDifferenceDecl import io.ksmt.decl.KRegexComplementDecl import io.ksmt.decl.KRegexOptionDecl import io.ksmt.decl.KRegexRangeDecl +import io.ksmt.decl.KRegexPowerDecl +import io.ksmt.decl.KRegexLoopDecl import io.ksmt.decl.KIteDecl import io.ksmt.decl.KNotDecl import io.ksmt.decl.KOrDecl @@ -352,6 +354,8 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexPowerExpr +import io.ksmt.expr.KRegexLoopExpr import io.ksmt.expr.KIteExpr import io.ksmt.expr.KLeArithExpr import io.ksmt.expr.KLtArithExpr @@ -2677,6 +2681,44 @@ open class KContext( KRegexRangeExpr(this, arg0, arg1) } + private val regexPowerExprCache = mkAstInterner() + + /** + * Constructs a regex expression that represents the concatenation + * of the given `arg` regex repeated `power` times. + * */ + open fun mkRegexPower(power: Int, arg: KExpr): KExpr = + mkSimplified(power, arg, KContext::mkRegexPowerNoSimplify, ::mkRegexPowerNoSimplify) // Add simplified version + + /** + * Constructs a regex expression that represents the concatenation + * of the given `arg` regex repeated `power` times. + * */ + open fun mkRegexPowerNoSimplify(power: Int, arg: KExpr): KRegexPowerExpr = + regexPowerExprCache.createIfContextActive { + ensureContextMatch(arg) + KRegexPowerExpr(this, power, arg) + } + + private val regexLoopExprCache = mkAstInterner() + + /** + * Constructs a regex expression that represents the union of regexes + * formed by repeating the given `arg` regex from `from` to `to` times inclusively. + * */ + open fun mkRegexLoop(from: Int, to: Int, arg: KExpr): KExpr = + mkSimplified(from, to, arg, KContext::mkRegexLoopNoSimplify, ::mkRegexLoopNoSimplify) // Add simplified version + + /** + * Constructs a regex expression that represents the union of regexes + * formed by repeating the given `arg` regex from `from` to `to` times inclusively. + * */ + open fun mkRegexLoopNoSimplify(from: Int, to: Int, arg: KExpr): KRegexLoopExpr = + regexLoopExprCache.createIfContextActive { + ensureContextMatch(arg) + KRegexLoopExpr(this, from, to, arg) + } + val regexEpsilonExpr: KRegexEpsilon = KRegexEpsilon(this) /** @@ -5378,6 +5420,10 @@ open class KContext( fun mkRegexRangeDecl(): KRegexRangeDecl = KRegexRangeDecl(this) + fun mkRegexPowerDecl(power: Int): KRegexPowerDecl = KRegexPowerDecl(this, power) + + fun mkRegexLoopDecl(from: Int, to: Int): KRegexLoopDecl = KRegexLoopDecl(this, from, to) + fun mkRegexEpsilonDecl(): KRegexEpsilonDecl = KRegexEpsilonDecl(this) fun mkRegexAllDecl(): KRegexAllDecl = KRegexAllDecl(this) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt index 3f5c45b64..a439866dd 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/KDeclVisitor.kt @@ -172,6 +172,8 @@ interface KDeclVisitor { fun visit(decl: KRegexComplementDecl): T = visit(decl as KFuncDecl) fun visit(decl: KRegexOptionDecl): T = visit(decl as KFuncDecl) fun visit(decl: KRegexRangeDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRegexPowerDecl): T = visit(decl as KFuncDecl) + fun visit(decl: KRegexLoopDecl): T = visit(decl as KFuncDecl) fun visit(decl: KRegexEpsilonDecl): T = visit(decl as KConstDecl) fun visit(decl: KRegexAllDecl): T = visit(decl as KConstDecl) fun visit(decl: KRegexAllCharDecl): T = visit(decl as KConstDecl) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt index 9411f08d9..21def6469 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/decl/Regex.kt @@ -151,6 +151,39 @@ class KRegexRangeDecl internal constructor( ): KApp = mkRegexRangeNoSimplify(arg0, arg1) } +class KRegexPowerDecl internal constructor( + ctx: KContext, + val power: Int +) : KFuncDecl1( + ctx, + "(regex_power $power)", + ctx.mkRegexSort(), + ctx.mkRegexSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg: KExpr + ): KApp = mkRegexPowerNoSimplify(power, arg) +} + +class KRegexLoopDecl internal constructor( + ctx: KContext, + val from: Int, + val to: Int +) : KFuncDecl1( + ctx, + "(regex_loop $from $to)", + ctx.mkRegexSort(), + ctx.mkRegexSort() +) { + override fun accept(visitor: KDeclVisitor): R = visitor.visit(this) + + override fun KContext.apply( + arg: KExpr + ): KApp = mkRegexLoopNoSimplify(from, to, arg) +} + class KRegexEpsilonDecl internal constructor( ctx: KContext ) : KConstDecl( diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt index 8a3bc1c6a..60111e774 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/Regex.kt @@ -12,6 +12,8 @@ import io.ksmt.decl.KRegexDifferenceDecl import io.ksmt.decl.KRegexComplementDecl import io.ksmt.decl.KRegexOptionDecl import io.ksmt.decl.KRegexRangeDecl +import io.ksmt.decl.KRegexPowerDecl +import io.ksmt.decl.KRegexLoopDecl import io.ksmt.decl.KRegexEpsilonDecl import io.ksmt.decl.KRegexAllDecl import io.ksmt.decl.KRegexAllCharDecl @@ -204,6 +206,49 @@ class KRegexRangeExpr internal constructor( override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 }) } +class KRegexPowerExpr internal constructor( + ctx: KContext, + val power: Int, + val arg: KExpr, +) : KApp(ctx) { + override val sort: KRegexSort + get() = ctx.regexSort + + override val decl: KRegexPowerDecl + get() = ctx.mkRegexPowerDecl(power) + + override val args: List> + get() = listOf(arg) + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) + + override fun internHashCode(): Int = hash(arg, power) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg }, { power }) +} + +class KRegexLoopExpr internal constructor( + ctx: KContext, + val from: Int, + val to: Int, + val arg: KExpr, +) : KApp(ctx) { + override val sort: KRegexSort + get() = ctx.regexSort + + override val decl: KRegexLoopDecl + get() = ctx.mkRegexLoopDecl(from, to) + + override val args: List> + get() = listOf(arg) + + override fun accept(transformer: KTransformerBase): KExpr = + transformer.transform(this) + + override fun internHashCode(): Int = hash(arg, from, to) + override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg }, { from }, { to }) +} + class KRegexEpsilon(ctx: KContext) : KInterpretedValue(ctx) { override val sort: KRegexSort get() = ctx.regexSort diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt index 2c09c771f..0b1a229da 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt @@ -160,6 +160,8 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexPowerExpr +import io.ksmt.expr.KRegexLoopExpr import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -881,6 +883,16 @@ abstract class KNonRecursiveTransformer(override val ctx: KContext) : KNonRecurs expr, expr.arg0, expr.arg1, ::transformApp, KContext::mkRegexRange ) + override fun transform(expr: KRegexPowerExpr): KExpr = + transformExprAfterTransformedDefault(expr, expr.arg, ::transformApp) { + arg -> mkRegexPower(expr.power, arg) + } + + override fun transform(expr: KRegexLoopExpr): KExpr = + transformExprAfterTransformedDefault(expr, expr.arg, ::transformApp) { + arg -> mkRegexLoop(expr.from, expr.to, arg) + } + // quantified expressions override fun transform(expr: KExistentialQuantifier): KExpr = transformExprAfterTransformedDefault(expr, expr.body, ::transformExpr) { body -> diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt index 8d64be26e..50510ba64 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveVisitor.kt @@ -160,6 +160,8 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexPowerExpr +import io.ksmt.expr.KRegexLoopExpr import io.ksmt.sort.KArithSort import io.ksmt.sort.KArraySortBase import io.ksmt.sort.KBvSort @@ -775,6 +777,12 @@ abstract class KNonRecursiveVisitor( override fun visit(expr: KRegexRangeExpr): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.arg0, expr.arg1, ::visitApp) + override fun visit(expr: KRegexPowerExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + + override fun visit(expr: KRegexLoopExpr): KExprVisitResult = + visitExprAfterVisitedDefault(expr, expr.arg, ::visitApp) + // quantified expressions override fun visit(expr: KExistentialQuantifier): KExprVisitResult = visitExprAfterVisitedDefault(expr, expr.body, ::visitExpr) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt index 22e01501a..7d90e3299 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformer.kt @@ -187,6 +187,8 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexPowerExpr +import io.ksmt.expr.KRegexLoopExpr import io.ksmt.expr.KRegexEpsilon import io.ksmt.expr.KRegexAll import io.ksmt.expr.KRegexAllChar @@ -494,6 +496,8 @@ interface KTransformer : KTransformerBase { override fun transform(expr: KRegexComplementExpr): KExpr = transformApp(expr) override fun transform(expr: KRegexOptionExpr): KExpr = transformApp(expr) override fun transform(expr: KRegexRangeExpr): KExpr = transformApp(expr) + override fun transform(expr: KRegexPowerExpr): KExpr = transformApp(expr) + override fun transform(expr: KRegexLoopExpr): KExpr = transformApp(expr) override fun transform(expr: KRegexEpsilon): KExpr = transformValue(expr) override fun transform(expr: KRegexAll): KExpr = transformValue(expr) override fun transform(expr: KRegexAllChar): KExpr = transformValue(expr) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt index a5a867859..ffaef6a28 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KTransformerBase.kt @@ -178,6 +178,8 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexPowerExpr +import io.ksmt.expr.KRegexLoopExpr import io.ksmt.expr.KRegexEpsilon import io.ksmt.expr.KRegexAll import io.ksmt.expr.KRegexAllChar @@ -422,6 +424,8 @@ interface KTransformerBase { fun transform(expr: KRegexComplementExpr): KExpr fun transform(expr: KRegexOptionExpr): KExpr fun transform(expr: KRegexRangeExpr): KExpr + fun transform(expr: KRegexPowerExpr): KExpr + fun transform(expr: KRegexLoopExpr): KExpr fun transform(expr: KRegexEpsilon): KExpr fun transform(expr: KRegexAll): KExpr fun transform(expr: KRegexAllChar): KExpr diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt index 47af60183..0c7a1e140 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KVisitor.kt @@ -186,6 +186,8 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexPowerExpr +import io.ksmt.expr.KRegexLoopExpr import io.ksmt.expr.KRegexEpsilon import io.ksmt.expr.KRegexAll import io.ksmt.expr.KRegexAllChar @@ -725,6 +727,8 @@ interface KVisitor : KTransformer { fun visit(expr: KRegexComplementExpr): V = visitApp(expr) fun visit(expr: KRegexOptionExpr): V = visitApp(expr) fun visit(expr: KRegexRangeExpr): V = visitApp(expr) + fun visit(expr: KRegexPowerExpr): V = visitApp(expr) + fun visit(expr: KRegexLoopExpr): V = visitApp(expr) fun visit(expr: KRegexEpsilon): V = visitValue(expr) fun visit(expr: KRegexAll): V = visitValue(expr) fun visit(expr: KRegexAllChar): V = visitValue(expr) @@ -738,6 +742,8 @@ interface KVisitor : KTransformer { override fun transform(expr: KRegexComplementExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KRegexOptionExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KRegexRangeExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexPowerExpr): KExpr = visitExpr(expr, ::visit) + override fun transform(expr: KRegexLoopExpr): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KRegexEpsilon): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KRegexAll): KExpr = visitExpr(expr, ::visit) override fun transform(expr: KRegexAllChar): KExpr = visitExpr(expr, ::visit) diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt index 19c6f99e4..b01106262 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt @@ -26,6 +26,7 @@ import io.ksmt.sort.KArraySortBase import io.ksmt.sort.KBoolSort import io.ksmt.sort.KBv1Sort import io.ksmt.sort.KBvSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort @@ -422,12 +423,12 @@ open class KCvc5ExprConverter( Kind.REGEXP_ALL -> convert { mkRegexAll() } Kind.REGEXP_ALLCHAR -> convert { mkRegexAllChar() } Kind.REGEXP_RANGE -> expr.convert(::mkRegexRange) - Kind.REGEXP_REPEAT -> throw KSolverUnsupportedFeatureException( - "No direct mapping of ${Kind.REGEXP_REPEAT} in ksmt" - ) - Kind.REGEXP_LOOP -> throw KSolverUnsupportedFeatureException( - "No direct mapping of ${Kind.REGEXP_LOOP} in ksmt" - ) + Kind.REGEXP_REPEAT -> expr.convert { regexExpr: KExpr -> + mkRegexPower(expr.regexRepeatTime, regexExpr) + } + Kind.REGEXP_LOOP -> expr.convert { regexExpr: KExpr -> + mkRegexLoop(expr.regexLoopFrom, expr.regexLoopTo, regexExpr) + } Kind.EQ_RANGE -> throw KSolverUnsupportedFeatureException("EQ_RANGE is not supported") @@ -1021,4 +1022,28 @@ open class KCvc5ExprConverter( require(kind == Kind.DIVISIBLE) { "Required op is ${Kind.DIVISIBLE}, but was $kind" } return termOpArg(this, 0).integerValue.toInt() } + + private val Term.regexRepeatTime: Int + get() { + require(kind == Kind.REGEXP_REPEAT) { + "Required op is ${Kind.REGEXP_REPEAT}, but was $kind" + } + return termOpArg(this, 0).integerValue.toInt() + } + + private val Term.regexLoopFrom: Int + get() { + require(kind == Kind.REGEXP_LOOP) { + "Required op is ${Kind.REGEXP_LOOP}, but was $kind" + } + return termOpArg(this, 0).integerValue.toInt() + } + + private val Term.regexLoopTo: Int + get() { + require(kind == Kind.REGEXP_LOOP) { + "Required op is ${Kind.REGEXP_LOOP}, but was $kind" + } + return termOpArg(this, 1).integerValue.toInt() + } } diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt index 216e8b77b..2b26a96f5 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprInternalizer.kt @@ -192,6 +192,8 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexPowerExpr +import io.ksmt.expr.KRegexLoopExpr import io.ksmt.expr.KRegexEpsilon import io.ksmt.expr.KRegexAll import io.ksmt.expr.KRegexAllChar @@ -1405,6 +1407,20 @@ class KCvc5ExprInternalizer( } } + override fun transform(expr: KRegexPowerExpr) = with(expr) { + transform(arg) { arg: Term -> + val extractOp = tm.mkOp(Kind.REGEXP_REPEAT, power) + tm.mkTerm(extractOp, arg) + } + } + + override fun transform(expr: KRegexLoopExpr) = with(expr) { + transform(arg) { arg: Term -> + val extractOp = tm.mkOp(Kind.REGEXP_LOOP, from, to) + tm.mkTerm(extractOp, arg) + } + } + override fun transform(expr: KRegexEpsilon) = with(expr) { transform { tm.mkTerm(Kind.REGEXP_NONE) } } diff --git a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt index 5de3fe7bc..57733c159 100644 --- a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt +++ b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt @@ -316,6 +316,8 @@ class AstDeserializer( ExprKind.RegexComplementExpr -> deserialize(::mkRegexComplementNoSimplify) ExprKind.RegexOptionExpr -> deserialize(::mkRegexOptionNoSimplify) ExprKind.RegexRangeExpr -> deserialize(::mkRegexRangeNoSimplify) + ExprKind.RegexPowerExpr -> mkRegexPower(readExpr(), readInt()) + ExprKind.RegexLoopExpr -> mkRegexLoop(readExpr(), readInt(), readInt()) ExprKind.RegexEpsilonExpr -> mkRegexEpsilon() ExprKind.RegexAllExpr -> mkRegexAll() ExprKind.RegexAllCharExpr -> mkRegexAllChar() diff --git a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstSerializer.kt b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstSerializer.kt index d5afe93e4..89c3ba77e 100644 --- a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstSerializer.kt +++ b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstSerializer.kt @@ -184,6 +184,8 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexPowerExpr +import io.ksmt.expr.KRegexLoopExpr import io.ksmt.expr.KRegexEpsilon import io.ksmt.expr.KRegexAll import io.ksmt.expr.KRegexAllChar @@ -1298,6 +1300,25 @@ class AstSerializer( serialize(arg0, arg1) } + override fun transform(expr: KRegexPowerExpr) = with(expr) { + transform(arg) { idx -> + writeExpr { + writeAst(idx) + writeInt(power) + } + } + } + + override fun transform(expr: KRegexLoopExpr) = with(expr) { + transform(arg) { idx -> + writeExpr { + writeAst(idx) + writeInt(from) + writeInt(to) + } + } + } + override fun transform(expr: KRegexEpsilon) = with(expr) { serialize() } diff --git a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKind.kt b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKind.kt index eda73eecb..ee1dcccb7 100644 --- a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKind.kt +++ b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKind.kt @@ -175,6 +175,8 @@ enum class ExprKind { RegexComplementExpr, RegexOptionExpr, RegexRangeExpr, + RegexPowerExpr, + RegexLoopExpr, RegexEpsilonExpr, RegexAllExpr, RegexAllCharExpr, diff --git a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKindMapper.kt b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKindMapper.kt index 60728b102..4fd2c1e92 100644 --- a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKindMapper.kt +++ b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKindMapper.kt @@ -178,6 +178,8 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexPowerExpr +import io.ksmt.expr.KRegexLoopExpr import io.ksmt.expr.KRegexEpsilon import io.ksmt.expr.KRegexAll import io.ksmt.expr.KRegexAllChar @@ -780,6 +782,12 @@ class ExprKindMapper: KTransformerBase { override fun transform(expr: KRegexRangeExpr): KExpr = expr.kind(ExprKind.RegexRangeExpr) + override fun transform(expr: KRegexPowerExpr): KExpr = expr.kind(ExprKind.RegexPowerExpr) + + + override fun transform(expr: KRegexLoopExpr): KExpr = expr.kind(ExprKind.RegexLoopExpr) + + override fun transform(expr: KRegexEpsilon): KExpr = expr.kind(ExprKind.RegexEpsilonExpr) diff --git a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt index 71906e422..9e4af22ad 100644 --- a/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt +++ b/ksmt-yices/ksmt-yices-core/src/main/kotlin/io/ksmt/solver/yices/KYicesExprInternalizer.kt @@ -182,6 +182,8 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexPowerExpr +import io.ksmt.expr.KRegexLoopExpr import io.ksmt.expr.KRegexEpsilon import io.ksmt.expr.KRegexAll import io.ksmt.expr.KRegexAllChar @@ -1154,6 +1156,14 @@ open class KYicesExprInternalizer( throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } + override fun transform(expr: KRegexPowerExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + + override fun transform(expr: KRegexLoopExpr): KExpr { + throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") + } + override fun transform(expr: KRegexEpsilon): KExpr { throw KSolverUnsupportedFeatureException("string theory is not supported in Yices") } diff --git a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt index 0e1644679..dc67d5bdc 100644 --- a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt +++ b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt @@ -453,6 +453,17 @@ open class KZ3ExprConverter( Z3_decl_kind.Z3_OP_RE_COMPLEMENT -> expr.convert(::mkRegexComplement) Z3_decl_kind.Z3_OP_RE_OPTION -> expr.convert(::mkRegexOption) Z3_decl_kind.Z3_OP_RE_RANGE -> expr.convert(::mkRegexRange) + Z3_decl_kind.Z3_OP_RE_POWER -> { + val args = getAppArgs(nCtx, expr) + val power = Native.getDeclIntParameter(nCtx, decl, 0) + expr.convert(args) { arg -> mkRegexPower(power, arg) } + } + Z3_decl_kind.Z3_OP_RE_LOOP -> { + val args = getAppArgs(nCtx, expr) + val from = Native.getDeclIntParameter(nCtx, decl, 0) + val to = Native.getDeclIntParameter(nCtx, decl, 1) + expr.convert(args) { arg -> mkRegexLoop(from, to, arg) } + } Z3_decl_kind.Z3_OP_RE_EMPTY_SET -> ExprConversionResult(mkRegexEpsilon()) Z3_decl_kind.Z3_OP_RE_FULL_SET -> ExprConversionResult(mkRegexAll()) Z3_decl_kind.Z3_OP_RE_FULL_CHAR_SET -> ExprConversionResult(mkRegexAllChar()) diff --git a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt index 1a13efde3..d99ff3f01 100644 --- a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt +++ b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt @@ -186,6 +186,8 @@ import io.ksmt.expr.KRegexDifferenceExpr import io.ksmt.expr.KRegexComplementExpr import io.ksmt.expr.KRegexOptionExpr import io.ksmt.expr.KRegexRangeExpr +import io.ksmt.expr.KRegexPowerExpr +import io.ksmt.expr.KRegexLoopExpr import io.ksmt.expr.KRegexEpsilon import io.ksmt.expr.KRegexAll import io.ksmt.expr.KRegexAllChar @@ -1081,6 +1083,18 @@ open class KZ3ExprInternalizer( } } + override fun transform(expr: KRegexPowerExpr) = with(expr) { + transform(arg) { arg -> + Native.mkRePower(nCtx, arg, power) + } + } + + override fun transform(expr: KRegexLoopExpr) = with(expr) { + transform(arg) { arg -> + Native.mkReLoop(nCtx, arg, from, to) + } + } + override fun transform(expr: KRegexEpsilon) = with(expr) { transform { Native.mkReEmpty( From 57db57a714c320459b8f48e682853e43854c22b9 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Thu, 19 Dec 2024 02:08:07 +0300 Subject: [PATCH 61/84] Fix regex power and loop expr deserializer --- .../io/ksmt/runner/serializer/AstDeserializer.kt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt index 57733c159..766b65c1f 100644 --- a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt +++ b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/AstDeserializer.kt @@ -12,6 +12,7 @@ import io.ksmt.sort.KArraySortBase import io.ksmt.sort.KBoolSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KUninterpretedSort import io.ksmt.utils.uncheckedCast @@ -316,8 +317,17 @@ class AstDeserializer( ExprKind.RegexComplementExpr -> deserialize(::mkRegexComplementNoSimplify) ExprKind.RegexOptionExpr -> deserialize(::mkRegexOptionNoSimplify) ExprKind.RegexRangeExpr -> deserialize(::mkRegexRangeNoSimplify) - ExprKind.RegexPowerExpr -> mkRegexPower(readExpr(), readInt()) - ExprKind.RegexLoopExpr -> mkRegexLoop(readExpr(), readInt(), readInt()) + ExprKind.RegexPowerExpr -> { + val expr = readExpr() + val power = readInt() + mkRegexPower(power, expr) + } + ExprKind.RegexLoopExpr -> { + val expr = readExpr() + val from = readInt() + val to = readInt() + mkRegexLoop(from, to, expr) + } ExprKind.RegexEpsilonExpr -> mkRegexEpsilon() ExprKind.RegexAllExpr -> mkRegexAll() ExprKind.RegexAllCharExpr -> mkRegexAllChar() From 4f3c819e69c19402e7f4ac80c77fc1b9546a2115 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Thu, 19 Dec 2024 02:24:18 +0300 Subject: [PATCH 62/84] Add stubs in symfpu visitors --- .../main/kotlin/io/ksmt/symfpu/solver/FpToBvTransformer.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/ksmt-symfpu/src/main/kotlin/io/ksmt/symfpu/solver/FpToBvTransformer.kt b/ksmt-symfpu/src/main/kotlin/io/ksmt/symfpu/solver/FpToBvTransformer.kt index be044b27f..bd76840bc 100644 --- a/ksmt-symfpu/src/main/kotlin/io/ksmt/symfpu/solver/FpToBvTransformer.kt +++ b/ksmt-symfpu/src/main/kotlin/io/ksmt/symfpu/solver/FpToBvTransformer.kt @@ -69,6 +69,8 @@ import io.ksmt.sort.KFpRoundingModeSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KSort import io.ksmt.sort.KSortVisitor import io.ksmt.sort.KUninterpretedSort @@ -595,6 +597,8 @@ class FpToBvTransformer(ctx: KContext, private val packedBvOptimization: Boolean override fun visit(sort: KBoolSort): Boolean = false override fun visit(sort: KIntSort): Boolean = false override fun visit(sort: KRealSort): Boolean = false + override fun visit(sort: KStringSort): Boolean = false + override fun visit(sort: KRegexSort): Boolean = false override fun visit(sort: S): Boolean = false } @@ -636,6 +640,8 @@ class FpToBvTransformer(ctx: KContext, private val packedBvOptimization: Boolean override fun visit(sort: KBoolSort): KSort = sort override fun visit(sort: KIntSort): KSort = sort override fun visit(sort: KRealSort): KSort = sort + override fun visit(sort: KStringSort): KSort = sort + override fun visit(sort: KRegexSort): KSort = sort override fun visit(sort: S): KSort = sort } } From 0c2214754b80db6ffd12f505b94e25675cc259b5 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Thu, 19 Dec 2024 03:12:51 +0300 Subject: [PATCH 63/84] Fix typo in z3 converter --- .../src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt index dc67d5bdc..67ae4a9e4 100644 --- a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt +++ b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprConverter.kt @@ -132,8 +132,6 @@ open class KZ3ExprConverter( Z3_sort_kind.Z3_DATATYPE_SORT, Z3_sort_kind.Z3_RELATION_SORT, Z3_sort_kind.Z3_FINITE_DOMAIN_SORT, - Z3_sort_kind.Z3_SEQ_SORT, - Z3_sort_kind.Z3_RE_SORT, Z3_sort_kind.Z3_CHAR_SORT, Z3_sort_kind.Z3_TYPE_VAR, Z3_sort_kind.Z3_UNKNOWN_SORT -> TODO("$sort is not supported yet") From dbb853177cad7e139ade75d1a723e711fdac44f9 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Thu, 19 Dec 2024 04:30:02 +0300 Subject: [PATCH 64/84] Describe functions for further simplification of expressions --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 114 +++++++++----- .../rewrite/simplify/RegexSimplification.kt | 58 ++++++++ .../simplify/RegexSimplificationRules.kt | 2 + .../rewrite/simplify/StringSimplification.kt | 140 ++++++++++++++++++ .../simplify/StringSimplificationRules.kt | 2 + 5 files changed, 278 insertions(+), 38 deletions(-) create mode 100644 ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/RegexSimplification.kt create mode 100644 ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/RegexSimplificationRules.kt create mode 100644 ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt create mode 100644 ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index c8d54a0cb..d91da1743 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -483,6 +483,44 @@ import io.ksmt.expr.rewrite.simplify.simplifyRealIsInt import io.ksmt.expr.rewrite.simplify.simplifyRealToFpExpr import io.ksmt.expr.rewrite.simplify.simplifyRealToInt import io.ksmt.expr.rewrite.simplify.simplifyXor +import io.ksmt.expr.rewrite.simplify.simplifyStringConcat +import io.ksmt.expr.rewrite.simplify.simplifyStringLen +import io.ksmt.expr.rewrite.simplify.simplifyStringToRegex +import io.ksmt.expr.rewrite.simplify.simplifyStringInRegex +import io.ksmt.expr.rewrite.simplify.simplifyStringSuffixOf +import io.ksmt.expr.rewrite.simplify.simplifyStringPrefixOf +import io.ksmt.expr.rewrite.simplify.simplifyStringLt +import io.ksmt.expr.rewrite.simplify.simplifyStringLe +import io.ksmt.expr.rewrite.simplify.simplifyStringGt +import io.ksmt.expr.rewrite.simplify.simplifyStringGe +import io.ksmt.expr.rewrite.simplify.simplifyStringContains +import io.ksmt.expr.rewrite.simplify.simplifyStringSingletonSub +import io.ksmt.expr.rewrite.simplify.simplifyStringSub +import io.ksmt.expr.rewrite.simplify.simplifyStringIndexOf +import io.ksmt.expr.rewrite.simplify.simplifyStringIndexOfRegex +import io.ksmt.expr.rewrite.simplify.simplifyStringReplace +import io.ksmt.expr.rewrite.simplify.simplifyStringReplaceAll +import io.ksmt.expr.rewrite.simplify.simplifyStringReplaceWithRegex +import io.ksmt.expr.rewrite.simplify.simplifyStringReplaceAllWithRegex +import io.ksmt.expr.rewrite.simplify.simplifyStringToLower +import io.ksmt.expr.rewrite.simplify.simplifyStringToUpper +import io.ksmt.expr.rewrite.simplify.simplifyStringReverse +import io.ksmt.expr.rewrite.simplify.simplifyStringIsDigit +import io.ksmt.expr.rewrite.simplify.simplifyStringToCode +import io.ksmt.expr.rewrite.simplify.simplifyStringFromCode +import io.ksmt.expr.rewrite.simplify.simplifyStringToInt +import io.ksmt.expr.rewrite.simplify.simplifyStringFromInt +import io.ksmt.expr.rewrite.simplify.simplifyRegexConcat +import io.ksmt.expr.rewrite.simplify.simplifyRegexUnion +import io.ksmt.expr.rewrite.simplify.simplifyRegexIntersection +import io.ksmt.expr.rewrite.simplify.simplifyRegexStar +import io.ksmt.expr.rewrite.simplify.simplifyRegexCross +import io.ksmt.expr.rewrite.simplify.simplifyRegexDifference +import io.ksmt.expr.rewrite.simplify.simplifyRegexComplement +import io.ksmt.expr.rewrite.simplify.simplifyRegexOption +import io.ksmt.expr.rewrite.simplify.simplifyRegexRange +import io.ksmt.expr.rewrite.simplify.simplifyRegexPower +import io.ksmt.expr.rewrite.simplify.simplifyRegexLoop import io.ksmt.sort.KArithSort import io.ksmt.sort.KArray2Sort import io.ksmt.sort.KArray3Sort @@ -1996,7 +2034,7 @@ open class KContext( * Create String concatenation (`concat`) expression. * */ open fun mkStringConcat(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkStringConcatNoSimplify, ::mkStringConcatNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyStringConcat, ::mkStringConcatNoSimplify) // Add simplified version /** * Create String concatenation (`concat`) expression. @@ -2019,7 +2057,7 @@ open class KContext( * Create string's length expression. * */ open fun mkStringLen(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkStringLenNoSimplify, ::mkStringLenNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringLen, ::mkStringLenNoSimplify) // Add simplified version /** * Create string's length expression. @@ -2041,7 +2079,7 @@ open class KContext( * Check if first string is a suffix of second. * */ open fun mkStringSuffixOf(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkStringSuffixOfNoSimplify, ::mkStringSuffixOfNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyStringSuffixOf, ::mkStringSuffixOfNoSimplify) // Add simplified version /** * Check if first string is a suffix of second. @@ -2060,7 +2098,7 @@ open class KContext( * Check if first string is a prefix of second. * */ open fun mkStringPrefixOf(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkStringPrefixOfNoSimplify, ::mkStringPrefixOfNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyStringPrefixOf, ::mkStringPrefixOfNoSimplify) // Add simplified version /** * Check if first string is a prefix of second. @@ -2079,7 +2117,7 @@ open class KContext( * Create a lexicographic ordering (`<` (less)) expression. * */ open fun mkStringLt(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::mkStringLtNoSimplify, ::mkStringLtNoSimplify) // Add simplified version + mkSimplified(lhs, rhs, KContext::simplifyStringLt, ::mkStringLtNoSimplify) // Add simplified version /** * Create a lexicographic ordering (`<` (less)) expression. @@ -2099,7 +2137,7 @@ open class KContext( * Create a lexicographic ordering reflexive closure (`<=` (less or equal)) expression. * */ open fun mkStringLe(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::mkStringLeNoSimplify, ::mkStringLeNoSimplify) // Add simplified version + mkSimplified(lhs, rhs, KContext::simplifyStringLe, ::mkStringLeNoSimplify) // Add simplified version /** * Create a lexicographic ordering reflexive closure (`<=` (less or equal)) expression. @@ -2119,7 +2157,7 @@ open class KContext( * Create a lexicographic ordering (`>` (greater)) expression. * */ open fun mkStringGt(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::mkStringGtNoSimplify, ::mkStringGtNoSimplify) // Add simplified version + mkSimplified(lhs, rhs, KContext::simplifyStringGt, ::mkStringGtNoSimplify) // Add simplified version /** * Create a lexicographic ordering (`>` (greater)) expression. @@ -2139,7 +2177,7 @@ open class KContext( * Create a lexicographic ordering reflexive closure (`>=` (greater or equal)) expression. * */ open fun mkStringGe(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::mkStringGeNoSimplify, ::mkStringGeNoSimplify) // Add simplified version + mkSimplified(lhs, rhs, KContext::simplifyStringGe, ::mkStringGeNoSimplify) // Add simplified version /** * Create a lexicographic ordering reflexive closure (`>=` (greater or equal)) expression. @@ -2159,7 +2197,7 @@ open class KContext( * Check if first string contains second one. * */ open fun mkStringContains(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::mkStringContainsNoSimplify, ::mkStringContainsNoSimplify) // Add simplified version + mkSimplified(lhs, rhs, KContext::simplifyStringContains, ::mkStringContainsNoSimplify) // Add simplified version /** * Check if first string contains second one. @@ -2180,7 +2218,7 @@ open class KContext( * If position is out of range (less than 0, or grater than (string length - 1)), then returns empty string. * */ open fun mkStringSingletonSub(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkStringSingletonSubNoSimplify, ::mkStringSingletonSubNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyStringSingletonSub, ::mkStringSingletonSubNoSimplify) // Add simplified version /** * Returns singleton string containing a character at given position. @@ -2200,7 +2238,7 @@ open class KContext( * or the given position is out of bounds. */ open fun mkStringSub(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::mkStringSubNoSimplify, ::mkStringSubNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, arg2, KContext::simplifyStringSub, ::mkStringSubNoSimplify) // Add simplified version /** * Evaluates the longest substring from the input string, starting at the specified position @@ -2222,7 +2260,7 @@ open class KContext( * Returns the position if the second string is empty. */ open fun mkStringIndexOf(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::mkStringIndexOfNoSimplify, ::mkStringIndexOfNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, arg2, KContext::simplifyStringIndexOf, ::mkStringIndexOfNoSimplify) // Add simplified version /** * Find the index of the first occurrence of the second string in the first string, @@ -2244,7 +2282,7 @@ open class KContext( * or if the position is out of bounds. */ open fun mkStringIndexOfRegex(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::mkStringIndexOfRegexNoSimplify, ::mkStringIndexOfRegexNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, arg2, KContext::simplifyStringIndexOfRegex, ::mkStringIndexOfRegexNoSimplify) // Add simplified version /** * Find the index of the first match of a regular expression in the string, @@ -2265,7 +2303,7 @@ open class KContext( * If the second line is empty, then the third is inserted at the beginning of the first. * */ open fun mkStringReplace(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::mkStringReplaceNoSimplify, ::mkStringReplaceNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, arg2, KContext::simplifyStringReplace, ::mkStringReplaceNoSimplify) // Add simplified version /** * Replace the first occurrence of the second string in the first string with the third, @@ -2285,7 +2323,7 @@ open class KContext( * if there are such occurrences, otherwise return the first string. * */ open fun mkStringReplaceAll(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::mkStringReplaceAllNoSimplify, ::mkStringReplaceAllNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, arg2, KContext::simplifyStringReplaceAll, ::mkStringReplaceAllNoSimplify) // Add simplified version /** * Replace the all occurrences of the second string in the first string with the third, @@ -2304,7 +2342,7 @@ open class KContext( * If the language of r contains the empty string, the result is to prepend second string to first one. * */ open fun mkStringReplaceWithRegex(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::mkStringReplaceWithRegexNoSimplify, ::mkStringReplaceWithRegexNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, arg2, KContext::simplifyStringReplaceWithRegex, ::mkStringReplaceWithRegexNoSimplify) // Add simplified version /** * Replace the shortest leftmost match of regex in first string, if any, by second string. @@ -2322,7 +2360,7 @@ open class KContext( * Replace left-to right, each shortest non-empty match of regex in first string by seconds. * */ open fun mkStringReplaceAllWithRegex(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::mkStringReplaceAllWithRegexNoSimplify, ::mkStringReplaceAllWithRegexNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, arg2, KContext::simplifyStringReplaceAllWithRegex, ::mkStringReplaceAllWithRegexNoSimplify) // Add simplified version /** * Replace left-to right, each shortest non-empty match of regex in first string by seconds. @@ -2339,7 +2377,7 @@ open class KContext( * Convert string to lower case. * */ open fun mkStringToLower(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkStringToLowerNoSimplify, ::mkStringToLowerNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringToLower, ::mkStringToLowerNoSimplify) // Add simplified version /** * Convert string to lower case. @@ -2356,7 +2394,7 @@ open class KContext( * Convert string to upper case. * */ open fun mkStringToUpper(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkStringToUpperNoSimplify, ::mkStringToUpperNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringToUpper, ::mkStringToUpperNoSimplify) // Add simplified version /** * Convert string to upper case. @@ -2373,7 +2411,7 @@ open class KContext( * Reverse string. * */ open fun mkStringReverse(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkStringReverseNoSimplify, ::mkStringReverseNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringReverse, ::mkStringReverseNoSimplify) // Add simplified version /** * Reverse string. @@ -2390,7 +2428,7 @@ open class KContext( * Check that the string contains only decimal digit characters. * */ open fun mkStringIsDigit(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkStringIsDigitNoSimplify, ::mkStringIsDigitNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringIsDigit, ::mkStringIsDigitNoSimplify) // Add simplified version /** * Check that the string contains only decimal digit characters. @@ -2408,7 +2446,7 @@ open class KContext( * Otherwise, returns -1. * */ open fun mkStringToCode(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkStringToCodeNoSimplify, ::mkStringToCodeNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringToCode, ::mkStringToCodeNoSimplify) // Add simplified version /** * Returns the code point of the only character in the string if the string is a singleton. @@ -2427,7 +2465,7 @@ open class KContext( * If codepoint not in range [0, 196607], returns empty string. * */ open fun mkStringFromCode(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkStringFromCodeNoSimplify, ::mkStringFromCodeNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringFromCode, ::mkStringFromCodeNoSimplify) // Add simplified version /** * Returns a singleton string consisting of a character, with the given code point. @@ -2446,7 +2484,7 @@ open class KContext( * Otherwise, if the string contains a character that is not a decimal number, then returns -1. * */ open fun mkStringToInt(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkStringToIntNoSimplify, ::mkStringToIntNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringToInt, ::mkStringToIntNoSimplify) // Add simplified version /** * Converts a string containing only decimal digits to a positive integer. @@ -2465,7 +2503,7 @@ open class KContext( * If the number is negative, it returns an empty string. * */ open fun mkStringFromInt(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkStringFromIntNoSimplify, ::mkStringFromIntNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringFromInt, ::mkStringFromIntNoSimplify) // Add simplified version /** * Converts a positive integer to a string consisting of the decimal digits of that number, with no leading zeros. @@ -2483,7 +2521,7 @@ open class KContext( * Create a regular expression based on a string expression. * */ open fun mkStringToRegex(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkStringToRegexNoSimplify, ::mkStringToRegexNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringToRegex, ::mkStringToRegexNoSimplify) // Add simplified version /** * Create a regular expression based on a string expression. @@ -2503,7 +2541,7 @@ open class KContext( * Check if a string belongs to the language defined by the regular expression. * */ open fun mkStringInRegex(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkStringInRegexNoSimplify, ::mkStringInRegexNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyStringInRegex, ::mkStringInRegexNoSimplify) // Add simplified version /** * Check if a string belongs to the language defined by the regular expression. @@ -2527,7 +2565,7 @@ open class KContext( * Create Regex concatenation (`concat`) expression. * */ open fun mkRegexConcat(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkRegexConcatNoSimplify, ::mkRegexConcatNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyRegexConcat, ::mkRegexConcatNoSimplify) // Add simplified version /** * Create Regex concatenation (`concat`) expression. @@ -2547,7 +2585,7 @@ open class KContext( * Create Regex union (`union`) expression. * */ open fun mkRegexUnion(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkRegexUnionNoSimplify, ::mkRegexUnionNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyRegexUnion, ::mkRegexUnionNoSimplify) // Add simplified version /** * Create Regex union (`union`) expression. @@ -2564,7 +2602,7 @@ open class KContext( * Create Regex intersection (`intersect`) expression. * */ open fun mkRegexIntersection(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkRegexIntersectionNoSimplify, ::mkRegexIntersectionNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyRegexIntersection, ::mkRegexIntersectionNoSimplify) // Add simplified version /** * Create Regex intersection (`intersect`) expression. @@ -2581,7 +2619,7 @@ open class KContext( * Create regular expression's Kleene closure. * */ open fun mkRegexStar(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkRegexStarNoSimplify, ::mkRegexStarNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyRegexStar, ::mkRegexStarNoSimplify) // Add simplified version /** * Create regular expression's Kleene closure. @@ -2598,7 +2636,7 @@ open class KContext( * Create regular expression's Kleene cross. * */ open fun mkRegexCross(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkRegexCrossNoSimplify, ::mkRegexCrossNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyRegexCross, ::mkRegexCrossNoSimplify) // Add simplified version /** * Create regular expression's Kleene cross. @@ -2615,7 +2653,7 @@ open class KContext( * Create Regex difference (`diff`) expression. * */ open fun mkRegexDifference(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkRegexDifferenceNoSimplify, ::mkRegexDifferenceNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyRegexDifference, ::mkRegexDifferenceNoSimplify) // Add simplified version /** * Create Regex difference (`diff`) expression. @@ -2632,7 +2670,7 @@ open class KContext( * Create regular expression's complement. * */ open fun mkRegexComplement(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkRegexComplementNoSimplify, ::mkRegexComplementNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyRegexComplement, ::mkRegexComplementNoSimplify) // Add simplified version /** * Create regular expression's complement. @@ -2649,7 +2687,7 @@ open class KContext( * Equivalent to concatenating a regular expression with the empty string. * */ open fun mkRegexOption(arg: KExpr): KExpr = - mkSimplified(arg, KContext::mkRegexOptionNoSimplify, ::mkRegexOptionNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyRegexOption, ::mkRegexOptionNoSimplify) // Add simplified version /** * Make regular expression optional. @@ -2668,7 +2706,7 @@ open class KContext( * Otherwise the empty set. * */ open fun mkRegexRange(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::mkRegexRangeNoSimplify, ::mkRegexRangeNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyRegexRange, ::mkRegexRangeNoSimplify) // Add simplified version /** * Return the set of all singleton strings in the range @@ -2688,7 +2726,7 @@ open class KContext( * of the given `arg` regex repeated `power` times. * */ open fun mkRegexPower(power: Int, arg: KExpr): KExpr = - mkSimplified(power, arg, KContext::mkRegexPowerNoSimplify, ::mkRegexPowerNoSimplify) // Add simplified version + mkSimplified(power, arg, KContext::simplifyRegexPower, ::mkRegexPowerNoSimplify) // Add simplified version /** * Constructs a regex expression that represents the concatenation @@ -2707,7 +2745,7 @@ open class KContext( * formed by repeating the given `arg` regex from `from` to `to` times inclusively. * */ open fun mkRegexLoop(from: Int, to: Int, arg: KExpr): KExpr = - mkSimplified(from, to, arg, KContext::mkRegexLoopNoSimplify, ::mkRegexLoopNoSimplify) // Add simplified version + mkSimplified(from, to, arg, KContext::simplifyRegexLoop, ::mkRegexLoopNoSimplify) // Add simplified version /** * Constructs a regex expression that represents the union of regexes diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/RegexSimplification.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/RegexSimplification.kt new file mode 100644 index 000000000..0bc248fa4 --- /dev/null +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/RegexSimplification.kt @@ -0,0 +1,58 @@ +package io.ksmt.expr.rewrite.simplify + +import io.ksmt.KContext +import io.ksmt.expr.KExpr +import io.ksmt.sort.KRegexSort +import io.ksmt.sort.KStringSort + +fun KContext.simplifyRegexConcat( + arg0: KExpr, + arg1: KExpr +): KExpr = mkRegexConcatNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyRegexUnion( + arg0: KExpr, + arg1: KExpr +): KExpr = mkRegexUnionNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyRegexIntersection( + arg0: KExpr, + arg1: KExpr +): KExpr = mkRegexIntersectionNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyRegexStar( + arg: KExpr +): KExpr = mkRegexStarNoSimplify(arg) // Temporarily + +fun KContext.simplifyRegexCross( + arg: KExpr +): KExpr = mkRegexCrossNoSimplify(arg) // Temporarily + +fun KContext.simplifyRegexDifference( + arg0: KExpr, + arg1: KExpr +): KExpr = mkRegexDifferenceNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyRegexComplement( + arg: KExpr +): KExpr = mkRegexComplementNoSimplify(arg) // Temporarily + +fun KContext.simplifyRegexOption( + arg: KExpr +): KExpr = mkRegexOptionNoSimplify(arg) // Temporarily + +fun KContext.simplifyRegexRange( + arg0: KExpr, + arg1: KExpr +): KExpr = mkRegexRangeNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyRegexPower( + power: Int, + arg: KExpr, +): KExpr = mkRegexPowerNoSimplify(power, arg) // Temporarily + +fun KContext.simplifyRegexLoop( + from: Int, + to: Int, + arg: KExpr, +): KExpr = mkRegexLoopNoSimplify(from, to, arg) // Temporarily diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/RegexSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/RegexSimplificationRules.kt new file mode 100644 index 000000000..a8eda57c9 --- /dev/null +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/RegexSimplificationRules.kt @@ -0,0 +1,2 @@ +package io.ksmt.expr.rewrite.simplify + diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt new file mode 100644 index 000000000..d84c5cc44 --- /dev/null +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt @@ -0,0 +1,140 @@ +package io.ksmt.expr.rewrite.simplify + +import io.ksmt.KContext +import io.ksmt.expr.KExpr +import io.ksmt.sort.KBoolSort +import io.ksmt.sort.KIntSort +import io.ksmt.sort.KRegexSort +import io.ksmt.sort.KStringSort + +fun KContext.simplifyStringConcat( + arg0: KExpr, + arg1: KExpr +): KExpr = mkStringConcatNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyStringLen( + arg: KExpr +): KExpr = mkStringLenNoSimplify(arg) // Temporarily + +fun KContext.simplifyStringToRegex( + arg: KExpr +): KExpr = mkStringToRegexNoSimplify(arg) // Temporarily + +fun KContext.simplifyStringInRegex( + arg0: KExpr, + arg1: KExpr +): KExpr = mkStringInRegexNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyStringSuffixOf( + arg0: KExpr, + arg1: KExpr +): KExpr = mkStringSuffixOfNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyStringPrefixOf( + arg0: KExpr, + arg1: KExpr +): KExpr = mkStringPrefixOfNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyStringLt( + arg0: KExpr, + arg1: KExpr +): KExpr = mkStringLtNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyStringLe( + arg0: KExpr, + arg1: KExpr +): KExpr = mkStringLeNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyStringGt( + arg0: KExpr, + arg1: KExpr +): KExpr = mkStringGtNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyStringGe( + arg0: KExpr, + arg1: KExpr +): KExpr = mkStringGeNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyStringContains( + arg0: KExpr, + arg1: KExpr +): KExpr = mkStringContainsNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyStringSingletonSub( + arg0: KExpr, + arg1: KExpr +): KExpr = mkStringSingletonSubNoSimplify(arg0, arg1) // Temporarily + +fun KContext.simplifyStringSub( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr +): KExpr = mkStringSubNoSimplify(arg0, arg1, arg2) // Temporarily + +fun KContext.simplifyStringIndexOf( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr +): KExpr = mkStringIndexOfNoSimplify(arg0, arg1, arg2) // Temporarily + +fun KContext.simplifyStringIndexOfRegex( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr +): KExpr = mkStringIndexOfRegexNoSimplify(arg0, arg1, arg2) // Temporarily + +fun KContext.simplifyStringReplace( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr +): KExpr = mkStringReplaceNoSimplify(arg0, arg1, arg2) // Temporarily + +fun KContext.simplifyStringReplaceAll( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr +): KExpr = mkStringReplaceAllNoSimplify(arg0, arg1, arg2) // Temporarily + +fun KContext.simplifyStringReplaceWithRegex( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr +): KExpr = mkStringReplaceWithRegexNoSimplify(arg0, arg1, arg2) // Temporarily + +fun KContext.simplifyStringReplaceAllWithRegex( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr +): KExpr = mkStringReplaceAllWithRegexNoSimplify(arg0, arg1, arg2) // Temporarily + +fun KContext.simplifyStringToLower( + arg: KExpr +): KExpr = mkStringToLowerNoSimplify(arg) // Temporarily + +fun KContext.simplifyStringToUpper( + arg: KExpr +): KExpr = mkStringToUpperNoSimplify(arg) // Temporarily + +fun KContext.simplifyStringReverse( + arg: KExpr +): KExpr = mkStringReverseNoSimplify(arg) // Temporarily + +fun KContext.simplifyStringIsDigit( + arg: KExpr +): KExpr = mkStringIsDigitNoSimplify(arg) // Temporarily + +fun KContext.simplifyStringToCode( + arg: KExpr +): KExpr = mkStringToCodeNoSimplify(arg) // Temporarily + +fun KContext.simplifyStringFromCode( + arg: KExpr +): KExpr = mkStringFromCodeNoSimplify(arg) // Temporarily + +fun KContext.simplifyStringToInt( + arg: KExpr +): KExpr = mkStringToIntNoSimplify(arg) // Temporarily + +fun KContext.simplifyStringFromInt( + arg: KExpr +): KExpr = mkStringFromIntNoSimplify(arg) // Temporarily diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt new file mode 100644 index 000000000..a8eda57c9 --- /dev/null +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -0,0 +1,2 @@ +package io.ksmt.expr.rewrite.simplify + From a865074cfb70af766e02525aee18c434a3484ba5 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Thu, 19 Dec 2024 20:56:49 +0300 Subject: [PATCH 65/84] Fix cvc5 sort converter --- .../src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt index b01106262..7b9728edd 100644 --- a/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt +++ b/ksmt-cvc5/ksmt-cvc5-core/src/main/kotlin/io/ksmt/solver/cvc5/KCvc5ExprConverter.kt @@ -820,6 +820,8 @@ open class KCvc5ExprConverter( sort.isBitVector -> mkBvSort(sort.bitVectorSize.toUInt()) sort.isInteger -> intSort sort.isReal -> realSort + sort.isString -> stringSort + sort.isRegExp -> regexSort sort.isArray -> mkArrayAnySort( domain = convertArrayDomainSort(tm.sortOp(sort) { arrayIndexSort }), range = tm.sortOp(sort) { arrayElementSort }.convertSort() From 4c06853f5f7e51f6eb95b0a5ae375734281afee9 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sat, 1 Mar 2025 20:21:27 +0300 Subject: [PATCH 66/84] Add helper function for eval string literal operations --- .../rewrite/simplify/StringSimplificationRules.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt index a8eda57c9..a1170f8ec 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -1,2 +1,16 @@ package io.ksmt.expr.rewrite.simplify +import io.ksmt.expr.KExpr +import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.sort.KStringSort + +inline fun tryEvalStringLiteralOperation( + lhs: KExpr, + rhs: KExpr, + operation: (KStringLiteralExpr, KStringLiteralExpr) -> KStringLiteralExpr, + cont: () -> KExpr +): KExpr = if (lhs is KStringLiteralExpr && rhs is KStringLiteralExpr) { + operation(lhs, rhs) +} else { + cont() +} From 4eadbb08e7af2f22a17ff7af0edb92853fef7c7d Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sat, 1 Mar 2025 20:24:12 +0300 Subject: [PATCH 67/84] Add string utils object with basic string operations --- .../src/main/kotlin/io/ksmt/utils/StringUtils.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt new file mode 100644 index 000000000..cfce56380 --- /dev/null +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt @@ -0,0 +1,11 @@ +package io.ksmt.utils + +import io.ksmt.expr.KStringLiteralExpr + +object StringUtils { + + @JvmStatic + fun concatStrings(lhs: KStringLiteralExpr, rhs: KStringLiteralExpr): KStringLiteralExpr = with (lhs.ctx) { + mkStringLiteral(lhs.value + rhs.value) + } +} From 3944acabe8b6cc375bc82d105f8d4b293731e349 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sat, 1 Mar 2025 21:01:55 +0300 Subject: [PATCH 68/84] Implement basic and nested string concat simplification --- .../rewrite/simplify/StringSimplification.kt | 4 +- .../simplify/StringSimplificationRules.kt | 46 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt index d84c5cc44..c81e650ea 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt @@ -10,7 +10,9 @@ import io.ksmt.sort.KStringSort fun KContext.simplifyStringConcat( arg0: KExpr, arg1: KExpr -): KExpr = mkStringConcatNoSimplify(arg0, arg1) // Temporarily +): KExpr = simplifyStringBasicConcat(arg0, arg1) {arg2, arg3 -> + simplifyStringNestedConcat(arg2, arg3, KContext::simplifyStringConcat, ::mkStringConcatNoSimplify) +} fun KContext.simplifyStringLen( arg: KExpr diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt index a1170f8ec..e4c44bce7 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -1,8 +1,54 @@ package io.ksmt.expr.rewrite.simplify +import io.ksmt.KContext import io.ksmt.expr.KExpr +import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLiteralExpr import io.ksmt.sort.KStringSort +import io.ksmt.utils.StringUtils + +inline fun KContext.simplifyStringBasicConcat( + arg0: KExpr, + arg1: KExpr, + cont: (KExpr, KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg0, arg1, { a1, a2 -> StringUtils.concatStrings(a1, a2) }) { + cont(arg0, arg1) + } + +inline fun KContext.simplifyStringNestedConcat( + arg0: KExpr, + arg1: KExpr, + rewriteStringConcatExpr: KContext.(KExpr, KExpr) -> KExpr, + cont: (KExpr, KExpr) -> KExpr +): KExpr { + if (arg0 is KStringLiteralExpr && arg1 is KStringConcatExpr) { + val arg1Left = arg1.arg0 + if (arg1Left is KStringLiteralExpr) { + return rewriteStringConcatExpr(StringUtils.concatStrings(arg0, arg1Left), arg1.arg1) + } + } + + if (arg1 is KStringLiteralExpr && arg0 is KStringConcatExpr) { + val arg0Right = arg0.arg1 + if (arg0Right is KStringLiteralExpr) { + return rewriteStringConcatExpr(arg0.arg0, StringUtils.concatStrings(arg0Right, arg1)) + } + } + + if (arg0 is KStringConcatExpr && arg1 is KStringConcatExpr) { + val arg0Right = arg0.arg1 + val arg1Left = arg1.arg0 + if (arg0Right is KStringLiteralExpr && arg1Left is KStringLiteralExpr) { + return rewriteStringConcatExpr( + arg0.arg0, + mkStringConcat(StringUtils.concatStrings(arg0Right, arg1Left), arg1.arg1) + ) + } + } + + return cont(arg0, arg1) +} inline fun tryEvalStringLiteralOperation( lhs: KExpr, From 33a862fbca73baa8afe6d45609f126bc8d5fe85d Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sat, 1 Mar 2025 21:21:23 +0300 Subject: [PATCH 69/84] Implement simplification for string length expression --- .../rewrite/simplify/StringSimplification.kt | 2 +- .../simplify/StringSimplificationRules.kt | 52 ++++++++++++++++--- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt index c81e650ea..ba669db35 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt @@ -16,7 +16,7 @@ fun KContext.simplifyStringConcat( fun KContext.simplifyStringLen( arg: KExpr -): KExpr = mkStringLenNoSimplify(arg) // Temporarily +): KExpr = simplifyStringLenExpr(arg, ::mkStringLenNoSimplify) fun KContext.simplifyStringToRegex( arg: KExpr diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt index e4c44bce7..e872ddc92 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -2,11 +2,21 @@ package io.ksmt.expr.rewrite.simplify import io.ksmt.KContext import io.ksmt.expr.KExpr +import io.ksmt.expr.KInterpretedValue import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.sort.KIntSort +import io.ksmt.sort.KSort import io.ksmt.sort.KStringSort import io.ksmt.utils.StringUtils +/* +* String concatenation simplification +* */ + +/** + * Eval constants. + * (concat const1 const2) ==> (const3) */ inline fun KContext.simplifyStringBasicConcat( arg0: KExpr, arg1: KExpr, @@ -16,26 +26,32 @@ inline fun KContext.simplifyStringBasicConcat( cont(arg0, arg1) } +/** + * ((concat a const1) const2) ==> (concat a (concat const1 const2)) + * ((concat const1 (concat const2 a)) => (concat (concat const1 const2) a) + * ((concat (concat a const1) (concat const2 b)) ==> (concat a (concat (concat const1 const2) b)) + */ inline fun KContext.simplifyStringNestedConcat( arg0: KExpr, arg1: KExpr, rewriteStringConcatExpr: KContext.(KExpr, KExpr) -> KExpr, cont: (KExpr, KExpr) -> KExpr ): KExpr { + // ((concat a const1) const2) ==> (concat a (concat const1 const2)) if (arg0 is KStringLiteralExpr && arg1 is KStringConcatExpr) { val arg1Left = arg1.arg0 if (arg1Left is KStringLiteralExpr) { return rewriteStringConcatExpr(StringUtils.concatStrings(arg0, arg1Left), arg1.arg1) } } - + // ((concat const1 (concat const2 a)) => (concat (concat const1 const2) a) if (arg1 is KStringLiteralExpr && arg0 is KStringConcatExpr) { val arg0Right = arg0.arg1 if (arg0Right is KStringLiteralExpr) { return rewriteStringConcatExpr(arg0.arg0, StringUtils.concatStrings(arg0Right, arg1)) } } - + // ((concat (concat a const1) (concat const2 b)) ==> (concat a (concat (concat const1 const2) b)) if (arg0 is KStringConcatExpr && arg1 is KStringConcatExpr) { val arg0Right = arg0.arg1 val arg1Left = arg1.arg0 @@ -50,13 +66,37 @@ inline fun KContext.simplifyStringNestedConcat( return cont(arg0, arg1) } +/* +* String length expression simplification +* */ + +inline fun KContext.simplifyStringLenExpr( + arg: KExpr, + cont: (KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg, { literalArg -> + mkIntNum(literalArg.value.length) + }) { + cont(arg) + } + +inline fun tryEvalStringLiteralOperation( + arg: KExpr, + operation: (KStringLiteralExpr) -> KInterpretedValue, + cont: () -> KExpr +): KExpr = if (arg is KStringLiteralExpr) { + operation(arg) +} else { + cont() +} + inline fun tryEvalStringLiteralOperation( - lhs: KExpr, - rhs: KExpr, + arg0: KExpr, + arg1: KExpr, operation: (KStringLiteralExpr, KStringLiteralExpr) -> KStringLiteralExpr, cont: () -> KExpr -): KExpr = if (lhs is KStringLiteralExpr && rhs is KStringLiteralExpr) { - operation(lhs, rhs) +): KExpr = if (arg0 is KStringLiteralExpr && arg1 is KStringLiteralExpr) { + operation(arg0, arg1) } else { cont() } From cefcd1572820708fb0bc4804bd7d5858bd64fe8c Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sat, 1 Mar 2025 21:27:11 +0300 Subject: [PATCH 70/84] Fix old and add new helper function for eval str literal operations --- .../simplify/StringSimplificationRules.kt | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt index e872ddc92..e47ef5506 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -90,13 +90,25 @@ inline fun tryEvalStringLiteralOperation( cont() } -inline fun tryEvalStringLiteralOperation( +inline fun tryEvalStringLiteralOperation( arg0: KExpr, arg1: KExpr, - operation: (KStringLiteralExpr, KStringLiteralExpr) -> KStringLiteralExpr, - cont: () -> KExpr -): KExpr = if (arg0 is KStringLiteralExpr && arg1 is KStringLiteralExpr) { + operation: (KStringLiteralExpr, KStringLiteralExpr) -> KInterpretedValue, + cont: () -> KExpr +): KExpr = if (arg0 is KStringLiteralExpr && arg1 is KStringLiteralExpr) { operation(arg0, arg1) } else { cont() } + +inline fun tryEvalStringLiteralOperation( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr, + operation: (KStringLiteralExpr, KStringLiteralExpr, KStringLiteralExpr) -> KInterpretedValue, + cont: () -> KExpr +): KExpr = if (arg0 is KStringLiteralExpr && arg1 is KStringLiteralExpr && arg2 is KStringLiteralExpr) { + operation(arg0, arg1, arg2) +} else { + cont() +} From f51ce2e4b754a9d8fc6d89e908fa0c963149e8a0 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sat, 1 Mar 2025 21:42:23 +0300 Subject: [PATCH 71/84] Implement basic simplifications for suffixOf and prefixOf expressions --- .../rewrite/simplify/StringSimplification.kt | 4 +-- .../simplify/StringSimplificationRules.kt | 29 +++++++++++++++++++ .../main/kotlin/io/ksmt/utils/StringUtils.kt | 12 ++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt index ba669db35..0f3e0c8fe 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt @@ -30,12 +30,12 @@ fun KContext.simplifyStringInRegex( fun KContext.simplifyStringSuffixOf( arg0: KExpr, arg1: KExpr -): KExpr = mkStringSuffixOfNoSimplify(arg0, arg1) // Temporarily +): KExpr = simplifyStringBasicSuffixOfExpr(arg0, arg1, ::mkStringSuffixOfNoSimplify) fun KContext.simplifyStringPrefixOf( arg0: KExpr, arg1: KExpr -): KExpr = mkStringPrefixOfNoSimplify(arg0, arg1) // Temporarily +): KExpr = simplifyStringBasicPrefixOfExpr(arg0, arg1, ::mkStringPrefixOfNoSimplify) fun KContext.simplifyStringLt( arg0: KExpr, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt index e47ef5506..698837722 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -5,6 +5,7 @@ import io.ksmt.expr.KExpr import io.ksmt.expr.KInterpretedValue import io.ksmt.expr.KStringConcatExpr import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.sort.KBoolSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KSort import io.ksmt.sort.KStringSort @@ -70,6 +71,8 @@ inline fun KContext.simplifyStringNestedConcat( * String length expression simplification * */ +/** + * Eval length of string constant. */ inline fun KContext.simplifyStringLenExpr( arg: KExpr, cont: (KExpr) -> KExpr @@ -80,6 +83,32 @@ inline fun KContext.simplifyStringLenExpr( cont(arg) } +/* +* SuffixOf and PrefixOf expression simplifications +* */ + +/** Simplifies string suffix checking expressions + * (str_suffix_of strConst1 strConst2) ==> boolConst */ +inline fun KContext.simplifyStringBasicSuffixOfExpr( + arg0: KExpr, + arg1: KExpr, + cont: (KExpr, KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg0, arg1, { a0, a1 -> StringUtils.isStringSuffix(a0, a1) }) { + cont(arg0, arg1) + } + +/** Simplifies string prefix checking expressions + * (str_prefix_of strConst1 strConst2) ==> boolConst */ +inline fun KContext.simplifyStringBasicPrefixOfExpr( + arg0: KExpr, + arg1: KExpr, + cont: (KExpr, KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg0, arg1, { a0, a1 -> StringUtils.isStringPrefix(a0, a1) }) { + cont(arg0, arg1) + } + inline fun tryEvalStringLiteralOperation( arg: KExpr, operation: (KStringLiteralExpr) -> KInterpretedValue, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt index cfce56380..430f4670b 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt @@ -1,6 +1,8 @@ package io.ksmt.utils +import io.ksmt.expr.KInterpretedValue import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.sort.KBoolSort object StringUtils { @@ -8,4 +10,14 @@ object StringUtils { fun concatStrings(lhs: KStringLiteralExpr, rhs: KStringLiteralExpr): KStringLiteralExpr = with (lhs.ctx) { mkStringLiteral(lhs.value + rhs.value) } + + @JvmStatic + fun isStringSuffix(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + mkBool(arg1.value.endsWith(arg0.value)).uncheckedCast() + } + + @JvmStatic + fun isStringPrefix(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + mkBool(arg1.value.startsWith(arg0.value)).uncheckedCast() + } } From cdd24fe84047a763dd2dbadb4e9b867366ebf713 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sat, 1 Mar 2025 21:54:29 +0300 Subject: [PATCH 72/84] Implement basic simplifications for string comparison expr --- .../rewrite/simplify/StringSimplification.kt | 8 ++-- .../simplify/StringSimplificationRules.kt | 48 +++++++++++++++++++ .../main/kotlin/io/ksmt/utils/StringUtils.kt | 20 ++++++++ 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt index 0f3e0c8fe..c74ac846c 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt @@ -40,22 +40,22 @@ fun KContext.simplifyStringPrefixOf( fun KContext.simplifyStringLt( arg0: KExpr, arg1: KExpr -): KExpr = mkStringLtNoSimplify(arg0, arg1) // Temporarily +): KExpr = simplifyStringBasicLtExpr(arg0, arg1, ::mkStringLtNoSimplify) fun KContext.simplifyStringLe( arg0: KExpr, arg1: KExpr -): KExpr = mkStringLeNoSimplify(arg0, arg1) // Temporarily +): KExpr = simplifyStringBasicLeExpr(arg0, arg1, ::mkStringLeNoSimplify) fun KContext.simplifyStringGt( arg0: KExpr, arg1: KExpr -): KExpr = mkStringGtNoSimplify(arg0, arg1) // Temporarily +): KExpr = simplifyStringBasicGtExpr(arg0, arg1, ::mkStringGtNoSimplify) fun KContext.simplifyStringGe( arg0: KExpr, arg1: KExpr -): KExpr = mkStringGeNoSimplify(arg0, arg1) // Temporarily +): KExpr = simplifyStringBasicGeExpr(arg0, arg1, ::mkStringGeNoSimplify) fun KContext.simplifyStringContains( arg0: KExpr, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt index 698837722..c2fb9a96a 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -109,6 +109,54 @@ inline fun KContext.simplifyStringBasicPrefixOfExpr( cont(arg0, arg1) } +/* +* String comparison expression simplifications +* */ + +/** Simplifies string "less than" comparison expressions + * (str_lt strConst1 strConst2) ==> boolConst */ +inline fun KContext.simplifyStringBasicLtExpr( + arg0: KExpr, + arg1: KExpr, + cont: (KExpr, KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg0, arg1, { a0, a1 -> StringUtils.stringLt(a0, a1) }) { + cont(arg0, arg1) + } + +/** Simplifies string "less than or equal" comparison expressions + * (str_le strConst1 strConst2) ==> boolConst */ +inline fun KContext.simplifyStringBasicLeExpr( + arg0: KExpr, + arg1: KExpr, + cont: (KExpr, KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg0, arg1, { a0, a1 -> StringUtils.stringLe(a0, a1) }) { + cont(arg0, arg1) + } + +/** Simplifies string "greater than" comparison expressions + * (str_gt strConst1 strConst2) ==> boolConst */ +inline fun KContext.simplifyStringBasicGtExpr( + arg0: KExpr, + arg1: KExpr, + cont: (KExpr, KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg0, arg1, { a0, a1 -> StringUtils.stringGt(a0, a1) }) { + cont(arg0, arg1) + } + +/** Simplifies string "greater than or equal" comparison expressions + * (str_ge strConst1 strConst2) ==> boolConst */ +inline fun KContext.simplifyStringBasicGeExpr( + arg0: KExpr, + arg1: KExpr, + cont: (KExpr, KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg0, arg1, { a0, a1 -> StringUtils.stringGe(a0, a1) }) { + cont(arg0, arg1) + } + inline fun tryEvalStringLiteralOperation( arg: KExpr, operation: (KStringLiteralExpr) -> KInterpretedValue, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt index 430f4670b..bac9d5bf2 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt @@ -20,4 +20,24 @@ object StringUtils { fun isStringPrefix(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { mkBool(arg1.value.startsWith(arg0.value)).uncheckedCast() } + + @JvmStatic + fun stringLt(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + mkBool(arg0.value < arg1.value).uncheckedCast() + } + + @JvmStatic + fun stringLe(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + mkBool(arg0.value <= arg1.value).uncheckedCast() + } + + @JvmStatic + fun stringGt(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + mkBool(arg0.value > arg1.value).uncheckedCast() + } + + @JvmStatic + fun stringGe(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + mkBool(arg0.value >= arg1.value).uncheckedCast() + } } From c98613abc4202703b9412b46dfadda48ecba10c8 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Sat, 1 Mar 2025 22:49:51 +0300 Subject: [PATCH 73/84] Implement simplifiers for contains, toLower, toUpper, reverse operations --- .../rewrite/simplify/StringSimplification.kt | 8 +-- .../simplify/StringSimplificationRules.kt | 55 +++++++++++++++++-- .../main/kotlin/io/ksmt/utils/StringUtils.kt | 30 ++++++++++ 3 files changed, 83 insertions(+), 10 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt index c74ac846c..9423aa4df 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt @@ -60,7 +60,7 @@ fun KContext.simplifyStringGe( fun KContext.simplifyStringContains( arg0: KExpr, arg1: KExpr -): KExpr = mkStringContainsNoSimplify(arg0, arg1) // Temporarily +): KExpr = simplifyStringBasicContainsExpr(arg0, arg1, ::mkStringContainsNoSimplify) fun KContext.simplifyStringSingletonSub( arg0: KExpr, @@ -111,15 +111,15 @@ fun KContext.simplifyStringReplaceAllWithRegex( fun KContext.simplifyStringToLower( arg: KExpr -): KExpr = mkStringToLowerNoSimplify(arg) // Temporarily +): KExpr = simplifyStringBasicToLowerExpr(arg, ::mkStringToLowerNoSimplify) fun KContext.simplifyStringToUpper( arg: KExpr -): KExpr = mkStringToUpperNoSimplify(arg) // Temporarily +): KExpr = simplifyStringBasicToUpperExpr(arg, ::mkStringToUpperNoSimplify) fun KContext.simplifyStringReverse( arg: KExpr -): KExpr = mkStringReverseNoSimplify(arg) // Temporarily +): KExpr = simplifyStringBasicReverseExpr(arg, ::mkStringReverseNoSimplify) fun KContext.simplifyStringIsDigit( arg: KExpr diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt index c2fb9a96a..4878ae1f0 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -1,10 +1,7 @@ package io.ksmt.expr.rewrite.simplify import io.ksmt.KContext -import io.ksmt.expr.KExpr -import io.ksmt.expr.KInterpretedValue -import io.ksmt.expr.KStringConcatExpr -import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.* import io.ksmt.sort.KBoolSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KSort @@ -77,8 +74,8 @@ inline fun KContext.simplifyStringLenExpr( arg: KExpr, cont: (KExpr) -> KExpr ): KExpr = - tryEvalStringLiteralOperation(arg, { literalArg -> - mkIntNum(literalArg.value.length) + tryEvalStringLiteralOperation(arg, { + a -> StringUtils.getStringLen(a) }) { cont(arg) } @@ -157,6 +154,52 @@ inline fun KContext.simplifyStringBasicGeExpr( cont(arg0, arg1) } +/* +* String contains expression simplifications +* */ + +/** Basic simplify string contains expression + * (str_contains strConst1 strConst2) ==> boolConst */ +inline fun KContext.simplifyStringBasicContainsExpr( + arg0: KExpr, + arg1: KExpr, + cont: (KExpr, KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg0, arg1, { a0, a1 -> StringUtils.stringContains(a0, a1) }) { + cont(arg0, arg1) + } + +/* +* String to lower/upper case expression simplifications +* */ + +/** Converting all letters of a string constant to lowercase. */ +inline fun KContext.simplifyStringBasicToLowerExpr( + arg: KExpr, + cont: (KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg, { a -> StringUtils.stringToLowerCase(a) }) { + cont(arg) + } + +/** Converting all letters of a string constant to uppercase. */ +inline fun KContext.simplifyStringBasicToUpperExpr( + arg: KExpr, + cont: (KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg, { a -> StringUtils.stringToUpperCase(a) }) { + cont(arg) + } + +/** Reverses a string constant */ +inline fun KContext.simplifyStringBasicReverseExpr( + arg: KExpr, + cont: (KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg, { a -> StringUtils.stringReverse(a) }) { + cont(arg) + } + inline fun tryEvalStringLiteralOperation( arg: KExpr, operation: (KStringLiteralExpr) -> KInterpretedValue, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt index bac9d5bf2..8d610a6e7 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt @@ -1,11 +1,20 @@ package io.ksmt.utils +import io.ksmt.expr.KInt32NumExpr +import io.ksmt.expr.KInt64NumExpr +import io.ksmt.expr.KIntBigNumExpr +import io.ksmt.expr.KIntNumExpr import io.ksmt.expr.KInterpretedValue import io.ksmt.expr.KStringLiteralExpr import io.ksmt.sort.KBoolSort object StringUtils { + @JvmStatic + fun getStringLen(arg: KStringLiteralExpr): KIntNumExpr = with (arg.ctx) { + mkIntNum(arg.value.length) + } + @JvmStatic fun concatStrings(lhs: KStringLiteralExpr, rhs: KStringLiteralExpr): KStringLiteralExpr = with (lhs.ctx) { mkStringLiteral(lhs.value + rhs.value) @@ -40,4 +49,25 @@ object StringUtils { fun stringGe(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { mkBool(arg0.value >= arg1.value).uncheckedCast() } + + @JvmStatic + fun stringContains(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + mkBool(arg0.value.contains(arg1.value)).uncheckedCast() + } + + @JvmStatic + fun stringToLowerCase(arg: KStringLiteralExpr): KStringLiteralExpr = with (arg.ctx) { + mkStringLiteral(arg.value.lowercase()) + } + + @JvmStatic + fun stringToUpperCase(arg: KStringLiteralExpr): KStringLiteralExpr = with (arg.ctx) { + mkStringLiteral(arg.value.uppercase()) + } + + @JvmStatic + fun stringReverse(arg: KStringLiteralExpr): KStringLiteralExpr = with (arg.ctx) { + mkStringLiteral(arg.value.reversed()) + } + } From f5bd81b891d2cbe37dd1fcb13be1a95c74dbf26c Mon Sep 17 00:00:00 2001 From: raf-nr Date: Mon, 3 Mar 2025 13:48:11 +0300 Subject: [PATCH 74/84] Implement basic simplifications for mapping between str/int expressions --- ksmt-core/src/main/kotlin/Main.kt | 13 ++++ .../rewrite/simplify/StringSimplification.kt | 10 +-- .../simplify/StringSimplificationRules.kt | 71 ++++++++++++++++++- .../main/kotlin/io/ksmt/utils/StringUtils.kt | 45 ++++++++---- 4 files changed, 121 insertions(+), 18 deletions(-) create mode 100644 ksmt-core/src/main/kotlin/Main.kt diff --git a/ksmt-core/src/main/kotlin/Main.kt b/ksmt-core/src/main/kotlin/Main.kt new file mode 100644 index 000000000..68722266c --- /dev/null +++ b/ksmt-core/src/main/kotlin/Main.kt @@ -0,0 +1,13 @@ +import io.ksmt.KContext +import io.ksmt.utils.getValue + +fun main() { + val ctx = KContext(simplificationMode = KContext.SimplificationMode.SIMPLIFY) + with(ctx) { + println(mkStringFromInt( 2147483643337.expr)) +// val a by stringSort +// val b by stringSort +// println((a + "k".expr) + ("ok".expr + b)) +// println("aaaa".expr.len) + } +} \ No newline at end of file diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt index 9423aa4df..808a3ce5f 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt @@ -123,20 +123,20 @@ fun KContext.simplifyStringReverse( fun KContext.simplifyStringIsDigit( arg: KExpr -): KExpr = mkStringIsDigitNoSimplify(arg) // Temporarily +): KExpr = simplifyStringIsDigitExprBasic(arg, ::mkStringIsDigitNoSimplify) fun KContext.simplifyStringToCode( arg: KExpr -): KExpr = mkStringToCodeNoSimplify(arg) // Temporarily +): KExpr = simplifyStringToCodeExprBasic(arg, ::mkStringToCodeNoSimplify) fun KContext.simplifyStringFromCode( arg: KExpr -): KExpr = mkStringFromCodeNoSimplify(arg) // Temporarily +): KExpr = simplifyStringFromCodeExprBasic(arg, ::mkStringFromCodeNoSimplify) fun KContext.simplifyStringToInt( arg: KExpr -): KExpr = mkStringToIntNoSimplify(arg) // Temporarily +): KExpr = simplifyStringToIntExprBasic(arg, ::mkStringToIntNoSimplify) fun KContext.simplifyStringFromInt( arg: KExpr -): KExpr = mkStringFromIntNoSimplify(arg) // Temporarily +): KExpr = simplifyStringFromIntExprBasic(arg, ::mkStringFromIntNoSimplify) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt index 4878ae1f0..2d0f90f19 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -7,6 +7,7 @@ import io.ksmt.sort.KIntSort import io.ksmt.sort.KSort import io.ksmt.sort.KStringSort import io.ksmt.utils.StringUtils +import io.ksmt.utils.StringUtils.STRING_FROM_CODE_UPPER_BOUND /* * String concatenation simplification @@ -191,7 +192,7 @@ inline fun KContext.simplifyStringBasicToUpperExpr( cont(arg) } -/** Reverses a string constant */ +/** Reverses a string constan.t */ inline fun KContext.simplifyStringBasicReverseExpr( arg: KExpr, cont: (KExpr) -> KExpr @@ -200,6 +201,74 @@ inline fun KContext.simplifyStringBasicReverseExpr( cont(arg) } +/* +* Mapping between strings and integers simplifications +* */ + +/** Eval constants: if string literal consist of one digit - return true, otherwise false. */ +inline fun KContext.simplifyStringIsDigitExprBasic( + arg: KExpr, + cont: (KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg, { a -> StringUtils.stringIsDigit(a) }) { + cont(arg) + } + +/** Eval constants: if string literal consist of one character - return its code, otherwise return -1. */ +inline fun KContext.simplifyStringToCodeExprBasic( + arg: KExpr, + cont: (KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg, { a -> StringUtils.stringToCode(a) }) { + cont(arg) + } + +/** Eval constants: if int constant is in the range [0; STRING_FROM_CODE_UPPER_BOUND], then + * return code point of constant, otherwise return empty string. */ +inline fun KContext.simplifyStringFromCodeExprBasic( + arg: KExpr, + cont: (KExpr) -> KExpr +): KExpr { + val value = when (arg) { + is KInt32NumExpr -> arg.value.toLong() + is KInt64NumExpr -> arg.value + is KIntBigNumExpr -> arg.value.toLong() + else -> return cont(arg) + } + + return if (value in 0..STRING_FROM_CODE_UPPER_BOUND) { + mkStringLiteral(value.toInt().toChar().toString()) + } else { + mkStringLiteral("") + } +} + +/** Eval constants: if string literal consist of digits, then + * return the positive integer denoted by literal; + * otherwise, return -1. */ +inline fun KContext.simplifyStringToIntExprBasic( + arg: KExpr, + cont: (KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg, { a -> StringUtils.stringToInt(a) }) { + cont(arg) + } + +/** Eval constants: if the integer is non-negative, return its string representation; + * otherwise, return an empty string. */ +inline fun KContext.simplifyStringFromIntExprBasic( + arg: KExpr, + cont: (KExpr) -> KExpr +): KExpr { + val intValue = when (arg) { + is KInt32NumExpr -> arg.value.toLong() + is KInt64NumExpr -> arg.value + is KIntBigNumExpr -> arg.value.toLong() + else -> return cont(arg) + } + return mkStringLiteral(if (intValue >= 0) intValue.toString() else "") +} + inline fun tryEvalStringLiteralOperation( arg: KExpr, operation: (KStringLiteralExpr) -> KInterpretedValue, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt index 8d610a6e7..327d7f74c 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt @@ -7,67 +7,88 @@ import io.ksmt.expr.KIntNumExpr import io.ksmt.expr.KInterpretedValue import io.ksmt.expr.KStringLiteralExpr import io.ksmt.sort.KBoolSort +import io.ksmt.sort.KStringSort object StringUtils { + const val STRING_FROM_CODE_UPPER_BOUND: Int = 196607 + @JvmStatic - fun getStringLen(arg: KStringLiteralExpr): KIntNumExpr = with (arg.ctx) { + fun getStringLen(arg: KStringLiteralExpr): KIntNumExpr = with(arg.ctx) { mkIntNum(arg.value.length) } @JvmStatic - fun concatStrings(lhs: KStringLiteralExpr, rhs: KStringLiteralExpr): KStringLiteralExpr = with (lhs.ctx) { + fun concatStrings(lhs: KStringLiteralExpr, rhs: KStringLiteralExpr): KStringLiteralExpr = with(lhs.ctx) { mkStringLiteral(lhs.value + rhs.value) } @JvmStatic - fun isStringSuffix(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + fun isStringSuffix(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { mkBool(arg1.value.endsWith(arg0.value)).uncheckedCast() } @JvmStatic - fun isStringPrefix(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + fun isStringPrefix(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { mkBool(arg1.value.startsWith(arg0.value)).uncheckedCast() } @JvmStatic - fun stringLt(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + fun stringLt(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { mkBool(arg0.value < arg1.value).uncheckedCast() } @JvmStatic - fun stringLe(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + fun stringLe(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { mkBool(arg0.value <= arg1.value).uncheckedCast() } @JvmStatic - fun stringGt(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + fun stringGt(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { mkBool(arg0.value > arg1.value).uncheckedCast() } @JvmStatic - fun stringGe(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + fun stringGe(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { mkBool(arg0.value >= arg1.value).uncheckedCast() } @JvmStatic - fun stringContains(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with (arg0.ctx) { + fun stringContains(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { mkBool(arg0.value.contains(arg1.value)).uncheckedCast() } @JvmStatic - fun stringToLowerCase(arg: KStringLiteralExpr): KStringLiteralExpr = with (arg.ctx) { + fun stringToLowerCase(arg: KStringLiteralExpr): KStringLiteralExpr = with(arg.ctx) { mkStringLiteral(arg.value.lowercase()) } @JvmStatic - fun stringToUpperCase(arg: KStringLiteralExpr): KStringLiteralExpr = with (arg.ctx) { + fun stringToUpperCase(arg: KStringLiteralExpr): KStringLiteralExpr = with(arg.ctx) { mkStringLiteral(arg.value.uppercase()) } @JvmStatic - fun stringReverse(arg: KStringLiteralExpr): KStringLiteralExpr = with (arg.ctx) { + fun stringReverse(arg: KStringLiteralExpr): KStringLiteralExpr = with(arg.ctx) { mkStringLiteral(arg.value.reversed()) } + @JvmStatic + fun stringIsDigit(arg: KStringLiteralExpr): KInterpretedValue = with(arg.ctx) { + mkBool(arg.value.length == 1 && arg.value[0].isDigit()).uncheckedCast() + } + + @JvmStatic + fun stringToCode(arg: KStringLiteralExpr): KIntNumExpr = with(arg.ctx) { + mkIntNum(arg.value.singleOrNull()?.code ?: -1) + } + + @JvmStatic + fun stringToInt(arg: KStringLiteralExpr): KIntNumExpr = with(arg.ctx) { + return if (arg.value.isNotEmpty() && arg.value.all { it.isDigit() }) { + mkIntNum(arg.value.toLongOrNull() ?: -1) + } else { + mkIntNum(-1) + } + } } From f5640e39de7c5c387024d6c996d4a81d245ada96 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Mon, 3 Mar 2025 19:24:22 +0300 Subject: [PATCH 75/84] Implement simplifications for replace string expressions --- ksmt-core/src/main/kotlin/Main.kt | 13 ---------- .../rewrite/simplify/StringSimplification.kt | 4 ++-- .../simplify/StringSimplificationRules.kt | 24 +++++++++++++++++++ .../main/kotlin/io/ksmt/utils/StringUtils.kt | 16 +++++++++++++ 4 files changed, 42 insertions(+), 15 deletions(-) delete mode 100644 ksmt-core/src/main/kotlin/Main.kt diff --git a/ksmt-core/src/main/kotlin/Main.kt b/ksmt-core/src/main/kotlin/Main.kt deleted file mode 100644 index 68722266c..000000000 --- a/ksmt-core/src/main/kotlin/Main.kt +++ /dev/null @@ -1,13 +0,0 @@ -import io.ksmt.KContext -import io.ksmt.utils.getValue - -fun main() { - val ctx = KContext(simplificationMode = KContext.SimplificationMode.SIMPLIFY) - with(ctx) { - println(mkStringFromInt( 2147483643337.expr)) -// val a by stringSort -// val b by stringSort -// println((a + "k".expr) + ("ok".expr + b)) -// println("aaaa".expr.len) - } -} \ No newline at end of file diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt index 808a3ce5f..13b98d55e 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt @@ -89,13 +89,13 @@ fun KContext.simplifyStringReplace( arg0: KExpr, arg1: KExpr, arg2: KExpr -): KExpr = mkStringReplaceNoSimplify(arg0, arg1, arg2) // Temporarily +): KExpr = simplifyStringReplaceExprBasic(arg0, arg1, arg2, ::mkStringReplaceNoSimplify) fun KContext.simplifyStringReplaceAll( arg0: KExpr, arg1: KExpr, arg2: KExpr -): KExpr = mkStringReplaceAllNoSimplify(arg0, arg1, arg2) // Temporarily +): KExpr = simplifyStringReplaceAllExprBasic(arg0, arg1, arg2, ::mkStringReplaceAllNoSimplify) fun KContext.simplifyStringReplaceWithRegex( arg0: KExpr, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt index 2d0f90f19..e0d172267 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -170,6 +170,30 @@ inline fun KContext.simplifyStringBasicContainsExpr( cont(arg0, arg1) } +/* +* String replace expressions simplifications +* */ + +inline fun KContext.simplifyStringReplaceExprBasic( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr, + cont: (KExpr, KExpr, KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg0, arg1, arg2, { a0, a1, a2 -> StringUtils.strintReplace(a0, a1, a2) }) { + cont(arg0, arg1, arg2) + } + +inline fun KContext.simplifyStringReplaceAllExprBasic( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr, + cont: (KExpr, KExpr, KExpr) -> KExpr +): KExpr = + tryEvalStringLiteralOperation(arg0, arg1, arg2, { a0, a1, a2 -> StringUtils.strintReplaceAll(a0, a1, a2) }) { + cont(arg0, arg1, arg2) + } + /* * String to lower/upper case expression simplifications * */ diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt index 327d7f74c..fd0a02116 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt @@ -91,4 +91,20 @@ object StringUtils { mkIntNum(-1) } } + + @JvmStatic + fun strintReplace(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr, arg2: KStringLiteralExpr): KStringLiteralExpr = with(arg0.ctx) { + val str = arg0.value + val search = arg1.value + val replace = arg2.value + return mkStringLiteral(if (search.isEmpty()) (replace + str) else str.replaceFirst(search, replace)) + } + + @JvmStatic + fun strintReplaceAll(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr, arg2: KStringLiteralExpr): KStringLiteralExpr = with(arg0.ctx) { + val str = arg0.value + val search = arg1.value + val replace = arg2.value + return mkStringLiteral(if (search.isEmpty()) str else str.replace(search, replace)) + } } From 55a64347cd1d775b37877ead6dbacbd8e0f13dd8 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Mon, 3 Mar 2025 20:35:13 +0300 Subject: [PATCH 76/84] Implement basic simplifications for substring expressions --- .../rewrite/simplify/StringSimplification.kt | 6 +- .../simplify/StringSimplificationRules.kt | 91 +++++++++++++++++++ 2 files changed, 94 insertions(+), 3 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt index 13b98d55e..b458a122f 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt @@ -65,19 +65,19 @@ fun KContext.simplifyStringContains( fun KContext.simplifyStringSingletonSub( arg0: KExpr, arg1: KExpr -): KExpr = mkStringSingletonSubNoSimplify(arg0, arg1) // Temporarily +): KExpr = simplifyStringSingletonSubExprBasic(arg0, arg1, ::mkStringSingletonSubNoSimplify) fun KContext.simplifyStringSub( arg0: KExpr, arg1: KExpr, arg2: KExpr -): KExpr = mkStringSubNoSimplify(arg0, arg1, arg2) // Temporarily +): KExpr = simplifyStringSubExprBasic(arg0, arg1, arg2, ::mkStringSubNoSimplify) fun KContext.simplifyStringIndexOf( arg0: KExpr, arg1: KExpr, arg2: KExpr -): KExpr = mkStringIndexOfNoSimplify(arg0, arg1, arg2) // Temporarily +): KExpr = simplifyStringIndexOfExprBasic(arg0, arg1, arg2, ::mkStringIndexOfNoSimplify) fun KContext.simplifyStringIndexOfRegex( arg0: KExpr, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt index e0d172267..2aa68a9b5 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -170,6 +170,90 @@ inline fun KContext.simplifyStringBasicContainsExpr( cont(arg0, arg1) } +/* +* Substring expressions simplifications +* */ + +inline fun KContext.simplifyStringSingletonSubExprBasic( + arg0: KExpr, + arg1: KExpr, + cont: (KExpr, KExpr) -> KExpr +): KExpr { + return if (arg0 is KStringLiteralExpr && arg1 is KIntNumExpr) { + val str = arg0.value + val pos = when (arg1) { + is KInt32NumExpr -> arg1.value.toLong() + is KInt64NumExpr -> arg1.value + is KIntBigNumExpr -> arg1.value.toLong() + else -> return cont(arg0, arg1) + } + val result = if (pos <= Int.MAX_VALUE && pos >= 0 && pos < str.length) { + str[pos.toInt()].toString() + } else { + "" + } + mkStringLiteral(result) + } else { + cont(arg0, arg1) + } +} + +inline fun KContext.simplifyStringSubExprBasic( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr, + cont: (KExpr, KExpr, KExpr) -> KExpr +): KExpr { + return if (arg0 is KStringLiteralExpr && arg1 is KIntNumExpr && arg2 is KIntNumExpr) { + val str = arg0.value + val startPos = arg1.toLongValue() + val length = arg2.toLongValue() + val result = if (startPos in 0..Int.MAX_VALUE && length in 0..Int.MAX_VALUE && startPos < str.length) { + val endPos = minOf(startPos + length, str.length.toLong()).toInt() + str.substring(startPos.toInt(), endPos) + } else { + "" + } + mkStringLiteral(result) + } else { + cont(arg0, arg1, arg2) + } +} + +inline fun KContext.simplifyStringIndexOfExprBasic( + arg0: KExpr, // Исходная строка (s) + arg1: KExpr, // Подстрока для поиска (t) + arg2: KExpr, // Начальная позиция (i) + cont: (KExpr, KExpr, KExpr) -> KExpr +): KExpr = with(arg0.ctx) { + + if (arg0 is KStringLiteralExpr && arg1 is KStringLiteralExpr && arg2 is KIntNumExpr) { + val str = arg0.value + val search = arg1.value + val startPosLong = arg2.toLongValue() + val startPos: Int + if (startPosLong <= Int.MAX_VALUE) { + startPos = startPosLong.toInt() + } else { + return cont(arg0, arg1, arg2) + } + + val result = if (startPos >= 0 && startPos <= str.length) { + if (search.isEmpty()) { + startPos + } else { + val index = str.indexOf(search, startPos) + if (index >= 0) index else -1 + } + } else { + -1 + } + return mkIntNum(result) + } else { + return cont(arg0, arg1, arg2) + } +} + /* * String replace expressions simplifications * */ @@ -325,3 +409,10 @@ inline fun tryEvalStringLiteralOperation( } else { cont() } + +fun KIntNumExpr.toLongValue(): Long = when (this) { + is KInt32NumExpr -> value.toLong() + is KInt64NumExpr -> value + is KIntBigNumExpr -> value.toLong() + else -> throw IllegalArgumentException("Unsupported KIntNumExpr type: ${this::class}") +} From b93aad94cc9bb3dc10fc1c34c43e877d52be7f44 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Mon, 3 Mar 2025 20:37:42 +0300 Subject: [PATCH 77/84] Add comments --- .../expr/rewrite/simplify/StringSimplificationRules.kt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt index 2aa68a9b5..e3e30582d 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -174,6 +174,7 @@ inline fun KContext.simplifyStringBasicContainsExpr( * Substring expressions simplifications * */ +/** Eval constants. */ inline fun KContext.simplifyStringSingletonSubExprBasic( arg0: KExpr, arg1: KExpr, @@ -198,6 +199,7 @@ inline fun KContext.simplifyStringSingletonSubExprBasic( } } +/** Eval constants. */ inline fun KContext.simplifyStringSubExprBasic( arg0: KExpr, arg1: KExpr, @@ -220,10 +222,11 @@ inline fun KContext.simplifyStringSubExprBasic( } } +/** Eval constants. */ inline fun KContext.simplifyStringIndexOfExprBasic( - arg0: KExpr, // Исходная строка (s) - arg1: KExpr, // Подстрока для поиска (t) - arg2: KExpr, // Начальная позиция (i) + arg0: KExpr, + arg1: KExpr, + arg2: KExpr, cont: (KExpr, KExpr, KExpr) -> KExpr ): KExpr = with(arg0.ctx) { From 6bb5cdb90827b0860b2fec5d946cc317b0b47b6f Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 5 Mar 2025 22:59:31 +0300 Subject: [PATCH 78/84] Format code --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 216 +++++++++++++----- .../simplify/StringSimplificationRules.kt | 10 +- .../transformer/KNonRecursiveTransformer.kt | 1 + .../main/kotlin/io/ksmt/utils/StringUtils.kt | 76 ++++-- .../ksmt/runner/serializer/ExprKindMapper.kt | 12 +- 5 files changed, 238 insertions(+), 77 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index d91da1743..bf99444d3 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -2034,7 +2034,7 @@ open class KContext( * Create String concatenation (`concat`) expression. * */ open fun mkStringConcat(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::simplifyStringConcat, ::mkStringConcatNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyStringConcat, ::mkStringConcatNoSimplify) /** * Create String concatenation (`concat`) expression. @@ -2057,7 +2057,7 @@ open class KContext( * Create string's length expression. * */ open fun mkStringLen(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyStringLen, ::mkStringLenNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringLen, ::mkStringLenNoSimplify) /** * Create string's length expression. @@ -2078,8 +2078,11 @@ open class KContext( /** * Check if first string is a suffix of second. * */ - open fun mkStringSuffixOf(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::simplifyStringSuffixOf, ::mkStringSuffixOfNoSimplify) // Add simplified version + open fun mkStringSuffixOf( + arg0: KExpr, + arg1: KExpr + ): KExpr = + mkSimplified(arg0, arg1, KContext::simplifyStringSuffixOf, ::mkStringSuffixOfNoSimplify) /** * Check if first string is a suffix of second. @@ -2097,8 +2100,11 @@ open class KContext( /** * Check if first string is a prefix of second. * */ - open fun mkStringPrefixOf(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::simplifyStringPrefixOf, ::mkStringPrefixOfNoSimplify) // Add simplified version + open fun mkStringPrefixOf( + arg0: KExpr, + arg1: KExpr + ): KExpr = + mkSimplified(arg0, arg1, KContext::simplifyStringPrefixOf, ::mkStringPrefixOfNoSimplify) /** * Check if first string is a prefix of second. @@ -2117,7 +2123,7 @@ open class KContext( * Create a lexicographic ordering (`<` (less)) expression. * */ open fun mkStringLt(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::simplifyStringLt, ::mkStringLtNoSimplify) // Add simplified version + mkSimplified(lhs, rhs, KContext::simplifyStringLt, ::mkStringLtNoSimplify) /** * Create a lexicographic ordering (`<` (less)) expression. @@ -2137,7 +2143,7 @@ open class KContext( * Create a lexicographic ordering reflexive closure (`<=` (less or equal)) expression. * */ open fun mkStringLe(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::simplifyStringLe, ::mkStringLeNoSimplify) // Add simplified version + mkSimplified(lhs, rhs, KContext::simplifyStringLe, ::mkStringLeNoSimplify) /** * Create a lexicographic ordering reflexive closure (`<=` (less or equal)) expression. @@ -2157,7 +2163,7 @@ open class KContext( * Create a lexicographic ordering (`>` (greater)) expression. * */ open fun mkStringGt(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::simplifyStringGt, ::mkStringGtNoSimplify) // Add simplified version + mkSimplified(lhs, rhs, KContext::simplifyStringGt, ::mkStringGtNoSimplify) /** * Create a lexicographic ordering (`>` (greater)) expression. @@ -2177,7 +2183,7 @@ open class KContext( * Create a lexicographic ordering reflexive closure (`>=` (greater or equal)) expression. * */ open fun mkStringGe(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::simplifyStringGe, ::mkStringGeNoSimplify) // Add simplified version + mkSimplified(lhs, rhs, KContext::simplifyStringGe, ::mkStringGeNoSimplify) /** * Create a lexicographic ordering reflexive closure (`>=` (greater or equal)) expression. @@ -2197,7 +2203,7 @@ open class KContext( * Check if first string contains second one. * */ open fun mkStringContains(lhs: KExpr, rhs: KExpr): KExpr = - mkSimplified(lhs, rhs, KContext::simplifyStringContains, ::mkStringContainsNoSimplify) // Add simplified version + mkSimplified(lhs, rhs, KContext::simplifyStringContains, ::mkStringContainsNoSimplify) /** * Check if first string contains second one. @@ -2217,8 +2223,16 @@ open class KContext( * Returns singleton string containing a character at given position. * If position is out of range (less than 0, or grater than (string length - 1)), then returns empty string. * */ - open fun mkStringSingletonSub(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::simplifyStringSingletonSub, ::mkStringSingletonSubNoSimplify) // Add simplified version + open fun mkStringSingletonSub( + arg0: KExpr, + arg1: KExpr + ): KExpr = + mkSimplified( + arg0, + arg1, + KContext::simplifyStringSingletonSub, + ::mkStringSingletonSubNoSimplify + ) /** * Returns singleton string containing a character at given position. @@ -2238,14 +2252,18 @@ open class KContext( * or the given position is out of bounds. */ open fun mkStringSub(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::simplifyStringSub, ::mkStringSubNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, arg2, KContext::simplifyStringSub, ::mkStringSubNoSimplify) /** * Evaluates the longest substring from the input string, starting at the specified position * and extending up to the given length. Returns an empty string if the given length is negative * or the given position is out of bounds. */ - open fun mkStringSubNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringSubExpr = + open fun mkStringSubNoSimplify( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KStringSubExpr = stringSubCache.createIfContextActive { ensureContextMatch(arg0, arg1) KStringSubExpr(this, arg0, arg1, arg2) @@ -2259,8 +2277,18 @@ open class KContext( * or if the position is out of bounds. * Returns the position if the second string is empty. */ - open fun mkStringIndexOf(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::simplifyStringIndexOf, ::mkStringIndexOfNoSimplify) // Add simplified version + open fun mkStringIndexOf( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KExpr = + mkSimplified( + arg0, + arg1, + arg2, + KContext::simplifyStringIndexOf, + ::mkStringIndexOfNoSimplify + ) /** * Find the index of the first occurrence of the second string in the first string, @@ -2268,7 +2296,11 @@ open class KContext( * or if the position is out of bounds. * Returns the position if the second string is empty. */ - open fun mkStringIndexOfNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringIndexOfExpr = + open fun mkStringIndexOfNoSimplify( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KStringIndexOfExpr = stringIndexOfCache.createIfContextActive { ensureContextMatch(arg0, arg1) KStringIndexOfExpr(this, arg0, arg1, arg2) @@ -2281,15 +2313,23 @@ open class KContext( * starting at the specified position. Returns -1 if not found * or if the position is out of bounds. */ - open fun mkStringIndexOfRegex(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::simplifyStringIndexOfRegex, ::mkStringIndexOfRegexNoSimplify) // Add simplified version + open fun mkStringIndexOfRegex( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KExpr = + mkSimplified(arg0, arg1, arg2, KContext::simplifyStringIndexOfRegex, ::mkStringIndexOfRegexNoSimplify) /** * Find the index of the first match of a regular expression in the string, * starting at the specified position. Returns -1 if not found * or if the position is out of bounds. */ - open fun mkStringIndexOfRegexNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringIndexOfRegexExpr = + open fun mkStringIndexOfRegexNoSimplify( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KStringIndexOfRegexExpr = stringIndexOfRegexCache.createIfContextActive { ensureContextMatch(arg0, arg1) KStringIndexOfRegexExpr(this, arg0, arg1, arg2) @@ -2302,15 +2342,29 @@ open class KContext( * if there are such occurrences, otherwise return the first string. * If the second line is empty, then the third is inserted at the beginning of the first. * */ - open fun mkStringReplace(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::simplifyStringReplace, ::mkStringReplaceNoSimplify) // Add simplified version + open fun mkStringReplace( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KExpr = + mkSimplified( + arg0, + arg1, + arg2, + KContext::simplifyStringReplace, + ::mkStringReplaceNoSimplify + ) /** * Replace the first occurrence of the second string in the first string with the third, * if there are such occurrences, otherwise return the first string. * If the second line is empty, then the third is inserted at the beginning of the first. * */ - open fun mkStringReplaceNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringReplaceExpr = + open fun mkStringReplaceNoSimplify( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KStringReplaceExpr = stringReplaceCache.createIfContextActive { ensureContextMatch(arg0, arg1, arg2) KStringReplaceExpr(this, arg0, arg1, arg2) @@ -2322,14 +2376,28 @@ open class KContext( * Replace the all occurrences of the second string in the first string with the third, * if there are such occurrences, otherwise return the first string. * */ - open fun mkStringReplaceAll(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::simplifyStringReplaceAll, ::mkStringReplaceAllNoSimplify) // Add simplified version + open fun mkStringReplaceAll( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KExpr = + mkSimplified( + arg0, + arg1, + arg2, + KContext::simplifyStringReplaceAll, + ::mkStringReplaceAllNoSimplify + ) /** * Replace the all occurrences of the second string in the first string with the third, * if there are such occurrences, otherwise return the first string. * */ - open fun mkStringReplaceAllNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringReplaceAllExpr = + open fun mkStringReplaceAllNoSimplify( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KStringReplaceAllExpr = stringReplaceAllCache.createIfContextActive { ensureContextMatch(arg0, arg1, arg2) KStringReplaceAllExpr(this, arg0, arg1, arg2) @@ -2341,14 +2409,28 @@ open class KContext( * Replace the shortest leftmost match of regex in first string, if any, by second string. * If the language of r contains the empty string, the result is to prepend second string to first one. * */ - open fun mkStringReplaceWithRegex(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::simplifyStringReplaceWithRegex, ::mkStringReplaceWithRegexNoSimplify) // Add simplified version + open fun mkStringReplaceWithRegex( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KExpr = + mkSimplified( + arg0, + arg1, + arg2, + KContext::simplifyStringReplaceWithRegex, + ::mkStringReplaceWithRegexNoSimplify + ) /** * Replace the shortest leftmost match of regex in first string, if any, by second string. * If the language of r contains the empty string, the result is to prepend second string to first one. * */ - open fun mkStringReplaceWithRegexNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringReplaceWithRegexExpr = + open fun mkStringReplaceWithRegexNoSimplify( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KStringReplaceWithRegexExpr = stringReplaceWithRegexCache.createIfContextActive { ensureContextMatch(arg0, arg1, arg2) KStringReplaceWithRegexExpr(this, arg0, arg1, arg2) @@ -2359,13 +2441,27 @@ open class KContext( /** * Replace left-to right, each shortest non-empty match of regex in first string by seconds. * */ - open fun mkStringReplaceAllWithRegex(arg0: KExpr, arg1: KExpr, arg2: KExpr): KExpr = - mkSimplified(arg0, arg1, arg2, KContext::simplifyStringReplaceAllWithRegex, ::mkStringReplaceAllWithRegexNoSimplify) // Add simplified version + open fun mkStringReplaceAllWithRegex( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KExpr = + mkSimplified( + arg0, + arg1, + arg2, + KContext::simplifyStringReplaceAllWithRegex, + ::mkStringReplaceAllWithRegexNoSimplify + ) /** * Replace left-to right, each shortest non-empty match of regex in first string by seconds. * */ - open fun mkStringReplaceAllWithRegexNoSimplify(arg0: KExpr, arg1: KExpr, arg2: KExpr): KStringReplaceAllWithRegexExpr = + open fun mkStringReplaceAllWithRegexNoSimplify( + arg0: KExpr, + arg1: KExpr, + arg2: KExpr + ): KStringReplaceAllWithRegexExpr = stringReplaceAllWithRegexCache.createIfContextActive { ensureContextMatch(arg0, arg1, arg2) KStringReplaceAllWithRegexExpr(this, arg0, arg1, arg2) @@ -2377,7 +2473,7 @@ open class KContext( * Convert string to lower case. * */ open fun mkStringToLower(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyStringToLower, ::mkStringToLowerNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringToLower, ::mkStringToLowerNoSimplify) /** * Convert string to lower case. @@ -2394,7 +2490,7 @@ open class KContext( * Convert string to upper case. * */ open fun mkStringToUpper(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyStringToUpper, ::mkStringToUpperNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringToUpper, ::mkStringToUpperNoSimplify) /** * Convert string to upper case. @@ -2411,7 +2507,7 @@ open class KContext( * Reverse string. * */ open fun mkStringReverse(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyStringReverse, ::mkStringReverseNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringReverse, ::mkStringReverseNoSimplify) /** * Reverse string. @@ -2428,7 +2524,7 @@ open class KContext( * Check that the string contains only decimal digit characters. * */ open fun mkStringIsDigit(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyStringIsDigit, ::mkStringIsDigitNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringIsDigit, ::mkStringIsDigitNoSimplify) /** * Check that the string contains only decimal digit characters. @@ -2446,7 +2542,7 @@ open class KContext( * Otherwise, returns -1. * */ open fun mkStringToCode(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyStringToCode, ::mkStringToCodeNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringToCode, ::mkStringToCodeNoSimplify) /** * Returns the code point of the only character in the string if the string is a singleton. @@ -2465,7 +2561,7 @@ open class KContext( * If codepoint not in range [0, 196607], returns empty string. * */ open fun mkStringFromCode(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyStringFromCode, ::mkStringFromCodeNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringFromCode, ::mkStringFromCodeNoSimplify) /** * Returns a singleton string consisting of a character, with the given code point. @@ -2484,7 +2580,7 @@ open class KContext( * Otherwise, if the string contains a character that is not a decimal number, then returns -1. * */ open fun mkStringToInt(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyStringToInt, ::mkStringToIntNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringToInt, ::mkStringToIntNoSimplify) /** * Converts a string containing only decimal digits to a positive integer. @@ -2503,7 +2599,7 @@ open class KContext( * If the number is negative, it returns an empty string. * */ open fun mkStringFromInt(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyStringFromInt, ::mkStringFromIntNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringFromInt, ::mkStringFromIntNoSimplify) /** * Converts a positive integer to a string consisting of the decimal digits of that number, with no leading zeros. @@ -2521,12 +2617,14 @@ open class KContext( * Create a regular expression based on a string expression. * */ open fun mkStringToRegex(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyStringToRegex, ::mkStringToRegexNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyStringToRegex, ::mkStringToRegexNoSimplify) /** * Create a regular expression based on a string expression. * */ - open fun mkStringToRegexNoSimplify(arg: KExpr): KStringToRegexExpr = stringToRegexExprCache.createIfContextActive { + open fun mkStringToRegexNoSimplify( + arg: KExpr + ): KStringToRegexExpr = stringToRegexExprCache.createIfContextActive { ensureContextMatch(arg) KStringToRegexExpr(this, arg) } @@ -2541,7 +2639,7 @@ open class KContext( * Check if a string belongs to the language defined by the regular expression. * */ open fun mkStringInRegex(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::simplifyStringInRegex, ::mkStringInRegexNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyStringInRegex, ::mkStringInRegexNoSimplify) /** * Check if a string belongs to the language defined by the regular expression. @@ -2565,7 +2663,7 @@ open class KContext( * Create Regex concatenation (`concat`) expression. * */ open fun mkRegexConcat(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::simplifyRegexConcat, ::mkRegexConcatNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyRegexConcat, ::mkRegexConcatNoSimplify) /** * Create Regex concatenation (`concat`) expression. @@ -2585,7 +2683,7 @@ open class KContext( * Create Regex union (`union`) expression. * */ open fun mkRegexUnion(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::simplifyRegexUnion, ::mkRegexUnionNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyRegexUnion, ::mkRegexUnionNoSimplify) /** * Create Regex union (`union`) expression. @@ -2602,7 +2700,7 @@ open class KContext( * Create Regex intersection (`intersect`) expression. * */ open fun mkRegexIntersection(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::simplifyRegexIntersection, ::mkRegexIntersectionNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyRegexIntersection, ::mkRegexIntersectionNoSimplify) /** * Create Regex intersection (`intersect`) expression. @@ -2619,7 +2717,7 @@ open class KContext( * Create regular expression's Kleene closure. * */ open fun mkRegexStar(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyRegexStar, ::mkRegexStarNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyRegexStar, ::mkRegexStarNoSimplify) /** * Create regular expression's Kleene closure. @@ -2636,7 +2734,7 @@ open class KContext( * Create regular expression's Kleene cross. * */ open fun mkRegexCross(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyRegexCross, ::mkRegexCrossNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyRegexCross, ::mkRegexCrossNoSimplify) /** * Create regular expression's Kleene cross. @@ -2653,7 +2751,7 @@ open class KContext( * Create Regex difference (`diff`) expression. * */ open fun mkRegexDifference(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::simplifyRegexDifference, ::mkRegexDifferenceNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyRegexDifference, ::mkRegexDifferenceNoSimplify) /** * Create Regex difference (`diff`) expression. @@ -2670,12 +2768,14 @@ open class KContext( * Create regular expression's complement. * */ open fun mkRegexComplement(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyRegexComplement, ::mkRegexComplementNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyRegexComplement, ::mkRegexComplementNoSimplify) /** * Create regular expression's complement. * */ - open fun mkRegexComplementNoSimplify(arg: KExpr): KRegexComplementExpr = regexComplementExprCache.createIfContextActive { + open fun mkRegexComplementNoSimplify( + arg: KExpr + ): KRegexComplementExpr = regexComplementExprCache.createIfContextActive { ensureContextMatch(arg) KRegexComplementExpr(this, arg) } @@ -2687,13 +2787,15 @@ open class KContext( * Equivalent to concatenating a regular expression with the empty string. * */ open fun mkRegexOption(arg: KExpr): KExpr = - mkSimplified(arg, KContext::simplifyRegexOption, ::mkRegexOptionNoSimplify) // Add simplified version + mkSimplified(arg, KContext::simplifyRegexOption, ::mkRegexOptionNoSimplify) /** * Make regular expression optional. * Equivalent to concatenating a regular expression with the empty string. * */ - open fun mkRegexOptionNoSimplify(arg: KExpr): KRegexOptionExpr = regexOptionExprCache.createIfContextActive { + open fun mkRegexOptionNoSimplify( + arg: KExpr + ): KRegexOptionExpr = regexOptionExprCache.createIfContextActive { ensureContextMatch(arg) KRegexOptionExpr(this, arg) } @@ -2706,7 +2808,7 @@ open class KContext( * Otherwise the empty set. * */ open fun mkRegexRange(arg0: KExpr, arg1: KExpr): KExpr = - mkSimplified(arg0, arg1, KContext::simplifyRegexRange, ::mkRegexRangeNoSimplify) // Add simplified version + mkSimplified(arg0, arg1, KContext::simplifyRegexRange, ::mkRegexRangeNoSimplify) /** * Return the set of all singleton strings in the range @@ -2726,7 +2828,7 @@ open class KContext( * of the given `arg` regex repeated `power` times. * */ open fun mkRegexPower(power: Int, arg: KExpr): KExpr = - mkSimplified(power, arg, KContext::simplifyRegexPower, ::mkRegexPowerNoSimplify) // Add simplified version + mkSimplified(power, arg, KContext::simplifyRegexPower, ::mkRegexPowerNoSimplify) /** * Constructs a regex expression that represents the concatenation @@ -2745,7 +2847,7 @@ open class KContext( * formed by repeating the given `arg` regex from `from` to `to` times inclusively. * */ open fun mkRegexLoop(from: Int, to: Int, arg: KExpr): KExpr = - mkSimplified(from, to, arg, KContext::simplifyRegexLoop, ::mkRegexLoopNoSimplify) // Add simplified version + mkSimplified(from, to, arg, KContext::simplifyRegexLoop, ::mkRegexLoopNoSimplify) /** * Constructs a regex expression that represents the union of regexes diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt index e3e30582d..3b0d6d4b4 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -1,7 +1,14 @@ package io.ksmt.expr.rewrite.simplify import io.ksmt.KContext -import io.ksmt.expr.* +import io.ksmt.expr.KStringConcatExpr +import io.ksmt.expr.KStringLiteralExpr +import io.ksmt.expr.KIntNumExpr +import io.ksmt.expr.KInt32NumExpr +import io.ksmt.expr.KInt64NumExpr +import io.ksmt.expr.KIntBigNumExpr +import io.ksmt.expr.KInterpretedValue +import io.ksmt.expr.KExpr import io.ksmt.sort.KBoolSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KSort @@ -223,6 +230,7 @@ inline fun KContext.simplifyStringSubExprBasic( } /** Eval constants. */ +@Suppress("NestedBlockDepth") inline fun KContext.simplifyStringIndexOfExprBasic( arg0: KExpr, arg1: KExpr, diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt index 0b1a229da..a87ad0dac 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/transformer/KNonRecursiveTransformer.kt @@ -183,6 +183,7 @@ import io.ksmt.utils.uncheckedCast * Apply specialized non-recursive transformations for all KSMT expressions. * See [KNonRecursiveTransformerBase] for details. * */ +@Suppress("LargeClass") abstract class KNonRecursiveTransformer(override val ctx: KContext) : KNonRecursiveTransformerBase(), KTransformer { override fun transformApp(expr: KApp): KExpr = transformExpr(expr) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt index fd0a02116..2a85cd975 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt @@ -19,72 +19,108 @@ object StringUtils { } @JvmStatic - fun concatStrings(lhs: KStringLiteralExpr, rhs: KStringLiteralExpr): KStringLiteralExpr = with(lhs.ctx) { + fun concatStrings( + lhs: KStringLiteralExpr, + rhs: KStringLiteralExpr + ): KStringLiteralExpr = with(lhs.ctx) { mkStringLiteral(lhs.value + rhs.value) } @JvmStatic - fun isStringSuffix(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { + fun isStringSuffix( + arg0: KStringLiteralExpr, + arg1: KStringLiteralExpr + ): KInterpretedValue = with(arg0.ctx) { mkBool(arg1.value.endsWith(arg0.value)).uncheckedCast() } @JvmStatic - fun isStringPrefix(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { + fun isStringPrefix( + arg0: KStringLiteralExpr, + arg1: KStringLiteralExpr + ): KInterpretedValue = with(arg0.ctx) { mkBool(arg1.value.startsWith(arg0.value)).uncheckedCast() } @JvmStatic - fun stringLt(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { + fun stringLt( + arg0: KStringLiteralExpr, + arg1: KStringLiteralExpr + ): KInterpretedValue = with(arg0.ctx) { mkBool(arg0.value < arg1.value).uncheckedCast() } @JvmStatic - fun stringLe(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { + fun stringLe( + arg0: KStringLiteralExpr, + arg1: KStringLiteralExpr + ): KInterpretedValue = with(arg0.ctx) { mkBool(arg0.value <= arg1.value).uncheckedCast() } @JvmStatic - fun stringGt(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { + fun stringGt( + arg0: KStringLiteralExpr, + arg1: KStringLiteralExpr + ): KInterpretedValue = with(arg0.ctx) { mkBool(arg0.value > arg1.value).uncheckedCast() } @JvmStatic - fun stringGe(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { + fun stringGe( + arg0: KStringLiteralExpr, + arg1: KStringLiteralExpr + ): KInterpretedValue = with(arg0.ctx) { mkBool(arg0.value >= arg1.value).uncheckedCast() } @JvmStatic - fun stringContains(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr): KInterpretedValue = with(arg0.ctx) { + fun stringContains( + arg0: KStringLiteralExpr, + arg1: KStringLiteralExpr + ): KInterpretedValue = with(arg0.ctx) { mkBool(arg0.value.contains(arg1.value)).uncheckedCast() } @JvmStatic - fun stringToLowerCase(arg: KStringLiteralExpr): KStringLiteralExpr = with(arg.ctx) { + fun stringToLowerCase( + arg: KStringLiteralExpr + ): KStringLiteralExpr = with(arg.ctx) { mkStringLiteral(arg.value.lowercase()) } @JvmStatic - fun stringToUpperCase(arg: KStringLiteralExpr): KStringLiteralExpr = with(arg.ctx) { + fun stringToUpperCase( + arg: KStringLiteralExpr + ): KStringLiteralExpr = with(arg.ctx) { mkStringLiteral(arg.value.uppercase()) } @JvmStatic - fun stringReverse(arg: KStringLiteralExpr): KStringLiteralExpr = with(arg.ctx) { + fun stringReverse( + arg: KStringLiteralExpr + ): KStringLiteralExpr = with(arg.ctx) { mkStringLiteral(arg.value.reversed()) } @JvmStatic - fun stringIsDigit(arg: KStringLiteralExpr): KInterpretedValue = with(arg.ctx) { + fun stringIsDigit( + arg: KStringLiteralExpr + ): KInterpretedValue = with(arg.ctx) { mkBool(arg.value.length == 1 && arg.value[0].isDigit()).uncheckedCast() } @JvmStatic - fun stringToCode(arg: KStringLiteralExpr): KIntNumExpr = with(arg.ctx) { + fun stringToCode( + arg: KStringLiteralExpr + ): KIntNumExpr = with(arg.ctx) { mkIntNum(arg.value.singleOrNull()?.code ?: -1) } @JvmStatic - fun stringToInt(arg: KStringLiteralExpr): KIntNumExpr = with(arg.ctx) { + fun stringToInt( + arg: KStringLiteralExpr + ): KIntNumExpr = with(arg.ctx) { return if (arg.value.isNotEmpty() && arg.value.all { it.isDigit() }) { mkIntNum(arg.value.toLongOrNull() ?: -1) } else { @@ -93,7 +129,11 @@ object StringUtils { } @JvmStatic - fun strintReplace(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr, arg2: KStringLiteralExpr): KStringLiteralExpr = with(arg0.ctx) { + fun strintReplace( + arg0: KStringLiteralExpr, + arg1: KStringLiteralExpr, + arg2: KStringLiteralExpr + ): KStringLiteralExpr = with(arg0.ctx) { val str = arg0.value val search = arg1.value val replace = arg2.value @@ -101,7 +141,11 @@ object StringUtils { } @JvmStatic - fun strintReplaceAll(arg0: KStringLiteralExpr, arg1: KStringLiteralExpr, arg2: KStringLiteralExpr): KStringLiteralExpr = with(arg0.ctx) { + fun strintReplaceAll( + arg0: KStringLiteralExpr, + arg1: KStringLiteralExpr, + arg2: KStringLiteralExpr + ): KStringLiteralExpr = with(arg0.ctx) { val str = arg0.value val search = arg1.value val replace = arg2.value diff --git a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKindMapper.kt b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKindMapper.kt index 4fd2c1e92..c679d8b02 100644 --- a/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKindMapper.kt +++ b/ksmt-runner/src/main/kotlin/io/ksmt/runner/serializer/ExprKindMapper.kt @@ -704,7 +704,9 @@ class ExprKindMapper: KTransformerBase { override fun transform(expr: KStringContainsExpr): KExpr = expr.kind(ExprKind.StringContainsExpr) - override fun transform(expr: KStringSingletonSubExpr): KExpr = expr.kind(ExprKind.StringSingletonSubExpr) + override fun transform( + expr: KStringSingletonSubExpr + ): KExpr = expr.kind(ExprKind.StringSingletonSubExpr) override fun transform(expr: KStringSubExpr): KExpr = expr.kind(ExprKind.StringSubExpr) @@ -722,10 +724,14 @@ class ExprKindMapper: KTransformerBase { override fun transform(expr: KStringReplaceAllExpr): KExpr = expr.kind(ExprKind.StringReplaceAllExpr) - override fun transform(expr: KStringReplaceWithRegexExpr): KExpr = expr.kind(ExprKind.StringReplaceWithRegexExpr) + override fun transform( + expr: KStringReplaceWithRegexExpr + ): KExpr = expr.kind(ExprKind.StringReplaceWithRegexExpr) - override fun transform(expr: KStringReplaceAllWithRegexExpr): KExpr = expr.kind(ExprKind.StringReplaceAllWithRegexExpr) + override fun transform( + expr: KStringReplaceAllWithRegexExpr + ): KExpr = expr.kind(ExprKind.StringReplaceAllWithRegexExpr) override fun transform(expr: KStringToLowerExpr): KExpr = expr.kind(ExprKind.StringToLowerExpr) From 55b2a40ca35363b822215393602855ed6e532db2 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 5 Mar 2025 23:38:01 +0300 Subject: [PATCH 79/84] Add string and regex sort to random expression generator --- .../main/kotlin/io/ksmt/test/RandomExpressionGenerator.kt | 6 ++++++ .../main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt | 1 + 2 files changed, 7 insertions(+) diff --git a/ksmt-test/src/main/kotlin/io/ksmt/test/RandomExpressionGenerator.kt b/ksmt-test/src/main/kotlin/io/ksmt/test/RandomExpressionGenerator.kt index 78aa7cf40..dfd155897 100644 --- a/ksmt-test/src/main/kotlin/io/ksmt/test/RandomExpressionGenerator.kt +++ b/ksmt-test/src/main/kotlin/io/ksmt/test/RandomExpressionGenerator.kt @@ -15,6 +15,8 @@ import io.ksmt.sort.KBvSort import io.ksmt.sort.KFp128Sort import io.ksmt.sort.KFp64Sort import io.ksmt.sort.KFpRoundingModeSort +import io.ksmt.sort.KStringSort +import io.ksmt.sort.KRegexSort import io.ksmt.sort.KFpSort import io.ksmt.sort.KIntSort import io.ksmt.sort.KRealSort @@ -219,6 +221,8 @@ class RandomExpressionGenerator { private val boolGen by lazy { generators.single { it.function.match("mkBool", Boolean::class) } } private val intGen by lazy { generators.single { it.function.match("mkIntNum", Int::class) } } private val realGen by lazy { generators.single { it.function.match("mkRealNum", Int::class) } } + private val stringGen by lazy { generators.single { it.function.match("mkStringLiteral", String::class) } } + private val regexGen by lazy { generators.single { it.function.match("mkStringToRegex", String::class) } } private val bvGen by lazy { generators.single { it.function.match("mkBv", Int::class, UInt::class) } } private val fpGen by lazy { generators.single { it.function.match("mkFp", Double::class, KSort::class) } } private val arrayGen by lazy { @@ -415,6 +419,8 @@ class RandomExpressionGenerator { override fun visit(sort: KIntSort): AstGenerator = intGen override fun visit(sort: KRealSort): AstGenerator = realGen override fun visit(sort: KFpRoundingModeSort): AstGenerator = fpRmGen + override fun visit(sort: KStringSort): AstGenerator = stringGen + override fun visit(sort: KRegexSort): AstGenerator = regexGen override fun visit(sort: S): AstGenerator = AstGenerator(bvGen.function, bvGen.refSortProviders, listOf(SimpleProvider(Int::class))) { args -> diff --git a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt index d99ff3f01..3f80a3ec8 100644 --- a/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt +++ b/ksmt-z3/ksmt-z3-core/src/main/kotlin/io/ksmt/solver/z3/KZ3ExprInternalizer.kt @@ -211,6 +211,7 @@ import io.ksmt.sort.KRealSort import io.ksmt.sort.KSort import io.ksmt.sort.KUninterpretedSort +@Suppress("LargeClass") open class KZ3ExprInternalizer( val ctx: KContext, private val z3InternCtx: KZ3Context From 15ffe39ffd90ab901b1e7024403eaa6130c31985 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Wed, 5 Mar 2025 23:55:27 +0300 Subject: [PATCH 80/84] Rename string simplifications and add them to readme --- .../io/ksmt/expr/rewrite/simplify/Rules.md | 50 +++++++++++++++++++ .../rewrite/simplify/StringSimplification.kt | 46 ++++++++--------- .../simplify/StringSimplificationRules.kt | 46 ++++++++--------- 3 files changed, 96 insertions(+), 46 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/Rules.md b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/Rules.md index 36ba6194c..40642625c 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/Rules.md +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/Rules.md @@ -412,3 +412,53 @@ Note: todo -- additional simplification rules implemented in Z3 * eval constants 32. KEqExpr(KFp, KFp) * eval constants + +### Strings + +1. KStringConcat + * eval constants + * ``((concat a const1) const2) ==> (concat a (concat const1 const2))`` + * ``((concat const1 (concat const2 a)) => (concat (concat const1 const2) a)`` + * ``((concat (concat a const1) (concat const2 b)) ==> (concat a (concat (concat const1 const2) b))`` +2. KStringLen + * eval constants +3. KStringSuffixOf + * eval constants +4. KStringPrefixOf + * eval constants +5. KStringLt + * eval constants +6. KStringLe + * eval constants +7. KStringGt + * eval constants +8. KStringGe + * eval constants +9. KStringContains + * eval constants +10. KStringSingletonSub + * eval constants +11. KStringSub + * eval constants +12. KStringIndexOf + * eval constants +13. KStringReplace + * eval constants +14. KStringReplaceAll + * eval constants +15. KStringToLower + * eval constants +16. KStringToUpper + * eval constants +17. KStringReverse + * eval constants +18. KStringIsDigit + * eval constants +19. KStringToCode + * eval constants +20. KStringFromCode + * eval constants +21. KStringToInt + * eval constants +22. KStringFromInt + * eval constants diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt index b458a122f..57f49c36c 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplification.kt @@ -10,13 +10,13 @@ import io.ksmt.sort.KStringSort fun KContext.simplifyStringConcat( arg0: KExpr, arg1: KExpr -): KExpr = simplifyStringBasicConcat(arg0, arg1) {arg2, arg3 -> - simplifyStringNestedConcat(arg2, arg3, KContext::simplifyStringConcat, ::mkStringConcatNoSimplify) +): KExpr = simplifyStringConcatBasic(arg0, arg1) {arg2, arg3 -> + simplifyStringConcatNested(arg2, arg3, KContext::simplifyStringConcat, ::mkStringConcatNoSimplify) } fun KContext.simplifyStringLen( arg: KExpr -): KExpr = simplifyStringLenExpr(arg, ::mkStringLenNoSimplify) +): KExpr = simplifyStringLenBasic(arg, ::mkStringLenNoSimplify) fun KContext.simplifyStringToRegex( arg: KExpr @@ -30,54 +30,54 @@ fun KContext.simplifyStringInRegex( fun KContext.simplifyStringSuffixOf( arg0: KExpr, arg1: KExpr -): KExpr = simplifyStringBasicSuffixOfExpr(arg0, arg1, ::mkStringSuffixOfNoSimplify) +): KExpr = simplifyStringSuffixOfBasic(arg0, arg1, ::mkStringSuffixOfNoSimplify) fun KContext.simplifyStringPrefixOf( arg0: KExpr, arg1: KExpr -): KExpr = simplifyStringBasicPrefixOfExpr(arg0, arg1, ::mkStringPrefixOfNoSimplify) +): KExpr = simplifyStringPrefixOfBasic(arg0, arg1, ::mkStringPrefixOfNoSimplify) fun KContext.simplifyStringLt( arg0: KExpr, arg1: KExpr -): KExpr = simplifyStringBasicLtExpr(arg0, arg1, ::mkStringLtNoSimplify) +): KExpr = simplifyStringLtBasic(arg0, arg1, ::mkStringLtNoSimplify) fun KContext.simplifyStringLe( arg0: KExpr, arg1: KExpr -): KExpr = simplifyStringBasicLeExpr(arg0, arg1, ::mkStringLeNoSimplify) +): KExpr = simplifyStringLeBasic(arg0, arg1, ::mkStringLeNoSimplify) fun KContext.simplifyStringGt( arg0: KExpr, arg1: KExpr -): KExpr = simplifyStringBasicGtExpr(arg0, arg1, ::mkStringGtNoSimplify) +): KExpr = simplifyStringGtBasic(arg0, arg1, ::mkStringGtNoSimplify) fun KContext.simplifyStringGe( arg0: KExpr, arg1: KExpr -): KExpr = simplifyStringBasicGeExpr(arg0, arg1, ::mkStringGeNoSimplify) +): KExpr = simplifyStringGeBasic(arg0, arg1, ::mkStringGeNoSimplify) fun KContext.simplifyStringContains( arg0: KExpr, arg1: KExpr -): KExpr = simplifyStringBasicContainsExpr(arg0, arg1, ::mkStringContainsNoSimplify) +): KExpr = simplifyStringContainsBasic(arg0, arg1, ::mkStringContainsNoSimplify) fun KContext.simplifyStringSingletonSub( arg0: KExpr, arg1: KExpr -): KExpr = simplifyStringSingletonSubExprBasic(arg0, arg1, ::mkStringSingletonSubNoSimplify) +): KExpr = simplifyStringSingletonSubBasic(arg0, arg1, ::mkStringSingletonSubNoSimplify) fun KContext.simplifyStringSub( arg0: KExpr, arg1: KExpr, arg2: KExpr -): KExpr = simplifyStringSubExprBasic(arg0, arg1, arg2, ::mkStringSubNoSimplify) +): KExpr = simplifyStringSubBasic(arg0, arg1, arg2, ::mkStringSubNoSimplify) fun KContext.simplifyStringIndexOf( arg0: KExpr, arg1: KExpr, arg2: KExpr -): KExpr = simplifyStringIndexOfExprBasic(arg0, arg1, arg2, ::mkStringIndexOfNoSimplify) +): KExpr = simplifyStringIndexOfBasic(arg0, arg1, arg2, ::mkStringIndexOfNoSimplify) fun KContext.simplifyStringIndexOfRegex( arg0: KExpr, @@ -89,13 +89,13 @@ fun KContext.simplifyStringReplace( arg0: KExpr, arg1: KExpr, arg2: KExpr -): KExpr = simplifyStringReplaceExprBasic(arg0, arg1, arg2, ::mkStringReplaceNoSimplify) +): KExpr = simplifyStringReplaceBasic(arg0, arg1, arg2, ::mkStringReplaceNoSimplify) fun KContext.simplifyStringReplaceAll( arg0: KExpr, arg1: KExpr, arg2: KExpr -): KExpr = simplifyStringReplaceAllExprBasic(arg0, arg1, arg2, ::mkStringReplaceAllNoSimplify) +): KExpr = simplifyStringReplaceAllBasic(arg0, arg1, arg2, ::mkStringReplaceAllNoSimplify) fun KContext.simplifyStringReplaceWithRegex( arg0: KExpr, @@ -111,32 +111,32 @@ fun KContext.simplifyStringReplaceAllWithRegex( fun KContext.simplifyStringToLower( arg: KExpr -): KExpr = simplifyStringBasicToLowerExpr(arg, ::mkStringToLowerNoSimplify) +): KExpr = simplifyStringToLowerBasic(arg, ::mkStringToLowerNoSimplify) fun KContext.simplifyStringToUpper( arg: KExpr -): KExpr = simplifyStringBasicToUpperExpr(arg, ::mkStringToUpperNoSimplify) +): KExpr = simplifyStringToUpperBasic(arg, ::mkStringToUpperNoSimplify) fun KContext.simplifyStringReverse( arg: KExpr -): KExpr = simplifyStringBasicReverseExpr(arg, ::mkStringReverseNoSimplify) +): KExpr = simplifyStringReverseBasic(arg, ::mkStringReverseNoSimplify) fun KContext.simplifyStringIsDigit( arg: KExpr -): KExpr = simplifyStringIsDigitExprBasic(arg, ::mkStringIsDigitNoSimplify) +): KExpr = simplifyStringIsDigitBasic(arg, ::mkStringIsDigitNoSimplify) fun KContext.simplifyStringToCode( arg: KExpr -): KExpr = simplifyStringToCodeExprBasic(arg, ::mkStringToCodeNoSimplify) +): KExpr = simplifyStringToCodeBasic(arg, ::mkStringToCodeNoSimplify) fun KContext.simplifyStringFromCode( arg: KExpr -): KExpr = simplifyStringFromCodeExprBasic(arg, ::mkStringFromCodeNoSimplify) +): KExpr = simplifyStringFromCodeBasic(arg, ::mkStringFromCodeNoSimplify) fun KContext.simplifyStringToInt( arg: KExpr -): KExpr = simplifyStringToIntExprBasic(arg, ::mkStringToIntNoSimplify) +): KExpr = simplifyStringToIntBasic(arg, ::mkStringToIntNoSimplify) fun KContext.simplifyStringFromInt( arg: KExpr -): KExpr = simplifyStringFromIntExprBasic(arg, ::mkStringFromIntNoSimplify) +): KExpr = simplifyStringFromIntBasic(arg, ::mkStringFromIntNoSimplify) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt index 3b0d6d4b4..b33631f4c 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/expr/rewrite/simplify/StringSimplificationRules.kt @@ -23,7 +23,7 @@ import io.ksmt.utils.StringUtils.STRING_FROM_CODE_UPPER_BOUND /** * Eval constants. * (concat const1 const2) ==> (const3) */ -inline fun KContext.simplifyStringBasicConcat( +inline fun KContext.simplifyStringConcatBasic( arg0: KExpr, arg1: KExpr, cont: (KExpr, KExpr) -> KExpr @@ -37,7 +37,7 @@ inline fun KContext.simplifyStringBasicConcat( * ((concat const1 (concat const2 a)) => (concat (concat const1 const2) a) * ((concat (concat a const1) (concat const2 b)) ==> (concat a (concat (concat const1 const2) b)) */ -inline fun KContext.simplifyStringNestedConcat( +inline fun KContext.simplifyStringConcatNested( arg0: KExpr, arg1: KExpr, rewriteStringConcatExpr: KContext.(KExpr, KExpr) -> KExpr, @@ -78,7 +78,7 @@ inline fun KContext.simplifyStringNestedConcat( /** * Eval length of string constant. */ -inline fun KContext.simplifyStringLenExpr( +inline fun KContext.simplifyStringLenBasic( arg: KExpr, cont: (KExpr) -> KExpr ): KExpr = @@ -94,7 +94,7 @@ inline fun KContext.simplifyStringLenExpr( /** Simplifies string suffix checking expressions * (str_suffix_of strConst1 strConst2) ==> boolConst */ -inline fun KContext.simplifyStringBasicSuffixOfExpr( +inline fun KContext.simplifyStringSuffixOfBasic( arg0: KExpr, arg1: KExpr, cont: (KExpr, KExpr) -> KExpr @@ -105,7 +105,7 @@ inline fun KContext.simplifyStringBasicSuffixOfExpr( /** Simplifies string prefix checking expressions * (str_prefix_of strConst1 strConst2) ==> boolConst */ -inline fun KContext.simplifyStringBasicPrefixOfExpr( +inline fun KContext.simplifyStringPrefixOfBasic( arg0: KExpr, arg1: KExpr, cont: (KExpr, KExpr) -> KExpr @@ -120,7 +120,7 @@ inline fun KContext.simplifyStringBasicPrefixOfExpr( /** Simplifies string "less than" comparison expressions * (str_lt strConst1 strConst2) ==> boolConst */ -inline fun KContext.simplifyStringBasicLtExpr( +inline fun KContext.simplifyStringLtBasic( arg0: KExpr, arg1: KExpr, cont: (KExpr, KExpr) -> KExpr @@ -131,7 +131,7 @@ inline fun KContext.simplifyStringBasicLtExpr( /** Simplifies string "less than or equal" comparison expressions * (str_le strConst1 strConst2) ==> boolConst */ -inline fun KContext.simplifyStringBasicLeExpr( +inline fun KContext.simplifyStringLeBasic( arg0: KExpr, arg1: KExpr, cont: (KExpr, KExpr) -> KExpr @@ -142,7 +142,7 @@ inline fun KContext.simplifyStringBasicLeExpr( /** Simplifies string "greater than" comparison expressions * (str_gt strConst1 strConst2) ==> boolConst */ -inline fun KContext.simplifyStringBasicGtExpr( +inline fun KContext.simplifyStringGtBasic( arg0: KExpr, arg1: KExpr, cont: (KExpr, KExpr) -> KExpr @@ -153,7 +153,7 @@ inline fun KContext.simplifyStringBasicGtExpr( /** Simplifies string "greater than or equal" comparison expressions * (str_ge strConst1 strConst2) ==> boolConst */ -inline fun KContext.simplifyStringBasicGeExpr( +inline fun KContext.simplifyStringGeBasic( arg0: KExpr, arg1: KExpr, cont: (KExpr, KExpr) -> KExpr @@ -168,7 +168,7 @@ inline fun KContext.simplifyStringBasicGeExpr( /** Basic simplify string contains expression * (str_contains strConst1 strConst2) ==> boolConst */ -inline fun KContext.simplifyStringBasicContainsExpr( +inline fun KContext.simplifyStringContainsBasic( arg0: KExpr, arg1: KExpr, cont: (KExpr, KExpr) -> KExpr @@ -182,7 +182,7 @@ inline fun KContext.simplifyStringBasicContainsExpr( * */ /** Eval constants. */ -inline fun KContext.simplifyStringSingletonSubExprBasic( +inline fun KContext.simplifyStringSingletonSubBasic( arg0: KExpr, arg1: KExpr, cont: (KExpr, KExpr) -> KExpr @@ -207,7 +207,7 @@ inline fun KContext.simplifyStringSingletonSubExprBasic( } /** Eval constants. */ -inline fun KContext.simplifyStringSubExprBasic( +inline fun KContext.simplifyStringSubBasic( arg0: KExpr, arg1: KExpr, arg2: KExpr, @@ -231,7 +231,7 @@ inline fun KContext.simplifyStringSubExprBasic( /** Eval constants. */ @Suppress("NestedBlockDepth") -inline fun KContext.simplifyStringIndexOfExprBasic( +inline fun KContext.simplifyStringIndexOfBasic( arg0: KExpr, arg1: KExpr, arg2: KExpr, @@ -269,7 +269,7 @@ inline fun KContext.simplifyStringIndexOfExprBasic( * String replace expressions simplifications * */ -inline fun KContext.simplifyStringReplaceExprBasic( +inline fun KContext.simplifyStringReplaceBasic( arg0: KExpr, arg1: KExpr, arg2: KExpr, @@ -279,7 +279,7 @@ inline fun KContext.simplifyStringReplaceExprBasic( cont(arg0, arg1, arg2) } -inline fun KContext.simplifyStringReplaceAllExprBasic( +inline fun KContext.simplifyStringReplaceAllBasic( arg0: KExpr, arg1: KExpr, arg2: KExpr, @@ -294,7 +294,7 @@ inline fun KContext.simplifyStringReplaceAllExprBasic( * */ /** Converting all letters of a string constant to lowercase. */ -inline fun KContext.simplifyStringBasicToLowerExpr( +inline fun KContext.simplifyStringToLowerBasic( arg: KExpr, cont: (KExpr) -> KExpr ): KExpr = @@ -303,7 +303,7 @@ inline fun KContext.simplifyStringBasicToLowerExpr( } /** Converting all letters of a string constant to uppercase. */ -inline fun KContext.simplifyStringBasicToUpperExpr( +inline fun KContext.simplifyStringToUpperBasic( arg: KExpr, cont: (KExpr) -> KExpr ): KExpr = @@ -312,7 +312,7 @@ inline fun KContext.simplifyStringBasicToUpperExpr( } /** Reverses a string constan.t */ -inline fun KContext.simplifyStringBasicReverseExpr( +inline fun KContext.simplifyStringReverseBasic( arg: KExpr, cont: (KExpr) -> KExpr ): KExpr = @@ -325,7 +325,7 @@ inline fun KContext.simplifyStringBasicReverseExpr( * */ /** Eval constants: if string literal consist of one digit - return true, otherwise false. */ -inline fun KContext.simplifyStringIsDigitExprBasic( +inline fun KContext.simplifyStringIsDigitBasic( arg: KExpr, cont: (KExpr) -> KExpr ): KExpr = @@ -334,7 +334,7 @@ inline fun KContext.simplifyStringIsDigitExprBasic( } /** Eval constants: if string literal consist of one character - return its code, otherwise return -1. */ -inline fun KContext.simplifyStringToCodeExprBasic( +inline fun KContext.simplifyStringToCodeBasic( arg: KExpr, cont: (KExpr) -> KExpr ): KExpr = @@ -344,7 +344,7 @@ inline fun KContext.simplifyStringToCodeExprBasic( /** Eval constants: if int constant is in the range [0; STRING_FROM_CODE_UPPER_BOUND], then * return code point of constant, otherwise return empty string. */ -inline fun KContext.simplifyStringFromCodeExprBasic( +inline fun KContext.simplifyStringFromCodeBasic( arg: KExpr, cont: (KExpr) -> KExpr ): KExpr { @@ -365,7 +365,7 @@ inline fun KContext.simplifyStringFromCodeExprBasic( /** Eval constants: if string literal consist of digits, then * return the positive integer denoted by literal; * otherwise, return -1. */ -inline fun KContext.simplifyStringToIntExprBasic( +inline fun KContext.simplifyStringToIntBasic( arg: KExpr, cont: (KExpr) -> KExpr ): KExpr = @@ -375,7 +375,7 @@ inline fun KContext.simplifyStringToIntExprBasic( /** Eval constants: if the integer is non-negative, return its string representation; * otherwise, return an empty string. */ -inline fun KContext.simplifyStringFromIntExprBasic( +inline fun KContext.simplifyStringFromIntBasic( arg: KExpr, cont: (KExpr) -> KExpr ): KExpr { From 41a52bd10955b787e5b09bb1503c347548a42eb5 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Thu, 6 Mar 2025 00:25:39 +0300 Subject: [PATCH 81/84] Implement simplifications' tests for string len and comparisons expressions --- .../main/kotlin/io/ksmt/utils/StringUtils.kt | 16 ++-- .../test/kotlin/io/ksmt/StringSimplifyTest.kt | 78 +++++++++++++++++++ 2 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 ksmt-core/src/test/kotlin/io/ksmt/StringSimplifyTest.kt diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt index 2a85cd975..abdbe0925 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt @@ -1,13 +1,10 @@ package io.ksmt.utils -import io.ksmt.expr.KInt32NumExpr -import io.ksmt.expr.KInt64NumExpr -import io.ksmt.expr.KIntBigNumExpr +import io.ksmt.KContext +import io.ksmt.expr.KStringLiteralExpr import io.ksmt.expr.KIntNumExpr import io.ksmt.expr.KInterpretedValue -import io.ksmt.expr.KStringLiteralExpr import io.ksmt.sort.KBoolSort -import io.ksmt.sort.KStringSort object StringUtils { @@ -151,4 +148,13 @@ object StringUtils { val replace = arg2.value return mkStringLiteral(if (search.isEmpty()) str else str.replace(search, replace)) } + + @JvmStatic + fun KContext.sequentialStringsForComparisons(): List { + val alphabet = ('A'..'Z') + ('a'..'z') + + return alphabet.map { char -> + this.mkStringLiteral(char.toString()) + } + } } diff --git a/ksmt-core/src/test/kotlin/io/ksmt/StringSimplifyTest.kt b/ksmt-core/src/test/kotlin/io/ksmt/StringSimplifyTest.kt new file mode 100644 index 000000000..88bc37c18 --- /dev/null +++ b/ksmt-core/src/test/kotlin/io/ksmt/StringSimplifyTest.kt @@ -0,0 +1,78 @@ +package io.ksmt + +import io.ksmt.expr.KExpr +import io.ksmt.sort.KSort +import io.ksmt.sort.KStringSort +import io.ksmt.utils.StringUtils.sequentialStringsForComparisons +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.parallel.Execution +import org.junit.jupiter.api.parallel.ExecutionMode + +@Execution(ExecutionMode.CONCURRENT) +class StringSimplifyTest: ExpressionSimplifyTest() { + + @Test + fun testStringLen() = testOperation(KContext::mkStringLen, KContext::mkStringLenNoSimplify) + + @Test + fun testStringLt() = testOperation(KContext::mkStringLt, KContext::mkStringLtNoSimplify) { + sequentialStringsForComparisons() + } + + @Test + fun testStringLe() = testOperation(KContext::mkStringLe, KContext::mkStringLeNoSimplify) { + sequentialStringsForComparisons() + } + + @Test + fun testStringGt() = testOperation(KContext::mkStringGt, KContext::mkStringGtNoSimplify) { + sequentialStringsForComparisons() + } + + @Test + fun testStringGe() = testOperation(KContext::mkStringGe, KContext::mkStringGeNoSimplify) { + sequentialStringsForComparisons() + } + + @JvmName("testUnary") + private fun testOperation( + operation: KContext.(KExpr) -> KExpr, + operationNoSimplify: KContext.(KExpr) -> KExpr, + mkSpecialValues: KContext.(KStringSort) -> List> = { emptyList() }, + ) = runTest { sort: KStringSort, checker -> + val x = mkConst("x", sort) + val specialValues = mkSpecialValues(sort) + + (listOf(x) + specialValues).forEach { value -> + val unsimplifiedExpr = operationNoSimplify(value) + val simplifiedExpr = operation(value) + checker.check(unsimplifiedExpr = unsimplifiedExpr, simplifiedExpr = simplifiedExpr) { "$value" } + } + } + + @JvmName("testBinaryNotNested") + private fun testOperation( + operation: KContext.(KExpr, KExpr) -> KExpr, + operationNoSimplify: KContext.(KExpr, KExpr) -> KExpr, + mkSpecialValues: KContext.(KStringSort) -> List> = { emptyList() } + ) = runTest { sort: KStringSort, checker -> + val a = mkConst("a", sort) + val b = mkConst("b", sort) + val specialValues = mkSpecialValues(sort) + + (listOf(a) + specialValues).forEach { lhs -> + (listOf(b) + specialValues).forEach { rhs -> + val unsimplifiedExpr = operationNoSimplify(lhs, rhs) + val simplifiedExpr = operation(lhs, rhs) + checker.check(unsimplifiedExpr = unsimplifiedExpr, simplifiedExpr = simplifiedExpr) { + "$lhs, $rhs" + } + } + } + } + + private fun runTest(test: KContext.(KStringSort, TestRunner) -> Unit) = runTest( + mkSort = { stringSort }, + test = test + ) +} From 70ac7c7fe5fbda23d8191eb3b35bc26e55fb30eb Mon Sep 17 00:00:00 2001 From: raf-nr Date: Fri, 7 Mar 2025 20:42:57 +0300 Subject: [PATCH 82/84] Implement other tests for string simplifications --- .../main/kotlin/io/ksmt/utils/StringUtils.kt | 2 +- .../test/kotlin/io/ksmt/StringSimplifyTest.kt | 80 +++++++++++++++++-- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt index abdbe0925..86ffb7aaf 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/utils/StringUtils.kt @@ -150,7 +150,7 @@ object StringUtils { } @JvmStatic - fun KContext.sequentialStringsForComparisons(): List { + fun KContext.sequentialEngAlphabetChars(): List { val alphabet = ('A'..'Z') + ('a'..'z') return alphabet.map { char -> diff --git a/ksmt-core/src/test/kotlin/io/ksmt/StringSimplifyTest.kt b/ksmt-core/src/test/kotlin/io/ksmt/StringSimplifyTest.kt index 88bc37c18..d3b811e00 100644 --- a/ksmt-core/src/test/kotlin/io/ksmt/StringSimplifyTest.kt +++ b/ksmt-core/src/test/kotlin/io/ksmt/StringSimplifyTest.kt @@ -3,7 +3,7 @@ package io.ksmt import io.ksmt.expr.KExpr import io.ksmt.sort.KSort import io.ksmt.sort.KStringSort -import io.ksmt.utils.StringUtils.sequentialStringsForComparisons +import io.ksmt.utils.StringUtils.sequentialEngAlphabetChars import org.junit.jupiter.api.Test import org.junit.jupiter.api.parallel.Execution import org.junit.jupiter.api.parallel.ExecutionMode @@ -14,24 +14,70 @@ class StringSimplifyTest: ExpressionSimplifyTest() { @Test fun testStringLen() = testOperation(KContext::mkStringLen, KContext::mkStringLenNoSimplify) + @Test + fun testSuffixOf() = testOperation(KContext::mkStringSuffixOf, KContext::mkStringSuffixOfNoSimplify) { + listOf( + "prefixsuffix".expr, + "prefix".expr, + "suffix".expr + ) + } + + @Test + fun testPrefixOf() = testOperation(KContext::mkStringPrefixOf, KContext::mkStringPrefixOfNoSimplify) { + listOf( + "prefixsuffix".expr, + "prefix".expr, + "suffix".expr + ) + } + @Test fun testStringLt() = testOperation(KContext::mkStringLt, KContext::mkStringLtNoSimplify) { - sequentialStringsForComparisons() + sequentialEngAlphabetChars() } @Test fun testStringLe() = testOperation(KContext::mkStringLe, KContext::mkStringLeNoSimplify) { - sequentialStringsForComparisons() + sequentialEngAlphabetChars() } @Test fun testStringGt() = testOperation(KContext::mkStringGt, KContext::mkStringGtNoSimplify) { - sequentialStringsForComparisons() + sequentialEngAlphabetChars() } @Test fun testStringGe() = testOperation(KContext::mkStringGe, KContext::mkStringGeNoSimplify) { - sequentialStringsForComparisons() + sequentialEngAlphabetChars() + } + + @Test + fun testStringContais() = testOperation(KContext::mkStringContains, KContext::mkStringContainsNoSimplify) { + listOf( + "containsSomeString".expr, + "Some".expr, + "None".expr + ) + } + + @Test + fun testStringReplace() = testOperation(KContext::mkStringReplace, KContext::mkStringReplaceNoSimplify) { + listOf( + "containsSomeSomeString".expr, + "Some".expr, + "None".expr + ) + } + + @Test + fun testStringToCode() = testOperation(KContext::mkStringToCode, KContext::mkStringToCodeNoSimplify) { + sequentialEngAlphabetChars() + } + + @Test + fun testStringToInt() = testOperation(KContext::mkStringToInt, KContext::mkStringToIntNoSimplify) { + listOf("1".expr, "123".expr, "01".expr) } @JvmName("testUnary") @@ -71,6 +117,30 @@ class StringSimplifyTest: ExpressionSimplifyTest() { } } + @JvmName("testTernaryNotNested") + private fun testOperation( + operation: KContext.(KExpr, KExpr, KExpr) -> KExpr, + operationNoSimplify: KContext.(KExpr, KExpr, KExpr) -> KExpr, + mkSpecialValues: KContext.(KStringSort) -> List> = { emptyList() } + ) = runTest { sort: KStringSort, checker -> + val a = mkConst("a", sort) + val b = mkConst("b", sort) + val c = mkConst("c", sort) + val specialValues = mkSpecialValues(sort) + + (listOf(a) + specialValues).forEach { arg0 -> + (listOf(b) + specialValues).forEach { arg1 -> + (listOf(c) + specialValues).forEach { arg2 -> + val unsimplifiedExpr = operationNoSimplify(arg0, arg1, arg2) + val simplifiedExpr = operation(arg0, arg1, arg2) + checker.check(unsimplifiedExpr = unsimplifiedExpr, simplifiedExpr = simplifiedExpr) { + "$arg0, $arg1, $arg2" + } + } + } + } + } + private fun runTest(test: KContext.(KStringSort, TestRunner) -> Unit) = runTest( mkSort = { stringSort }, test = test From 88e132ef150f18fd40f90433cd7564204aa70f84 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Fri, 7 Mar 2025 20:43:32 +0300 Subject: [PATCH 83/84] Add some syntax sugar for string expr creating --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index bf99444d3..e166d8e47 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -2243,6 +2243,8 @@ open class KContext( ensureContextMatch(arg0, arg1) KStringSingletonSubExpr(this, arg0, arg1) } + + fun KExpr.charAtPos(arg: KExpr) = mkStringSingletonSub(this, arg) private val stringSubCache = mkAstInterner() @@ -2268,6 +2270,8 @@ open class KContext( ensureContextMatch(arg0, arg1) KStringSubExpr(this, arg0, arg1, arg2) } + + fun KExpr.substring(arg1: KExpr, arg2: KExpr) = mkStringSub(this, arg1, arg2) private val stringIndexOfCache = mkAstInterner() @@ -2306,6 +2310,8 @@ open class KContext( KStringIndexOfExpr(this, arg0, arg1, arg2) } + fun KExpr.indexOf(arg1: KExpr, arg2: KExpr) = mkStringIndexOf(this, arg1, arg2) + private val stringIndexOfRegexCache = mkAstInterner() /** @@ -2334,6 +2340,8 @@ open class KContext( ensureContextMatch(arg0, arg1) KStringIndexOfRegexExpr(this, arg0, arg1, arg2) } + + fun KExpr.indexOf(arg1: KExpr, arg2: KExpr) = mkStringIndexOfRegex(this, arg1, arg2) private val stringReplaceCache = mkAstInterner() @@ -2370,6 +2378,8 @@ open class KContext( KStringReplaceExpr(this, arg0, arg1, arg2) } + fun KExpr.replaceWith(arg1: KExpr, arg2: KExpr) = mkStringReplace(this, arg1, arg2) + private val stringReplaceAllCache = mkAstInterner() /** @@ -2402,6 +2412,8 @@ open class KContext( ensureContextMatch(arg0, arg1, arg2) KStringReplaceAllExpr(this, arg0, arg1, arg2) } + + fun KExpr.replaceAllWith(arg1: KExpr, arg2: KExpr) = mkStringReplaceAll(this, arg1, arg2) private val stringReplaceWithRegexCache = mkAstInterner() @@ -2435,6 +2447,8 @@ open class KContext( ensureContextMatch(arg0, arg1, arg2) KStringReplaceWithRegexExpr(this, arg0, arg1, arg2) } + + fun KExpr.replaceWith(arg1: KExpr, arg2: KExpr) = mkStringReplaceWithRegex(this, arg1, arg2) private val stringReplaceAllWithRegexCache = mkAstInterner() @@ -2466,6 +2480,8 @@ open class KContext( ensureContextMatch(arg0, arg1, arg2) KStringReplaceAllWithRegexExpr(this, arg0, arg1, arg2) } + + fun KExpr.replaceAllWith(arg1: KExpr, arg2: KExpr) = mkStringReplaceAllWithRegex(this, arg1, arg2) private val stringToLowerExprCache = mkAstInterner() @@ -2483,6 +2499,8 @@ open class KContext( ensureContextMatch(arg) KStringToLowerExpr(this, arg) } + + fun KExpr.toLower() = mkStringToLower(this) private val stringToUpperExprCache = mkAstInterner() @@ -2500,6 +2518,8 @@ open class KContext( ensureContextMatch(arg) KStringToUpperExpr(this, arg) } + + fun KExpr.toUpper() = mkStringToUpper(this) private val stringReverseExprCache = mkAstInterner() @@ -2517,6 +2537,8 @@ open class KContext( ensureContextMatch(arg) KStringReverseExpr(this, arg) } + + fun KExpr.reverse() = mkStringReverse(this) private val stringIsDigitCache = mkAstInterner() @@ -2534,6 +2556,8 @@ open class KContext( ensureContextMatch(arg) KStringIsDigitExpr(this, arg) } + + fun KExpr.isDigit() = mkStringIsDigit(this) private val stringToCodeCache = mkAstInterner() @@ -2553,6 +2577,8 @@ open class KContext( ensureContextMatch(arg) KStringToCodeExpr(this, arg) } + + fun KExpr.toCode() = mkStringToCode(this) private val stringFromCodeCache = mkAstInterner() @@ -2572,6 +2598,8 @@ open class KContext( ensureContextMatch(arg) KStringFromCodeExpr(this, arg) } + + fun KExpr.toChar() = mkStringFromCode(this) private val stringToIntCache = mkAstInterner() @@ -2591,6 +2619,9 @@ open class KContext( ensureContextMatch(arg) KStringToIntExpr(this, arg) } + + + fun KExpr.toInt() = mkStringToInt(this) private val stringFromIntCache = mkAstInterner() @@ -2610,6 +2641,8 @@ open class KContext( ensureContextMatch(arg) KStringFromIntExpr(this, arg) } + + fun KExpr.convertToString() = mkStringFromInt(this) private val stringToRegexExprCache = mkAstInterner() @@ -2693,6 +2726,8 @@ open class KContext( ensureContextMatch(arg0, arg1) KRegexUnionExpr(this, arg0, arg1) } + + infix fun KExpr.union(other: KExpr) = mkRegexUnion(this, other) private val regexIntersectionExprCache = mkAstInterner() @@ -2710,6 +2745,8 @@ open class KContext( ensureContextMatch(arg0, arg1) KRegexIntersectionExpr(this, arg0, arg1) } + + infix fun KExpr.intersect(other: KExpr) = mkRegexIntersection(this, other) private val regexStarExprCache = mkAstInterner() @@ -2727,6 +2764,8 @@ open class KContext( ensureContextMatch(arg) KRegexStarExpr(this, arg) } + + fun KExpr.kleeneStar() = mkRegexStar(this) private val regexCrossExprCache = mkAstInterner() @@ -2744,6 +2783,8 @@ open class KContext( ensureContextMatch(arg) KRegexCrossExpr(this, arg) } + + fun KExpr.kleeneCross() = mkRegexCross(this) private val regexDifferenceExprCache = mkAstInterner() @@ -2761,6 +2802,8 @@ open class KContext( ensureContextMatch(arg0, arg1) KRegexDifferenceExpr(this, arg0, arg1) } + + infix fun KExpr.diff(other: KExpr) = mkRegexDifference(this, other) private val regexComplementExprCache = mkAstInterner() @@ -2780,6 +2823,8 @@ open class KContext( KRegexComplementExpr(this, arg) } + fun KExpr.complement() = mkRegexComplement(this) + private val regexOptionExprCache = mkAstInterner() /** @@ -2800,6 +2845,8 @@ open class KContext( KRegexOptionExpr(this, arg) } + fun KExpr.opt() = mkRegexOption(this) + private val regexRangeExprCache = mkAstInterner() /** @@ -2839,6 +2886,8 @@ open class KContext( ensureContextMatch(arg) KRegexPowerExpr(this, power, arg) } + + fun KExpr.toPow(power: Int) = mkRegexPower(power, this) private val regexLoopExprCache = mkAstInterner() @@ -2858,6 +2907,8 @@ open class KContext( ensureContextMatch(arg) KRegexLoopExpr(this, from, to, arg) } + + fun KExpr.loop(from: Int, to: Int) = mkRegexLoop(from, to, this) val regexEpsilonExpr: KRegexEpsilon = KRegexEpsilon(this) From 6c208aa7820dabe7ff108aa9b00d9d12f436723e Mon Sep 17 00:00:00 2001 From: raf-nr Date: Fri, 7 Mar 2025 20:54:59 +0300 Subject: [PATCH 84/84] Format code --- ksmt-core/src/main/kotlin/io/ksmt/KContext.kt | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt index e166d8e47..3624f6c7a 100644 --- a/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt +++ b/ksmt-core/src/main/kotlin/io/ksmt/KContext.kt @@ -2341,7 +2341,10 @@ open class KContext( KStringIndexOfRegexExpr(this, arg0, arg1, arg2) } - fun KExpr.indexOf(arg1: KExpr, arg2: KExpr) = mkStringIndexOfRegex(this, arg1, arg2) + fun KExpr.indexOfRegex( + arg1: KExpr, + arg2: KExpr + ) = mkStringIndexOfRegex(this, arg1, arg2) private val stringReplaceCache = mkAstInterner() @@ -2378,7 +2381,10 @@ open class KContext( KStringReplaceExpr(this, arg0, arg1, arg2) } - fun KExpr.replaceWith(arg1: KExpr, arg2: KExpr) = mkStringReplace(this, arg1, arg2) + fun KExpr.replaceWith( + arg1: KExpr, + arg2: KExpr + ) = mkStringReplace(this, arg1, arg2) private val stringReplaceAllCache = mkAstInterner() @@ -2413,7 +2419,10 @@ open class KContext( KStringReplaceAllExpr(this, arg0, arg1, arg2) } - fun KExpr.replaceAllWith(arg1: KExpr, arg2: KExpr) = mkStringReplaceAll(this, arg1, arg2) + fun KExpr.replaceAllWith( + arg1: KExpr, + arg2: KExpr + ) = mkStringReplaceAll(this, arg1, arg2) private val stringReplaceWithRegexCache = mkAstInterner() @@ -2448,7 +2457,10 @@ open class KContext( KStringReplaceWithRegexExpr(this, arg0, arg1, arg2) } - fun KExpr.replaceWith(arg1: KExpr, arg2: KExpr) = mkStringReplaceWithRegex(this, arg1, arg2) + fun KExpr.replaceWithRegex( + arg1: KExpr, + arg2: KExpr + ) = mkStringReplaceWithRegex(this, arg1, arg2) private val stringReplaceAllWithRegexCache = mkAstInterner() @@ -2481,7 +2493,10 @@ open class KContext( KStringReplaceAllWithRegexExpr(this, arg0, arg1, arg2) } - fun KExpr.replaceAllWith(arg1: KExpr, arg2: KExpr) = mkStringReplaceAllWithRegex(this, arg1, arg2) + fun KExpr.replaceAllWithRegex( + arg1: KExpr, + arg2: KExpr + ) = mkStringReplaceAllWithRegex(this, arg1, arg2) private val stringToLowerExprCache = mkAstInterner()