@@ -170,6 +170,90 @@ inline fun KContext.simplifyStringBasicContainsExpr(
170170 cont(arg0, arg1)
171171 }
172172
173+ /*
174+ * Substring expressions simplifications
175+ * */
176+
177+ inline fun KContext.simplifyStringSingletonSubExprBasic (
178+ arg0 : KExpr <KStringSort >,
179+ arg1 : KExpr <KIntSort >,
180+ cont : (KExpr <KStringSort >, KExpr <KIntSort >) -> KExpr <KStringSort >
181+ ): KExpr <KStringSort > {
182+ return if (arg0 is KStringLiteralExpr && arg1 is KIntNumExpr ) {
183+ val str = arg0.value
184+ val pos = when (arg1) {
185+ is KInt32NumExpr -> arg1.value.toLong()
186+ is KInt64NumExpr -> arg1.value
187+ is KIntBigNumExpr -> arg1.value.toLong()
188+ else -> return cont(arg0, arg1)
189+ }
190+ val result = if (pos <= Int .MAX_VALUE && pos >= 0 && pos < str.length) {
191+ str[pos.toInt()].toString()
192+ } else {
193+ " "
194+ }
195+ mkStringLiteral(result)
196+ } else {
197+ cont(arg0, arg1)
198+ }
199+ }
200+
201+ inline fun KContext.simplifyStringSubExprBasic (
202+ arg0 : KExpr <KStringSort >,
203+ arg1 : KExpr <KIntSort >,
204+ arg2 : KExpr <KIntSort >,
205+ cont : (KExpr <KStringSort >, KExpr <KIntSort >, KExpr <KIntSort >) -> KExpr <KStringSort >
206+ ): KExpr <KStringSort > {
207+ return if (arg0 is KStringLiteralExpr && arg1 is KIntNumExpr && arg2 is KIntNumExpr ) {
208+ val str = arg0.value
209+ val startPos = arg1.toLongValue()
210+ val length = arg2.toLongValue()
211+ val result = if (startPos in 0 .. Int .MAX_VALUE && length in 0 .. Int .MAX_VALUE && startPos < str.length) {
212+ val endPos = minOf(startPos + length, str.length.toLong()).toInt()
213+ str.substring(startPos.toInt(), endPos)
214+ } else {
215+ " "
216+ }
217+ mkStringLiteral(result)
218+ } else {
219+ cont(arg0, arg1, arg2)
220+ }
221+ }
222+
223+ inline fun KContext.simplifyStringIndexOfExprBasic (
224+ arg0 : KExpr <KStringSort >, // Исходная строка (s)
225+ arg1 : KExpr <KStringSort >, // Подстрока для поиска (t)
226+ arg2 : KExpr <KIntSort >, // Начальная позиция (i)
227+ cont : (KExpr <KStringSort >, KExpr <KStringSort >, KExpr <KIntSort >) -> KExpr <KIntSort >
228+ ): KExpr <KIntSort > = with (arg0.ctx) {
229+
230+ if (arg0 is KStringLiteralExpr && arg1 is KStringLiteralExpr && arg2 is KIntNumExpr ) {
231+ val str = arg0.value
232+ val search = arg1.value
233+ val startPosLong = arg2.toLongValue()
234+ val startPos: Int
235+ if (startPosLong <= Int .MAX_VALUE ) {
236+ startPos = startPosLong.toInt()
237+ } else {
238+ return cont(arg0, arg1, arg2)
239+ }
240+
241+ val result = if (startPos >= 0 && startPos <= str.length) {
242+ if (search.isEmpty()) {
243+ startPos
244+ } else {
245+ val index = str.indexOf(search, startPos)
246+ if (index >= 0 ) index else - 1
247+ }
248+ } else {
249+ - 1
250+ }
251+ return mkIntNum(result)
252+ } else {
253+ return cont(arg0, arg1, arg2)
254+ }
255+ }
256+
173257/*
174258* String replace expressions simplifications
175259* */
@@ -325,3 +409,10 @@ inline fun <K: KSort> tryEvalStringLiteralOperation(
325409} else {
326410 cont()
327411}
412+
413+ fun KIntNumExpr.toLongValue (): Long = when (this ) {
414+ is KInt32NumExpr -> value.toLong()
415+ is KInt64NumExpr -> value
416+ is KIntBigNumExpr -> value.toLong()
417+ else -> throw IllegalArgumentException (" Unsupported KIntNumExpr type: ${this ::class } " )
418+ }
0 commit comments