Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
100 commits
Select commit Hold shift + click to select a range
05cb44a
first steps to allow scripts in jml
mattulbrich Sep 8, 2025
f2dda5a
first working example of a proof script in Java code (albeit with Jav…
mattulbrich Sep 8, 2025
4344a2d
added missing files for script aware macros
mattulbrich Jan 30, 2023
1c3fc38
more infrastructure for proof scripts
mattulbrich Sep 8, 2025
c196cde
more infrastructure for proof scripts
mattulbrich Feb 4, 2023
2ea4459
more infrastructure for proof scripts
mattulbrich Sep 8, 2025
8c54f24
adapting to new Script AST nodes
mattulbrich Sep 8, 2025
69b8fea
renaming AssertCommand to FailUnlessCommand
mattulbrich Sep 8, 2025
50666bc
correcting the grammar for nested \by clauses
mattulbrich Sep 8, 2025
ffa7ba6
improving the value injector
mattulbrich Sep 10, 2025
db9eb87
renaming a deprecated command "assert" --> "assertOpenGoals"
mattulbrich Sep 10, 2025
2a8304c
spotless
mattulbrich Sep 12, 2025
6c67dc4
working version of scripts
mattulbrich Sep 24, 2025
c7b56ea
Position info for scripts with url=null, run scripted goals before ot…
mattulbrich Sep 24, 2025
034e24a
Use AutoPilotPrepareProofMacro instead of FinishSymbolicExecutionMacr…
mattulbrich Sep 24, 2025
0740303
working on improved script commands
mattulbrich Sep 24, 2025
6b758af
advancing the immutable list interface
mattulbrich May 26, 2023
f104911
reorganisation of proof script commands
mattulbrich Sep 24, 2025
42eb9de
advancing for scripts from JML
mattulbrich May 26, 2023
05b95aa
slight adaptation of the macro used for scripting
mattulbrich May 26, 2023
cb0d400
more script commands
mattulbrich Jun 2, 2023
6b47d13
improving/correcting script commands
mattulbrich Jun 5, 2023
b887c35
settings for the auto command
mattulbrich Jun 8, 2023
78982e7
propagating strategy settings to the strategy to be used
mattulbrich Jun 9, 2023
faa2111
proof scripts: adding a CHEAT command
mattulbrich Jun 15, 2023
a8d7f05
updating a few of the script commands
mattulbrich Jun 17, 2023
8bbceb9
introducing the script-aware prep macro
mattulbrich Jun 19, 2023
ff86820
issue dialog: skip spaces for squiggly lines
mattulbrich Jun 19, 2023
9dc5bce
value injector: towards reporting unknown arguments
mattulbrich Jun 19, 2023
f130727
improved script error reporting
mattulbrich Jun 19, 2023
70a573b
documentation for script commands
mattulbrich Jun 23, 2023
05d8231
better error messaging in ScriptLineParser
mattulbrich Jun 30, 2023
07449d6
implement a recall mechanism
mattulbrich Jun 30, 2023
02d0d13
allow let commands without "@"
mattulbrich Jul 7, 2023
1643e32
a formula parameter for the expand command
mattulbrich Jul 22, 2023
00a0b5e
spotlessing
mattulbrich Sep 27, 2025
f989a26
towards 'obtain' in JML scripts
mattulbrich Oct 1, 2025
73d8a3c
update ProofScriptEngine's workflow
mattulbrich Oct 1, 2025
a40923e
consolidating, introducing test cases for jml scripts
mattulbrich Oct 1, 2025
ae3af93
first working obtain scripts
mattulbrich Oct 1, 2025
ca5535c
pimping the document generation for proof script commands
mattulbrich Oct 2, 2025
784cb6b
lots of script documentation
mattulbrich Oct 2, 2025
b50ae5b
fixing a bug regarding proof script application
mattulbrich Oct 3, 2025
91e7683
repairing some weird self variable treatment in SpecStatement
mattulbrich Oct 3, 2025
b9eaea0
introducing "auto add_*" to scripts.
mattulbrich Jul 19, 2024
ea845b4
smaller fixes in proof script treatment
mattulbrich Oct 3, 2025
560a9db
The Boyer-Moore example now runs on scripts
mattulbrich Oct 3, 2025
dc36bcf
improved document generation
mattulbrich Oct 3, 2025
ce2626e
more proof script power, update inlining.
mattulbrich Oct 3, 2025
93b9f06
making sure that cuts work with boolean terms instead of formulas.
mattulbrich Oct 4, 2025
e412872
better symbex-only machine
mattulbrich Oct 5, 2025
1e4337c
Allowing "auto only: ..."
mattulbrich Oct 5, 2025
ebbdc4a
quicksort example with JML scripts (partially)
mattulbrich Oct 5, 2025
e436ac6
enabling the quicksort example with JML proof scripts!
mattulbrich Oct 5, 2025
7710004
limiting the symbex only macro a bit
mattulbrich Oct 6, 2025
dacea48
introducing hole placeholders for terms and for formulas
mattulbrich Jul 18, 2024
414c5ee
introducing witness command
mattulbrich Aug 11, 2024
b170888
adapting the cherry-picked commits
mattulbrich Oct 6, 2025
a8a6233
allowing switching off rules in auto
mattulbrich Oct 6, 2025
e973459
a more robust term-with-holes implementation
mattulbrich Oct 9, 2025
5aeb143
improved treatment of terms with holes
mattulbrich Oct 10, 2025
0fa404d
introduce match identifiers with leading '?'
mattulbrich Oct 10, 2025
d6e5919
introducing sort::FOCUS for usage in scripts
mattulbrich Jul 18, 2024
3ae260f
introducing sort::ELLIP for ellipsis search patterns
mattulbrich Jul 18, 2024
791b5d7
improving sophisticated term matching
mattulbrich Oct 10, 2025
487a3dc
accomodating "focus inside find"
mattulbrich Oct 10, 2025
9e380cb
add "assumes" parameter to rule command
mattulbrich Jul 19, 2024
c0e5311
bugfixing matching with program variables
mattulbrich Oct 10, 2025
744e747
updating the focus rule
mattulbrich Oct 10, 2025
6bfb288
allow terms with holes in expand command
WolframPfeifer Aug 13, 2024
ea2d7e2
added convenience macro to close all NPE and Out-of-bounds branches
WolframPfeifer Aug 28, 2024
f26c74c
bug fixes in script engine
mattulbrich Oct 11, 2025
59c6e36
repairing JML script tests
mattulbrich Oct 11, 2025
e2559ac
fixing a NPE bug in JavaProfile
mattulbrich Oct 15, 2025
eb4048c
improving symbex only macro
mattulbrich Oct 24, 2025
8dafd3e
adding an infinity catch on "throw null" in symb ex.
mattulbrich Oct 24, 2025
353d192
making the assume command use a local taclet.
mattulbrich Feb 17, 2026
dd7002e
correcting conversion in JML scripts
mattulbrich Feb 17, 2026
61671e3
adapting taclets.old.txt to changed throws treatment
mattulbrich Feb 17, 2026
c69c306
Repaired a merge test case
mattulbrich Feb 17, 2026
d0cd89f
missing sameUpdateLevel for tryCatchThrow
mattulbrich Feb 17, 2026
060368b
spotless
wadoon Feb 23, 2026
9f02f93
fix regression fixtures taclets.old.txt
wadoon Feb 23, 2026
459dd8c
fix rebasing
wadoon Apr 9, 2026
eeeba50
fix tests
wadoon Apr 9, 2026
5b9bc66
remove codecov
wadoon Apr 9, 2026
56caad6
spotless
wadoon Apr 12, 2026
fbb756f
add converter
wadoon Apr 17, 2026
7ed41e8
make userData type safe
wadoon Apr 19, 2026
83117b3
spotless
wadoon Apr 23, 2026
4053b76
fix SortDependingFunction uses
wadoon Apr 23, 2026
f2f0c1d
fix rebasing issue
wadoon Apr 25, 2026
7bd0ba3
update taclets.old.txt
wadoon Apr 25, 2026
91cc378
fix proof
wadoon Apr 25, 2026
d747893
fix lexer
wadoon Apr 25, 2026
d22aab3
fix checkerframework
wadoon Apr 25, 2026
f17bcf4
update proof
wadoon Apr 27, 2026
2c4cbd9
spotless
wadoon May 1, 2026
919643d
fix test case
wadoon May 1, 2026
5ce47e7
fix wrong test fixtures
wadoon May 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,6 @@ jobs:
**/build/reports/
!**/jacocoTestReport.xml

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v6

integration-tests:
env:
GH_TOKEN: ${{ github.token }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public Strategy<Goal> create(Proof proof, StrategyProperties sp) {
*/
@Override
public StrategySettingsDefinition getSettingsDefinition() {
return JavaProfile.DEFAULT.getSettingsDefinition();
return JavaProfile.getDefault().getSettingsDefinition();
}
}
}
9 changes: 9 additions & 0 deletions key.core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ dependencies {

api project(':key.util')

// Make Javadoc accessible at runtime
annotationProcessor 'com.github.therapi:therapi-runtime-javadoc-scribe:0.13.0'
implementation 'com.github.therapi:therapi-runtime-javadoc:0.13.0'

def JP_VERSION = "3.28.0-K13.5"
api "org.key-project.proofjava:javaparser-core:$JP_VERSION"
api "org.key-project.proofjava:javaparser-core-serialization:$JP_VERSION"
Expand All @@ -31,6 +35,10 @@ dependencies {
testFixturesApi(testFixtures(project(":key.util")))
}

tasks.withType(JavaCompile) {
options.compilerArgs << "-Ajavadoc.packages=de.uka.ilkd.key.scripts"
}

// The target directory for JavaCC (parser generation)
//def javaCCOutputDir = layout.buildDirectory.dir("generated-src/javacc").getOrNull()
//def javaCCOutputDirMain = file("$javaCCOutputDir/main")
Expand Down Expand Up @@ -97,6 +105,7 @@ classes.dependsOn << generateSolverPropsList

tasks.withType(Test) {
enableAssertions = true
systemProperties(System.properties.findAll { key, value -> key.startsWith("key.") })
}


Expand Down
3 changes: 3 additions & 0 deletions key.core/src/main/antlr4/JmlLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ mode expr;
/* Java keywords */
BOOLEAN: 'boolean';
BYTE: 'byte';
CASE: 'case';
DEFAULT: 'default';
FALSE: 'false';
INSTANCEOF: 'instanceof';
INT: 'int';
Expand Down Expand Up @@ -244,6 +246,7 @@ FP_SUBNORMAL: '\\fp_subnormal'; //KeY extension, not official JML
FP_ZERO: '\\fp_zero'; //KeY extension, not official JML
FREE: '\\free'; //KeY extension, not official JML
FRESH: '\\fresh';
FROM_GOAL: '\\from_goal'; //KeY extension, not official JML
INDEX: '\\index';
INDEXOF: '\\seq_indexOf'; //KeY extension, not official JML
INTERSECT: '\\intersect'; //KeY extension, not official JML
Expand Down
28 changes: 27 additions & 1 deletion key.core/src/main/antlr4/JmlParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ options { tokenVocab=JmlLexer; }
@members {
private SyntaxErrorReporter errorReporter = new SyntaxErrorReporter(getClass());
public SyntaxErrorReporter getErrorReporter() { return errorReporter;}
private boolean isNextToken(String tokenText) {
return _input.LA(1) != Token.EOF && tokenText.equals(_input.LT(1).getText());
}
}

modifiersEOF: modifiers EOF;
Expand Down Expand Up @@ -203,12 +206,35 @@ block_specification: method_specification;
block_loop_specification:
loop_contract_keyword spec_case ((also_keyword)+ loop_contract_keyword spec_case)*;
loop_contract_keyword: LOOP_CONTRACT;
assert_statement: (ASSERT expression | UNREACHABLE) SEMI_TOPLEVEL;
assert_statement: (ASSERT (label=IDENT COLON)? expression | UNREACHABLE) (assertionProof SEMI_TOPLEVEL? | SEMI_TOPLEVEL);
//breaks_clause: BREAKS expression;
//continues_clause: CONTINUES expression;
//returns_clause: RETURNS expression;


// --- proof scripts in JML
assertionProof: BY (proofCmd | LBRACE ( proofCmd )+ RBRACE) ;
proofCmd:
// TODO allow more than one var in obtain
{ isNextToken("obtain") }? obtain=IDENT typespec var=IDENT
( obtKind=EQUAL_SINGLE expression SEMI
| obtKind=SUCH_THAT expression proofCmdSuffix
| obtKind=FROM_GOAL SEMI
)
| cmd=IDENT ( proofArg )* proofCmdSuffix
;

proofCmdSuffix:
SEMI | BY ( proofCmd | LBRACE (proofCmd+ | proofCmdCase+) RBRACE )
;

proofCmdCase:
CASE ( label=STRING_LITERAL )? COLON ( proofCmd )*
| DEFAULT COLON ( proofCmd )*
;
proofArg: (argLabel=IDENT COLON)? expression;
Comment thread
wadoon marked this conversation as resolved.
// ---

mergeparamsspec:
MERGE_PARAMS
LBRACE
Expand Down
4 changes: 3 additions & 1 deletion key.core/src/main/antlr4/KeYLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ lexer grammar KeYLexer;
}

private Token tokenBackStorage = null;
// see: https://keyproject.github.io/key-docs/devel/NewKeyParser/#why-does-the-lexer-required-some-pieces-of-java-code
@Override
public void emit(Token token) {
int MAX_K = 10;
Expand Down Expand Up @@ -220,6 +221,7 @@ AXIOMS : '\\axioms';
PROBLEM : '\\problem';
CHOOSECONTRACT : '\\chooseContract';
PROOFOBLIGATION : '\\proofObligation';
// for PROOF see: https://keyproject.github.io/key-docs/devel/NewKeyParser/#why-does-the-lexer-required-some-pieces-of-java-code
PROOF : '\\proof';
PROOFSCRIPT : '\\proofScript';
CONTRACTS : '\\contracts';
Expand Down Expand Up @@ -428,7 +430,7 @@ fragment HEX
fragment LETTER: 'a'..'z'|'A'..'Z';
fragment IDCHAR: LETTER | DIGIT | '_' | '#' | '$';


MATCH_IDENT: '?' IDENT?;
IDENT: ( (LETTER | '_' | '#' | '$') (IDCHAR)*);

INT_LITERAL:
Expand Down
4 changes: 3 additions & 1 deletion key.core/src/main/antlr4/KeYParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ parser grammar KeYParser;
@members {
private SyntaxErrorReporter errorReporter = new SyntaxErrorReporter(getClass());
public SyntaxErrorReporter getErrorReporter() { return errorReporter;}
public boolean allowMatchId = false; // used in proof script parsing
}

options { tokenVocab=KeYLexer; } // use tokens from STLexer.g4
Expand Down Expand Up @@ -154,6 +155,7 @@ string_value: STRING_LITERAL;
simple_ident
:
id=IDENT
| {allowMatchId}? id=MATCH_IDENT
;

simple_ident_comma_list
Expand Down Expand Up @@ -901,7 +903,7 @@ proofScriptExpression:
| integer
| floatnum
| string_literal
| LPAREN (term | seq) RPAREN
| LPAREN {allowMatchId=true;} (term | seq) {allowMatchId=false;} RPAREN
| simple_ident
| abbreviation
| literals
Expand Down
2 changes: 1 addition & 1 deletion key.core/src/main/java/de/uka/ilkd/key/java/JavaInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,7 @@ public static boolean isVisibleTo(SpecificationElement ax, KeYJavaType visibleTo
/**
* returns a KeYJavaType having the given sort
*/
public KeYJavaType getKeYJavaType(Sort sort) {
public @Nullable KeYJavaType getKeYJavaType(Sort sort) {
List<KeYJavaType> l = lookupSort2KJTCache(sort);
if (l != null && l.size() > 0) {
// Return first KeYJavaType found for sort.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@
import de.uka.ilkd.key.java.ast.PositionInfo;
import de.uka.ilkd.key.java.ast.ProgramElement;
import de.uka.ilkd.key.java.visitor.Visitor;
import de.uka.ilkd.key.logic.op.LocationVariable;
import de.uka.ilkd.key.nparser.KeyAst;
import de.uka.ilkd.key.speclang.jml.pretranslation.TextualJMLAssertStatement;
import de.uka.ilkd.key.speclang.njml.JmlIO;
import de.uka.ilkd.key.speclang.njml.JmlParser;

import org.key_project.util.ExtList;
import org.key_project.util.collection.ImmutableList;

import org.jspecify.annotations.NonNull;
import org.jspecify.annotations.Nullable;

/**
* A JML assert statement.
Expand All @@ -29,24 +36,36 @@ public class JmlAssert extends JavaStatement {
*/
private final TextualJMLAssertStatement.Kind kind;

/*
* Temporary solution until full jml labels are there ...
* (To be clarified if compatible still)
*/
private final String optLabel;

/**
* the condition in parse tree form
*/
private KeyAst.Expression condition;
private final KeyAst.Expression condition;

/**
* the assertion proof in parse tree form
*/
private final KeyAst.@Nullable JMLProofScript assertionProof;

/**
* @param kind
* assert or assume
* @param condition
* the condition of this statement
* @param positionInfo
* the position information for this statement
* @param kind assert or assume
* @param condition the condition of this statement
* @param assertionProof the optional proof for an assert statement (not for assume)
* @param positionInfo the position information for this statement
*/
public JmlAssert(TextualJMLAssertStatement.Kind kind, KeyAst.Expression condition,
public JmlAssert(TextualJMLAssertStatement.Kind kind, String label, KeyAst.Expression condition,
KeyAst.@Nullable JMLProofScript assertionProof,
PositionInfo positionInfo) {
super(positionInfo);
this.kind = kind;
this.optLabel = label;
this.condition = condition;
this.assertionProof = assertionProof;
}

/**
Expand All @@ -56,11 +75,25 @@ public JmlAssert(TextualJMLAssertStatement.Kind kind, KeyAst.Expression conditio
public JmlAssert(ExtList children) {
super(children);
this.kind = Objects.requireNonNull(children.get(TextualJMLAssertStatement.Kind.class));
this.optLabel = children.get(String.class);
this.condition = Objects.requireNonNull(children.get(KeyAst.Expression.class));
// script may be null
this.assertionProof = children.get(KeyAst.JMLProofScript.class);
}

public JmlAssert(JmlAssert other) {
this(other.kind, other.condition, other.getPositionInfo());
this(other.kind, other.optLabel, other.condition, other.assertionProof,
other.getPositionInfo());
}

public JmlAssert(TextualJMLAssertStatement.Kind kind, TextualJMLAssertStatement construct,
PositionInfo pi) {
super(pi);
this.kind = kind;
this.optLabel = construct.getOptLabel();
this.condition = construct.getContext();
// script may be null
this.assertionProof = construct.getAssertionProof();
}

public TextualJMLAssertStatement.Kind getKind() {
Expand Down Expand Up @@ -152,6 +185,10 @@ protected int computeHashCode() {
return System.identityHashCode(this);
}

public KeyAst.@Nullable JMLProofScript getAssertionProof() {
return assertionProof;
}

@Override
public int getChildCount() {
return 0;
Expand All @@ -166,4 +203,30 @@ public ProgramElement getChildAt(int index) {
public void visit(Visitor v) {
v.performActionOnJmlAssert(this);
}

/**
* This method collects all terms contained in this assertion. This is at least the condition.
* If there is a proof script, all terms in the proof script are collected as well.
*
* @return a freshly created list of at least one term
*/
public @NonNull ImmutableList<JmlParser.ExpressionContext> collectTerms() {
ImmutableList<JmlParser.ExpressionContext> result = ImmutableList.of();
if (assertionProof != null) {
result = result.prepend(assertionProof.collectTerms());
}
result = result.prepend(condition.ctx);
return result;
}

public ImmutableList<LocationVariable> collectVariablesInProof(JmlIO io) {
if (assertionProof != null) {
return assertionProof.getObtainedProgramVars(io);
}
return ImmutableList.of();
}

public String getOptLabel() {
return optLabel;
}
}
Loading
Loading