Skip to content

Commit 5a139cd

Browse files
committed
Implement prefixOf and suffixOf strings' operations
1 parent 3a1c7c1 commit 5a139cd

File tree

3 files changed

+120
-0
lines changed

3 files changed

+120
-0
lines changed

ksmt-core/src/main/kotlin/io/ksmt/KContext.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ import io.ksmt.decl.KStringLiteralDecl
133133
import io.ksmt.decl.KStringConcatDecl
134134
import io.ksmt.decl.KStringLenDecl
135135
import io.ksmt.decl.KStringToRegexDecl
136+
import io.ksmt.decl.KSuffixOfDecl
137+
import io.ksmt.decl.KPrefixOfDecl
136138
import io.ksmt.decl.KRegexLiteralDecl
137139
import io.ksmt.decl.KRegexConcatDecl
138140
import io.ksmt.decl.KRegexUnionDecl
@@ -287,6 +289,8 @@ import io.ksmt.expr.KStringLiteralExpr
287289
import io.ksmt.expr.KStringConcatExpr
288290
import io.ksmt.expr.KStringLenExpr
289291
import io.ksmt.expr.KStringToRegexExpr
292+
import io.ksmt.expr.KSuffixOfExpr
293+
import io.ksmt.expr.KPrefixOfExpr
290294
import io.ksmt.expr.KRegexLiteralExpr
291295
import io.ksmt.expr.KRegexConcatExpr
292296
import io.ksmt.expr.KRegexUnionExpr
@@ -1971,6 +1975,41 @@ open class KContext(
19711975
KStringToRegexExpr(this, arg)
19721976
}
19731977

1978+
private val suffixOfExprCache = mkAstInterner<KSuffixOfExpr>()
1979+
1980+
/**
1981+
* Check if first string is a suffix of second.
1982+
* */
1983+
open fun mkSuffixOf(arg0: KExpr<KStringSort>, arg1: KExpr<KStringSort>): KExpr<KBoolSort> =
1984+
mkSimplified(arg0, arg1, KContext::mkSuffixOfNoSimplify, ::mkSuffixOfNoSimplify) // Add simplified version
1985+
1986+
/**
1987+
* Check if first string is a suffix of second.
1988+
* */
1989+
open fun mkSuffixOfNoSimplify(arg0: KExpr<KStringSort>, arg1: KExpr<KStringSort>): KSuffixOfExpr =
1990+
suffixOfExprCache.createIfContextActive {
1991+
ensureContextMatch(arg0, arg1)
1992+
KSuffixOfExpr(this, arg0, arg1)
1993+
}
1994+
1995+
private val prefixOfExprCache = mkAstInterner<KPrefixOfExpr>()
1996+
1997+
/**
1998+
* Check if first string is a prefix of second.
1999+
* */
2000+
open fun mkPrefixOf(arg0: KExpr<KStringSort>, arg1: KExpr<KStringSort>): KExpr<KBoolSort> =
2001+
mkSimplified(arg0, arg1, KContext::mkPrefixOfNoSimplify, ::mkPrefixOfNoSimplify) // Add simplified version
2002+
2003+
/**
2004+
* Check if first string is a prefix of second.
2005+
* */
2006+
open fun mkPrefixOfNoSimplify(arg0: KExpr<KStringSort>, arg1: KExpr<KStringSort>): KPrefixOfExpr =
2007+
prefixOfExprCache.createIfContextActive {
2008+
ensureContextMatch(arg0, arg1)
2009+
KPrefixOfExpr(this, arg0, arg1)
2010+
}
2011+
2012+
19742013
private val regexLiteralCache = mkAstInterner<KRegexLiteralExpr>()
19752014

