From 183449fb6fbb54c53d1262fb9c85a46793a3fc99 Mon Sep 17 00:00:00 2001 From: raf-nr Date: Tue, 3 Dec 2024 16:50:26 +0300 Subject: [PATCH 01/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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/65] 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()