Skip to content

Implement \real literals (#3570); fix LogicPrinter.quickPrintSemisequent (#243)#3865

Merged
unp1 merged 3 commits into
mainfrom
fix/key-core-printer-low
Jul 4, 2026
Merged

Implement \real literals (#3570); fix LogicPrinter.quickPrintSemisequent (#243)#3865
unp1 merged 3 commits into
mainfrom
fix/key-core-printer-low

Conversation

@unp1

@unp1 unp1 commented Jun 27, 2026

Copy link
Copy Markdown
Member

Related Issue

This pull request resolves #243 and #3570.

Intended Change

#243LogicPrinter.quickPrintSemisequent dropped the last formula

The method printed the semisequent without an enclosing layouter block, so the
pretty-printer never flushed its final pending break and the trailing formula was lost
(e.g. true, instead of true, false). The same formulas printed via a full sequent
rendered correctly because printSequent wraps its output in beginC/end. Fixed by
wrapping the semisequent in an explicit block, mirroring quickPrintTerm.

#3570 — real literals are now supported

\real literals such as 1.0r used to be rejected by the term parser. This PR
implements them end to end.

  • Exact, unbounded representation. A real is a mathematical value, so RealLiteral
    now stores it as an arbitrary-precision pair (unscaledValue, scale) with value
    unscaledValue * 10^(-scale) — the BigDecimal scheme, but with an unbounded
    BigInteger scale rather than an int, and kept in canonical form (trailing zeros
    stripped) so equal values have equal fields. BigDecimal is used only to parse bounded
    source strings, never to hold the value.
  • Term encoding. The literal is encoded as __R(unscaledValue, scale) over numbers
    (realHeader.key now declares real __R(numbers, numbers); and the real sort, moved
    out of integerHeader.key). TermBuilder.rTerm / RealLDT.translateLiteral /
    translateTerm build and decode it; because both operands are unbounded numbers, the
    value never passes through an int (a scale beyond Integer.MAX_VALUE round-trips).
  • Parsing. ExpressionBuilder.visitRealLiteral builds the term; a negative literal
    folds the sign into the literal (the real LDT has no neg), mirroring the existing
    integer-literal handling and using a bootstrap-safe namespace lookup.
  • Pretty-printing. A new Notation.RealLiteral prints __R(u, s) back as its
    canonical decimal with an r suffix (1.25r, -0.5r, 100r), the inverse of the
    parser; registered next to Z/FP/DFP.
  • Example + regression test. standard_key/reals/realLiterals.key showcases real
    literals, real-sorted quantification and a real-valued assignment (via an update); it is
    wired into runAllProofs (it proves and reloads, so the printer→parser round-trip is
    checked on every CI run).

Decisions worth highlighting

  • Reserved __ name. The wrapper is named __R rather than a bare identifier so it
    does not steal a name a user might declare in a problem file. This is the first user of a
    reserved-prefix convention; migrating the other built-in literal symbols
    (Z/C/FP/DFP) out of the user namespace is left as separate follow-up work.
  • Scope. The RealLDT is intentionally still a stub: there are no arithmetic axioms
    yet (no +, *, < on reals), so only equality/structural reasoning is available. The
    real type is also not yet usable inside Java program blocks (\<{ ... }\>), only in the
    logic and in JML; the example therefore models an assignment with an update. Axiomatising
    real arithmetic is a separate, larger piece of work.

Type of pull request

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • There are changes to the (Java) code

Ensuring quality

  • I made sure that introduced/changed code is well documented (javadoc and inline comments).
  • I added new test case(s):
    • Issue243Test — red before, green after the semisequent fix.
    • RealLDTTest — the (unscaledValue, scale) encoding round-trips (incl. negatives,
      leading-zero fractions, trailing-zero integers, and a scale beyond Integer.MAX_VALUE).
    • Issue3570Test — a real literal parses to sort real, and parser and pretty-printer
      are inverse (incl. negatives and trailing-zero canonicalization).
  • I have tested the feature as follows: the unit tests above, plus the full regression
    suites :key.core:testRAP -PrapForks=10 (674 — including the new reals proof, which is
    proved and reloaded) and :key.core:testProveRules (203) — all green.
  • I have checked that runtime performance has not deteriorated (the added parser/printer
    branches only fire for real literals; the extra namespace lookup mirrors the existing
    integer-literal handling on the same code path).

Additional information and contact(s)

PR prepared with AI tooling support.

The contributions within this pull request are licensed under GPLv2 (only) for inclusion in KeY.

@unp1 unp1 changed the title Fix semisequent printing (#243) and honest error for real literals (#3570) Fix semisequent printing (#243) and impoved error message for real literals (#3570) Jun 27, 2026
@unp1 unp1 self-assigned this Jun 27, 2026
@unp1 unp1 added the 🐞 Bug label Jun 27, 2026
@unp1 unp1 added this to the v3.0.0 milestone Jun 27, 2026
@unp1
unp1 marked this pull request as ready for review June 27, 2026 10:57
Comment thread key.core/src/main/java/de/uka/ilkd/key/nparser/builder/ExpressionBuilder.java Outdated
@unp1 unp1 modified the milestones: v3.0.0, v3.1.0 Jun 28, 2026
@unp1
unp1 force-pushed the fix/key-core-printer-low branch from be621b2 to b6407f4 Compare June 28, 2026 12:34
@unp1 unp1 changed the title Fix semisequent printing (#243) and impoved error message for real literals (#3570) Implement \real literals (#3570); fix LogicPrinter.quickPrintSemisequent (#243) Jun 28, 2026
@unp1
unp1 enabled auto-merge June 28, 2026 14:47
unp1 added 3 commits June 29, 2026 14:42
quickPrintSemisequent printed the semisequent without an enclosing
layouter block, so the pretty-printer never flushed its final pending
break and the trailing formula was lost (e.g. "true," instead of
"true, false"). The same formulas printed via a full sequent were
rendered correctly because printSequent wraps the output in beginC/end.

Wrap the semisequent in an explicit block, mirroring quickPrintTerm.

Created with AI tooling support
ExpressionBuilder.visitRealLiteral now builds the term form of a real
literal (__R(unscaledValue, scale)) instead of failing, reusing
RealLiteral for the exact decimal parse and TermBuilder.rTerm for the
encoding. A negative real folds the sign into the literal in
visitUnary_minus_term (the real LDT has no neg), mirroring the existing
integer-literal handling and using the bootstrap-safe namespace lookup
(the LDT objects are not yet constructed while the rule files are
parsed).

Notation.RealLiteral prints __R(u, s) back as its canonical decimal with
an 'r' suffix (e.g. 1.25r), registered for the __R symbol next to
Z/FP/DFP.

Issue3570Test now checks that a real literal parses to sort real and that
parser and printer are inverse (including negatives and trailing-zero
canonicalization).

Created with AI tooling support
@unp1
unp1 force-pushed the fix/key-core-printer-low branch from b6407f4 to dd8063f Compare June 29, 2026 14:30
@unp1
unp1 added this pull request to the merge queue Jul 4, 2026
Merged via the queue into main with commit 3913ff2 Jul 4, 2026
36 checks passed
@unp1
unp1 deleted the fix/key-core-printer-low branch July 4, 2026 15:11
@wadoon wadoon modified the milestones: v3.1.0, v3.0.0 Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No output of last term when using LogicPrinter.printSemisequent

2 participants