19762015
/**
@@ -4688,6 +4727,10 @@ open class KContext(
46884727

46894728
fun mkStringToRegexDecl(): KStringToRegexDecl = KStringToRegexDecl(this)
46904729

4730+
fun mkSuffixOfDecl(): KSuffixOfDecl = KSuffixOfDecl(this)
4731+
4732+
fun mkPrefixOfDecl(): KPrefixOfDecl = KPrefixOfDecl(this)
4733+
46914734
// regex
46924735
fun mkRegexLiteralDecl(value: String): KRegexLiteralDecl = KRegexLiteralDecl(this, value)
46934736

ksmt-core/src/main/kotlin/io/ksmt/decl/String.kt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,37 @@ class KStringToRegexDecl internal constructor(
4646
override fun KContext.apply(arg: KExpr<KStringSort>): KApp<KRegexSort, KStringSort> = mkStringToRegexNoSimplify(arg)
4747
override fun <R> accept(visitor: KDeclVisitor<R>): R = visitor.visit(this)
4848
}
49+
50+
class KSuffixOfDecl internal constructor(
51+
ctx: KContext,
52+
) : KFuncDecl2<KBoolSort, KStringSort, KStringSort>(
53+
ctx,
54+
name = "suffix_of",
55+
resultSort = ctx.mkBoolSort(),
56+
ctx.mkStringSort(),
57+
ctx.mkStringSort()
58+
) {
59+
override fun <R> accept(visitor: KDeclVisitor<R>): R = visitor.visit(this)
60+
61+
override fun KContext.apply(
62+
arg0: KExpr<KStringSort>,
63+
arg1: KExpr<KStringSort>
64+
): KApp<KBoolSort, *> = mkSuffixOfNoSimplify(arg0, arg1)
65+
}
66+
67+
class KPrefixOfDecl internal constructor(
68+
ctx: KContext,
69+
) : KFuncDecl2<KBoolSort, KStringSort, KStringSort>(
70+
ctx,
71+
name = "prefix_of",
72+
resultSort = ctx.mkBoolSort(),
73+
ctx.mkStringSort(),
74+
ctx.mkStringSort()
75+
) {
76+
override fun <R> accept(visitor: KDeclVisitor<R>): R = visitor.visit(this)
77+
78+
override fun KContext.apply(
79+
arg0: KExpr<KStringSort>,
80+
arg1: KExpr<KStringSort>
81+
): KApp<KBoolSort, *> = mkPrefixOfNoSimplify(arg0, arg1)
82+
}

ksmt-core/src/main/kotlin/io/ksmt/expr/String.kt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import io.ksmt.cache.hash
55
import io.ksmt.cache.structurallyEqual
66
import io.ksmt.decl.*
77
import io.ksmt.expr.transformer.KTransformerBase
8+
import io.ksmt.sort.KBoolSort
89
import io.ksmt.sort.KIntSort
910
import io.ksmt.sort.KRegexSort
1011
import io.ksmt.sort.KStringSort
@@ -87,3 +88,45 @@ class KStringToRegexExpr internal constructor(
8788
override fun internHashCode(): Int = hash(arg)
8889
override fun internEquals(other: Any): Boolean = structurallyEqual(other) { arg }
8990
}
91+
92+
class KSuffixOfExpr internal constructor(
93+
ctx: KContext,
94+
val arg0: KExpr<KStringSort>,
95+
val arg1: KExpr<KStringSort>
96+
) : KApp<KBoolSort, KStringSort>(ctx) {
97+
override val sort: KBoolSort = ctx.mkBoolSort()
98+
99+
override val args: List<KExpr<KStringSort>>
100+
get() = listOf(arg0, arg1)
101+
102+
override val decl: KDecl<KBoolSort>
103+
get() = ctx.mkSuffixOfDecl()
104+
105+
override fun accept(transformer: KTransformerBase): KExpr<KBoolSort> {
106+
TODO("Not yet implemented")
107+
}
108+
109+
override fun internHashCode(): Int = hash(arg0, arg1)
110+
override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 })
111+
}
112+
113+
class KPrefixOfExpr internal constructor(
114+
ctx: KContext,
115+
val arg0: KExpr<KStringSort>,
116+
val arg1: KExpr<KStringSort>
117+
) : KApp<KBoolSort, KStringSort>(ctx) {
118+
override val sort: KBoolSort = ctx.mkBoolSort()
119+
120+
override val args: List<KExpr<KStringSort>>
121+
get() = listOf(arg0, arg1)
122+
123+
override val decl: KDecl<KBoolSort>
124+
get() = ctx.mkPrefixOfDecl()
125+
126+
override fun accept(transformer: KTransformerBase): KExpr<KBoolSort> {
127+
TODO("Not yet implemented")
128+
}
129+
130+
override fun internHashCode(): Int = hash(arg0, arg1)
131+
override fun internEquals(other: Any): Boolean = structurallyEqual(other, { arg0 }, { arg1 })
132+
}

0 commit comments

Comments
 (0)