Skip to content

Support SMT string literals and common string ops in translateTerm#1109

Open
tautschnig wants to merge 3 commits intomainfrom
fix-smt-translate-string-literal
Open

Support SMT string literals and common string ops in translateTerm#1109
tautschnig wants to merge 3 commits intomainfrom
fix-smt-translate-string-literal

Conversation

@tautschnig
Copy link
Copy Markdown
Contributor

translateSort already handles .prim .string, but translateTerm had no arm for .prim (.string _): any SMT string literal produced by the encoder would fall through to the catch-all and raise 'unsupported term'. Add the missing arm plus the two string operations already supported in Denote.lean so that the two translators agree on the end-to-end-supported subset.

Specifically, add arms for:

  • .prim (.string s) -> (mkString, toExpr s)
  • .app .str_length [s] _ -> (mkInt, Int.ofNat s.length)
  • .app .str_concat as _ -> (mkString, leftAssocOp mkStringAppend as)

mkStringAppend uses instHAppendOfAppend + instAppendString, which is the same instance chain Lean elaborates inferInstance to for HAppend String String String.

Regression tests in StrataTest/DL/SMT/TranslateTests.lean cover all three arms; each fails on origin/main (catch-all throw observable via #guard_msgs mismatch) and passes with this change. I additionally verified under a Meta.check-enabled harness that the produced Expr type-checks in the kernel, so the (fst = mkString/mkInt, snd = ...) pairs are internally consistent.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

translateSort already handles .prim .string, but translateTerm had no
arm for .prim (.string _): any SMT string literal produced by the
encoder would fall through to the catch-all and raise
'unsupported term'. Add the missing arm plus the two string operations
already supported in Denote.lean so that the two translators agree on
the end-to-end-supported subset.

Specifically, add arms for:
- .prim (.string s) -> (mkString, toExpr s)
- .app .str_length [s] _ -> (mkInt, Int.ofNat s.length)
- .app .str_concat as _ -> (mkString, leftAssocOp mkStringAppend as)

mkStringAppend uses instHAppendOfAppend + instAppendString, which is
the same instance chain Lean elaborates inferInstance to for
HAppend String String String.

Regression tests in StrataTest/DL/SMT/TranslateTests.lean cover all
three arms; each fails on origin/main (catch-all throw observable via
#guard_msgs mismatch) and passes with this change. I additionally
verified under a Meta.check-enabled harness that the produced Expr
type-checks in the kernel, so the (fst = mkString/mkInt, snd = ...)
pairs are internally consistent.

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the SMT-to-Lean translator so the supported string subset matches the string features already denoted elsewhere in the SMT layer. It adds missing translation support for string literals, string length, and string concatenation, plus regression tests covering those happy paths.

Changes:

  • Add translateTerm support for SMT string literals.
  • Add translation for str_length and str_concat into Lean Exprs.
  • Add regression tests for string literals, length, and concatenation translation.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
Strata/DL/SMT/Translate.lean Adds the new string-expression constructors and translation arms in translateTerm.
StrataTest/DL/SMT/TranslateTests.lean Adds #guard_msgs regression tests for the newly supported string cases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Strata/DL/SMT/Translate.lean Outdated
Comment thread Strata/DL/SMT/Translate.lean Outdated
Addresses the two review comments on PR #1109:

1. `.app .str_length` silently built `Int.ofNat (String.length x)` even
   when `x` was not a `String`.  Check the operand's translated type
   against `mkString` via a new `expectString` helper (shape mirrors
   `getBitVecWidth`), so malformed terms throw rather than producing an
   ill-typed `Expr` that only fails much later.

2. `.app .str_concat` delegated to `leftAssocOp`, which neither rejects
   fewer-than-two operands (despite its error message claiming it does)
   nor checks that operands have the expected type.  So
   `.app .str_concat [s]` silently translated to `s`, and a mixed-type
   list produced an ill-typed `HAppend.hAppend`.  Both diverged from
   `Denote.leftAssoc`.  Inline the op instead: require two or more
   operands explicitly and `expectString` every operand, matching what
   `Denote.leftAssoc` does for `str_concat`.

The underlying `leftAssocOp` bug (silent-singleton) affects every other
caller (`.app .add`, `.app .sub`, `.app .mul`, `.app .div`, `.app .mod`,
plus the bitvec analogues); it is pre-existing and will be fixed in a
separate PR so that the change set can be reviewed on its own merits.

Regression tests added in StrataTest/DL/SMT/TranslateTests.lean:
- A >2-ary happy-path `str_concat` to cover the foldl tail.
- `str_length` applied to a non-string operand.
- Singleton `str_concat`.
- `str_concat` with a non-string operand in first position.

Each error-path test fails on the previous commit (producing the
ill-typed `Expr` or the singleton pass-through) and passes here.  Tests
use `.prim (.bool _)` for the non-string operand so that the expected
error message is stable regardless of how `.prim (.int _)` happens to
be typed (see PR #1107).

Co-authored-by: Kiro <kiro-agent@users.noreply.github.com>
aqjune-aws
aqjune-aws previously approved these changes May 5, 2026
Copy link
Copy Markdown
Contributor

@aqjune-aws aqjune-aws left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine to me, but probably @kondylidou or @abdoo8080's view might be helpful.

@tautschnig
Copy link
Copy Markdown
Contributor Author

@keyboardDrummer-bot Please resolve git conflicts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants