From 7f701241985c0f04b6c6b7934749302bc9e33ec2 Mon Sep 17 00:00:00 2001 From: Mattias Ulbrich Date: Sat, 8 Dec 2018 10:17:13 +0100 Subject: [PATCH 01/13] adding "replace" in immutable lists. --- .../util/collection/TestSLList.java | 47 +++++++++++++++++++ .../util/suite/AllCollectionTests.java | 2 + .../util/collection/ImmutableList.java | 10 ++++ .../util/collection/ImmutableSLList.java | 20 ++++++++ 4 files changed, 79 insertions(+) create mode 100644 key/key.util.test/src/org/key_project/util/collection/TestSLList.java diff --git a/key/key.util.test/src/org/key_project/util/collection/TestSLList.java b/key/key.util.test/src/org/key_project/util/collection/TestSLList.java new file mode 100644 index 00000000000..5057a0697c7 --- /dev/null +++ b/key/key.util.test/src/org/key_project/util/collection/TestSLList.java @@ -0,0 +1,47 @@ +package org.key_project.util.collection; + +import static org.junit.Assert.*; + +import org.junit.Test; + +public class TestSLList { + + @Test + public void testRemoveAll() { + ImmutableList l = ImmutableSLList.nil().prepend(1,2,1,2); + + assertEquals("[1,1]", l.removeAll(2).toString()); + } + + @Test + public void testMap() { + ImmutableList l = ImmutableSLList.nil().prepend(1,2,-1,-2); + + assertEquals("[1,4,1,4]", l.map(x -> x*x).toString()); + } + + @Test + public void testReplace() { + ImmutableList l = ImmutableSLList.nil().prepend(1,2,3,4); + + assertEquals("[1,2,0,4]", l.replace(2, 0).toString()); + assertEquals("[0,2,3,4]", l.replace(0, 0).toString()); + assertEquals("[1,2,3,0]", l.replace(3, 0).toString()); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void testReplaceBounds1() { + ImmutableList l = ImmutableSLList.nil().prepend(1,2,3,4); + + System.out.println(l.replace(-1, 0)); + } + + // revealed a bug + @Test(expected = IndexOutOfBoundsException.class) + public void testReplaceBounds2() { + ImmutableList l = ImmutableSLList.nil().prepend(1,2,3,4); + + System.out.println(l.replace(4, 0)); + } + +} diff --git a/key/key.util.test/src/org/key_project/util/suite/AllCollectionTests.java b/key/key.util.test/src/org/key_project/util/suite/AllCollectionTests.java index edae5abe1e7..023425c8187 100644 --- a/key/key.util.test/src/org/key_project/util/suite/AllCollectionTests.java +++ b/key/key.util.test/src/org/key_project/util/suite/AllCollectionTests.java @@ -16,6 +16,7 @@ import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.key_project.util.collection.TestImmutables; +import org.key_project.util.collection.TestSLList; import org.key_project.util.testcase.collection.TestLeftistHeapOfInteger; import org.key_project.util.testcase.collection.TestMapAsListFromIntegerToString; import org.key_project.util.testcase.collection.TestSLListOfString; @@ -31,6 +32,7 @@ TestMapAsListFromIntegerToString.class, TestSetAsListOfString.class, TestSLListOfString.class, + TestSLList.class, TestImmutables.class }) public class AllCollectionTests { diff --git a/key/key.util/src/org/key_project/util/collection/ImmutableList.java b/key/key.util/src/org/key_project/util/collection/ImmutableList.java index 6dbf51b23a5..4e15d887d62 100644 --- a/key/key.util/src/org/key_project/util/collection/ImmutableList.java +++ b/key/key.util/src/org/key_project/util/collection/ImmutableList.java @@ -176,4 +176,14 @@ default Stream stream() { return StreamSupport.stream(this.spliterator(), false); } + /** + * Replace the element at position {@code pos} in the list + * by the value {@code t}. + * + * @param pos the position within the list {@code 0 <= pos && pos < size()} + * @param t the element to set, may be {@code null}. + * @return an immutable list in which only the element at pos has been replaced. + * @throws IndexOutOfBoundsException if pos is not a valid index in the list. + */ + ImmutableList replace(int pos, T t); } \ No newline at end of file diff --git a/key/key.util/src/org/key_project/util/collection/ImmutableSLList.java b/key/key.util/src/org/key_project/util/collection/ImmutableSLList.java index 0a062efc6fa..39954c87f7a 100644 --- a/key/key.util/src/org/key_project/util/collection/ImmutableSLList.java +++ b/key/key.util/src/org/key_project/util/collection/ImmutableSLList.java @@ -162,6 +162,26 @@ public ImmutableList take(int n) { } + // Implemented imperatively to avoid arbitrarily deep recursion + @Override + public ImmutableList replace(int pos, T s) { + if(pos < 0 || pos >= size()) { + throw new IndexOutOfBoundsException(); + } + + ImmutableList already = nil(); + ImmutableList rest = this; + + while(pos > 0) { + already = already.prepend(rest.head()); + rest = rest.tail(); + pos --; + } + + return rest.tail().prepend(s).prepend(already.reverse()); + } + + private static class Cons extends ImmutableSLList { /** From 41dc52a49110f502494c7a3058301e4abcb25beb Mon Sep 17 00:00:00 2001 From: Mattias Ulbrich Date: Sat, 8 Dec 2018 10:21:07 +0100 Subject: [PATCH 02/13] cleaning up the sort infrastructure a little --- .../uka/ilkd/key/logic/sort/AbstractSort.java | 34 ---------- .../de/uka/ilkd/key/logic/sort/NullSort.java | 40 ++--------- .../ilkd/key/logic/sort/ProgramSVSort.java | 4 -- .../src/de/uka/ilkd/key/logic/sort/Sort.java | 68 +++++++++++++++---- 4 files changed, 59 insertions(+), 87 deletions(-) diff --git a/key/key.core/src/de/uka/ilkd/key/logic/sort/AbstractSort.java b/key/key.core/src/de/uka/ilkd/key/logic/sort/AbstractSort.java index e9bc10c0e11..a4a1187f328 100644 --- a/key/key.core/src/de/uka/ilkd/key/logic/sort/AbstractSort.java +++ b/key/key.core/src/de/uka/ilkd/key/logic/sort/AbstractSort.java @@ -80,44 +80,10 @@ public final Name name() { public final boolean isAbstract() { return isAbstract; } - - @Override - public final SortDependingFunction getCastSymbol(TermServices services) { - SortDependingFunction result - = SortDependingFunction.getFirstInstance(CAST_NAME, services) - .getInstanceFor(this, services); - assert result.getSortDependingOn() == this && result.sort() == this; - return result; - } - - - @Override - public final SortDependingFunction getInstanceofSymbol(TermServices services) { - SortDependingFunction result - = SortDependingFunction.getFirstInstance(INSTANCE_NAME, services) - .getInstanceFor(this, services); - assert result.getSortDependingOn() == this; - return result; - } - - - @Override - public final SortDependingFunction getExactInstanceofSymbol(TermServices services) { - SortDependingFunction result - = SortDependingFunction.getFirstInstance(EXACT_INSTANCE_NAME, services) - .getInstanceFor(this, services); - assert result.getSortDependingOn() == this; - return result; - } - - @Override public final String toString() { return name.toString(); } - public String declarationString() { - return name.toString(); - } } \ No newline at end of file diff --git a/key/key.core/src/de/uka/ilkd/key/logic/sort/NullSort.java b/key/key.core/src/de/uka/ilkd/key/logic/sort/NullSort.java index 9efb9f9da48..604a393e455 100644 --- a/key/key.core/src/de/uka/ilkd/key/logic/sort/NullSort.java +++ b/key/key.core/src/de/uka/ilkd/key/logic/sort/NullSort.java @@ -71,6 +71,12 @@ public ImmutableSet extendsSorts(Services services) { assert objectSort == services.getJavaInfo().objectSort(); ImmutableSet result = extCache.get(); + + // FIXME: This cache may be illegal. + // The service object may be the same, yet some types + // may have been added to the sort namespace. + // MU 2018 + if(result == null || lastServices.get() != services) { result = DefaultImmutableSet.nil(); @@ -103,43 +109,9 @@ public boolean isAbstract() { } - @Override - public final SortDependingFunction getCastSymbol(TermServices services) { - SortDependingFunction result - = SortDependingFunction.getFirstInstance(CAST_NAME, services) - .getInstanceFor(this, services); - assert result.getSortDependingOn() == this && result.sort() == this; - return result; - } - - - @Override - public final SortDependingFunction getInstanceofSymbol(TermServices services) { - SortDependingFunction result - = SortDependingFunction.getFirstInstance(INSTANCE_NAME, services) - .getInstanceFor(this, services); - assert result.getSortDependingOn() == this; - return result; - } - - - @Override - public final SortDependingFunction getExactInstanceofSymbol(TermServices services) { - SortDependingFunction result - = SortDependingFunction.getFirstInstance(EXACT_INSTANCE_NAME, services) - .getInstanceFor(this, services); - assert result.getSortDependingOn() == this; - return result; - } - - @Override public final String toString() { return NAME.toString(); } - @Override - public String declarationString() { - return NAME.toString(); - } } \ No newline at end of file diff --git a/key/key.core/src/de/uka/ilkd/key/logic/sort/ProgramSVSort.java b/key/key.core/src/de/uka/ilkd/key/logic/sort/ProgramSVSort.java index a1fbad68796..b8aa4a7026e 100644 --- a/key/key.core/src/de/uka/ilkd/key/logic/sort/ProgramSVSort.java +++ b/key/key.core/src/de/uka/ilkd/key/logic/sort/ProgramSVSort.java @@ -1028,10 +1028,6 @@ public ProgramSVSort createInstance(String parameter) { return new MethodNameSort(new ProgramElementName(parameter)); } - public String declarationString() { - return name().toString(); - } - } /** diff --git a/key/key.core/src/de/uka/ilkd/key/logic/sort/Sort.java b/key/key.core/src/de/uka/ilkd/key/logic/sort/Sort.java index a74a0c158e8..554605e42e2 100644 --- a/key/key.core/src/de/uka/ilkd/key/logic/sort/Sort.java +++ b/key/key.core/src/de/uka/ilkd/key/logic/sort/Sort.java @@ -27,28 +27,41 @@ public interface Sort extends Named { /** * Formulas are represented as "terms" of this sort. */ - final Sort FORMULA = new SortImpl(new Name("Formula")); + Sort FORMULA = new SortImpl(new Name("Formula")); /** * Updates are represented as "terms" of this sort. */ - final Sort UPDATE = new SortImpl(new Name("Update")); + Sort UPDATE = new SortImpl(new Name("Update")); /** * Term labels are represented as "terms" of this sort. */ - final Sort TERMLABEL = new SortImpl(new Name("TermLabel")); + Sort TERMLABEL = new SortImpl(new Name("TermLabel")); /** * Any is a supersort of all sorts. */ - final Sort ANY = new SortImpl(new Name("any")); - - public final Name CAST_NAME = new Name("cast"); - final Name INSTANCE_NAME = new Name("instance"); - final Name EXACT_INSTANCE_NAME = new Name("exactInstance"); - - + Sort ANY = new SortImpl(new Name("any")); + + /** + * The base name for the cast function family. + * Individual functions are called e.g. "C::cast" for sort C. + */ + Name CAST_NAME = new Name("cast"); + + /** + * The base name for the instance (type membership) function family. + * Individual functions are called e.g. "C::instance" for sort C. + */ + Name INSTANCE_NAME = new Name("instance"); + + /** + * The base name for the exact type membership function family. + * Individual functions are called e.g. "C::exactInstace" for sort C. + */ + Name EXACT_INSTANCE_NAME = new Name("exactInstance"); + /** * Returns the direct supersorts of this sort. Not supported by NullSort. */ @@ -73,17 +86,42 @@ public interface Sort extends Named { /** * returns the cast symbol of this Sort */ - SortDependingFunction getCastSymbol(TermServices services); + default SortDependingFunction getCastSymbol(TermServices services) { + SortDependingFunction result + = SortDependingFunction.getFirstInstance(CAST_NAME, services) + .getInstanceFor(this, services); + assert result.getSortDependingOn() == this && result.sort() == this; + return result; + } /** * returns the instanceof symbol of this Sort */ - SortDependingFunction getInstanceofSymbol(TermServices services); - + default SortDependingFunction getInstanceofSymbol(TermServices services) { + SortDependingFunction result + = SortDependingFunction.getFirstInstance(INSTANCE_NAME, services) + .getInstanceFor(this, services); + assert result.getSortDependingOn() == this; + return result; + } + /** * returns the exactinstanceof symbol of this Sort */ - SortDependingFunction getExactInstanceofSymbol(TermServices services); + default SortDependingFunction getExactInstanceofSymbol(TermServices services) { + SortDependingFunction result + = SortDependingFunction.getFirstInstance(EXACT_INSTANCE_NAME, services) + .getInstanceFor(this, services); + assert result.getSortDependingOn() == this; + return result; + } - String declarationString(); + /** + * returns the string to be used for declarations. + * + * As of Dec 2018, all implementations use {@link #name()} for this value. + */ + default String declarationString() { + return name().toString(); + } } From 06eaf1570da6425ff9d47a50bc360cf5e6d4f729 Mon Sep 17 00:00:00 2001 From: Mattias Ulbrich Date: Thu, 29 Nov 2018 19:06:50 +0100 Subject: [PATCH 03/13] towards parameterised types --- .../ilkd/key/logic/sort/ParametricSort.java | 108 ++++++++++++++++++ .../logic/sort/ParametricSortInstance.java | 93 +++++++++++++++ .../src/de/uka/ilkd/key/parser/KeYLexer.g | 6 + .../src/de/uka/ilkd/key/parser/KeYParser.g | 11 +- .../util/collection/DefaultImmutableSet.java | 10 +- .../util/collection/ImmutableList.java | 15 ++- .../util/collection/ImmutableSLList.java | 9 ++ .../util/collection/ImmutableSet.java | 13 +++ 8 files changed, 260 insertions(+), 5 deletions(-) create mode 100644 key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSort.java create mode 100644 key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java diff --git a/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSort.java b/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSort.java new file mode 100644 index 00000000000..96fbf3858d6 --- /dev/null +++ b/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSort.java @@ -0,0 +1,108 @@ +package de.uka.ilkd.key.logic.sort; + +import de.uka.ilkd.key.logic.Name; +import org.key_project.util.collection.ImmutableList; +import org.key_project.util.collection.ImmutableSet; + +import java.util.IdentityHashMap; +import java.util.function.Function; + +/** + * + * Here is a short class diagram, written for PlantUML. + * You can create the PNG file by feeding this SourceFile into PlantUML or + * by entering the text into https://www.planttext.com/, e.g. + * + * @startuml + * + * interface Sort + * abstract class AbstractSort + * class SortImpl + * + * class PolymorphicSort + * class PolymorphicSortInstance + * class NullSort + * class GenericSort + * + * Sort <|-- AbstractSort + * AbstractSort <|-- SortImpl + * AbstractSort <|-- PolymorphicSort + * AbstractSort <|-- GenericSort + * Sort <|-- PolymorphicSortInstance + * Sort <|-- NullSort + * + * PolymorphicSortInstance --> "1" PolymorphicSort : base + * PolymorphicSortInstance --> "*" Sort :args + * PolymorphicSort --> "*" GenericSort : typeParameters + * + * + * PolymorphicSort : bounds : List[Variance] + * + * enum Variance { + * COVARIANT + * CONTRAVARIANT + * INVARIANT + * } + * @enduml + */ + +public class ParametricSort extends AbstractSort { + + public enum Variance { + COVARIANT, + CONTRAVARIANT, + INVARIANT + } + + private final ImmutableList parameters; + + private final ImmutableList covariances; + + public ParametricSort(Name name, ImmutableSet ext, boolean isAbstract, + ImmutableList parameters, ImmutableList covariances) { + super(name, ext, isAbstract); + this.parameters = parameters; + this.covariances = covariances; + } + + public Function getInstantiation(ImmutableList args) { + IdentityHashMap map = new IdentityHashMap<>(); + + if(args.size() != parameters.size()) { + throw new IllegalArgumentException("Parametric type " + name() + + " expected " + parameters.size() + " arguments, but received " + + args); + } + + ImmutableList p = parameters; + while(!args.isEmpty()) { + map.put(p.head(), args.head()); + p = p.tail(); + args = args.tail(); + } + + return new Function() { + @Override + public Sort apply(Sort sort) { + Sort mapped = map.get(sort); + if(mapped != null) { + return mapped; + } + if (sort instanceof ParametricSortInstance) { + ParametricSortInstance psort = (ParametricSortInstance) sort; + return psort.map(this::apply); + } else { + return sort; + } + } + }; + } + + public ImmutableList getParameters() { + return parameters; + } + + public ImmutableList getCovariances() { + return covariances; + } +} diff --git a/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java b/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java new file mode 100644 index 00000000000..4a3e9bb6f0d --- /dev/null +++ b/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java @@ -0,0 +1,93 @@ +package de.uka.ilkd.key.logic.sort; + +import de.uka.ilkd.key.logic.Name; +import org.key_project.util.collection.DefaultImmutableSet; +import org.key_project.util.collection.ImmutableList; +import org.key_project.util.collection.ImmutableSet; + +import java.util.Map; +import java.util.WeakHashMap; +import java.util.function.Function; + +public class ParametricSortInstance extends AbstractSort { + + private static Map CACHE = new WeakHashMap<>(); + + private final ImmutableList parameters; + + private final ParametricSort base; + + public static ParametricSortInstance get(ParametricSort base, ImmutableList parameters) { + ParametricSortInstance sort = new ParametricSortInstance(base, parameters); + ParametricSortInstance cached = CACHE.get(sort); + if (cached != null) { + return cached; + } else { + return sort; + } + } + + private ParametricSortInstance(ParametricSort base, ImmutableList parameters) { + super(makeName(base, parameters), + computeExt(base, parameters), base.isAbstract()); + + this.base = base; + this.parameters = parameters; + } + + private static ImmutableSet computeExt(ParametricSort base, ImmutableList parameters) { + + ImmutableSet result = DefaultImmutableSet.nil(); + + // 1. extensions by base sort + ImmutableSet baseExt = base.extendsSorts(); + if(!baseExt.isEmpty()) { + Function inster = base.getInstantiation(parameters); + for (Sort s : baseExt) { + result = result.add(inster.apply(s)); + } + } + + // 2. extensions by variances + ImmutableList cov = base.getCovariances(); + for (int i = 0; !cov.isEmpty(); i++) { + switch(cov.head()) { + case COVARIANT: + // take all bases of that arg and add the modified sort as ext class + for (Sort s : parameters) { + ImmutableList newArgs = parameters.replace(i, s); + result = result.add(ParametricSortInstance.get(base, newArgs)); + } + break; + + case CONTRAVARIANT: + throw new UnsupportedOperationException("Contravariance can currently not be supported"); + + case INVARIANT: + // Nothing to be done + break; + } + } + + return result; + + } + + private static Name makeName(Sort base, ImmutableList parameters) { + return new Name(base + "<" + parameters + ">"); + } + + public Sort getBase() { + return base; + } + + public ImmutableList getParameters() { + return parameters; + } + + public ParametricSortInstance map(Function f) { + ImmutableList newParameters = parameters.map(f); + // The cache ensures that no unnecessary duplicates are kept. + return get(base, newParameters); + } +} diff --git a/key/key.core/src/de/uka/ilkd/key/parser/KeYLexer.g b/key/key.core/src/de/uka/ilkd/key/parser/KeYLexer.g index 11f107497f2..33b339d5f2c 100644 --- a/key/key.core/src/de/uka/ilkd/key/parser/KeYLexer.g +++ b/key/key.core/src/de/uka/ilkd/key/parser/KeYLexer.g @@ -494,6 +494,12 @@ GREATEREQUAL RGUILLEMETS : '>' '>' ; + +OPENTYPEPARAMS + : '<' '[' ; + +CLOSETYPEPARAMS + : ']' '>' ; WS : (' ' diff --git a/key/key.core/src/de/uka/ilkd/key/parser/KeYParser.g b/key/key.core/src/de/uka/ilkd/key/parser/KeYParser.g index abbc79b3b05..43b439d4d17 100644 --- a/key/key.core/src/de/uka/ilkd/key/parser/KeYParser.g +++ b/key/key.core/src/de/uka/ilkd/key/parser/KeYParser.g @@ -2391,7 +2391,8 @@ sortId_check_help [boolean checkSort] returns [Pair _sort_id_check_he // Generic and non-generic sorts any_sortId_check_help [boolean checkSort] returns [Pair result = null] : - name = simple_sort_name + name = simple_sort_name + ( OPENTYPEPARAMS parameter=any_sortId_check[checkSort] CLOSETYPEPARAMS )? { //Special handling for byte, char, short, long: //these are *not* sorts, but they are nevertheless valid @@ -2427,7 +2428,13 @@ any_sortId_check_help [boolean checkSort] returns [Pair result = null throw new NotDeclException(input, "sort", name); } } - + + if(parameter != null) { + s = ParametricSort.get(s, parameter); + } + + System.out.println("Sort " + s); + result = new Pair(s, t); } ; diff --git a/key/key.util/src/org/key_project/util/collection/DefaultImmutableSet.java b/key/key.util/src/org/key_project/util/collection/DefaultImmutableSet.java index 7e58349dc2a..65300b3814c 100644 --- a/key/key.util/src/org/key_project/util/collection/DefaultImmutableSet.java +++ b/key/key.util/src/org/key_project/util/collection/DefaultImmutableSet.java @@ -15,6 +15,7 @@ import java.util.Iterator; import java.util.Set; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -198,8 +199,13 @@ public boolean subset(ImmutableSet s) { public boolean exists(Predicate predicate) { return elementList.exists(predicate); } - - /** @return int the cardinality of the set */ + + @Override + public ImmutableSet map(Function f) { + return new DefaultImmutableSet(elementList.map(f)); + } + + /** @return int the cardinality of the set */ public int size() { return elementList.size(); } diff --git a/key/key.util/src/org/key_project/util/collection/ImmutableList.java b/key/key.util/src/org/key_project/util/collection/ImmutableList.java index 4e15d887d62..989c4846d1c 100644 --- a/key/key.util/src/org/key_project/util/collection/ImmutableList.java +++ b/key/key.util/src/org/key_project/util/collection/ImmutableList.java @@ -14,6 +14,7 @@ package org.key_project.util.collection; import java.util.Iterator; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -96,7 +97,19 @@ public interface ImmutableList extends Iterable, java.io.Serializable { * @return the first element in list */ T head(); - + + + /** + * Apply a function f to the elements of the list. + * The resulting list contains the elements in the same order, but after the + * application of f. + * + * @param f the function to apply to the elements + * @param result type of the mapping + * @return a new immutable list instance, not null. + */ + ImmutableList map(Function f); + /** * return true if predicate is fullfilled for at least one element * @param predicate the predicate diff --git a/key/key.util/src/org/key_project/util/collection/ImmutableSLList.java b/key/key.util/src/org/key_project/util/collection/ImmutableSLList.java index 39954c87f7a..8abb35d670e 100644 --- a/key/key.util/src/org/key_project/util/collection/ImmutableSLList.java +++ b/key/key.util/src/org/key_project/util/collection/ImmutableSLList.java @@ -15,6 +15,7 @@ import java.lang.reflect.Array; import java.util.Iterator; +import java.util.function.Function; import java.util.function.Predicate; /** @@ -161,6 +162,14 @@ public ImmutableList take(int n) { return rest; } + @Override + public ImmutableList map(Function f) { + ImmutableList result = nil(); + for (T t : reverse()) { + result = result.prepend(f.apply(t)); + } + return result; + } // Implemented imperatively to avoid arbitrarily deep recursion @Override diff --git a/key/key.util/src/org/key_project/util/collection/ImmutableSet.java b/key/key.util/src/org/key_project/util/collection/ImmutableSet.java index 082c02285a2..d1025d63a77 100644 --- a/key/key.util/src/org/key_project/util/collection/ImmutableSet.java +++ b/key/key.util/src/org/key_project/util/collection/ImmutableSet.java @@ -14,6 +14,7 @@ package org.key_project.util.collection; import java.util.Iterator; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; @@ -47,6 +48,18 @@ public interface ImmutableSet extends Iterable, java.io.Serializable { */ boolean exists(Predicate predicate); + /** + * Apply a function f to the elements of the set. + * If the set has an order: + * The result contains the elements in the same order, but after the + * application of f. + * + * @param f the function to apply to the elements + * @param result type of the mapping + * @return a new immutable list instance, not null. + */ + ImmutableSet map(Function f); + /** @return true iff obj in set */ boolean contains(T obj); From 8b32e4ea5a15a398a4527fb753c01b2ef56807cb Mon Sep 17 00:00:00 2001 From: Mattias Ulbrich Date: Sat, 8 Dec 2018 18:41:04 +0100 Subject: [PATCH 04/13] 1st working version for polymorphic types --- .../uka/ilkd/key/parser/TestDeclParser.java | 107 +++++++++++++++++- .../key/logic/op/SortDependingFunction.java | 23 ++-- .../ilkd/key/logic/sort/ParametricSort.java | 49 +++++--- .../logic/sort/ParametricSortInstance.java | 20 +++- .../src/de/uka/ilkd/key/parser/KeYParser.g | 96 +++++++++++++--- .../key/proof/init/ProblemInitializer.java | 15 ++- .../ilkd/key/proof/io/IProofFileParser.java | 1 + .../key/rule/inst/GenericSortCondition.java | 57 +++++----- .../rule/inst/GenericSortInstantiations.java | 31 +++-- .../util/collection/ImmutableList.java | 7 +- .../util/collection/Immutables.java | 21 ++++ 11 files changed, 339 insertions(+), 88 deletions(-) diff --git a/key/key.core.test/src/de/uka/ilkd/key/parser/TestDeclParser.java b/key/key.core.test/src/de/uka/ilkd/key/parser/TestDeclParser.java index 6173c830040..5c8750b8e02 100644 --- a/key/key.core.test/src/de/uka/ilkd/key/parser/TestDeclParser.java +++ b/key/key.core.test/src/de/uka/ilkd/key/parser/TestDeclParser.java @@ -16,6 +16,8 @@ import java.io.PrintWriter; import java.io.StringWriter; +import de.uka.ilkd.key.logic.op.SortDependingFunction; +import de.uka.ilkd.key.logic.sort.*; import junit.framework.TestCase; import org.antlr.runtime.RecognitionException; @@ -31,11 +33,10 @@ import de.uka.ilkd.key.logic.op.Function; import de.uka.ilkd.key.logic.op.SchemaVariable; import de.uka.ilkd.key.logic.op.VariableSV; -import de.uka.ilkd.key.logic.sort.ArraySort; -import de.uka.ilkd.key.logic.sort.GenericSort; -import de.uka.ilkd.key.logic.sort.ProxySort; -import de.uka.ilkd.key.logic.sort.Sort; +import de.uka.ilkd.key.logic.sort.ParametricSort; +import static de.uka.ilkd.key.logic.sort.ParametricSort.Variance.*; import de.uka.ilkd.key.proof.init.AbstractProfile; +import org.key_project.util.collection.Immutables; public class TestDeclParser extends TestCase { @@ -88,6 +89,8 @@ private void parseDecls(String s) { } public void testSortDecl() { + + parseDecls("\\sorts { elem; list; }"); assertEquals("find sort elem", new Name("elem"), nss.sorts().lookup(new Name("elem")).name()); @@ -95,6 +98,80 @@ public void testSortDecl() { nss.sorts().lookup(new Name("list")).name()); } + public void testSortDeclFail() { + try { + String s = "\\sorts { X; X; }"; + KeYParserF p = stringParser(s); + p.decls(); + fail("Parsing " + s + " should have failed"); + } catch (Exception ex) { + assertTrue(ex.getMessage().contains("already declared")); + } + + } + + public void testParametericSortDecl() { + parseDecls("\\sorts { \\generic E, F, G; " + + "coll<[E]>; list<[+E]> \\extends coll<[E]>;" + + "var<[-E, +F, G]>; }"); + + Sort e = nss.sorts().lookup("E"); + ParametricSort list = (ParametricSort) nss.sorts().lookup("list"); + ParametricSort coll = (ParametricSort) nss.sorts().lookup("coll"); + ParametricSort var = (ParametricSort) nss.sorts().lookup("var"); + + assertTrue(e instanceof GenericSort); + assertTrue(coll instanceof ParametricSort); + assertTrue(list instanceof ParametricSort); + + assertEquals( + Immutables.listOf(CONTRAVARIANT, COVARIANT, INVARIANT), + var.getCovariances()); + + assertEquals("{coll<[E]>}", list.extendsSorts().toString()); + + assertEquals("{any}", coll.extendsSorts().toString()); + } + + public void testParametericSortDeclFails() { + try { + String s = "\\sorts { parametric<[E]>; }"; + KeYParserF p = stringParser(s); + p.decls(); + fail("Parsing " + s + " should have failed"); + } catch (Exception ex) { + assertTrue(ex.getMessage().contains("Formal type parameters must be (already declared) generic sorts")); + } + + try { + String s = "\\sorts { \\generic E; doubled<[E,E]>; }"; + KeYParserF p = stringParser(s); + p.decls(); + fail("Parsing " + s + " should have failed"); + } catch (Exception ex) { + assertTrue(ex.getMessage().contains("unique")); + } + + + try { + String s = "\\sorts { parametric<[int]>; }"; + KeYParserF p = stringParser(s); + p.decls(); + fail("Parsing " + s + " should have failed"); + } catch (Exception ex) { + assertTrue(ex.getMessage().contains("Formal type parameters must be (already declared) generic sorts")); + } + + try { + String s = "\\sorts { \\generic E; int<[E]>; }"; + KeYParserF p = stringParser(s); + p.decls(); + fail("Parsing " + s + " should have failed"); + } catch (Exception ex) { + assertTrue(ex.getMessage().contains("already declared")); + } + } + protected GenericSort checkGenericSort ( Named p_n, ImmutableSet p_ext, @@ -293,6 +370,28 @@ public void testArrayDecl() { assertTrue("Cloneable should extend Object ", cloneableSort.extendsSorts().contains(objectSort)); } + + public void testFunctionPolymorphicDecl() { + parseDecls("\\sorts { \\generic elem; list<[+elem]>; }\n" + + "\\functions {\n" + + " elem elem::head(list<[elem]>);\n" + + " list<[elem]> elem::tail(list<[elem]>);\n" + + " list<[elem]> elem::nil;\n" + + " list<[elem]> elem::cons(elem, list<[elem]>);\n" + + "}\n"); + + + SortDependingFunction head = (SortDependingFunction) nss.functions().lookup("any::head"); + SortDependingFunction inthead = head.getInstanceFor(nss.sorts().lookup("int"), serv); + assertEquals("int", inthead.sort().toString()); + assertEquals("[list<[int]>]", inthead.argSorts().toString()); + + SortDependingFunction cons = (SortDependingFunction) nss.functions().lookup("any::cons"); + SortDependingFunction intcons = cons.getInstanceFor(nss.sorts().lookup("int"), serv); + assertEquals("list<[int]>", intcons.sort().toString()); + assertEquals("[int,list<[int]>]", intcons.argSorts().toString()); + + } public void testFunctionDecl() { parseDecls("\\sorts { elem; list; }\n" + diff --git a/key/key.core/src/de/uka/ilkd/key/logic/op/SortDependingFunction.java b/key/key.core/src/de/uka/ilkd/key/logic/op/SortDependingFunction.java index 9d1f702760b..35c7dae2d79 100644 --- a/key/key.core/src/de/uka/ilkd/key/logic/op/SortDependingFunction.java +++ b/key/key.core/src/de/uka/ilkd/key/logic/op/SortDependingFunction.java @@ -13,6 +13,7 @@ package de.uka.ilkd.key.logic.op; +import de.uka.ilkd.key.logic.sort.ParametricSort; import org.key_project.util.collection.ImmutableArray; import de.uka.ilkd.key.logic.Name; @@ -23,6 +24,9 @@ import de.uka.ilkd.key.logic.sort.ProgramSVSort; import de.uka.ilkd.key.logic.sort.Sort; +import java.util.IdentityHashMap; +import java.util.Map; + /** * The objects of this class represent families of function symbols, where @@ -68,9 +72,10 @@ private static Name instantiateName(Name kind, private static Sort instantiateResultSort( SortDependingFunctionTemplate template, Sort sortDependingOn) { - return template.sort == template.sortDependingOn - ? sortDependingOn - : template.sort; + Map map = new IdentityHashMap<>(); + map.put(template.sortDependingOn, sortDependingOn); + ParametricSort.SortInstantiator inst = new ParametricSort.SortInstantiator(map); + return inst.apply(template.sort); } @@ -78,12 +83,14 @@ private static ImmutableArray instantiateArgSorts( SortDependingFunctionTemplate template, Sort sortDependingOn) { Sort[] result = new Sort[template.argSorts.size()]; + Map map = new IdentityHashMap<>(); + map.put(template.sortDependingOn, sortDependingOn); + ParametricSort.SortInstantiator inst = new ParametricSort.SortInstantiator(map); + for(int i = 0; i < result.length; i++) { - result[i] - = (template.argSorts.get(i) == template.sortDependingOn - ? sortDependingOn - : template.argSorts.get(i)); + result[i] = inst.apply(template.argSorts.get(i)); } + return new ImmutableArray(result); } @@ -122,7 +129,7 @@ public static SortDependingFunction getFirstInstance(Name kind, * returns the variant for the given sort * @param sort the {@link Sort} for which to retrieve the corresponding * variant of this function - * @param services the {@link Services} + * @param services the {@link de.uka.ilkd.key.java.Services} * @return the variant for the given sort */ public synchronized SortDependingFunction getInstanceFor(Sort sort, diff --git a/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSort.java b/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSort.java index 96fbf3858d6..20b5c95ae00 100644 --- a/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSort.java +++ b/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSort.java @@ -1,10 +1,12 @@ package de.uka.ilkd.key.logic.sort; import de.uka.ilkd.key.logic.Name; +import de.uka.ilkd.key.util.Pair; import org.key_project.util.collection.ImmutableList; import org.key_project.util.collection.ImmutableSet; import java.util.IdentityHashMap; +import java.util.Map; import java.util.function.Function; /** @@ -48,12 +50,13 @@ public class ParametricSort extends AbstractSort { + + public enum Variance { COVARIANT, CONTRAVARIANT, - INVARIANT + INVARIANT; } - private final ImmutableList parameters; private final ImmutableList covariances; @@ -65,6 +68,11 @@ public ParametricSort(Name name, ImmutableSet ext, boolean isAbstract, this.covariances = covariances; } + public ParametricSort(Name name, ImmutableSet ext, boolean isAbstract, + ImmutableList> sortParams) { + this(name, ext, isAbstract, sortParams.map(x->x.first), sortParams.map(x->x.second)); + } + public Function getInstantiation(ImmutableList args) { IdentityHashMap map = new IdentityHashMap<>(); @@ -81,21 +89,30 @@ public Function getInstantiation(ImmutableList args) { args = args.tail(); } - return new Function() { - @Override - public Sort apply(Sort sort) { - Sort mapped = map.get(sort); - if(mapped != null) { - return mapped; - } - if (sort instanceof ParametricSortInstance) { - ParametricSortInstance psort = (ParametricSortInstance) sort; - return psort.map(this::apply); - } else { - return sort; - } + return new SortInstantiator(map); + } + + public static class SortInstantiator implements Function { + + private final Map map; + + public SortInstantiator(Map map) { + this.map = map; + } + + @Override + public Sort apply(Sort sort) { + Sort mapped = map.get(sort); + if(mapped != null) { + return mapped; + } + if (sort instanceof ParametricSortInstance) { + ParametricSortInstance psort = (ParametricSortInstance) sort; + return psort.map(this::apply); + } else { + return sort; } - }; + } } public ImmutableList getParameters() { diff --git a/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java b/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java index 4a3e9bb6f0d..e2912ac0c90 100644 --- a/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java +++ b/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java @@ -6,6 +6,7 @@ import org.key_project.util.collection.ImmutableSet; import java.util.Map; +import java.util.Objects; import java.util.WeakHashMap; import java.util.function.Function; @@ -23,6 +24,7 @@ public static ParametricSortInstance get(ParametricSort base, ImmutableList computeExt(ParametricSort base, ImmutableList< // 2. extensions by variances ImmutableList cov = base.getCovariances(); - for (int i = 0; !cov.isEmpty(); i++) { + for (int i = 0; !cov.isEmpty(); i++, cov = cov.tail()) { switch(cov.head()) { case COVARIANT: // take all bases of that arg and add the modified sort as ext class - for (Sort s : parameters) { + for (Sort s : parameters.get(i).extendsSorts()) { ImmutableList newArgs = parameters.replace(i, s); result = result.add(ParametricSortInstance.get(base, newArgs)); } @@ -90,4 +92,18 @@ public ParametricSortInstance map(Function f) { // The cache ensures that no unnecessary duplicates are kept. return get(base, newParameters); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ParametricSortInstance that = (ParametricSortInstance) o; + return Objects.equals(parameters, that.parameters) && + base == that.base; + } + + @Override + public int hashCode() { + return Objects.hash(parameters, base); + } } diff --git a/key/key.core/src/de/uka/ilkd/key/parser/KeYParser.g b/key/key.core/src/de/uka/ilkd/key/parser/KeYParser.g index 43b439d4d17..ce6b68a753f 100644 --- a/key/key.core/src/de/uka/ilkd/key/parser/KeYParser.g +++ b/key/key.core/src/de/uka/ilkd/key/parser/KeYParser.g @@ -62,9 +62,11 @@ options { import org.key_project.util.collection.ImmutableList; import org.key_project.util.collection.ImmutableSLList; import org.key_project.util.collection.ImmutableSet; + import org.key_project.util.collection.Immutables; import de.uka.ilkd.key.logic.*; import de.uka.ilkd.key.logic.op.*; import de.uka.ilkd.key.logic.sort.*; + import de.uka.ilkd.key.logic.sort.ParametricSort.Variance; import de.uka.ilkd.key.logic.label.*; import de.uka.ilkd.key.proof.init.*; @@ -1710,7 +1712,9 @@ one_sort_decl returns [ImmutableList createdSorts = ImmutableSLList. boolean isProxySort = false; sortExt=new Sort [0]; sortOneOf=new Sort [0]; - sortIds = ImmutableSLList.nil(); + sortIds = ImmutableSLList.nil(); + // every sort can have multiple parameters. Every parameter is a generic sort + its variance + ImmutableList>> sortParameters = ImmutableSLList.nil(); } : ( GENERIC {isGenericSort=true;} sortIds = simple_ident_comma_list @@ -1720,11 +1724,15 @@ one_sort_decl returns [ImmutableList createdSorts = ImmutableSLList. ( EXTENDS sortExt = extends_sorts )? | (ABSTRACT {isAbstractSort = true;})? firstSort = simple_ident_dots { sortIds = sortIds.prepend(firstSort); } + parameters=formal_sort_parameters { sortParameters = sortParameters.prepend(parameters); } ( - (EXTENDS sortExt = extends_sorts ) - | ((COMMA) sortIds = simple_ident_comma_list { sortIds = sortIds.prepend(firstSort) ; } ) - )? - ) SEMI { + (EXTENDS sortExt = extends_sorts ) + // TODO parametrised sorts cannot be comma-listed + | ((COMMA) + id = simple_ident { sortIds = sortIds.prepend(id); } + parameters=formal_sort_parameters { sortParameters = sortParameters.prepend(parameters); } )* + ) + ) SEMI { if (!skip_sorts) { Iterator it = sortIds.iterator (); while ( it.hasNext () ) { @@ -1758,11 +1766,14 @@ one_sort_decl returns [ImmutableList createdSorts = ImmutableSLList. ext = ext.add ( sortExt[i] ); } - if(isProxySort) { - s = new ProxySort(sort_name, ext); - } else { - s = new SortImpl(sort_name, ext, isAbstractSort); - } + ImmutableList> sortParams = sortParameters.head(); + if(isProxySort) { + s = new ProxySort(sort_name, ext); + } else if(sortParams != null) { + s = new ParametricSort(sort_name, ext, isAbstractSort, sortParams); + } else { + s = new SortImpl(sort_name, ext, isAbstractSort); + } } assert s != null; sorts().add ( s ); @@ -1796,6 +1807,42 @@ extends_sorts returns [Sort[\] extendsSorts = null] } ; +formal_sort_parameters returns [ImmutableList> result = null] +@init { + Variance variance = null; +} + : + ( OPENTYPEPARAMS + ( PLUS { variance=Variance.COVARIANT; } + | MINUS { variance = Variance.CONTRAVARIANT; } + | { variance = Variance.INVARIANT; } + ) + id=simple_ident + {if (!skip_sorts) { + Sort genSort = sorts().lookup(id); + if(genSort == null || !(genSort instanceof GenericSort)) { + semanticError("Formal type parameters must be (already declared) generic sorts"); + } + result = Immutables.listOf(new Pair(genSort, variance)); + }} + ( COMMA + ( PLUS { variance=Variance.COVARIANT; } + | MINUS { variance = Variance.CONTRAVARIANT; } + | { variance = Variance.INVARIANT; } + ) + id=simple_ident + {if (!skip_sorts) { + Sort genSort = sorts().lookup(id); + if(genSort == null || !(genSort instanceof GenericSort)) { + semanticError("Formal type parameters must be (already declared) generic sorts"); + } + result = result.prepend(new Pair(genSort, variance)); + }} + )* + CLOSETYPEPARAMS { if (!skip_sorts) result = result.reverse(); } + )? + ; + oneof_sorts returns [Sort[\] oneOfSorts = null] @init{ List args = new LinkedList(); @@ -2365,7 +2412,14 @@ any_sortId_check [boolean checkSort] returns [Sort _any_sort_id_check = null] s = array_decls[p, checkSort] ; - +// Generic and non-generic sorts, array sorts allowed +// This is Id*s*: It allows one or more comma-separated sorts +any_sortIds_check [boolean checkSort] returns [ImmutableList result = ImmutableSLList.nil()] + : + s=any_sortId_check[checkSort] { result = result.prepend(s); } + ( COMMA s2=any_sortId_check[checkSort] { result = result.prepend(s2); } )* + ; + // Non-generic sorts sortId_check_help [boolean checkSort] returns [Pair _sort_id_check_help = null] @after{ _sort_id_check_help = result; } @@ -2379,11 +2433,12 @@ sortId_check_help [boolean checkSort] returns [Pair _sort_id_check_he s = ((ArraySort)s).elementSort (); } - if ( s instanceof GenericSort ) { + // FIXME. This is a temporary fix -- + /* if ( s instanceof GenericSort ) { throw new GenericSortException ( "sort", "Non-generic sort expected", s, getSourceName (), getLine (), getColumn () ); - } + }*/ } ; @@ -2392,7 +2447,7 @@ sortId_check_help [boolean checkSort] returns [Pair _sort_id_check_he any_sortId_check_help [boolean checkSort] returns [Pair result = null] : name = simple_sort_name - ( OPENTYPEPARAMS parameter=any_sortId_check[checkSort] CLOSETYPEPARAMS )? + ( OPENTYPEPARAMS parameters=any_sortIds_check[checkSort] CLOSETYPEPARAMS )? { //Special handling for byte, char, short, long: //these are *not* sorts, but they are nevertheless valid @@ -2427,13 +2482,18 @@ any_sortId_check_help [boolean checkSort] returns [Pair result = null if(s == null) { throw new NotDeclException(input, "sort", name); } - } - if(parameter != null) { - s = ParametricSort.get(s, parameter); + if(parameters != null) { + if (s instanceof ParametricSort) { + ParametricSort ps = (ParametricSort) s; + s = ParametricSortInstance.get(ps, parameters); + } else { + semanticError("Not a polymorphic sort: " + name); + } + } } - System.out.println("Sort " + s); +// System.out.println("Sort " + s); result = new Pair(s, t); } diff --git a/key/key.core/src/de/uka/ilkd/key/proof/init/ProblemInitializer.java b/key/key.core/src/de/uka/ilkd/key/proof/init/ProblemInitializer.java index e00d41f3c49..8af52f5e7d6 100644 --- a/key/key.core/src/de/uka/ilkd/key/proof/init/ProblemInitializer.java +++ b/key/key.core/src/de/uka/ilkd/key/proof/init/ProblemInitializer.java @@ -338,17 +338,22 @@ private void cleanupNamespaces(InitConfig initConfig) { Namespace newVarNS = new Namespace<>(); Namespace newSortNS = new Namespace<>(); Namespace newFuncNS = new Namespace<>(); + + // FIXME. This is a temporary fix -- + // https://git.key-project.org/key/key/issues/720 + // It does not really work like this. + for(Sort n : initConfig.sortNS().allElements()) { - if(!(n instanceof GenericSort)) { + // if(!(n instanceof GenericSort)) { newSortNS.addSafely(n); - } + // } } for(Function n : initConfig.funcNS().allElements()) { - if(!(n instanceof SortDependingFunction + /* if(!(n instanceof SortDependingFunction && ((SortDependingFunction)n).getSortDependingOn() - instanceof GenericSort)) { + instanceof GenericSort)) {*/ newFuncNS.addSafely(n); - } + // } } //System.out.println(initConfig.funcNS().hashCode() + " ---> " + newFuncNS.hashCode()); initConfig.getServices().getNamespaces().setVariables(newVarNS); diff --git a/key/key.core/src/de/uka/ilkd/key/proof/io/IProofFileParser.java b/key/key.core/src/de/uka/ilkd/key/proof/io/IProofFileParser.java index c75591d5db5..7d0172c1a3e 100644 --- a/key/key.core/src/de/uka/ilkd/key/proof/io/IProofFileParser.java +++ b/key/key.core/src/de/uka/ilkd/key/proof/io/IProofFileParser.java @@ -15,6 +15,7 @@ import java.util.List; +import de.uka.ilkd.key.logic.sort.Sort; import de.uka.ilkd.key.parser.KeYParser; /** diff --git a/key/key.core/src/de/uka/ilkd/key/rule/inst/GenericSortCondition.java b/key/key.core/src/de/uka/ilkd/key/rule/inst/GenericSortCondition.java index b65251647b0..a5696e86c5f 100644 --- a/key/key.core/src/de/uka/ilkd/key/rule/inst/GenericSortCondition.java +++ b/key/key.core/src/de/uka/ilkd/key/rule/inst/GenericSortCondition.java @@ -14,11 +14,12 @@ package de.uka.ilkd.key.rule.inst; import de.uka.ilkd.key.logic.op.SchemaVariable; -import de.uka.ilkd.key.logic.op.SortDependingFunction; import de.uka.ilkd.key.logic.op.TermSV; import de.uka.ilkd.key.logic.sort.ArraySort; import de.uka.ilkd.key.logic.sort.GenericSort; +import de.uka.ilkd.key.logic.sort.ParametricSortInstance; import de.uka.ilkd.key.logic.sort.Sort; +import org.key_project.util.collection.*; /** @@ -40,7 +41,7 @@ public abstract class GenericSortCondition { * (no generic sorts) or never compatible (non generic sorts that * don't match) */ - public static GenericSortCondition createCondition(SchemaVariable sv, + public static ImmutableSet createCondition(SchemaVariable sv, InstantiationEntry p_entry) { if (!( p_entry instanceof TermInstantiation)) { @@ -54,24 +55,6 @@ public static GenericSortCondition createCondition(SchemaVariable sv, !subSortsAllowed ( sv ) ); } - /** - * Create a condition ensuring that the two given symbols become - * identical; "p0" may be of generic sort, "p1" not - * @return the resulting condition; null if the symbols are either - * incompatible or equal - */ - public static GenericSortCondition createCondition - ( SortDependingFunction p0, - SortDependingFunction p1 ) { - - if ( !p0.isSimilar ( p1 ) ) - return null; - - return createCondition ( p0.getSortDependingOn (), - p1.getSortDependingOn (), - true ); - } - /** * @return true iff the variable p_sv is * allowed to be instantiated with expressions that have a real @@ -93,8 +76,7 @@ static boolean subSortsAllowed (SchemaVariable p_sv) { * sorts) or never compatible (e.g. non generic sorts that don't * match) */ - protected static GenericSortCondition createCondition - ( Sort s0, Sort s1, boolean p_identity ) { + private static ImmutableSet createCondition(Sort s0, Sort s1, boolean p_identity) { while ( s0 instanceof ArraySort ) { // Currently the sort hierarchy is not inherited by // collection sorts; therefore identity has to be ensured @@ -107,17 +89,40 @@ static boolean subSortsAllowed (SchemaVariable p_sv) { s1 = ((ArraySort)s1).elementSort (); } + if ( s0 instanceof ParametricSortInstance ) { + if ( !(s1 instanceof ParametricSortInstance) ) { + return null; + } + ParametricSortInstance ps0 = (ParametricSortInstance) s0; + ParametricSortInstance ps1 = (ParametricSortInstance) s1; + + if(ps0.getBase() != ps1.getBase()) { + return null; + } + + ImmutableSet result = DefaultImmutableSet.nil(); + ImmutableList pa0 = ps0.getParameters(); + ImmutableList pa1 = ps1.getParameters(); + while(!pa0.isEmpty()) { + result = result.union(createCondition(pa0.head(), pa1.head(), p_identity)); + pa0 = pa0.tail(); + pa1 = pa1.tail(); + } + + return result; + } + + if ( !( s0 instanceof GenericSort ) - || s1 == Sort.FORMULA - || s1 == Sort.UPDATE) + || s1 == Sort.FORMULA || s1 == Sort.UPDATE) return null; final GenericSort gs = (GenericSort) s0; if ( p_identity ) { - return createIdentityCondition ( gs, s1 ); + return Immutables.setOf(createIdentityCondition ( gs, s1 )); } else { - return createSupersortCondition ( gs, s1 ); + return Immutables.setOf(createSupersortCondition ( gs, s1 )); } } diff --git a/key/key.core/src/de/uka/ilkd/key/rule/inst/GenericSortInstantiations.java b/key/key.core/src/de/uka/ilkd/key/rule/inst/GenericSortInstantiations.java index 81fab31b207..31252f02522 100644 --- a/key/key.core/src/de/uka/ilkd/key/rule/inst/GenericSortInstantiations.java +++ b/key/key.core/src/de/uka/ilkd/key/rule/inst/GenericSortInstantiations.java @@ -73,7 +73,7 @@ private GenericSortInstantiations ( ImmutableMap p_insts ) { ImmutableList sorts = ImmutableSLList.nil(); - GenericSortCondition c; + ImmutableSet cs; final Iterator it; @@ -85,11 +85,12 @@ private GenericSortInstantiations ( ImmutableMap p_insts ) { while ( p_instantiations.hasNext () ) { final ImmutableMapEntry> entry = p_instantiations.next (); - c = GenericSortCondition.createCondition - ( entry.key(), entry.value () ); - if ( c != null ) { - p_conditions = p_conditions.prepend ( c ); - sorts = sorts .prepend ( c.getGenericSort () ); + cs = GenericSortCondition.createCondition( entry.key(), entry.value () ); + if ( cs != null ) { + for (GenericSortCondition c : cs) { + p_conditions = p_conditions.prepend(c); + sorts = sorts.prepend(c.getGenericSort()); + } } } return create ( sorts, p_conditions, services ); @@ -130,9 +131,23 @@ public Boolean checkSorts ( SchemaVariable sv, InstantiationEntry p_entry ) { sv instanceof ProgramSV ) return Boolean.TRUE; - final GenericSortCondition c = + final ImmutableSet cs = GenericSortCondition.createCondition ( sv, p_entry ); - if ( c != null ) return checkCondition ( c ); + + if ( cs != null ) { + boolean oneNull = false; + for (GenericSortCondition c : cs) { + Boolean retCheck = checkCondition(c); + if(retCheck == Boolean.FALSE) { + return retCheck; + } + if(retCheck == null) { + oneNull = true; + } + } + + return oneNull ? null : Boolean.TRUE; + } final Term term = ( (TermInstantiation)p_entry ).getInstantiation (); diff --git a/key/key.util/src/org/key_project/util/collection/ImmutableList.java b/key/key.util/src/org/key_project/util/collection/ImmutableList.java index 989c4846d1c..aca946fb775 100644 --- a/key/key.util/src/org/key_project/util/collection/ImmutableList.java +++ b/key/key.util/src/org/key_project/util/collection/ImmutableList.java @@ -199,4 +199,9 @@ default Stream stream() { * @throws IndexOutOfBoundsException if pos is not a valid index in the list. */ ImmutableList replace(int pos, T t); -} \ No newline at end of file + + // TODO DOC! + default T get(int pos) { + return take(pos).head(); + } +} diff --git a/key/key.util/src/org/key_project/util/collection/Immutables.java b/key/key.util/src/org/key_project/util/collection/Immutables.java index ab94656b5c7..62df01d688d 100644 --- a/key/key.util/src/org/key_project/util/collection/Immutables.java +++ b/key/key.util/src/org/key_project/util/collection/Immutables.java @@ -154,4 +154,25 @@ public static ImmutableList createListFrom(Iterable iterable) { return result.reverse(); } + public static ImmutableList listOf(T... elements) { + ImmutableList result = ImmutableSLList.nil(); + for (T t : elements) { + result = result.prepend(t); + } + return result.reverse(); + } + + public static ImmutableList listOf(T element) { + ImmutableList result = ImmutableSLList.nil(); + result = result.prepend(element); + return result.reverse(); + } + + public static ImmutableSet setOf(T... elements) { + return DefaultImmutableSet.fromImmutableList(listOf(elements)); + } + + public static ImmutableSet setOf(T element) { + return DefaultImmutableSet.fromImmutableList(listOf(element)); + } } From 24c0d3f9b9a5c5bbeedfaa31a373d3feafdf9c78 Mon Sep 17 00:00:00 2001 From: Alexander Weigl Date: Wed, 28 Jul 2021 02:00:36 +0200 Subject: [PATCH 05/13] Finalize merge... * branch should be up-to-date with current infrastructure --- .../ilkd/key/logic/sort/ProgramSVSort.java | 1594 +++--- .../src/de/uka/ilkd/key/parser/KeYLexer.g | 791 --- .../src/de/uka/ilkd/key/parser/KeYParser.g | 4789 ----------------- key/key.core/src/main/antlr4/KeYLexer.g4 | 3 + key/key.core/src/main/antlr4/KeYParser.g4 | 27 +- .../uka/ilkd/key/logic/sort/AbstractSort.java | 2 +- .../ilkd/key/logic/sort/ParametricSort.java | 4 +- .../logic/sort/ParametricSortInstance.java | 0 .../ilkd/key/logic/sort/ProgramSVSort.java | 260 +- .../java/de/uka/ilkd/key/logic/sort/Sort.java | 10 +- .../nparser/builder/DeclarationBuilder.java | 62 +- .../key/nparser/builder/DefaultBuilder.java | 56 +- .../ilkd/key/proof/io/IProofFileParser.java | 7 +- .../uka/ilkd/key/parser/TestDeclParser.java | 121 +- .../util/suite/AllCollectionTests.java | 39 - .../util/collection/DefaultImmutableSet.java | 14 +- .../util/collection/ImmutableList.java | 1 + .../util/collection/ImmutableSet.java | 13 + .../util/collection/DefaultImmutableSet.java | 398 -- .../util/collection/ImmutableSet.java | 97 - 20 files changed, 1184 insertions(+), 7104 deletions(-) delete mode 100644 key/key.core/src/de/uka/ilkd/key/parser/KeYLexer.g delete mode 100644 key/key.core/src/de/uka/ilkd/key/parser/KeYParser.g rename key/key.core/src/{ => main/java}/de/uka/ilkd/key/logic/sort/ParametricSort.java (98%) rename key/key.core/src/{ => main/java}/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java (100%) delete mode 100644 key/key.util.test/src/org/key_project/util/suite/AllCollectionTests.java delete mode 100644 key/key.util/src/org/key_project/util/collection/DefaultImmutableSet.java delete mode 100644 key/key.util/src/org/key_project/util/collection/ImmutableSet.java diff --git a/key/key.core/src/de/uka/ilkd/key/logic/sort/ProgramSVSort.java b/key/key.core/src/de/uka/ilkd/key/logic/sort/ProgramSVSort.java index b8aa4a7026e..da6f56f5902 100644 --- a/key/key.core/src/de/uka/ilkd/key/logic/sort/ProgramSVSort.java +++ b/key/key.core/src/de/uka/ilkd/key/logic/sort/ProgramSVSort.java @@ -66,8 +66,8 @@ import de.uka.ilkd.key.logic.op.SchemaVariable; /** - * Special "sorts" used for schema variables matching program constructs - * (class ProgramSV). Not really sorts in the theoretical meaning of the word. + * Special "sorts" used for schema variables matching program constructs + * (class ProgramSV). Not really sorts in the theoretical meaning of the word. */ public abstract class ProgramSVSort extends AbstractSort { @@ -75,206 +75,205 @@ public abstract class ProgramSVSort extends AbstractSort { // ProgramSVSort instances (helpful in parsing // schema variable declarations) private static final Map name2sort = - new LinkedHashMap(60); + new LinkedHashMap(60); //----------- Types of Expression Program SVs ---------------------------- - + public static final ProgramSVSort LEFTHANDSIDE - = new LeftHandSideSort(); + = new LeftHandSideSort(); public static final ProgramSVSort VARIABLE - = new ProgramVariableSort(); + = new ProgramVariableSort(); public static final ProgramSVSort STATICVARIABLE - = new StaticVariableSort(); - + = new StaticVariableSort(); + public static final ProgramSVSort LOCALVARIABLE - = new LocalVariableSort(); + = new LocalVariableSort(); - public static final ProgramSVSort SIMPLEEXPRESSION - = new SimpleExpressionSort(); + public static final ProgramSVSort SIMPLEEXPRESSION + = new SimpleExpressionSort(); - public static final ProgramSVSort NONSIMPLEEXPRESSION - = new NonSimpleExpressionSort(); + public static final ProgramSVSort NONSIMPLEEXPRESSION + = new NonSimpleExpressionSort(); public static final ProgramSVSort NONSIMPLEEXPRESSIONNOCLASSREFERENCE - = new NonSimpleExpressionNoClassReferenceSort(); + = new NonSimpleExpressionNoClassReferenceSort(); public static final ProgramSVSort EXPRESSION - = new ExpressionSort(); + = new ExpressionSort(); //----------- Initialisation and Creation expressions ------------------- - + public static final ProgramSVSort SIMPLE_NEW = new SimpleNewSVSort(); - - public static final ProgramSVSort NONSIMPLE_NEW = new NonSimpleNewSVSort(); + + public static final ProgramSVSort NONSIMPLE_NEW = new NonSimpleNewSVSort(); public static final ProgramSVSort NEWARRAY = new NewArraySVSort(); public static final ProgramSVSort ARRAYINITIALIZER - = new ArrayInitializerSVSort(); + = new ArrayInitializerSVSort(); public static final ProgramSVSort SPECIALCONSTRUCTORREFERENCE - = new SpecialConstructorReferenceSort(); + = new SpecialConstructorReferenceSort(); + - //----------- Expressions with restrictions on kind of type ------------- public static final NonSimpleMethodReferenceSort NONSIMPLEMETHODREFERENCE - = new NonSimpleMethodReferenceSort(); + = new NonSimpleMethodReferenceSort(); //----------- Types of Statement Program SVs ----------------------------- - + public static final ProgramSVSort STATEMENT - = new StatementSort(); + = new StatementSort(); public static final ProgramSVSort CATCH - = new CatchSort(); + = new CatchSort(); public static final ProgramSVSort METHODBODY - = new MethodBodySort(); + = new MethodBodySort(); public static final ProgramSVSort NONMODELMETHODBODY - = new NonModelMethodBodySort(); + = new NonModelMethodBodySort(); public static final ProgramSVSort PROGRAMMETHOD - = new ProgramMethodSort(); + = new ProgramMethodSort(); //-----------Types-------------------------------------------------------- - + public static final ProgramSVSort TYPE - = new TypeReferenceSort(); + = new TypeReferenceSort(); public static final ProgramSVSort TYPENOTPRIMITIVE - = new TypeReferenceNotPrimitiveSort(); + = new TypeReferenceNotPrimitiveSort(); public static final ProgramSVSort CLASSREFERENCE - = new MetaClassReferenceSort(); + = new MetaClassReferenceSort(); //-----------Others------------------------------------------------------- public static final ProgramSVSort METHODNAME - = new MethodNameSort(); - + = new MethodNameSort(); + public static final ProgramSVSort LABEL - = new LabelSort(); - - + = new LabelSort(); + + //-----------Specials for primitive types--------------------------------- - - public static final ProgramSVSort JAVABOOLEANEXPRESSION - = new ExpressionSpecialPrimitiveTypeSort - ("JavaBooleanExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BOOLEAN}); - - public static final ProgramSVSort SIMPLEJAVABYTEEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaByteExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BYTE}); - - public static final ProgramSVSort SIMPLEJAVACHAREXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaCharExpression", new - PrimitiveType[]{PrimitiveType.JAVA_CHAR}); - - public static final ProgramSVSort SIMPLEJAVASHORTEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaShortExpression", new - PrimitiveType[]{PrimitiveType.JAVA_SHORT}); - - public static final ProgramSVSort SIMPLEJAVAINTEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaIntExpression", new - PrimitiveType[]{PrimitiveType.JAVA_INT}); - - public static final ProgramSVSort SIMPLEJAVALONGEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaLongExpression", new - PrimitiveType[]{PrimitiveType.JAVA_LONG}); + + public static final ProgramSVSort JAVABOOLEANEXPRESSION + = new ExpressionSpecialPrimitiveTypeSort + ("JavaBooleanExpression", new + PrimitiveType[]{PrimitiveType.JAVA_BOOLEAN}); + + public static final ProgramSVSort SIMPLEJAVABYTEEXPRESSION + = new SimpleExpressionSpecialPrimitiveTypeSort + ("JavaByteExpression", new + PrimitiveType[]{PrimitiveType.JAVA_BYTE}); + + public static final ProgramSVSort SIMPLEJAVACHAREXPRESSION + = new SimpleExpressionSpecialPrimitiveTypeSort + ("JavaCharExpression", new + PrimitiveType[]{PrimitiveType.JAVA_CHAR}); + + public static final ProgramSVSort SIMPLEJAVASHORTEXPRESSION + = new SimpleExpressionSpecialPrimitiveTypeSort + ("JavaShortExpression", new + PrimitiveType[]{PrimitiveType.JAVA_SHORT}); + + public static final ProgramSVSort SIMPLEJAVAINTEXPRESSION + = new SimpleExpressionSpecialPrimitiveTypeSort + ("JavaIntExpression", new + PrimitiveType[]{PrimitiveType.JAVA_INT}); + + public static final ProgramSVSort SIMPLEJAVALONGEXPRESSION + = new SimpleExpressionSpecialPrimitiveTypeSort + ("JavaLongExpression", new + PrimitiveType[]{PrimitiveType.JAVA_LONG}); public static final ProgramSVSort SIMPLEJAVABYTESHORTEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaByteShortExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT}); + = new SimpleExpressionSpecialPrimitiveTypeSort + ("JavaByteShortExpression", new + PrimitiveType[]{PrimitiveType.JAVA_BYTE, + PrimitiveType.JAVA_SHORT}); public static final ProgramSVSort SIMPLEJAVABYTESHORTINTEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaByteShortIntExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT}); - - - public static final ProgramSVSort SIMPLEANYJAVATYPEEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("AnyJavaTypeExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG}); - - - public static final ProgramSVSort SIMPLEANYJAVANUMBERTYPEEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("AnyJavaNumberTypeExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG, - PrimitiveType.JAVA_CHAR}); + = new SimpleExpressionSpecialPrimitiveTypeSort + ("JavaByteShortIntExpression", new + PrimitiveType[]{PrimitiveType.JAVA_BYTE, + PrimitiveType.JAVA_SHORT, + PrimitiveType.JAVA_INT}); + + + public static final ProgramSVSort SIMPLEANYJAVATYPEEXPRESSION + = new SimpleExpressionSpecialPrimitiveTypeSort + ("AnyJavaTypeExpression", new + PrimitiveType[]{PrimitiveType.JAVA_BYTE, + PrimitiveType.JAVA_SHORT, + PrimitiveType.JAVA_INT, + PrimitiveType.JAVA_LONG}); + + + public static final ProgramSVSort SIMPLEANYJAVANUMBERTYPEEXPRESSION + = new SimpleExpressionSpecialPrimitiveTypeSort + ("AnyJavaNumberTypeExpression", new + PrimitiveType[]{PrimitiveType.JAVA_BYTE, + PrimitiveType.JAVA_SHORT, + PrimitiveType.JAVA_INT, + PrimitiveType.JAVA_LONG, + PrimitiveType.JAVA_CHAR}); public static final ProgramSVSort SIMPLEJAVASHORTINTLONGEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaShortIntLongExpression", new - PrimitiveType[]{PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG}); + = new SimpleExpressionSpecialPrimitiveTypeSort + ("JavaShortIntLongExpression", new + PrimitiveType[]{PrimitiveType.JAVA_SHORT, + PrimitiveType.JAVA_INT, + PrimitiveType.JAVA_LONG}); public static final ProgramSVSort SIMPLEJAVAINTLONGEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaIntLongExpression", new - PrimitiveType[]{PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG}); + = new SimpleExpressionSpecialPrimitiveTypeSort + ("JavaIntLongExpression", new + PrimitiveType[]{PrimitiveType.JAVA_INT, + PrimitiveType.JAVA_LONG}); public static final ProgramSVSort SIMPLEJAVACHARBYTESHORTINTEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaCharByteShortIntExpression", new - PrimitiveType[]{PrimitiveType.JAVA_CHAR, - PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT}); - + = new SimpleExpressionSpecialPrimitiveTypeSort + ("JavaCharByteShortIntExpression", new + PrimitiveType[]{PrimitiveType.JAVA_CHAR, + PrimitiveType.JAVA_BYTE, + PrimitiveType.JAVA_SHORT, + PrimitiveType.JAVA_INT}); + public static final ProgramSVSort SIMPLEJAVABIGINTEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaBigintExpression", new PrimitiveType[]{PrimitiveType.JAVA_BIGINT}); - - - public static final ProgramSVSort SIMPLEANYNUMBERTYPEEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("AnyNumberTypeExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG, - PrimitiveType.JAVA_CHAR, - PrimitiveType.JAVA_BIGINT}); - - public static final ProgramSVSort SIMPLEJAVABOOLEANEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("SimpleJavaBooleanExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BOOLEAN}); + = new SimpleExpressionSpecialPrimitiveTypeSort + ("JavaBigintExpression", new PrimitiveType[]{PrimitiveType.JAVA_BIGINT}); + + + public static final ProgramSVSort SIMPLEANYNUMBERTYPEEXPRESSION + = new SimpleExpressionSpecialPrimitiveTypeSort + ("AnyNumberTypeExpression", new + PrimitiveType[]{PrimitiveType.JAVA_BYTE, + PrimitiveType.JAVA_SHORT, + PrimitiveType.JAVA_INT, + PrimitiveType.JAVA_LONG, + PrimitiveType.JAVA_CHAR, + PrimitiveType.JAVA_BIGINT}); + + public static final ProgramSVSort SIMPLEJAVABOOLEANEXPRESSION + = new SimpleExpressionSpecialPrimitiveTypeSort + ("SimpleJavaBooleanExpression", new + PrimitiveType[]{PrimitiveType.JAVA_BOOLEAN}); public static final ProgramSVSort SIMPLESTRINGEXPRESSION - = new SimpleExpressionStringSort("SimpleStringExpression"); - + = new SimpleExpressionStringSort("SimpleStringExpression"); + public static final ProgramSVSort SIMPLENONSTRINGOBJECTEXPRESSION - = new SimpleExpressionNonStringObjectSort("SimpleNonStringObjectExpression"); + = new SimpleExpressionNonStringObjectSort("SimpleNonStringObjectExpression"); - //--------------- Specials that can be get rid of perhaps-------------- @@ -283,29 +282,29 @@ public abstract class ProgramSVSort extends AbstractSort { public static final ProgramSVSort GUARD = new GuardSort(); public static final ProgramSVSort FORUPDATES = new ForUpdatesSort(); - + public static final ProgramSVSort FORLOOP = new ForLoopSort(); public static final ProgramSVSort MULTIPLEVARDECL - = new MultipleVariableDeclarationSort(); + = new MultipleVariableDeclarationSort(); public static final ProgramSVSort ARRAYPOSTDECL - = new ArrayPostDeclarationSort(); - + = new ArrayPostDeclarationSort(); + public static final ProgramSVSort SWITCH - = new SwitchSVSort(); + = new SwitchSVSort(); public static final ProgramSVSort CONSTANT_PRIMITIVE_TYPE_VARIABLE - = new ConstantProgramVariableSort(new Name("ConstantPrimitiveTypeVariable"), false); + = new ConstantProgramVariableSort(new Name("ConstantPrimitiveTypeVariable"), false); public static final ProgramSVSort CONSTANT_STRING_VARIABLE - = new ConstantProgramVariableSort(new Name("ConstantStringVariable"), true); + = new ConstantProgramVariableSort(new Name("ConstantStringVariable"), true); + - public static final ProgramSVSort VARIABLEINIT - = new ProgramSVSort(new Name("VariableInitializer")) { - public boolean canStandFor(ProgramElement pe, - Services services) { + = new ProgramSVSort(new Name("VariableInitializer")) { + public boolean canStandFor(ProgramElement pe, + Services services) { return true; } }; @@ -316,36 +315,36 @@ public boolean canStandFor(ProgramElement pe, //--------------- Specials that match on certain names----------------- public static final ProgramSVSort ARRAYLENGTH - = new ArrayLengthSort(); - + = new ArrayLengthSort(); + //---------------REFERENCE SORTS ------------------------ public static final ProgramSVSort EXECUTIONCONTEXT = new ExecutionContextSort(); //-------------------------------------------------------------------------- - + public ProgramSVSort(Name name) { - super(name, DefaultImmutableSet.nil(), false); - name2sort.put(name, this); + super(name, DefaultImmutableSet.nil(), false); + name2sort.put(name, this); } public boolean canStandFor(Term t) { - return true; + return true; } public boolean canStandFor(ProgramElement check, - ExecutionContext ec, - Services services) { - return canStandFor(check, services); + ExecutionContext ec, + Services services) { + return canStandFor(check, services); } protected abstract boolean canStandFor(ProgramElement check, - Services services); + Services services); public ProgramSVSort createInstance(String parameter) { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException(); } //-------------Now the inner classes representing the----------------------- @@ -360,42 +359,42 @@ public ProgramSVSort createInstance(String parameter) { */ private static class LeftHandSideSort extends ProgramSVSort { - public LeftHandSideSort() { - super(new Name("LeftHandSide")); - } - - public LeftHandSideSort(Name name) { - super(name); - } - - public boolean canStandFor(Term t) { - return t.op() instanceof ProgramVariable; - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - - if (pe instanceof ProgramVariable || - pe instanceof ThisReference || - pe instanceof VariableSpecification) { - return true; - } - - if (pe instanceof FieldReference){ - FieldReference fr = (FieldReference)pe; - // we allow only static field references with a - // sequence of PVs or TypeRef - ReferencePrefix rp = fr.getReferencePrefix(); - if ((fr.getProgramVariable()).isStatic()) { - return (rp == null || - rp instanceof ThisReference || - rp instanceof TypeReference || - canStandFor(rp, services)); + public LeftHandSideSort() { + super(new Name("LeftHandSide")); + } + + public LeftHandSideSort(Name name) { + super(name); + } + + public boolean canStandFor(Term t) { + return t.op() instanceof ProgramVariable; + } + + protected boolean canStandFor(ProgramElement pe, + Services services) { + + if (pe instanceof ProgramVariable || + pe instanceof ThisReference || + pe instanceof VariableSpecification) { + return true; + } + + if (pe instanceof FieldReference) { + FieldReference fr = (FieldReference) pe; + // we allow only static field references with a + // sequence of PVs or TypeRef + ReferencePrefix rp = fr.getReferencePrefix(); + if ((fr.getProgramVariable()).isStatic()) { + return (rp == null || + rp instanceof ThisReference || + rp instanceof TypeReference || + canStandFor(rp, services)); } - } + } - return false; - } + return false; + } } /** @@ -407,85 +406,85 @@ protected boolean canStandFor(ProgramElement pe, * super class it matches only if the field reference does not * trigger static initialisation (i.e. if it is no active reference) */ - private static class ProgramVariableSort - extends LeftHandSideSort { - - public ProgramVariableSort() { - super(new Name("Variable")); - } - - public boolean canStandFor(Term t) { - return t.op() instanceof ProgramVariable; - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - - ProgramVariable accessedField = null; - if (pe instanceof FieldReference){ - accessedField = ((FieldReference)pe).getProgramVariable(); - } else if (pe instanceof ProgramVariable) { - accessedField = (ProgramVariable) pe; - } - - if (accessedField != null && - accessedField.isStatic() && - !(accessedField instanceof ProgramConstant)) { - return false; - } - - return super.canStandFor(pe, services); - } - + private static class ProgramVariableSort + extends LeftHandSideSort { + + public ProgramVariableSort() { + super(new Name("Variable")); + } + + public boolean canStandFor(Term t) { + return t.op() instanceof ProgramVariable; + } + + protected boolean canStandFor(ProgramElement pe, + Services services) { + + ProgramVariable accessedField = null; + if (pe instanceof FieldReference) { + accessedField = ((FieldReference) pe).getProgramVariable(); + } else if (pe instanceof ProgramVariable) { + accessedField = (ProgramVariable) pe; + } + + if (accessedField != null && + accessedField.isStatic() && + !(accessedField instanceof ProgramConstant)) { + return false; + } + + return super.canStandFor(pe, services); + } + } - private static class StaticVariableSort - extends LeftHandSideSort { - - public StaticVariableSort() { - super (new Name("StaticVariable")); - } - - public boolean canStandFor(Term t) { - return t.op() instanceof ProgramVariable && - ((ProgramVariable)t.op()).isStatic(); - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - - ProgramVariable accessedField = null; - if (pe instanceof FieldReference){ - accessedField = ((FieldReference)pe).getProgramVariable(); - } else if (pe instanceof ProgramVariable) { - accessedField = (ProgramVariable) pe; - } - if (accessedField != null) { - return - accessedField.isStatic() && - !(accessedField instanceof ProgramConstant) && - super.canStandFor(pe, services); - } - return false; - } + private static class StaticVariableSort + extends LeftHandSideSort { + + public StaticVariableSort() { + super(new Name("StaticVariable")); + } + + public boolean canStandFor(Term t) { + return t.op() instanceof ProgramVariable && + ((ProgramVariable) t.op()).isStatic(); + } + + protected boolean canStandFor(ProgramElement pe, + Services services) { + + ProgramVariable accessedField = null; + if (pe instanceof FieldReference) { + accessedField = ((FieldReference) pe).getProgramVariable(); + } else if (pe instanceof ProgramVariable) { + accessedField = (ProgramVariable) pe; + } + if (accessedField != null) { + return + accessedField.isStatic() && + !(accessedField instanceof ProgramConstant) && + super.canStandFor(pe, services); + } + return false; + } } - - private static class LocalVariableSort - extends LeftHandSideSort { + + private static class LocalVariableSort + extends LeftHandSideSort { public LocalVariableSort() { - super (new Name("LocalVariable")); + super(new Name("LocalVariable")); } - public boolean canStandFor(Term t) { + public boolean canStandFor(Term t) { return t.op() instanceof ProgramVariable && - !((ProgramVariable)t.op()).isStatic(); + !((ProgramVariable) t.op()).isStatic(); } protected boolean canStandFor(ProgramElement pe, - Services services) { + Services services) { return pe instanceof ProgramVariable && !((ProgramVariable) pe).isStatic(); } @@ -501,67 +500,67 @@ protected boolean canStandFor(ProgramElement pe, * expressions or
  • instanceof expressions v instanceof T with an * expression v that matches on a program variable SV */ - private static class SimpleExpressionSort extends ProgramSVSort{ - - public SimpleExpressionSort() { - super(new Name("SimpleExpression")); - } - - protected SimpleExpressionSort(Name n) { - super(n); - } - - public boolean canStandFor(Term t) { - return true; - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - if (pe instanceof Negative) { - return ((Negative)pe).getChildAt(0) instanceof Literal; - } - - if (pe instanceof StringLiteral) - return false; - - if (pe instanceof Literal) { - return true; - } - - if (pe instanceof Instanceof) { - ProgramElement v = ((Instanceof) pe).getChildAt(0); - return VARIABLE.canStandFor(v, services); - } - - if(pe instanceof SetUnion - || pe instanceof Singleton - || pe instanceof Intersect - || pe instanceof SetMinus - || pe instanceof AllFields - || pe instanceof SeqSingleton - || pe instanceof SeqConcat - || pe instanceof SeqLength - || pe instanceof SeqGet - || pe instanceof SeqIndexOf - || pe instanceof SeqConcat - || pe instanceof SeqSub - || pe instanceof SeqReverse) { - if (pe instanceof NonTerminalProgramElement) { - final NonTerminalProgramElement npe = (NonTerminalProgramElement) pe; - for (int i = 0, childCount = npe.getChildCount(); i * It can also be made to match only specific method names * defined by the parameter "name". */ - private static class MethodNameSort extends ProgramSVSort{ + private static class MethodNameSort extends ProgramSVSort { private final ProgramElementName methodName; - public MethodNameSort() { - super(new Name("MethodName")); + public MethodNameSort() { + super(new Name("MethodName")); this.methodName = null; - } + } public MethodNameSort(ProgramElementName name) { - super(new Name("MethodName" + (name != null ? "[name="+name+"]" : ""))); + super(new Name("MethodName" + (name != null ? "[name=" + name + "]" : ""))); this.methodName = name; } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - if(pe instanceof MethodName) { + + protected boolean canStandFor(ProgramElement pe, + Services services) { + if (pe instanceof MethodName) { return methodName == null || pe.equals(methodName); } return false; - } + } public ProgramSVSort createInstance(String parameter) { - return new MethodNameSort(new ProgramElementName(parameter)); + return new MethodNameSort(new ProgramElementName(parameter)); } } @@ -1034,16 +1032,16 @@ public ProgramSVSort createInstance(String parameter) { * This sort represents a type of program schema variables that match * on labels. */ - private static final class LabelSort extends ProgramSVSort{ + private static final class LabelSort extends ProgramSVSort { - public LabelSort() { - super(new Name("Label")); - } + public LabelSort() { + super(new Name("Label")); + } - protected boolean canStandFor(ProgramElement pe, - Services services) { - return (pe instanceof Label); - } + protected boolean canStandFor(ProgramElement pe, + Services services) { + return (pe instanceof Label); + } } @@ -1051,54 +1049,54 @@ protected boolean canStandFor(ProgramElement pe, * This sort represents a type of program schema variables that match * on string literals and string variables. */ - public static final class SimpleExpressionStringSort - extends SimpleExpressionSort{ - - public SimpleExpressionStringSort(String name) { - super(new Name(name)); - } - - /* Will only match on String variables */ - public boolean canStandFor(ProgramElement check, - ExecutionContext ec, - Services services) { - if (!super.canStandFor(check, ec, services)) { - return false; - } - //String Literal has SideEffects, but SimpleExpressionSort will not match - //if (check instanceof StringLiteral) return false; - if (check instanceof ProgramVariable) { - Namespace ns = services.getNamespaces().sorts(); - Sort stringSort = ns.lookup(new Name("java.lang.String")); - return ((ProgramVariable)check).getKeYJavaType().getSort().equals(stringSort); - } - return false; - } + public static final class SimpleExpressionStringSort + extends SimpleExpressionSort { + + public SimpleExpressionStringSort(String name) { + super(new Name(name)); + } + + /* Will only match on String variables */ + public boolean canStandFor(ProgramElement check, + ExecutionContext ec, + Services services) { + if (!super.canStandFor(check, ec, services)) { + return false; + } + //String Literal has SideEffects, but SimpleExpressionSort will not match + //if (check instanceof StringLiteral) return false; + if (check instanceof ProgramVariable) { + Namespace ns = services.getNamespaces().sorts(); + Sort stringSort = ns.lookup(new Name("java.lang.String")); + return ((ProgramVariable) check).getKeYJavaType().getSort().equals(stringSort); + } + return false; + } } - - - public static class SimpleExpressionNonStringObjectSort - extends SimpleExpressionSort{ - - public SimpleExpressionNonStringObjectSort(String name) { - super(new Name(name)); - } - - public boolean canStandFor(ProgramElement check, - ExecutionContext ec, - Services services) { - if (!super.canStandFor(check, ec, services)) { - return false; - } - if (check instanceof ProgramVariable) { - final Sort checkSort = ((ProgramVariable)check).sort(); - Namespace ns = services.getNamespaces().sorts(); - Sort stringSort = ns.lookup(new Name("java.lang.String")); - return checkSort.extendsTrans(services.getJavaInfo().objectSort()) - && !checkSort.equals(stringSort); - } - return false; - } + + + public static class SimpleExpressionNonStringObjectSort + extends SimpleExpressionSort { + + public SimpleExpressionNonStringObjectSort(String name) { + super(new Name(name)); + } + + public boolean canStandFor(ProgramElement check, + ExecutionContext ec, + Services services) { + if (!super.canStandFor(check, ec, services)) { + return false; + } + if (check instanceof ProgramVariable) { + final Sort checkSort = ((ProgramVariable) check).sort(); + Namespace ns = services.getNamespaces().sorts(); + Sort stringSort = ns.lookup(new Name("java.lang.String")); + return checkSort.extendsTrans(services.getJavaInfo().objectSort()) + && !checkSort.equals(stringSort); + } + return false; + } } //-----------Specials for primitive types--------------------------------- @@ -1108,25 +1106,25 @@ public boolean canStandFor(ProgramElement check, * This sort represents a type of program schema variables that match * on simple expressions which have a special primitive type. */ - private static final class SimpleExpressionSpecialPrimitiveTypeSort - extends SimpleExpressionSort{ - - private final PrimitiveType[] allowed_types; - - public SimpleExpressionSpecialPrimitiveTypeSort - (String name, PrimitiveType[] allowed_types) { - - super(new Name(name)); - this.allowed_types = allowed_types; - } - - public boolean canStandFor(ProgramElement check, - ExecutionContext ec, - Services services) { - if (!super.canStandFor(check, ec, services)) { - return false; - } - final KeYJavaType kjt = getKeYJavaType(check, ec, services); + private static final class SimpleExpressionSpecialPrimitiveTypeSort + extends SimpleExpressionSort { + + private final PrimitiveType[] allowed_types; + + public SimpleExpressionSpecialPrimitiveTypeSort + (String name, PrimitiveType[] allowed_types) { + + super(new Name(name)); + this.allowed_types = allowed_types; + } + + public boolean canStandFor(ProgramElement check, + ExecutionContext ec, + Services services) { + if (!super.canStandFor(check, ec, services)) { + return false; + } + final KeYJavaType kjt = getKeYJavaType(check, ec, services); if (kjt != null) { final Type type = kjt.getJavaType(); for (PrimitiveType allowed_type : allowed_types) { @@ -1135,233 +1133,235 @@ public boolean canStandFor(ProgramElement check, } } return false; - } + } } /** * This sort represents a type of program schema variables that match * on simple expressions which have a special primitive type. */ - private static final class ExpressionSpecialPrimitiveTypeSort - extends ExpressionSort{ - - private final PrimitiveType[] allowed_types; - - public ExpressionSpecialPrimitiveTypeSort - (String name, PrimitiveType[] allowed_types) { - - super(new Name(name)); - this.allowed_types = allowed_types; - } - - public boolean canStandFor(ProgramElement check, - ExecutionContext ec, - Services services) { - if (!super.canStandFor(check, ec, services)) { - return false; - } - - final KeYJavaType kjt = getKeYJavaType(check, ec, services); - if (kjt != null) { - final Type type = kjt.getJavaType(); + private static final class ExpressionSpecialPrimitiveTypeSort + extends ExpressionSort { - for (PrimitiveType allowed_type : allowed_types) { - if (type == allowed_type) - return true; + private final PrimitiveType[] allowed_types; + + public ExpressionSpecialPrimitiveTypeSort + (String name, PrimitiveType[] allowed_types) { + + super(new Name(name)); + this.allowed_types = allowed_types; + } + + public boolean canStandFor(ProgramElement check, + ExecutionContext ec, + Services services) { + if (!super.canStandFor(check, ec, services)) { + return false; } + + final KeYJavaType kjt = getKeYJavaType(check, ec, services); + if (kjt != null) { + final Type type = kjt.getJavaType(); + + for (PrimitiveType allowed_type : allowed_types) { + if (type == allowed_type) + return true; + } } - return false; - } + return false; + } } //-----------Specials (unnecessary?)-------------------------------------- - - private static final class LoopInitSort extends ProgramSVSort{ - public LoopInitSort() { - super(new Name("LoopInit")); - } + private static final class LoopInitSort extends ProgramSVSort { + + public LoopInitSort() { + super(new Name("LoopInit")); + } - protected boolean canStandFor(ProgramElement check, Services services) { - return (check instanceof LoopInit); - } + protected boolean canStandFor(ProgramElement check, Services services) { + return (check instanceof LoopInit); + } } - private static final class GuardSort extends ProgramSVSort{ - public GuardSort() { - super(new Name("Guard")); - } - - protected boolean canStandFor(ProgramElement check, Services services) { - return (check instanceof Guard); - } + private static final class GuardSort extends ProgramSVSort { + public GuardSort() { + super(new Name("Guard")); + } + + protected boolean canStandFor(ProgramElement check, Services services) { + return (check instanceof Guard); + } } - private static final class ForUpdatesSort extends ProgramSVSort{ - public ForUpdatesSort() { - super(new Name("ForUpdates")); - } - protected boolean canStandFor(ProgramElement check, Services services) { - return (check instanceof ForUpdates); + private static final class ForUpdatesSort extends ProgramSVSort { + public ForUpdatesSort() { + super(new Name("ForUpdates")); + } - } + protected boolean canStandFor(ProgramElement check, Services services) { + return (check instanceof ForUpdates); + + } } - + private static final class ForLoopSort extends ProgramSVSort { public ForLoopSort() { super(new Name("ForLoop")); } + protected boolean canStandFor(ProgramElement check, Services services) { return (check instanceof For); } } - - private static final class SwitchSVSort extends ProgramSVSort{ - public SwitchSVSort(){ - super(new Name("Switch")); - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - return (pe instanceof Switch); - } + + private static final class SwitchSVSort extends ProgramSVSort { + public SwitchSVSort() { + super(new Name("Switch")); + } + + protected boolean canStandFor(ProgramElement pe, + Services services) { + return (pe instanceof Switch); + } } - private static final class MultipleVariableDeclarationSort extends ProgramSVSort{ + private static final class MultipleVariableDeclarationSort extends ProgramSVSort { - public MultipleVariableDeclarationSort() { - super(new Name("MultipleVariableDeclaration")); - } + public MultipleVariableDeclarationSort() { + super(new Name("MultipleVariableDeclaration")); + } - protected boolean canStandFor(ProgramElement pe, - Services services) { - return pe instanceof VariableDeclaration && - ((VariableDeclaration) pe).getVariables().size() > 1; - } + protected boolean canStandFor(ProgramElement pe, + Services services) { + return pe instanceof VariableDeclaration && + ((VariableDeclaration) pe).getVariables().size() > 1; + } } - private static final class ArrayPostDeclarationSort extends ProgramSVSort{ + private static final class ArrayPostDeclarationSort extends ProgramSVSort { - public ArrayPostDeclarationSort() { - super(new Name("ArrayPostDeclaration")); - } + public ArrayPostDeclarationSort() { + super(new Name("ArrayPostDeclaration")); + } - protected boolean canStandFor(ProgramElement pe, - Services services) { - return pe instanceof VariableDeclaration && - ((VariableDeclaration) pe).getVariables().size() == 1 && - ((VariableDeclaration) pe).getVariables(). - get(0).getDimensions() > 0; + protected boolean canStandFor(ProgramElement pe, + Services services) { + return pe instanceof VariableDeclaration && + ((VariableDeclaration) pe).getVariables().size() == 1 && + ((VariableDeclaration) pe).getVariables(). + get(0).getDimensions() > 0; - } + } } //------------------ stuff concerned with explicit and implicit elements---- - - - private static final class ConstantProgramVariableSort - extends ProgramSVSort { - - private final Name type = new Name("java.lang.String"); - private final boolean isString; - - public ConstantProgramVariableSort(Name svSortName, boolean string) { - super(svSortName); - isString = string; - } - - - public boolean canStandFor(Term t) { - return t.op () instanceof ProgramConstant && - isString == t.sort().name().equals(type); - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - return false; - } + + + private static final class ConstantProgramVariableSort + extends ProgramSVSort { + + private final Name type = new Name("java.lang.String"); + private final boolean isString; + + public ConstantProgramVariableSort(Name svSortName, boolean string) { + super(svSortName); + isString = string; + } + + + public boolean canStandFor(Term t) { + return t.op() instanceof ProgramConstant && + isString == t.sort().name().equals(type); + } + + protected boolean canStandFor(ProgramElement pe, + Services services) { + return false; + } } private static final class ArrayLengthSort extends ProgramSVSort { public ArrayLengthSort() { - super(new Name("ArrayLength")); + super(new Name("ArrayLength")); } - protected boolean canStandFor(ProgramElement check, - Services services) { + protected boolean canStandFor(ProgramElement check, + Services services) { if (check instanceof ProgramVariable) { return check == services.getJavaInfo().getArrayLength(); } return false; } } - + private static final class ExecutionContextSort extends ProgramSVSort { - public ExecutionContextSort() { - super(new Name("ExecutionContext")); - } - - protected boolean canStandFor(ProgramElement check, - Services services) { - return (check instanceof ExecutionContext); - } - } - - + public ExecutionContextSort() { + super(new Name("ExecutionContext")); + } + + protected boolean canStandFor(ProgramElement check, + Services services) { + return (check instanceof ExecutionContext); + } + } + + //-------------------helper methods ------------------------------------ - + static boolean methodConstrReference(ProgramElement pe) { - return (pe instanceof MethodReference) - || (pe instanceof ConstructorReference); + return (pe instanceof MethodReference) + || (pe instanceof ConstructorReference); } public ProgramElement getSVWithSort(ExtList l, Class alternative) { for (final Object o : l) { - if (o instanceof SchemaVariable - && (((SchemaVariable)o).sort()==this)) { + if (o instanceof SchemaVariable + && (((SchemaVariable) o).sort() == this)) { return (ProgramElement) o; } else if ((alternative.isInstance(o)) && (!(o instanceof SchemaVariable))) { return (ProgramElement) o; } } - return null; + return null; } static KeYJavaType getKeYJavaType(ProgramElement pe, ExecutionContext ec, Services services) { - return services.getTypeConverter().getKeYJavaType((Expression)pe, ec); + return services.getTypeConverter().getKeYJavaType((Expression) pe, ec); } static boolean implicit(ProgramElement pe) { - if (pe instanceof ProgramVariable) { - if (!((ProgramVariable)pe).isMember()) return false; - } - - final String elemname; - if (pe instanceof NamedProgramElement) { - elemname = ((NamedProgramElement)pe).getProgramElementName().getProgramName(); - } else if (pe instanceof Named) { - final Name n = ((Named)pe).name(); - if (n instanceof ProgramElementName) { - elemname = ((ProgramElementName)n).getProgramName(); - } else { - elemname = n.toString(); - } - } else { - System.err.println("Please check implicit in ProgramSVSort"); - return false; - } - return elemname.charAt(0)=='<'; + if (pe instanceof ProgramVariable) { + if (!((ProgramVariable) pe).isMember()) return false; + } + + final String elemname; + if (pe instanceof NamedProgramElement) { + elemname = ((NamedProgramElement) pe).getProgramElementName().getProgramName(); + } else if (pe instanceof Named) { + final Name n = ((Named) pe).name(); + if (n instanceof ProgramElementName) { + elemname = ((ProgramElementName) n).getProgramName(); + } else { + elemname = n.toString(); + } + } else { + System.err.println("Please check implicit in ProgramSVSort"); + return false; + } + return elemname.charAt(0) == '<'; } public static Map name2sort() { return name2sort; } - + } diff --git a/key/key.core/src/de/uka/ilkd/key/parser/KeYLexer.g b/key/key.core/src/de/uka/ilkd/key/parser/KeYLexer.g deleted file mode 100644 index 33b339d5f2c..00000000000 --- a/key/key.core/src/de/uka/ilkd/key/parser/KeYLexer.g +++ /dev/null @@ -1,791 +0,0 @@ -// This file is part of KeY - Integrated Deductive Software Design -// Copyright (C) 2001-2011 Universitaet Karlsruhe, Germany -// Universitaet Koblenz-Landau, Germany -// Chalmers University of Technology, Sweden -// -// The KeY system is protected by the GNU General Public License. -// See LICENSE.TXT for details. -// -// This file is part of KeY - Integrated Deductive Software Design -// Copyright (C) 2001-2009 Universitaet Karlsruhe, Germany -// Universitaet Koblenz-Landau, Germany -// Chalmers University of Technology, Sweden -// -// The KeY system is protected by the GNU General Public License. -// See LICENSE.TXT for details. -// -// - -lexer grammar KeYLexer; - -//options { -// k=2; -//} - -/* -*-Antlr-*- */ - -@header { - package de.uka.ilkd.key.parser; - - import java.io.InputStream; - import de.uka.ilkd.key.util.*; - import java.util.HashMap; - import java.util.LinkedHashMap; - import antlr.CharStreamException; - import antlr.TokenStreamException; - import org.antlr.runtime.*; - import java.util.NoSuchElementException; - import java.io.*; -} - -@annotateclass{ @SuppressWarnings("all") } - -@members{ - class SaveStruct { - SaveStruct (CharStream input) { - this.input = input; - this.marker = input.mark(); - } - - public CharStream input; - public int marker; - } - - protected Stack selector = new Stack();; - - public Stack getSelector() { - return selector; - } - - // We should override this method for handling EOF of included file - @Override - public Token nextToken(){ - Token token = super.nextToken(); - - if (token.getType() == Token.EOF && !selector.empty()) { - // We've got EOF and have non empty stack. - SaveStruct ss = selector.pop(); - setCharStream(ss.input); - input.rewind(ss.marker); - // this should be used instead of super [like below] to handle exits from nested includes - // it matters, when the 'include' token is the last in previous stream (using super, lexer 'crashes' returning EOF token) - token = this.nextToken(); - } - - // Skip first token after switching on another input. - // You need to use this rather than super as there may be nested include files - if (((CommonToken)token).getStartIndex() < 0) { - token = this.nextToken(); - } - - return token; - } - - private String modalityBegin = null; - private String modalityEnd = null; - - private static HashMap modNames = new LinkedHashMap(20); - private static HashMap modPairs = new LinkedHashMap(20); - - static { - modNames.put("\\<","diamond"); - modNames.put("\\diamond","diamond"); - modNames.put("\\diamond_transaction","diamond_transaction"); - modNames.put("\\[","box"); - modNames.put("\\box","box"); - modNames.put("\\box_transaction","box_transaction"); - modNames.put("\\[[","throughout"); - modNames.put("\\throughout","throughout"); - modNames.put("\\throughout_transaction","throughout_transaction"); - - modPairs.put("\\<","\\>"); - modPairs.put("\\modality","\\endmodality"); - modPairs.put("\\diamond","\\endmodality"); - modPairs.put("\\diamond_transaction","\\endmodality"); - modPairs.put("\\[","\\]"); - modPairs.put("\\box","\\endmodality"); - modPairs.put("\\box_transaction","\\endmodality"); - modPairs.put("\\[[","\\]]"); - modPairs.put("\\throughout","\\endmodality"); - modPairs.put("\\throughout_transaction","\\endmodality"); - } - - public void recover( RecognitionException ex, BitSet tokenSet ) throws CharStreamException { - input.consume(); - int ttype = input.LA(1); - while (ttype != Token.EOF && !tokenSet.member(ttype)) { - input.consume(); - ttype = input.LA(1); - } - } - - private void matchAndTransformModality(int beginIndex) throws RecognitionException { - if(!modalityEnd.equals((String)modPairs.get(modalityBegin))) - throw new NoViableAltException("Unknown modality " + - "expression "+modalityBegin+"..."+modalityEnd+". (" + - getSourceName() + ", " + getLine() + ", " + getCharPositionInLine() + ")", -1, -1, input); - - StringBuffer newText = new StringBuffer(); - int index = 0; - int first = 0; - int last = 0; - String s = getText(); - newText.append(s.substring(0,beginIndex)); - index = beginIndex + modalityBegin.length(); - String modName = ""; - if("\\modality".equals(modalityBegin)) { - // Have to extract the name of (schema) modality inside the first {} - while(s.charAt(index) == ' ' || s.charAt(index) == '\t' || - s.charAt(index) == '\n' || s.charAt(index) == '\r') index++; - if(s.charAt(index) != '{') { - throw new NoViableAltException("Expression "+modalityBegin+" should be followed by {...}. (" + - getSourceName() + ", " + getLine() + ", " + getCharPositionInLine() + ")", -1, -1, input); - } - index++; - first = index; - char currChar = s.charAt(index); - while(currChar == ' ' || currChar == '\t' || - currChar == '\r' || currChar == '\n') { - index++; first = index; - currChar = s.charAt(index); - } - last = first; - while((currChar >= 'a' && currChar <= 'z') || - (currChar >= 'A' && currChar <= 'Z') || - currChar == '_' || currChar == '#') { - index++; last = index; - currChar = s.charAt(index); - } - while(currChar == ' ' || currChar == '\t' || - currChar == '\r' || currChar == '\n') { - index++; - currChar = s.charAt(index); - } - if(s.charAt(index) != '}') { - throw new NoViableAltException("Expected '}', found "+s.charAt(index)+". (" + getSourceName() + ", " + getLine() + ", " + getCharPositionInLine() + ")", -1, -1, input); - } - index++; - modName=s.substring(first,last); - if("".equals(modName)) { - throw new NoViableAltException("Empty modality name. Modality block was: "+s + "(" + getSourceName() + ", " + getLine() + ", " + getCharPositionInLine() + ")", -1, -1, input); - } - }else{ - modName = (String)modNames.get(modalityBegin); - if(modName==null) { - throw new NoViableAltException("Unknown modality "+modalityBegin+". (" + getSourceName() + ", " + getLine() + ", " + getCharPositionInLine() + ")", -1, -1, input); - } - - } - newText.append(modName+"\n"); - //Debug.out("Modality name :", modName); - last = s.lastIndexOf(modalityEnd); - newText.append(s.substring(index,last)); - setText(newText.toString()); - //Debug.out("Lexer: recognised Java block string: ", getText()); - } - -} - -//@rulecatch { -// catch(RecognitionException e) { -// throw e; -// } -//} - -/** - * The common lexer for declarations, terms, formulae, Taclets, etc. - */ - - // Keywords used in sort declarations - SORTS:'\\sorts'; - GENERIC : '\\generic'; - PROXY : '\\proxy'; - EXTENDS : '\\extends'; - ONEOF : '\\oneof'; - ABSTRACT : '\\abstract'; - - // Keywords used in schema variable declarations - SCHEMAVARIABLES : '\\schemaVariables'; - SCHEMAVAR : '\\schemaVar'; - MODALOPERATOR : '\\modalOperator'; - PROGRAM : '\\program'; - FORMULA : '\\formula'; - TERM : '\\term'; - UPDATE : '\\update'; - VARIABLES : '\\variables'; - VARIABLE : '\\variable'; - SKOLEMTERM : '\\skolemTerm'; - SKOLEMFORMULA : '\\skolemFormula'; - TERMLABEL : '\\termlabel'; - - // used in contracts - MODIFIES : '\\modifies'; - - // Keywords used in program variable declarations - PROGRAMVARIABLES : '\\programVariables'; - - // Keywords for varcond and related stuff - VARCOND : '\\varcond'; - APPLY_UPDATE_ON_RIGID : '\\applyUpdateOnRigid'; - DEPENDINGON : '\\dependingOn'; - DISJOINTMODULONULL : '\\disjointModuloNull'; - DROP_EFFECTLESS_ELEMENTARIES : '\\dropEffectlessElementaries'; - DROP_EFFECTLESS_STORES : '\\dropEffectlessStores'; - SIMPLIFY_IF_THEN_ELSE_UPDATE : '\\simplifyIfThenElseUpdate'; - ENUM_CONST : '\\enumConstant'; - FREELABELIN : '\\freeLabelIn'; - HASSORT : '\\hasSort'; - FIELDTYPE : '\\fieldType'; - FINAL : '\\final'; - ELEMSORT : '\\elemSort'; - HASLABEL : '\\hasLabel'; - HASSUBFORMULAS : '\\hasSubFormulas'; - ISARRAY:'\\isArray'; - ISARRAYLENGTH:'\\isArrayLength'; - ISCONSTANT: '\\isConstant'; - ISENUMTYPE:'\\isEnumType'; - ISINDUCTVAR:'\\isInductVar'; - ISLOCALVARIABLE : '\\isLocalVariable'; - ISOBSERVER : '\\isObserver'; - DIFFERENT : '\\different'; - METADISJOINT : '\\metaDisjoint'; - ISTHISREFERENCE:'\\isThisReference'; - DIFFERENTFIELDS:'\\differentFields'; - ISREFERENCE:'\\isReference'; - ISREFERENCEARRAY:'\\isReferenceArray'; - ISSTATICFIELD : '\\isStaticField'; - ISSUBTYPE : '\\sub'; - EQUAL_UNIQUE : '\\equalUnique'; - NEW : '\\new'; - NEWLABEL : '\\newLabel'; - CONTAINS_ASSIGNMENT : '\\containsAssignment'; -// label occurs again for character `!' - NOT_ : '\\not'; - NOTFREEIN : '\\notFreeIn'; - SAME : '\\same'; - STATIC : '\\static'; - STATICMETHODREFERENCE : '\\staticMethodReference'; - STRICT : '\\strict'; - TYPEOF : '\\typeof'; - INSTANTIATE_GENERIC : '\\instantiateGeneric'; - - // Quantifiers, binding, substitution - FORALL : '\\forall' | '\u2200'; - EXISTS : '\\exists' | '\u2203'; - SUBST : '\\subst'; - IF : '\\if'; - IFEX : '\\ifEx'; - THEN : '\\then'; - ELSE : '\\else'; - - // inclusion and stuff, things that (usually) come at the beginning - // of the file - INCLUDE:'\\include'; - INCLUDELDTS:'\\includeLDTs'; - CLASSPATH:'\\classpath'; - BOOTCLASSPATH:'\\bootclasspath'; - NODEFAULTCLASSES:'\\noDefaultClasses'; - JAVASOURCE:'\\javaSource'; - WITHOPTIONS:'\\withOptions'; - OPTIONSDECL:'\\optionsDecl'; - KEYSETTINGS : '\\settings'; - PROFILE : '\\profile'; - - // Those guys can stay being keywords - TRUE : 'true'; - FALSE : 'false'; - - // Keywords related to taclets - SAMEUPDATELEVEL : '\\sameUpdateLevel'; - INSEQUENTSTATE : '\\inSequentState'; - ANTECEDENTPOLARITY : '\\antecedentPolarity'; - SUCCEDENTPOLARITY : '\\succedentPolarity'; - CLOSEGOAL : '\\closegoal'; - HEURISTICSDECL : '\\heuristicsDecl'; - NONINTERACTIVE : '\\noninteractive'; - DISPLAYNAME : '\\displayname'; - HELPTEXT : '\\helptext'; - REPLACEWITH : '\\replacewith'; - ADDRULES : '\\addrules'; - ADDPROGVARS : '\\addprogvars'; - HEURISTICS : '\\heuristics'; - FIND : '\\find'; - ADD : '\\add'; - ASSUMES : '\\assumes'; - TRIGGER : '\\trigger'; - AVOID : '\\avoid'; - - PREDICATES : '\\predicates'; - FUNCTIONS : '\\functions'; - TRANSFORMERS : '\\transformers'; - UNIQUE : '\\unique'; - - RULES : '\\rules'; - AXIOMS : '\\axioms'; - PROBLEM : '\\problem'; - CHOOSECONTRACT : '\\chooseContract'; - PROOFOBLIGATION : '\\proofObligation'; - PROOF : '\\proof'; - PROOFSCRIPT : '\\proofScript'; - CONTRACTS : '\\contracts'; - INVARIANTS : '\\invariants'; - - // Taclet annotations (see TacletAnnotations.java for more details) - LEMMA : '\\lemma'; - - // The first two guys are not really meta operators, treated separately - IN_TYPE : '\\inType'; - IS_ABSTRACT_OR_INTERFACE : '\\isAbstractOrInterface'; - CONTAINERTYPE : '\\containerType'; - - // types that need to be declared as keywords - LOCSET : '\\locset'; - SEQ : '\\seq'; - BIGINT : '\\bigint'; - - // Unicode symbols for special functions/predicates - UTF_PRECEDES : '\u227A'; - UTF_IN : '\u220A'; - UTF_EMPTY : '\u2205'; - UTF_UNION : '\u222A'; - UTF_INTERSECT : '\u2229'; - UTF_SUBSET : '\u2286'; - UTF_SETMINUS : '\u2216'; - -fragment -VOCAB - : '\u0003'..'\u0377' - ; - -SEMI -: ';' - ; - -SLASH -: '/' - ; - -BACKSLASH -: '\\' - ; - -COLON -: ':' - ; - -DOUBLECOLON -: '::' - ; - -ASSIGN -: ':=' - ; - -DOT -: '.' - ; - -DOTRANGE -: '.' '.' - ; - -COMMA -: ',' - ; - -LPAREN -: - '(' - ; - -RPAREN -: ')' - ; - -LBRACE -: '{' - ; - -RBRACE -: '}' - ; - -LBRACKET -: '[' - ; - -RBRACKET -: ']' - ; - -EMPTYBRACKETS -: '[' ']' - ; - -AT -: '@' - ; - -PARALLEL -: '|' '|' - ; - - -OR -: '|' | '\u2228' - ; - -AND -: '&' | '\u2227' - ; - -NOT -: '!' | '\u00AC' - ; - -IMP -: '->' | '\u2192' - ; - -EQUALS -: '=' - ; - -NOT_EQUALS -: '!=' | '\u2260' - ; - -SEQARROW -: '==>' - ; - -EXP -: '^' - ; - -TILDE -: '~' - ; - -PERCENT -: '%' - ; - -STAR -: '*' - ; - -MINUS -: '-' - ; - -PLUS -: '+' - ; - -GREATER -: '>' - ; - -GREATEREQUAL -: '>' '=' | '\u2265' - ; - -RGUILLEMETS - : '>' '>' - ; - -OPENTYPEPARAMS - : '<' '[' ; - -CLOSETYPEPARAMS - : ']' '>' ; - -WS -: (' ' - | '\t' - | '\n' - | '\r' ) - { $channel = HIDDEN; } - ; - -STRING_LITERAL - :'"' ('\\' . | ~( '"' | '\\') )* '"' ; - - -LESS_DISPATCH -: - ('<' (LETTER)+ '>') => IMPLICIT_IDENT {$type = IDENT;} - | - ('<' '-' '>') => EQV {$type = EQV;} - | - ('<' '=' ) => LESSEQUAL {$type = LESSEQUAL;} - | - ('<' '<' ) => LGUILLEMETS {$type = LGUILLEMETS;} - | - LESS {$type = LESS;} - ; - -fragment LESS -: - '<' -; - -fragment LESSEQUAL -: - '<' '=' | '\u2264' - ; - -fragment LGUILLEMETS -: - '<' '<' - ; - - -fragment IMPLICIT_IDENT -: - '<' (LETTER)+ '>' -; - -fragment EQV -: '<->' | '\u2194' -; - -PRIMES_OR_CHARLITERAL -: - ('\'' '\'') => PRIMES {$type = PRIMES;} - | - ('\'' '\\') => CHAR_LITERAL {$type = CHAR_LITERAL;} - | - ('\'' ~('\'') '\'') => CHAR_LITERAL {$type = CHAR_LITERAL;} - | - PRIMES {$type = PRIMES;} - ; - - -fragment -PRIMES -: ('\'')+ - ; - -fragment -CHAR_LITERAL -: '\'' - ((' '..'&') | - ('('..'[') | - (']'..'~') | - ('\\' ('\'' | '\\' | 'n' | 'r' | 't' | 'b' | 'f' | '"' | 'u' HEX )) - ) - '\'' - ; - -fragment -QUOTED_STRING_LITERAL - : '"' ('\\' . | '\n' | ~('\n' | '"' | '\\') )* '"' ; - -SL_COMMENT -: - '//' - (~('\n' | '\uFFFF'))* ('\n' | '\uFFFF' | EOF) - { $channel = HIDDEN; } - ; - -ML_COMMENT -: - '/*' { - - final int startAtLine = input.getLine(); - final int startAtColumn = input.getCharPositionInLine() - 2; - - while(true) { - if(input.LA(1) == '*' && input.LA(2) == '/') { - match("*/"); - break; - } - if (input.LA(1) == EOF) { - throw new RecognitionException(input){ - @Override - public String getMessage() { - return "Unclosed comment in " + input.getSourceName() + "\n\n" - + "Started a comment with '/*' at line " + startAtLine - + " column " + startAtColumn - + " but reached end of file without encountering '*/'."; - } - }; - } else { - input.consume(); - } - } - $channel = HIDDEN; - - } - ; - -// A single Digit that is followed by a ( is an ident, otherwise it's a number - -DIGIT_DISPATCH -: - (DIGIT (' ' | '\t' | '\r' | '\n')* LPAREN) => DIGIT {$type = IDENT;} - | ('0' 'x') => HEX_LITERAL {$type = NUM_LITERAL;} - | NUM_LITERAL {$type = NUM_LITERAL;} -; - -fragment -HEX_LITERAL -: '0' 'x' (DIGIT | 'a'..'f' | 'A'..'F')+ - ; - -fragment -DIGIT -: '0'..'9' - ; - - -fragment -HEX -: ('a'..'f'|'A'..'F'|DIGIT ) - ('a'..'f'|'A'..'F'|DIGIT ) - ('a'..'f'|'A'..'F'|DIGIT ) - ('a'..'f'|'A'..'F'|DIGIT ) - ; - -fragment -LETTER -: 'a'..'z'|'A'..'Z' - ; - - -fragment IDCHAR -: LETTER | DIGIT | '_' | '#' | '$' - ; - -IDENT -: ( (LETTER | '_' | '#' | '$') (IDCHAR)* - ) -; - -fragment -NUM_LITERAL -: - (DIGIT)+ - ; - -/** - * Here we have to accept all strings of kind \\[a-z_] - * and make the decision our selves as to what to do with it - * (i.e. is it a modality, keyword, or possibly something else) - */ -MODALITY -@init { - int _begin = getText().length(); -} -: '\\' ( (LETTER | '_')+ | '<' | '[' | '[[') { - modalityBegin = getText(); - Debug.out("modalityBegin == ", modalityBegin); - //int literalTest = testLiteralsTable(MODALITY); - //Debug.out("testLiteralsTable == ", literalTest); - //$type = testLiteralsTable($type); - if(/*literalTest == MODALITY && */modPairs.get(modalityBegin) != null) { - /* This while with the following call to mMODALITYEND is - * and alternative to calling mJAVABLOCK, but it should be faster - */ - while(true) { - if(input.LA(1) == '/' && input.LA(2) == '/') { - mSL_COMMENT(); continue; - } - if(input.LA(1) == '/' && input.LA(2) == '*') { - mML_COMMENT(); continue; - } - if(input.LA(1) == '/' && input.LA(2) == '*') { - mML_COMMENT(); continue; - } - if(input.LA(1) == '\"') { - mQUOTED_STRING_LITERAL(); continue; - } - if(input.LA(1) == '\'') { - mCHAR_LITERAL(); continue; - } - if(input.LA(1) == '\\' && (input.LA(2) == 'e' || input.LA(2) == '>' || input.LA(2) == ']')) - // check whether it follows an ENDMODALITY - break; - if (input.LA(1) == EOF) { - throw new NoViableAltException("Matched EOF", -1, -1, input); - } else { - input.consume(); - } - } - mMODALITYEND(); - // mJAVABLOCK(false); - matchAndTransformModality(_begin); - }else{ - if("\\includeFile".equals(modalityBegin)) { - // File inclusion - while(input.LA(1) == ' ' || input.LA(1) == '\t' || input.LA(1) == '\n') - match(input.LA(1)); - int startIndex = getText().length()+1; - mQUOTED_STRING_LITERAL(); - int stopIndex = getText().length()-1; - while(input.LA(1) == ' ' || input.LA(1) == '\t' || input.LA(1) == '\n') - match(input.LA(1)); - mSEMI(); - $channel = HIDDEN; - String fileName = getText().toString().substring(startIndex,stopIndex); - Debug.out("File to be included: ", fileName); - File incf = new File(fileName); - File f = new File(getSourceName()); - if((f.isAbsolute() || f.getParentFile() != null) && !incf.isAbsolute()) { - f = new File(f.getParentFile(), fileName); - fileName = f.getAbsolutePath(); - } - Debug.out("File to be included: ", fileName); - try { - // save current lexer's state - SaveStruct ss = new SaveStruct(input); - selector.push(ss); - - Debug.out("Pushed lexer."); - - // switch on new input stream - setCharStream(new ANTLRFileStream(fileName)); - reset(); - } catch (IOException fnf) { - throw new NoViableAltException("File '" + fileName + "' not found. (" + - getSourceName() + ", " + getLine() + ", " + getCharPositionInLine() + ")", -1, -1, input); - } - } else { - $type = IDENT; // make it an IDENT starting with '\\' - // (it will not contain digits!) - } - } -} -; - -fragment MODALITYEND -@init{ int _begin = getText().length(); } -: '\\' ( 'endmodality' | '>' | ']' | ']]') { - modalityEnd = getText().substring(_begin); - Debug.out("modalityEnd == ", modalityEnd); - } - ; - -fragment -JAVABLOCK -: - ( - SL_COMMENT - | ML_COMMENT - | '/' ~('/' | '*') - | CHAR_LITERAL - | QUOTED_STRING_LITERAL - | '\r' - | '\n' - | 'a'..'z' | 'A'..'Z' | '_' - | '0'..'9' - | ' ' | '\t' - | '{' | '}' | '(' | ')' | '[' | ']' | '<' | '>' - | '.' | ',' | ';' | ':' | '?' - | '%' | '*' | '-' | '=' | '+' | '~' | '&' | '|' | '^' - | '!' | '@' | '#' | '$' - )* MODALITYEND - ; - diff --git a/key/key.core/src/de/uka/ilkd/key/parser/KeYParser.g b/key/key.core/src/de/uka/ilkd/key/parser/KeYParser.g deleted file mode 100644 index ce6b68a753f..00000000000 --- a/key/key.core/src/de/uka/ilkd/key/parser/KeYParser.g +++ /dev/null @@ -1,4789 +0,0 @@ - -// This file is part of KeY - Integrated Deductive Software Design -// Copyright (C) 2001-2011 Universitaet Karlsruhe, Germany -// Universitaet Koblenz-Landau, Germany -// Chalmers University of Technology, Sweden -// -// The KeY system is protected by the GNU General Public License. -// See LICENSE.TXT for details. -// -// This file is part of KeY - Integrated Deductive Software Design -// Copyright (C) 2001-2009 Universitaet Karlsruhe, Germany -// Universitaet Koblenz-Landau, Germany -// Chalmers University of Technology, Sweden -// -// The KeY system is protected by the GNU General Public License. -// See LICENSE.TXT for details. -// -// - -parser grammar KeYParser; - -options { - tokenVocab=KeYLexer; - k = 1; -} - -/* -*-antlr-*- */ -@header { - - package de.uka.ilkd.key.parser; - - import de.uka.ilkd.key.parser.AmbigiousDeclException; - import de.uka.ilkd.key.parser.GenericSortException; - import de.uka.ilkd.key.parser.InvalidFindException; - import de.uka.ilkd.key.parser.KeYSemanticException; - import de.uka.ilkd.key.parser.NotDeclException; - import de.uka.ilkd.key.parser.SchemaVariableModifierSet; - import de.uka.ilkd.key.parser.UnfittingReplacewithException; - import de.uka.ilkd.key.parser.ParserMode; - import de.uka.ilkd.key.parser.IdDeclaration; - import de.uka.ilkd.key.parser.ParserConfig; - - import antlr.CharScanner; - import antlr.SemanticException; - import antlr.LexerSharedInputState; - import antlr.TokenStreamException; - import antlr.TokenStreamSelector; - import org.antlr.runtime.*; - - import java.io.*; - import java.util.HashSet; - import java.util.Iterator; - import java.util.LinkedHashMap; - import java.util.LinkedHashSet; - import java.util.LinkedList; - import java.util.Set; - import java.util.Vector; - import java.math.BigInteger; - - import org.key_project.util.collection.DefaultImmutableSet; - import org.key_project.util.collection.ImmutableArray; - import org.key_project.util.collection.ImmutableList; - import org.key_project.util.collection.ImmutableSLList; - import org.key_project.util.collection.ImmutableSet; - import org.key_project.util.collection.Immutables; - import de.uka.ilkd.key.logic.*; - import de.uka.ilkd.key.logic.op.*; - import de.uka.ilkd.key.logic.sort.*; - import de.uka.ilkd.key.logic.sort.ParametricSort.Variance; - import de.uka.ilkd.key.logic.label.*; - - import de.uka.ilkd.key.proof.init.*; - import de.uka.ilkd.key.proof.io.*; - import static de.uka.ilkd.key.proof.io.IProofFileParser.*; - - import de.uka.ilkd.key.rule.*; - import de.uka.ilkd.key.rule.tacletbuilder.*; - import de.uka.ilkd.key.rule.conditions.*; - import de.uka.ilkd.key.rule.label.*; - - import de.uka.ilkd.key.speclang.*; - - import de.uka.ilkd.key.speclang.dl.translation.DLSpecFactory; - - import de.uka.ilkd.key.util.*; - - import de.uka.ilkd.key.java.JavaInfo; - import de.uka.ilkd.key.java.Services; - import de.uka.ilkd.key.java.JavaReader; - import de.uka.ilkd.key.java.SchemaJavaReader; - import de.uka.ilkd.key.java.abstraction.*; - import de.uka.ilkd.key.java.visitor.*; - import de.uka.ilkd.key.java.Recoder2KeY; - import de.uka.ilkd.key.java.SchemaRecoder2KeY; - import de.uka.ilkd.key.java.StatementBlock; - import de.uka.ilkd.key.java.declaration.VariableDeclaration; - import de.uka.ilkd.key.java.recoderext.*; - import de.uka.ilkd.key.pp.AbbrevMap; - import de.uka.ilkd.key.pp.LogicPrinter; - - import de.uka.ilkd.key.ldt.SeqLDT; - import de.uka.ilkd.key.ldt.IntegerLDT; - - -} - -@annotateclass{ @SuppressWarnings("all") } - -@members{ - - private static final Sort[] AN_ARRAY_OF_SORTS = new Sort[0]; - private static final Term[] AN_ARRAY_OF_TERMS = new Term[0]; - - private static final int NORMAL_NONRIGID = 0; - private static final int LOCATION_MODIFIER = 1; - - private static final String LIMIT_SUFFIX = "\$lmtd"; - - static HashMap prooflabel2tag = new LinkedHashMap<>(15); - static { - prooflabel2tag.put("branch", ProofElementID.BRANCH); - prooflabel2tag.put("rule", ProofElementID.RULE); - prooflabel2tag.put("term", ProofElementID.TERM); - prooflabel2tag.put("formula", ProofElementID.FORMULA); - prooflabel2tag.put("inst", ProofElementID.INSTANTIATION); - prooflabel2tag.put("ifseqformula", ProofElementID.ASSUMES_FORMULA_IN_SEQUENT); - prooflabel2tag.put("ifdirectformula", ProofElementID.ASSUMES_FORMULA_DIRECT); - prooflabel2tag.put("heur", ProofElementID.RULESET); - prooflabel2tag.put("builtin", ProofElementID.BUILT_IN_RULE); - prooflabel2tag.put("keyLog", ProofElementID.KeY_LOG); - prooflabel2tag.put("keyUser", ProofElementID.KeY_USER); - prooflabel2tag.put("keyVersion", ProofElementID.KeY_VERSION); - prooflabel2tag.put("keySettings", ProofElementID.KeY_SETTINGS); - prooflabel2tag.put("contract", ProofElementID.CONTRACT); - prooflabel2tag.put("ifInst", ProofElementID.ASSUMES_INST_BUILT_IN); - prooflabel2tag.put("userinteraction", ProofElementID.USER_INTERACTION); - prooflabel2tag.put("newnames", ProofElementID.NEW_NAMES); - prooflabel2tag.put("autoModeTime", ProofElementID.AUTOMODE_TIME); - prooflabel2tag.put("mergeProc", ProofElementID.MERGE_PROCEDURE); - prooflabel2tag.put("abstractionPredicates", ProofElementID.MERGE_ABSTRACTION_PREDICATES); - prooflabel2tag.put("latticeType", ProofElementID.MERGE_PREDICATE_ABSTRACTION_LATTICE_TYPE); - prooflabel2tag.put("nrMergePartners", ProofElementID.NUMBER_MERGE_PARTNERS); - prooflabel2tag.put("distFormula", ProofElementID.MERGE_DIST_FORMULA); - prooflabel2tag.put("mergeNode", ProofElementID.MERGE_NODE); - prooflabel2tag.put("mergeId", ProofElementID.MERGE_ID); - prooflabel2tag.put("userChoices", ProofElementID.MERGE_USER_CHOICES); - prooflabel2tag.put("opengoal", ProofElementID.OPEN_GOAL); - } - - private NamespaceSet nss; - private Namespace schemaVariablesNamespace; - private HashMap category2Default = new LinkedHashMap(); - private boolean onlyWith=false; - private ImmutableSet activatedChoices = DefaultImmutableSet.nil(); - private HashSet usedChoiceCategories = new LinkedHashSet(); - private HashMap taclet2Builder; - private AbbrevMap scm; - - - private String filename; - - // these variables are set if a file is read in step by - // step. This used when reading in LDTs because of cyclic - // dependencies. - private boolean skip_schemavariables; - private boolean skip_functions; - private boolean skip_transformers; - private boolean skip_predicates; - private boolean skip_sorts; - private boolean skip_rulesets; - private boolean skip_taclets; - private boolean parse_includes = false; - private Includes includes = new Includes(); - - private boolean schemaMode = false; - private ParserMode parserMode; - - private String chooseContract = null; - private String proofObligation = null; - private String problemHeader = null; - - private int savedGuessing = -1; - - /* - counter variable for parser rules accessterm and heap_selection suffix: - - stores nesting depth of alpha::select(heap,o,f)-terms created via pretty syntax (i.e. terms of the form: o.f) - - rule accessterm increases the counter - - rule heap_selection_suffix calls method heapSelectionSuffix(), which resets - the counter - - In case a term similar to o.f1.f2.f3.f4 would occur, this variable should have a value of 4. - The non-pretty syntax of this term would look similar to the following: - T::select(h, T::select(h, T::select(h, T::select(h, o, f1) , f2) , f3), f4) - */ - protected int globalSelectNestingDepth = 0; - - private int lineOffset=0; - private int colOffset=0; - private int stringLiteralLine=0; // HACK! - - private Services services; - private JavaReader javaReader; - - // if this is used then we can capture parts of the input for later use - private IProgramMethod pm = null; - - private LinkedHashMap taclets = new LinkedHashMap(); - - private ImmutableList contracts = ImmutableSLList.nil(); - private ImmutableSet invs = DefaultImmutableSet.nil(); - - private ParserConfig schemaConfig; - private ParserConfig normalConfig; - - // the current active config - private ParserConfig parserConfig; - - private Term quantifiedArrayGuard = null; - - private String profileName; - - private TokenStream lexer; - - /** - * Although the parser mode can be deduced from the particular constructor - * used we still require the caller to provide the parser mode explicitly, - * so that the code is readable. - */ - - public KeYParser(ParserMode mode, TokenStream lexer, Services services) { - this(mode, lexer); - } - - /* Most general constructor, should only be used internally */ - private KeYParser(TokenStream lexer, - Services services, - NamespaceSet nss, - ParserMode mode) { - this(lexer); - this.lexer = lexer; - this.parserMode = mode; - this.services = services; - this.nss = nss; - this.schemaVariablesNamespace = new Namespace<>(); - if (this.isTacletParser()) { - switchToSchemaMode(); - } else { - switchToNormalMode(); - } - } - - /** - * Used to construct Term parser - for first-order terms - * and formulae. - */ - public KeYParser(ParserMode mode, - TokenStream lexer, - JavaReader jr, - Services services, - NamespaceSet nss, - AbbrevMap scm) { - this(lexer, services, nss, mode); - this.javaReader = jr; - this.scm = scm; - } - - - /** ONLY FOR TEST CASES. - * Used to construct Global Declaration Term parser - for first-order - * terms and formulae. Variables in quantifiers are expected to be - * declared globally in the variable namespace. This parser is used - * for test cases, where you want to know in advance which objects - * will represent bound variables. - */ - public KeYParser(ParserMode mode, - TokenStream lexer, - Services services, - NamespaceSet nss) { - this(mode, - lexer, - new SchemaRecoder2KeY(services, nss), - services, - nss, - new LinkedHashMap()); - } - - /** - * Used to construct Taclet parser - */ - public KeYParser(ParserMode mode, - TokenStream lexer, - SchemaJavaReader jr, - Services services, - NamespaceSet nss, - HashMap taclet2Builder) { - this(lexer, services, nss, mode); - switchToSchemaMode(); - this.scm = new AbbrevMap(); - this.javaReader = jr; - this.taclet2Builder = taclet2Builder; - } - - - /** - * Used to construct Problem parser - */ - public KeYParser(ParserMode mode, - TokenStream lexer, - ParserConfig schemaConfig, - ParserConfig normalConfig, - HashMap taclet2Builder, - ImmutableList taclets) { - this(lexer, null, null, mode); - if (normalConfig!=null) - scm = new AbbrevMap(); - this.schemaConfig = schemaConfig; - this.normalConfig = normalConfig; - switchToNormalMode(); - this.taclet2Builder = taclet2Builder; - - if (taclets != null && !taclets.isEmpty()) { - for (Taclet t : taclets) { - this.taclets.put(new RuleKey(t), t); - } - } - - } - - public KeYParser(ParserMode mode, TokenStream lexer) { - this(lexer, null, null, mode); - scm = new AbbrevMap(); - this.schemaConfig = null; - this.normalConfig = null; - switchToNormalMode(); - this.taclet2Builder = null; - this.taclets = new LinkedHashMap(); - } - - - /** - * Parses taclet from string. - */ - public static Taclet parseTaclet(String s, Services services) { - try { - KeYParserF p = - new KeYParserF(ParserMode.TACLET, - new KeYLexerF(s, - "No file. KeYParser.parseTaclet(\n" + s + ")\n"), - services, - services.getNamespaces()); - return p.taclet(DefaultImmutableSet.nil(), false); - } catch (Exception e) { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - e.printStackTrace(pw); - throw new RuntimeException("Exc while Parsing:\n" + sw ); - } - } - - public String getSourceName() { - if (super.getSourceName() == null) { - return filename; - } - return super.getSourceName(); - } - - public String getChooseContract() { - return chooseContract; - } - - public String getProofObligation() { - return proofObligation; - } - public String getProblemHeader() { - return problemHeader; - } - - public String getProfileName() { - return profileName; - } - - private boolean isDeclParser() { - return parserMode == ParserMode.DECLARATION; - } - - private boolean isTermParser() { - return parserMode == ParserMode.TERM; - } - - private boolean isGlobalDeclTermParser() { - return parserMode == ParserMode.GLOBALDECL; - } - - private boolean isTacletParser() { - return parserMode == ParserMode.TACLET; - } - - private boolean isProblemParser() { - return parserMode == ParserMode.PROBLEM; - } - - public void raiseException(RecognitionException ex) throws RecognitionException { - throw ex; - } - - public ImmutableSet getActivatedChoices(){ - return activatedChoices; - } - - public Includes getIncludes(){ - return includes; - } - - public JavaInfo getJavaInfo() { - if(isProblemParser()) - return parserConfig.javaInfo(); - if(getServices() != null) - return getServices().getJavaInfo(); - else - return null; - } - - public Services getServices() { - if(isProblemParser()) - return parserConfig.services(); - return services; - } - - public TermFactory getTermFactory() { - return getServices().getTermFactory(); - } - - public NamespaceSet namespaces() { - if(isProblemParser()) - return parserConfig.namespaces(); - return nss; - } - - private Namespace sorts() { - return namespaces().sorts(); - } - - private Namespace functions() { - return namespaces().functions(); - } - - private Namespace ruleSets() { - return namespaces().ruleSets(); - } - - private Namespace variables() { - return namespaces().variables(); - } - - private Namespace programVariables() { - return namespaces().programVariables(); - } - - private Namespace choices(){ - return namespaces().choices(); - } - - public Namespace schemaVariables() { - return schemaVariablesNamespace; - } - - public void setSchemaVariablesNamespace(Namespace ns) { - this.schemaVariablesNamespace = ns; - } - - public ImmutableList getTaclets(){ - ImmutableList result = ImmutableSLList.nil(); - - /* maintain correct order for taclet lemma proofs */ - for (Taclet t : taclets.values()) { - result = result.prepend(t); - } - - // restore the order - result = result.reverse(); - - return result; - } - - public ImmutableSet getContracts(){ - return DefaultImmutableSet.fromImmutableList(contracts); - } - - public ImmutableSet getInvariants(){ - return invs; - } - - public HashMap getCategory2Default(){ - return category2Default; - } - - private boolean inSchemaMode() { - if(isTermParser() && schemaMode) - Debug.fail("In Term parser mode schemaMode cannot be true."); - if(isTacletParser() && !schemaMode) - Debug.fail("In Taclet parser mode schemaMode should always be true."); - return schemaMode; - } - - private void switchToSchemaMode() { - if(!isTermParser()) { - schemaMode = true; - if(isProblemParser()) - parserConfig = schemaConfig; - } - } - - private void switchToNormalMode() { - if(!isTermParser() && !isTacletParser()) { - schemaMode = false; - if(isProblemParser()) - parserConfig = normalConfig; - } - } - - private int getLine() { - Token token = ((TokenStream)input).LT(1); - return token.getLine(); - } - - private int getColumn() { - Token token = ((TokenStream)input).LT(1); - return token.getCharPositionInLine(); - } - - private void resetSkips() { - skip_schemavariables = false; - skip_functions = false; - skip_transformers = false; - skip_predicates = false; - skip_sorts = false; - skip_rulesets = false; - skip_taclets = false; - } - - private void skipFuncs() { - skip_functions = true; - } - - private void skipTransformers() { - skip_transformers = true; - } - - private void skipPreds() { - skip_predicates = true; - } - - private void skipTaclets() { - skip_taclets = true; - } - - private void skipVars() { - skip_schemavariables = true; - } - - private void skipSorts() { - skip_sorts = true; - } - - private void skipRuleSets() { - skip_rulesets = true; - } - - private Named lookup(Name n) { - if(isProblemParser()) { - final Namespace[] lookups = { - schemaConfig.namespaces().programVariables(), - normalConfig.namespaces().variables(), - schemaConfig.namespaces().variables(), - normalConfig.namespaces().functions(), - schemaConfig.namespaces().functions(), - }; - return doLookup(n,lookups); - } else { - final Namespace[] lookups = { - programVariables(), variables(), - functions() - }; - return doLookup(n,lookups); - } - } - - private Named doLookup(Name n, Namespace[] lookups) { - for (int i = 0; i choices) throws RecognitionException { - return taclet(choices, false); - } - - private void schema_var_decl(String name, - Sort s, - boolean makeVariableSV, - boolean makeSkolemTermSV, - boolean makeTermLabelSV, - SchemaVariableModifierSet mods) - throws AmbigiousDeclException { - if (!skip_schemavariables) { - SchemaVariable v; - if(s == Sort.FORMULA && !makeSkolemTermSV) { - v = SchemaVariableFactory.createFormulaSV(new Name(name), - mods.rigid()); - } else if(s == Sort.UPDATE) { - v = SchemaVariableFactory.createUpdateSV(new Name(name)); - } else if(s instanceof ProgramSVSort) { - v = SchemaVariableFactory.createProgramSV( - new ProgramElementName(name), - (ProgramSVSort) s, - mods.list()); - } else { - if(makeVariableSV) { - v = SchemaVariableFactory.createVariableSV - (new Name(name), s); - } else if(makeSkolemTermSV) { - v = SchemaVariableFactory.createSkolemTermSV(new Name(name), - s); - } else if (makeTermLabelSV) { - v = SchemaVariableFactory.createTermLabelSV(new Name(name)); - } else { v = SchemaVariableFactory.createTermSV( - new Name(name), - s, - mods.rigid(), - mods.strict()); - } - } - - if (inSchemaMode()) { - if (variables().lookup(v.name()) != null || - schemaVariables().lookup(v.name()) != null) { - throw new AmbigiousDeclException(v.name().toString(), - getSourceName(), - getLine(), - getColumn()); - } - schemaVariables().add(v); - } - } - } - - private Term toZNotation(String number, Namespace functions) { - String s = number; - final boolean negative = (s.charAt(0) == '-'); - if (negative) { - s = number.substring(1, s.length()); - } - if(s.startsWith("0x")) { - try { - BigInteger bi = new BigInteger(s.substring(2),16); - s = bi.toString(); - } catch(NumberFormatException nfe) { - Debug.fail("Not a hexadecimal constant (BTW, this should not have happened)."); - } - } - Term result = getTermFactory().createTerm((Function)functions.lookup(new Name("#"))); - - for(int i = 0; i vars) { - StringBuffer result = new StringBuffer(""); - final Iterator it = vars.iterator(); - while (it.hasNext()) { - result.append(it.next().getContainerType().getFullName()); - if (it.hasNext()) result.append(", "); - } - return result.toString(); - } - - private Operator getAttributeInPrefixSort(Sort prefixSort, String attributeName) - throws RecognitionException/*SemanticException*/ { - final JavaInfo javaInfo = getJavaInfo(); - - Operator result = null; - - if (inSchemaMode()) { - // if we are currently reading taclets we look for schema variables first - result = schemaVariables().lookup(new Name(attributeName)); - } - - assert inSchemaMode() || result == null; - if (result == null) { - - final boolean unambigousAttributeName = attributeName.indexOf(':') != -1; - - if (unambigousAttributeName) { - result = javaInfo.getAttribute(attributeName); - } else if(inSchemaMode() && attributeName.equals("length")) { - try { - result = javaInfo.getArrayLength(); - } catch(Exception ex) { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - } else if(attributeName.equals("")) { - // The invariant observer "" is implicit and - // not part of the class declaration - // A special case is needed, hence. - result = javaInfo.getInvProgramVar(); - } else { - if (inSchemaMode()) { - semanticError("Either undeclared schema variable '" + - attributeName + "' or a not fully qualified attribute in taclet."); - } - final KeYJavaType prefixKJT = javaInfo.getKeYJavaType(prefixSort); - if (prefixKJT == null) { - semanticError("Could not find type '"+prefixSort+"'. Maybe mispelled or "+ - "you use an array or object type in a .key-file with missing " + - "\\javaSource section."); - } - // WATCHOUT why not in DECLARATION MODE - if(!isDeclParser()) { - ProgramVariable var = javaInfo.getCanonicalFieldProgramVariable(attributeName, prefixKJT); - if (var == null) { - LogicVariable logicalvar = (LogicVariable)namespaces().variables().lookup(attributeName); - if(logicalvar == null) { - semanticError("There is no attribute '" + attributeName + - "' declared in type '" + prefixSort + "' and no logical variable of that name."); - } else { - result = logicalvar; - } - } else { - result = var; - } - } - } - } - - if ( result == null && !("length".equals(attributeName)) ) { - throw new NotDeclException (input, "Attribute ", attributeName); - } - return result; - } - - - public Term createAttributeTerm(Term prefix, - Operator attribute) throws RecognitionException/*SemanticException*/ { - Term result = prefix; - - if (attribute instanceof SchemaVariable) { - if (!inSchemaMode()) { - semanticError("Schemavariables may only occur inside taclets."); - } - SchemaVariable sv = (SchemaVariable) attribute; - if(sv.sort() instanceof ProgramSVSort - || sv.sort() == AbstractTermTransformer.METASORT) { - semanticError("Cannot use schema variable " + sv + " as an attribute"); - } - result = getServices().getTermBuilder().select(sv.sort(), - getServices().getTermBuilder().getBaseHeap(), - prefix, - getTermFactory().createTerm(attribute)); - } else { - if(attribute instanceof LogicVariable) { - Term attrTerm = getTermFactory().createTerm(attribute); - result = getServices().getTermBuilder().dot(Sort.ANY, result, attrTerm); - } else if(attribute instanceof ProgramConstant) { - result = getTermFactory().createTerm(attribute); - } else if(attribute == getServices().getJavaInfo().getArrayLength()) { - result = getServices().getTermBuilder().dotLength(result); - } else { - ProgramVariable pv = (ProgramVariable) attribute; - Function fieldSymbol - = getServices().getTypeConverter() - .getHeapLDT() - .getFieldSymbolForPV((LocationVariable)pv, - getServices()); - if (pv.isStatic()){ - result = getServices().getTermBuilder().staticDot(pv.sort(), fieldSymbol); - } else { - result = getServices().getTermBuilder().dot(pv.sort(), result, fieldSymbol); - } - } - } - return result; - } - - private LogicVariable bindVar(String id, Sort s) { - if(isGlobalDeclTermParser()) - Debug.fail("bindVar was called in Global Declaration Term parser."); - LogicVariable v=new LogicVariable(new Name(id), s); - namespaces().setVariables(variables().extended(v)); - return v; - } - - private void bindVar(LogicVariable v) { - if(isGlobalDeclTermParser()) - Debug.fail("bindVar was called in Global Declaration Term parser."); - namespaces().setVariables(variables().extended(v)); - } - - private void bindVar() { - if(isGlobalDeclTermParser()) - Debug.fail("bindVar was called in Global Declaration Term parser."); - namespaces().setVariables ( new Namespace ( variables () ) ); - } - - private KeYJavaType getTypeByClassName(String s) - throws RecognitionException/*KeYSemanticException*/ { - KeYJavaType kjt = null; - try { - kjt=getJavaInfo().getTypeByClassName(s, null); - } catch(RuntimeException e){ - return null; - } - - return kjt; - } - - private boolean isPackage(String name){ - try { - return getJavaInfo().isPackage(name); - } catch(RuntimeException e){ - // may be thrown in cases of invalid java identifiers - return false; - } - } - - protected boolean isHeapTerm(Term term) { - return term != null && term.sort() == - getServices().getTypeConverter().getHeapLDT().targetSort(); - } - - private boolean isSequenceTerm(Term reference) { - return reference != null && reference.sort().name().equals(SeqLDT.NAME); - } - - private boolean isIntTerm(Term reference) { - return reference.sort().name().equals(IntegerLDT.NAME); - } - - private void unbindVars(Namespace orig) { - if(isGlobalDeclTermParser()) { - Debug.fail("unbindVars was called in Global Declaration Term parser."); - } - namespaces().setVariables(orig); - } - - - private Set progVars(JavaBlock jb) { - if(isGlobalDeclTermParser()) { - ProgramVariableCollector pvc - = new ProgramVariableCollector(jb.program(), getServices()); - pvc.start(); - return pvc.result(); - }else - if(!isDeclParser()) { - if ((isTermParser() || isProblemParser()) && jb.isEmpty()) { - return new LinkedHashSet(); - } - DeclarationProgramVariableCollector pvc - = new DeclarationProgramVariableCollector(jb.program(), getServices()); - pvc.start(); - return pvc.result(); - } - Debug.fail("KeYParser.progVars(): this statement should not be reachable."); - return null; - } - - private Term termForParsedVariable(ParsableVariable v) - throws RecognitionException/*SemanticException*/ { - if ( v instanceof LogicVariable || v instanceof ProgramVariable) { - return getTermFactory().createTerm(v); - } else { - if(isGlobalDeclTermParser()) - semanticError(v + " is not a logic variable"); - if(isTermParser()) - semanticError(v + " is an unknown kind of variable."); - if (inSchemaMode() && v instanceof SchemaVariable ) { - return getTermFactory().createTerm(v); - } else { - String errorMessage = ""; - if ( inSchemaMode() ) { - errorMessage += v +" is not a program, logic or schema variable"; - } else { - errorMessage += v +" is not a logic or program variable"; - } - semanticError(errorMessage); - } - } - return null; - } - - private PairOfStringAndJavaBlock getJavaBlock(Token t) throws RecognitionException/*SemanticException*/ { - PairOfStringAndJavaBlock sjb = new PairOfStringAndJavaBlock(); - String s=t.getText(); - int index = s.indexOf("\n"); - sjb.opName = s.substring(0,index); - s = s.substring(index+1); - Debug.out("Modal operator name passed to getJavaBlock: ",sjb.opName); - Debug.out("Java block passed to getJavaBlock: ", s); - - JavaReader jr = javaReader; - - try { - if (inSchemaMode()) { - if(isProblemParser()) // Alt jr==null; - jr = new SchemaRecoder2KeY(parserConfig.services(), - parserConfig.namespaces()); - ((SchemaJavaReader)jr).setSVNamespace(schemaVariables()); - } else{ - if(isProblemParser()) // Alt jr==null; - jr = new Recoder2KeY(parserConfig.services(), - parserConfig.namespaces()); - } - - if (inSchemaMode() || isGlobalDeclTermParser()) { - sjb.javaBlock = jr.readBlockWithEmptyContext(s); - }else{ - sjb.javaBlock = jr.readBlockWithProgramVariables(programVariables(), s); - } - } catch (de.uka.ilkd.key.java.PosConvertException e) { - lineOffset=e.getLine()-1; - colOffset=e.getColumn()+1; - throw new RecognitionException(input); - //throw new JavaParserException(e.getMessage(), t.getText(), - // getSourceName(), t.getLine(), t.getCharPositionInLine(), lineOffset, colOffset); - } catch (de.uka.ilkd.key.java.ConvertException e) { - if (e.parseException()!=null - && e.parseException().currentToken != null - && e.parseException().currentToken.next != null) { - lineOffset=e.parseException().currentToken.next.beginLine; - colOffset=e.parseException().currentToken.next.beginColumn; - e.parseException().currentToken.next.beginLine=getLine()-1; - e.parseException().currentToken.next.beginColumn=getColumn(); - throw new RecognitionException(input); - //throw new JavaParserException(e.getMessage(), t.getText(), getSourceName(), t.getLine(), t.getCharPositionInLine(), -1, -1); // row/columns already in text - } - if (e.proofJavaException()!=null - && e.proofJavaException().currentToken != null - && e.proofJavaException().currentToken.next != null) { - lineOffset = e.proofJavaException().currentToken.next.beginLine-1; - colOffset=e.proofJavaException().currentToken.next.beginColumn; - e.proofJavaException().currentToken.next.beginLine=getLine(); - e.proofJavaException().currentToken.next.beginColumn =getColumn(); - throw new RecognitionException(input); - //throw new JavaParserException(e.getMessage(), t.getText(), getSourceName(), t.getLine(), t.getCharPositionInLine(), lineOffset, colOffset); - - } - throw new RecognitionException(input); - //throw new JavaParserException(e.getMessage(), t.getText(), getSourceName(), t.getLine(), t.getCharPositionInLine()); - } - return sjb; - } - - /** - * looks up and returns the sort of the given name or null if none has been found. - * If the sort is not found for the first time, the name is expanded with "java.lang." - * and the look up restarts - */ - private Sort lookupSort(String name) throws RecognitionException/*SemanticException*/ { - Sort result = (Sort) sorts().lookup(new Name(name)); - if (result == null) { - if(name.equals(NullSort.NAME.toString())) { - Sort objectSort - = (Sort) sorts().lookup(new Name("java.lang.Object")); - if(objectSort == null) { - semanticError("Null sort cannot be used before " - + "java.lang.Object is declared"); - } - result = new NullSort(objectSort); - sorts().add(result); - } else { - result = (Sort) sorts().lookup(new Name("java.lang."+name)); - } - } - return result; - } - - - /** looks up a function, (program) variable or static query of the - * given name varfunc_id and the argument terms args in the namespaces - * and java info. - * @param varfunc_name the String with the symbols name - * @param args is null iff no argument list is given, for instance `f', - * and is an array of size zero, if an empty argument list was given, - * for instance `f()'. - */ - private Operator lookupVarfuncId(String varfunc_name, Term[] args) - throws RecognitionException/*NotDeclException, SemanticException*/ { - - // case 1a: variable - // case 1b: schema variable - Name name = new Name(varfunc_name); - Operator v = variables().lookup(name); - if(v == null) { - v = schemaVariables().lookup(name); - } - - if (v != null && (args == null || (inSchemaMode() && v instanceof ModalOperatorSV))) { - return v; - } - - // case 2: program variable - v = (Operator) programVariables().lookup - (new ProgramElementName(varfunc_name)); - if (v != null && args==null) { - return v; - } - - // case 3: function - v = (Operator) functions().lookup(new Name(varfunc_name)); - if (v != null) { // we allow both args==null (e.g. `c') - // and args.length=0 (e.g. 'c())' here - return v; - } - - - // case 4: instantiation of sort depending function - int separatorIndex = varfunc_name.indexOf("::"); - if (separatorIndex > 0) { - String sortName = varfunc_name.substring(0, separatorIndex); - String baseName = varfunc_name.substring(separatorIndex + 2); - Sort sort = lookupSort(sortName); - SortDependingFunction firstInstance - = SortDependingFunction.getFirstInstance(new Name(baseName), - getServices()); - - if(sort != null && firstInstance != null) { - v = firstInstance.getInstanceFor(sort, getServices()); - if(v != null) { - return v; - } - } - } - - // not found - if (args==null) { - throw new NotDeclException - (input, "(program) variable or constant", varfunc_name); - } else { - throw new NotDeclException - (input, "function or static query", varfunc_name); - } - } - - private boolean isStaticAttribute() throws RecognitionException/*KeYSemanticException*/ { - if(inSchemaMode()) return false; - final JavaInfo javaInfo = getJavaInfo(); - KeYJavaType kjt = null; - boolean result = false; -// try { - int n = 1; - StringBuffer className = new StringBuffer(input.LT(n).getText()); - while (isPackage(className.toString()) || input.LA(n+2)==NUM_LITERAL || - (input.LT(n+2)!=null && input.LT(n+2).getText()!=null && - input.LT(n+2).getText().length() > 0 && input.LT(n+2).getText().charAt(0)<='Z' && input.LT(n+2).getText().charAt(0)>='A' && - (input.LT(n+2).getText().length()==1 || - input.LT(n+2).getText().charAt(1)<='z' && input.LT(n+2).getText().charAt(1)>='a'))){ - if (input.LA(n+1) != DOT && input.LA(n+1) != EMPTYBRACKETS) return false; - // maybe still an attribute starting with an uppercase letter followed by a lowercase letter - if(getTypeByClassName(className.toString()) != null){ - ProgramVariable maybeAttr = - javaInfo.getAttribute(input.LT(n+2).getText(), getTypeByClassName(className.toString())); - if(maybeAttr!=null){ - return true; - } - } - className.append("."); - className.append(input.LT(n+2).getText()); - n+=2; - } - while (input.LA(n+1) == EMPTYBRACKETS) { - className.append("[]"); - n++; - } - kjt = getTypeByClassName(className.toString()); - - if (kjt != null) { - // works as we do not have inner classes - if (input.LA(n+1) == DOT) { - final ProgramVariable pv = - javaInfo.getAttribute(input.LT(n+2).getText(), kjt); - result = (pv != null && pv.isStatic()); - } - }else{ - result = false; - } -// } catch (antlr.TokenStreamException tse) { -// // System.out.println("an exception occured"+tse); -// result = false; -// } - if(result && state.backtracking > 0) { - savedGuessing = state.backtracking; - state.backtracking = 0; - } - return result; - } - - private boolean isTermTransformer() /*throws TokenStreamException*/ { - if((input.LA(1) == IDENT && - AbstractTermTransformer.name2metaop(input.LT(1).getText())!=null) - || input.LA(1) == IN_TYPE) - return true; - return false; - } - - private boolean isStaticQuery() throws RecognitionException/*KeYSemanticException*/ { - if(inSchemaMode()) return false; - final JavaInfo javaInfo = getJavaInfo(); - boolean result = false; -// try { - int n = 1; - KeYJavaType kjt = null; - StringBuffer className = new StringBuffer(input.LT(n).getText()); - while (isPackage(className.toString())) { - if (input.LA(n+1) != DOT) return false; - className.append("."); - className.append(input.LT(n+2).getText()); - n+=2; - } - kjt = getTypeByClassName(className.toString()); - if (kjt != null) { - if (input.LA(n+1) == DOT && input.LA(n+3) == LPAREN) { - Iterator it = javaInfo.getAllProgramMethods(kjt).iterator(); - while(it.hasNext()) { - final IProgramMethod pm = it.next(); - final String name = kjt.getFullName()+"::"+input.LT(n+2).getText(); - if(pm != null && pm.isStatic() && pm.name().toString().equals(name) ) { - result = true; - break; - } - } - } - } -// } catch (antlr.TokenStreamException tse) { -// result = false; -// } - if(result && state.backtracking > 0) { - savedGuessing = state.backtracking; - state.backtracking = 0; - } - return result; - } - - - private TacletBuilder createTacletBuilderFor - (Object find, int applicationRestriction) - throws RecognitionException/*InvalidFindException*/ { - if ( applicationRestriction != RewriteTaclet.NONE && - applicationRestriction != RewriteTaclet.IN_SEQUENT_STATE && - !( find instanceof Term ) ) { - String mod = ""; - if ((applicationRestriction & RewriteTaclet.SAME_UPDATE_LEVEL) != 0) { - mod = "\"\\sameUpdateLevel\""; - } - if ((applicationRestriction & RewriteTaclet.ANTECEDENT_POLARITY) != 0) { - if (mod != "") mod += " and "; - mod += "\"\\antecedentPolarity\""; - } - if ((applicationRestriction & RewriteTaclet.SUCCEDENT_POLARITY) != 0) { - if (mod != "") mod += " and "; - mod += "\"\\succedentPolarity\""; - } - if (mod == "") { - mod = "Application restrictions"; - } - - throw new InvalidFindException - ( mod + " may only be used for rewrite taclets:" + find, - getSourceName(), getLine(), getColumn()); - } - if ( find == null ) { - return new NoFindTacletBuilder(); - } else if ( find instanceof Term ) { - return new RewriteTacletBuilder().setFind((Term)find) - .setApplicationRestriction(applicationRestriction); - } else if ( find instanceof Sequent ) { - Sequent findSeq = (Sequent) find; - if ( findSeq.isEmpty() ) { - return new NoFindTacletBuilder(); - } else if ( findSeq.antecedent().size() == 1 - && findSeq.succedent().size() == 0 ) { - Term findFma = findSeq.antecedent().get(0).formula(); - AntecTacletBuilder b = new AntecTacletBuilder(); - b.setFind(findFma); - b.setIgnoreTopLevelUpdates((applicationRestriction & RewriteTaclet.IN_SEQUENT_STATE) == 0); - return b; - } else if ( findSeq.antecedent().size() == 0 - && findSeq.succedent().size() == 1 ) { - Term findFma = findSeq.succedent().get(0).formula(); - SuccTacletBuilder b = new SuccTacletBuilder(); - b.setFind(findFma); - b.setIgnoreTopLevelUpdates((applicationRestriction & RewriteTaclet.IN_SEQUENT_STATE) == 0); - return b; - } else { - throw new InvalidFindException - ("Unknown find-sequent (perhaps null?):"+findSeq, - getSourceName(), getLine(), getColumn()); - } - } else { - throw new InvalidFindException - ("Unknown find class type: " + find.getClass().getName(), - getSourceName(), getLine(), getColumn()); - } - } - - private void addGoalTemplate(TacletBuilder b, - String id, - Object rwObj, - Sequent addSeq, - ImmutableList addRList, - ImmutableSet pvs, - ImmutableSet soc) - throws RecognitionException/*SemanticException*/ - { - TacletGoalTemplate gt = null; - if ( rwObj == null ) { - // there is no replacewith, so we take - gt = new TacletGoalTemplate(addSeq, - addRList, - pvs); - } else { - if ( b instanceof NoFindTacletBuilder ) { - // there is a replacewith without a find. - throw new RecognitionException(input); - //new UnfittingReplacewithException - //("Replacewith without find", getSourceName(), - // getLine(), getColumn()); - } else if ( b instanceof SuccTacletBuilder - || b instanceof AntecTacletBuilder ) { - if ( rwObj instanceof Sequent ) { - gt = new AntecSuccTacletGoalTemplate(addSeq, - addRList, - (Sequent)rwObj, - pvs); - } else { - throw new UnfittingReplacewithException - ("Replacewith in a Antec-or SuccTaclet has "+ - "to contain a sequent (not a term)", - getSourceName(), getLine(), getColumn()); - } - } else if ( b instanceof RewriteTacletBuilder ) { - if ( rwObj instanceof Term ) { - gt = new RewriteTacletGoalTemplate(addSeq, - addRList, - (Term)rwObj, - pvs); - } else { - throw new UnfittingReplacewithException - ("Replacewith in a RewriteTaclet has "+ - "to contain a term (not a sequent)", - getSourceName(), getLine(), getColumn()); - } - } - } - gt.setName(id); - b.addTacletGoalTemplate(gt); - if(soc != null) b.addGoal2ChoicesMapping(gt,soc); - } - - public void testLiteral(String l1, String l2) - throws RecognitionException/*KeYSemanticException*/ - { - if (!l1.equals(l2)){ - semanticError("Expecting '"+l1+"', found '"+l2+"'."); - }; - } - - /** parses a problem but without reading the declarations of - * sorts, functions and predicates. These have to be given - * explicitly. - * the rule sets of the current problem file will be added - */ - public Term parseTacletsAndProblem() - throws RecognitionException/*, antlr.TokenStreamException*/{ - resetSkips(); - skipSorts(); skipFuncs(); skipPreds(); - return problem(); - } - - /** - * returns the ProgramMethod parsed in the jml_specifications section. - */ - public IProgramMethod getProgramMethod(){ - return pm; - } - - public void addFunction(Function f) { - functions().add(f); - } - - private ImmutableSet lookupOperatorSV(String opName, ImmutableSet modalities) - throws RecognitionException/*KeYSemanticException*/ { - SchemaVariable sv = schemaVariables().lookup(new Name(opName)); - if(sv == null || !(sv instanceof ModalOperatorSV)) { - semanticError("Schema variable "+opName+" not defined."); - } - ModalOperatorSV osv = (ModalOperatorSV)sv; - modalities = modalities.union(osv.getModalities()); - return modalities; - } - - private ImmutableSet opSVHelper(String opName, - ImmutableSet modalities) - throws RecognitionException/*KeYSemanticException*/ { - if(opName.charAt(0) == '#') { - return lookupOperatorSV(opName, modalities); - } else { - switchToNormalMode(); - Modality m = Modality.getModality(opName); - switchToSchemaMode(); - if(m == null) { - semanticError("Unrecognised operator: "+opName); - } - modalities = modalities.add(m); - } - return modalities; - } - - protected void semanticError(String message) throws RecognitionException { - throw new KeYSemanticException(input, getSourceName(), message); - } - - private static class PairOfStringAndJavaBlock { - String opName; - JavaBlock javaBlock; - } - - private static boolean isSelectTerm(Term term) { - return term.op().name().toString().endsWith("::select") && term.arity() == 3; - } - - private boolean isImplicitHeap(Term t) { - return getServices().getTermBuilder().getBaseHeap().equals(t); - } - - // This is used for testing in TestTermParserHeap.java - public static final String NO_HEAP_EXPRESSION_BEFORE_AT_EXCEPTION_MESSAGE - = "Expecting select term before '@', not: "; - - private Term replaceHeap(Term term, Term heap, int depth) throws RecognitionException { - if (depth > 0) { - - if (isSelectTerm(term)) { - - if (!isImplicitHeap(term.sub(0))) { - semanticError("Expecting program variable heap as first argument of: " + term); - } - - Term[] params = new Term[]{heap, replaceHeap(term.sub(1), heap, depth - 1), term.sub(2)}; - return (getServices().getTermFactory().createTerm(term.op(), params)); - - } else if (term.op() instanceof ObserverFunction) { - if (!isImplicitHeap(term.sub(0))) { - semanticError("Expecting program variable heap as first argument of: " + term); - } - - Term[] params = new Term[term.arity()]; - params[0] = heap; - params[1] = replaceHeap(term.sub(1), heap, depth - 1); - for (int i = 2; i < params.length; i++) { - params[i] = term.sub(i); - } - - return (getServices().getTermFactory().createTerm(term.op(), params)); - - } else { - semanticError(NO_HEAP_EXPRESSION_BEFORE_AT_EXCEPTION_MESSAGE + term); - throw new RecognitionException(); - } - - } else { - return term; - } - } - - /* - * Replace standard heap by another heap in an observer function. - */ - protected Term heapSelectionSuffix(Term term, Term heap) throws RecognitionException { - - if (!isHeapTerm(heap)) { - semanticError("Expecting term of type Heap but sort is " + heap.sort() - + " for term: " + term); - } - - Term result = replaceHeap(term, heap, globalSelectNestingDepth); - - // reset globalSelectNestingDepth - globalSelectNestingDepth = 0; - - return result; - } - - private String unescapeString(String string) { - char[] chars = string.toCharArray(); - StringBuilder sb = new StringBuilder(); - for(int i = 0; i < chars.length; i++) { - if(chars[i] == '\\' && i < chars.length - 1) { - switch(chars[++i]) { - case 'n': sb.append("\n"); break; - case 'f': sb.append("\f"); break; - case 'r': sb.append("\r"); break; - case 't': sb.append("\t"); break; - case 'b': sb.append("\b"); break; - case ':': sb.append("\\:"); break; // this is so in KeY ... - default: sb.append(chars[i]); break; // this more relaxed than before, \a becomes a ... - } - } else { - sb.append(chars[i]); - } - } - return sb.toString(); - } - - /* ---- antlr stuff ---- (Exception handling) */ - - @Override - public void reportError(RecognitionException ex) { - // dont do anything - } - - public void recover(IntStream input, RecognitionException re) { - throw new RuntimeException(re); - } - - /** Not currently used */ - @Override - public Object recoverFromMismatchedSet(IntStream input, - RecognitionException e, BitSet follow) throws RecognitionException { - // comment says it is never used, still make sure ... - throw e; - } - - protected Object recoverFromMismatchedToken(IntStream input, int ttype, - BitSet follow) throws RecognitionException { - throw new MismatchedTokenException(ttype, input); - } - -} - -@rulecatch { - catch(RecognitionException e) { - throw e; - } -} - - -// WATCHOUT Don't remove this. Ever!!! -// Although it's not called, it is necessary for antlr to produce the -// right parser. -top : a=formula { - Debug.fail("KeYParser: top() should not be called. Ever."); -} -; - -decls : - (one_include_statement)* { - if(parse_includes) return; - activatedChoices = DefaultImmutableSet.nil(); - } - (options_choice)? - ( - {!onlyWith}?=> option_decls - | - {!onlyWith}?=> sort_decls - | - {!onlyWith}?=> prog_var_decls - | - {!onlyWith}?=> schema_var_decls - | - pred_decls - | - func_decls - | - transform_decls - | - {!onlyWith}?=> ruleset_decls - ) * - ; - -one_include_statement -@init{ - boolean ldts = false; -} -: - (INCLUDE | (INCLUDELDTS {ldts = true; })) - one_include[ldts] (COMMA one_include[ldts])* SEMI -; - -one_include [boolean ldt] -: - (absfile=IDENT{ - if(parse_includes){ - addInclude(absfile.getText(),false,ldt); - } - } - | relfile = string_literal { - if(parse_includes){ - addInclude(relfile, true,ldt); - } - }) - ; - -options_choice -: - (WITHOPTIONS activated_choice (COMMA activated_choice)* SEMI) -; - -activated_choice @init{ - String name; - Choice c; -}: - cat=IDENT COLON choice_=IDENT - {if(usedChoiceCategories.contains(cat.getText())){ - throw new IllegalArgumentException("You have already chosen a different option for "+cat.getText()); - } - usedChoiceCategories.add(cat.getText()); - name = cat.getText()+":"+choice_.getText(); - c = (Choice) choices().lookup(new Name(name)); - if(c==null){ - throw new NotDeclException(input, "Option", choice_.getText()); - }else{ - activatedChoices=activatedChoices.add(c); - } - } - ; - -option_decls -: - OPTIONSDECL LBRACE (choice SEMI)* RBRACE - ; - -choice @init{ - String cat=null; -}: - category=IDENT {cat=category.getText();} (COLON LBRACE choice_option[cat] (COMMA choice_option[cat])* RBRACE)? - { - if(!category2Default.containsKey(cat)){ - choices().add(new Choice("On",cat)); - choices().add(new Choice("Off",cat)); - category2Default.put(cat, cat+":On"); - } - } - ; - -choice_option[String cat]@init{ - String name; -}: - choice_=IDENT { name=cat+":"+choice_.getText(); - Choice c = (Choice) choices().lookup(new Name(name)); - if(c==null){ - c = new Choice(choice_.getText(),cat); - choices().add(c); - } - if(!category2Default.containsKey(cat)){ - category2Default.put(cat, name); - } - } - ; - -/* TODO: Why is the result of one_sort_decl stored in the local variables? - * It does not seem to be employed at all ?! (MU) - */ -sort_decls -@init{ - ImmutableList lsorts = ImmutableSLList.nil(); - multipleSorts = ImmutableSLList.nil(); -} -: SORTS LBRACE - ( multipleSorts = one_sort_decl { lsorts = lsorts.prepend(multipleSorts); })* - RBRACE -; - -one_sort_decl returns [ImmutableList createdSorts = ImmutableSLList.nil()] -@init{ - boolean isAbstractSort = false; - boolean isGenericSort = false; - boolean isProxySort = false; - sortExt=new Sort [0]; - sortOneOf=new Sort [0]; - sortIds = ImmutableSLList.nil(); - // every sort can have multiple parameters. Every parameter is a generic sort + its variance - ImmutableList>> sortParameters = ImmutableSLList.nil(); -} : - ( - GENERIC {isGenericSort=true;} sortIds = simple_ident_comma_list - ( ONEOF sortOneOf = oneof_sorts )? - ( EXTENDS sortExt = extends_sorts )? - | PROXY {isProxySort=true;} sortIds = simple_ident_comma_list - ( EXTENDS sortExt = extends_sorts )? - | (ABSTRACT {isAbstractSort = true;})? - firstSort = simple_ident_dots { sortIds = sortIds.prepend(firstSort); } - parameters=formal_sort_parameters { sortParameters = sortParameters.prepend(parameters); } - ( - (EXTENDS sortExt = extends_sorts ) - // TODO parametrised sorts cannot be comma-listed - | ((COMMA) - id = simple_ident { sortIds = sortIds.prepend(id); } - parameters=formal_sort_parameters { sortParameters = sortParameters.prepend(parameters); } )* - ) - ) SEMI { - if (!skip_sorts) { - Iterator it = sortIds.iterator (); - while ( it.hasNext () ) { - Name sort_name = new Name(it.next()); - // attention: no expand to java.lang here! - if (sorts().lookup(sort_name) == null) { - Sort s; - if (isGenericSort) { - int i; - ImmutableSet ext = DefaultImmutableSet.nil(); - ImmutableSet oneOf = DefaultImmutableSet.nil(); - - for ( i = 0; i != sortExt.length; ++i ) - ext = ext.add ( sortExt[i] ); - - for ( i = 0; i != sortOneOf.length; ++i ) - oneOf = oneOf.add ( sortOneOf[i] ); - - try { - s = new GenericSort(sort_name, ext, oneOf); - } catch (GenericSupersortException e) { - throw new GenericSortException ( "sort", "Illegal sort given", - e.getIllegalSort(), getSourceName(), getLine(), getColumn()); - } - } else if (new Name("any").equals(sort_name)) { - s = Sort.ANY; - } else { - ImmutableSet ext = DefaultImmutableSet.nil(); - - for ( int i = 0; i != sortExt.length; ++i ) { - ext = ext.add ( sortExt[i] ); - } - - ImmutableList> sortParams = sortParameters.head(); - if(isProxySort) { - s = new ProxySort(sort_name, ext); - } else if(sortParams != null) { - s = new ParametricSort(sort_name, ext, isAbstractSort, sortParams); - } else { - s = new SortImpl(sort_name, ext, isAbstractSort); - } - } - assert s != null; - sorts().add ( s ); - - createdSorts = createdSorts.append(s); - } - } - } - }; - - -simple_ident_dots returns [ String ident = ""; ] -: - id = simple_ident { ident += id; } - (DOT - (id = simple_ident | num=NUM_LITERAL {id=num.getText();}) - {ident += "." + id;})* - ; - -extends_sorts returns [Sort[\] extendsSorts = null] -@init{ - List args = new LinkedList(); -} - : - s = any_sortId_check[!skip_sorts] { args.add(s); } - ( - COMMA s = any_sortId_check[!skip_sorts] {args.add(s);} - ) * - { - extendsSorts = (Sort[])args.toArray(AN_ARRAY_OF_SORTS); - } - ; - -formal_sort_parameters returns [ImmutableList> result = null] -@init { - Variance variance = null; -} - : - ( OPENTYPEPARAMS - ( PLUS { variance=Variance.COVARIANT; } - | MINUS { variance = Variance.CONTRAVARIANT; } - | { variance = Variance.INVARIANT; } - ) - id=simple_ident - {if (!skip_sorts) { - Sort genSort = sorts().lookup(id); - if(genSort == null || !(genSort instanceof GenericSort)) { - semanticError("Formal type parameters must be (already declared) generic sorts"); - } - result = Immutables.listOf(new Pair(genSort, variance)); - }} - ( COMMA - ( PLUS { variance=Variance.COVARIANT; } - | MINUS { variance = Variance.CONTRAVARIANT; } - | { variance = Variance.INVARIANT; } - ) - id=simple_ident - {if (!skip_sorts) { - Sort genSort = sorts().lookup(id); - if(genSort == null || !(genSort instanceof GenericSort)) { - semanticError("Formal type parameters must be (already declared) generic sorts"); - } - result = result.prepend(new Pair(genSort, variance)); - }} - )* - CLOSETYPEPARAMS { if (!skip_sorts) result = result.reverse(); } - )? - ; - -oneof_sorts returns [Sort[\] oneOfSorts = null] -@init{ - List args = new LinkedList(); -} - : LBRACE - s = sortId_check[true] { args.add(s); } - ( - COMMA s = sortId_check[true] {args.add(s);} - ) * - RBRACE { - oneOfSorts = (Sort[])args.toArray(AN_ARRAY_OF_SORTS); - } - ; - -keyjavatype returns [KeYJavaType kjt=null] -@init{ - boolean array = false; -} -: - type = simple_ident_dots (EMPTYBRACKETS {type += "[]"; array=true;})* - { - kjt = getJavaInfo().getKeYJavaType(type); - - //expand to "java.lang" - if (kjt == null) { - try { - String guess = "java.lang." + type; - kjt = getJavaInfo().getKeYJavaType(guess); - } catch(Exception e) { - kjt = null; - } - } - - //arrays - if(kjt == null && array) { - try { - JavaBlock jb = getJavaInfo().readJavaBlock("{" + type + " k;}"); - kjt = ((VariableDeclaration) - ((StatementBlock) jb.program()).getChildAt(0)). - getTypeReference().getKeYJavaType(); - } catch (Exception e) { - kjt = null; - } - } - - //try as sort without Java type (neede e.g. for "Heap") - if(kjt == null) { - Sort sort = lookupSort(type); - if(sort != null) { - kjt = new KeYJavaType(null, sort); - } - } - - if(kjt == null) { - semanticError("Unknown type: " + type); - } - } -; - -prog_var_decls -@init{ - String var_name; -} - : - { switchToNormalMode();} - PROGRAMVARIABLES - LBRACE - ( - kjt = keyjavatype - var_names = simple_ident_comma_list - { - Iterator it = var_names.iterator(); - while(it.hasNext()){ - var_name = it.next(); - ProgramElementName pvName = new ProgramElementName(var_name); - Named name = lookup(pvName); - if (name != null ) { - // commented out as pv do not have unique name (at the moment) - // throw new AmbigiousDeclException - // (var_name, getSourceName(), getLine(), getColumn()); - if(!(name instanceof ProgramVariable) || (name instanceof ProgramVariable && - !((ProgramVariable)name).getKeYJavaType().equals(kjt))) { - namespaces().programVariables().add(new LocationVariable - (pvName, kjt)); - } - }else{ - namespaces().programVariables().add(new LocationVariable - (pvName, kjt)); - } - } - } - SEMI - ) * - RBRACE - ; - -string_literal returns [String lit = null] - : - id=STRING_LITERAL { - lit = unescapeString(id.getText()); - lit = lit.substring(1,lit.length()-1); - stringLiteralLine = id.getLine(); - } - ; - -simple_ident returns [String ident = null] - : - id=IDENT { ident = id.getText(); } - ; - -simple_ident_comma_list returns [ImmutableList ids = ImmutableSLList.nil()] - : - id = simple_ident { ids = ids.append(id); } - (COMMA id = simple_ident { ids = ids.append(id); })* - ; - - -schema_var_decls : - SCHEMAVARIABLES LBRACE { switchToSchemaMode(); } - ( one_schema_var_decl )* - RBRACE { switchToNormalMode(); } - ; - -one_schema_var_decl -@init{ - boolean makeVariableSV = false; - boolean makeSkolemTermSV = false; - boolean makeTermLabelSV = false; - SchemaVariableModifierSet mods = null; -} : - (MODALOPERATOR one_schema_modal_op_decl SEMI) - | - ( - ( - PROGRAM - { mods = new SchemaVariableModifierSet.ProgramSV (); } - ( schema_modifiers[mods] ) ? - id = simple_ident ( LBRACKET nameString = simple_ident EQUALS parameter = simple_ident_dots RBRACKET )? { - if(nameString != null && !"name".equals(nameString)) { - semanticError("Unrecognized token '"+nameString+"', expected 'name'"); - } - ProgramSVSort psv = ProgramSVSort.name2sort().get(new Name(id)); - s = (Sort) (parameter != null ? psv.createInstance(parameter) : psv); - if (s == null) { - semanticError - ("Program SchemaVariable of type "+id+" not found."); - } - } - ids = simple_ident_comma_list - | FORMULA - { mods = new SchemaVariableModifierSet.FormulaSV (); } - ( schema_modifiers[mods] ) ? - {s = Sort.FORMULA;} - ids = simple_ident_comma_list - | TERMLABEL - { makeTermLabelSV = true; } - { mods = new SchemaVariableModifierSet.TermLabelSV (); } - ( schema_modifiers[mods] ) ? - ids = simple_ident_comma_list - | UPDATE - { mods = new SchemaVariableModifierSet.FormulaSV (); } - ( schema_modifiers[mods] ) ? - {s = Sort.UPDATE;} - ids = simple_ident_comma_list - | SKOLEMFORMULA - { makeSkolemTermSV = true; } - { mods = new SchemaVariableModifierSet.FormulaSV (); } - ( schema_modifiers[mods] ) ? - {s = Sort.FORMULA;} - ids = simple_ident_comma_list - | ( TERM - { mods = new SchemaVariableModifierSet.TermSV (); } - ( schema_modifiers[mods] ) ? - | ( (VARIABLES | VARIABLE) - { makeVariableSV = true; } - { mods = new SchemaVariableModifierSet.VariableSV (); } - ( schema_modifiers[mods] ) ?) - | (SKOLEMTERM - { makeSkolemTermSV = true; } - { mods = new SchemaVariableModifierSet.SkolemTermSV (); } - ( schema_modifiers[mods] ) ?) - ) - s = any_sortId_check[true] - ids = simple_ident_comma_list - ) SEMI - { - Iterator it = ids.iterator(); - while(it.hasNext()) - schema_var_decl(it.next(), - s, - makeVariableSV, - makeSkolemTermSV, - makeTermLabelSV, - mods); - } - ) - - ; - -schema_modifiers[SchemaVariableModifierSet mods] - : - LBRACKET - opts = simple_ident_comma_list - RBRACKET - { - final Iterator it = opts.iterator (); - while ( it.hasNext () ) { - final String option = it.next(); - if (!mods.addModifier(option)) - semanticError(option+ - ": Illegal or unknown modifier in declaration of schema variable"); - } - } - ; - -one_schema_modal_op_decl -@init{ - ImmutableSet modalities = DefaultImmutableSet.nil(); - sort = Sort.FORMULA; -} - : - (LPAREN sort = any_sortId_check[true] { - if (sort != Sort.FORMULA) { - semanticError("Modal operator SV must be a FORMULA, not " + sort); - } - } RPAREN)? - LBRACE ids = simple_ident_comma_list RBRACE id = simple_ident - { if (skip_schemavariables) { - return; - } - Iterator it1 = ids.iterator(); - while(it1.hasNext()) { - modalities = opSVHelper(it1.next(), modalities); - } - SchemaVariable osv = schemaVariables().lookup(new Name(id)); - if(osv != null) - semanticError("Schema variable "+id+" already defined."); - - osv = SchemaVariableFactory.createModalOperatorSV(new Name(id), - sort, modalities); - - if (inSchemaMode()) { - schemaVariables().add(osv); - //functions().add(osv); - } - } - ; - -pred_decl - : - pred_name = funcpred_name - - ( - whereToBind = where_to_bind - )? - - - argSorts = arg_sorts[!skip_predicates] - { - if (!skip_predicates) { - - if(whereToBind != null - && whereToBind.length != argSorts.length) { - semanticError("Where-to-bind list must have same length " - + "as argument list"); - } - - Function p = null; - - int separatorIndex = pred_name.indexOf("::"); - if (separatorIndex > 0) { - String sortName = pred_name.substring(0, separatorIndex); - String baseName = pred_name.substring(separatorIndex + 2); - Sort genSort = lookupSort(sortName); - - if(genSort instanceof GenericSort) { - p = SortDependingFunction.createFirstInstance( - (GenericSort)genSort, - new Name(baseName), - Sort.FORMULA, - argSorts, - false); - } - } - - if(p == null) { - p = new Function(new Name(pred_name), - Sort.FORMULA, - argSorts, - whereToBind, - false); - } - if (lookup(p.name()) != null) { - if(!isProblemParser()) { - throw new AmbigiousDeclException(p.name().toString(), - getSourceName(), - getLine(), - getColumn()); - - } - }else{ - addFunction(p); - } - } - } - SEMI - ; - -pred_decls - : - PREDICATES - LBRACE - ( - pred_decl - ) * - RBRACE - ; - - -location_ident returns [int kind = NORMAL_NONRIGID] - : - id = simple_ident - { - if ("Location".equals(id)) { - kind = LOCATION_MODIFIER; - } else if (!"Location".equals(id)) { - semanticError( - id+": Attribute of a Non Rigid Function can only be 'Location'"); - } - } - ; - - - -func_decl -@init{ - boolean unique = false; -} - : - ( - UNIQUE {unique=true;} - )? - - retSort = any_sortId_check[!skip_functions] - - func_name = funcpred_name - - ( - whereToBind = where_to_bind - )? - - argSorts = arg_sorts[!skip_functions] - - { - if (!skip_functions) { - - if(whereToBind != null - && whereToBind.length != argSorts.length) { - semanticError("Where-to-bind list must have same length " - + "as argument list"); - } - - Function f = null; - - int separatorIndex = func_name.indexOf("::"); - if (separatorIndex > 0) { - String sortName = func_name.substring(0, separatorIndex); - String baseName = func_name.substring(separatorIndex + 2); - Sort genSort = lookupSort(sortName); - - if(genSort instanceof GenericSort) { - f = SortDependingFunction.createFirstInstance( - (GenericSort)genSort, - new Name(baseName), - retSort, - argSorts, - unique); - } - } - - if(f == null) { - f = new Function(new Name(func_name), - retSort, - argSorts, - whereToBind, - unique); - } - if (lookup(f.name()) != null) { - if(!isProblemParser()) { - throw new AmbigiousDeclException(f.name().toString(), - getSourceName(), - getLine(), - getColumn()); - } - }else{ - addFunction(f); - } - } - } - SEMI - ; - -func_decls - : - FUNCTIONS - LBRACE - ( - func_decl - ) * - RBRACE - ; - - -// like arg_sorts but admits also the keyword "\formula" -arg_sorts_or_formula[boolean checkSort] returns [Sort[\] argSorts = null] -@init{ - List args = new LinkedList(); -} - : - ( - LPAREN - - ( s = sortId_check[checkSort] { args.add(s); } - | FORMULA {args.add(Sort.FORMULA);} ) - - ( - COMMA ( s = sortId_check[checkSort] {args.add(s);} - | FORMULA {args.add(Sort.FORMULA);} ) - ) * - RPAREN - ) ? - { - argSorts = (Sort[])args.toArray(AN_ARRAY_OF_SORTS); - } - ; - - -transform_decl - : - ( - retSort = any_sortId_check[!skip_transformers] - | FORMULA { retSort = Sort.FORMULA; } - ) - - trans_name = funcpred_name - - argSorts = arg_sorts_or_formula[!skip_transformers] - - { - if (!skip_transformers) { - - Transformer t = - new Transformer(new Name(trans_name), - retSort, - new ImmutableArray(argSorts)); - - if (lookup(t.name()) != null) { - if(!isProblemParser()) { - throw new AmbigiousDeclException(t.name().toString(), - getSourceName(), - getLine(), - getColumn()); - } - } else { - addFunction(t); - } - } - } - SEMI - ; - -transform_decls - : - TRANSFORMERS - LBRACE - ( - transform_decl - ) * - RBRACE - ; - -arrayopid returns [KeYJavaType _array_op_id = null] -@after{ _array_op_id = componentType; } - : - EMPTYBRACKETS - LPAREN - componentType = keyjavatype - RPAREN - ; - -arg_sorts[boolean checkSort] returns [Sort[\] argSorts = null] -@init{ - List args = new LinkedList(); -} - : - ( - LPAREN - s = sortId_check[checkSort] { args.add(s); } - ( - COMMA s = sortId_check[checkSort] {args.add(s);} - ) * - RPAREN - ) ? - { - argSorts = (Sort[])args.toArray(AN_ARRAY_OF_SORTS); - } - ; - -where_to_bind returns [Boolean[\] result = null] -@init{ - List list = new ArrayList(); -} - : - LBRACE - ( - TRUE {list.add(true);} | FALSE {list.add(false);} - ) - ( - COMMA - ( - TRUE {list.add(true);} | FALSE {list.add(false);} - ) - )* - RBRACE - { - result = list.toArray(new Boolean[0]); - } - ; - -ruleset_decls - : - HEURISTICSDECL - LBRACE - ( - id = simple_ident SEMI - { - if (!skip_rulesets) { - RuleSet h = new RuleSet(new Name(id)); - if(ruleSets().lookup(new Name(id))==null){ - ruleSets().add(h); - } - } - } - ) * - RBRACE - ; - -sortId returns [Sort _sort_id = null] -@after{ _sort_id = s; } - : - s = sortId_check[true] - ; - -// Non-generic sorts, array sorts allowed -sortId_check [boolean checkSort] returns [Sort _sort_id_check = null] -@after{ _sort_id_check = s; } - : - p = sortId_check_help[checkSort] - s = array_decls[p, checkSort] - ; - -// Generic and non-generic sorts, array sorts allowed -any_sortId_check [boolean checkSort] returns [Sort _any_sort_id_check = null] -@after{ _any_sort_id_check = s; } - : - p = any_sortId_check_help[checkSort] - s = array_decls[p, checkSort] - ; - -// Generic and non-generic sorts, array sorts allowed -// This is Id*s*: It allows one or more comma-separated sorts -any_sortIds_check [boolean checkSort] returns [ImmutableList result = ImmutableSLList.nil()] - : - s=any_sortId_check[checkSort] { result = result.prepend(s); } - ( COMMA s2=any_sortId_check[checkSort] { result = result.prepend(s2); } )* - ; - -// Non-generic sorts -sortId_check_help [boolean checkSort] returns [Pair _sort_id_check_help = null] -@after{ _sort_id_check_help = result; } - : - result = any_sortId_check_help[checkSort] - { - // don't allow generic sorts or collection sorts of - // generic sorts at this point - Sort s = result.first; - while ( s instanceof ArraySort ) { - s = ((ArraySort)s).elementSort (); - } - - // FIXME. This is a temporary fix -- - /* if ( s instanceof GenericSort ) { - throw new GenericSortException ( "sort", - "Non-generic sort expected", s, - getSourceName (), getLine (), getColumn () ); - }*/ - } - ; - - -// Generic and non-generic sorts -any_sortId_check_help [boolean checkSort] returns [Pair result = null] - : - name = simple_sort_name - ( OPENTYPEPARAMS parameters=any_sortIds_check[checkSort] CLOSETYPEPARAMS )? - { - //Special handling for byte, char, short, long: - //these are *not* sorts, but they are nevertheless valid - //prefixes for array sorts such as byte[], char[][][]. - //Thus, we consider them aliases for the "int" sort, and remember - //the corresponding Java type for the case that an array sort - //is being declared. - Type t = null; - if(name.equals(PrimitiveType.JAVA_BYTE.getName())) { - t = PrimitiveType.JAVA_BYTE; - name = PrimitiveType.JAVA_INT.getName(); - } else if(name.equals(PrimitiveType.JAVA_CHAR.getName())) { - t = PrimitiveType.JAVA_CHAR; - name = PrimitiveType.JAVA_INT.getName(); - } else if(name.equals(PrimitiveType.JAVA_SHORT.getName())) { - t = PrimitiveType.JAVA_SHORT; - name = PrimitiveType.JAVA_INT.getName(); - } else if(name.equals(PrimitiveType.JAVA_INT.getName())) { - t = PrimitiveType.JAVA_INT; - name = PrimitiveType.JAVA_INT.getName(); - } else if(name.equals(PrimitiveType.JAVA_LONG.getName())) { - t = PrimitiveType.JAVA_LONG; - name = PrimitiveType.JAVA_INT.getName(); - } else if(name.equals(PrimitiveType.JAVA_BIGINT.getName())){ - t = PrimitiveType.JAVA_BIGINT; - name = PrimitiveType.JAVA_BIGINT.getName(); - } - - Sort s = null; - if(checkSort) { - s = lookupSort(name); - if(s == null) { - throw new NotDeclException(input, "sort", name); - } - - if(parameters != null) { - if (s instanceof ParametricSort) { - ParametricSort ps = (ParametricSort) s; - s = ParametricSortInstance.get(ps, parameters); - } else { - semanticError("Not a polymorphic sort: " + name); - } - } - } - -// System.out.println("Sort " + s); - - result = new Pair(s, t); - } - ; - - -array_decls[Pair p, boolean checksort] returns [Sort s = null] -@init{ - int n = 0; -} - : - (EMPTYBRACKETS {n++;})* - { if (!checksort) return s; - if(n != 0) { - final JavaInfo ji = getJavaInfo(); - s = ArraySort.getArraySortForDim(p.first, - p.second, - n, - ji.objectSort(), - ji.cloneableSort(), - ji.serializableSort()); - - Sort last = s; - do { - final ArraySort as = (ArraySort) last; - sorts().add(as); - last = as.elementSort(); - } while (last instanceof ArraySort && sorts().lookup(last.name()) == null); - } else { - s = p.first; - } - } - ; - -id_declaration returns [ IdDeclaration idd = null ] - : - id=IDENT - ( COLON s = sortId_check[true] ) ? - { - idd = new IdDeclaration ( id.getText (), s ); - } - ; - -funcpred_name returns [String result = null] - : - - (sort_name DOUBLECOLON) => (prefix = sort_name - DOUBLECOLON name = simple_ident {result = prefix + "::" + name;}) - | - (prefix = simple_ident {result = prefix; }) -; - - -// no array sorts -simple_sort_name returns [String name = ""] - : - id = simple_ident_dots { name = id; } - ; - - -sort_name returns [String _sort_name = null] -@after{ _sort_name = name; } - : - name = simple_sort_name - (brackets=EMPTYBRACKETS {name += brackets.getText();} )* -; - -/** - * In the special but important case of Taclets, we don't yet know - * whether we are going to have a term or a formula, and it is hard - * to decide a priori what we are looking at. So the `term' - * non-terminal will recognize a term or a formula. The `formula' - * reads a formula/term and throws an error if it wasn't a formula. - * This gives a rather late error message. */ - -formula returns [Term _formula = null] -@after { _formula = a; } - : - a = term - { - if (a != null && a.sort() != Sort.FORMULA ) { - semanticError("Just Parsed a Term where a Formula was expected."); - } - } - ; - -term returns [Term _term = null] -@after { _term = result; } - : - result=elementary_update_term - ( - PARALLEL a=elementary_update_term - { - result = getTermFactory().createTerm(UpdateJunctor.PARALLEL_UPDATE, result, a); - } - - )* - ; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -termEOF returns [Term _term = null] -@after { _term = result; } - : - result = term EOF - ; - -elementary_update_term returns[Term _elementary_update_term=null] -@after { _elementary_update_term = result; } -: - result=equivalence_term - ( - ASSIGN a=equivalence_term - { - result = getServices().getTermBuilder().elementary(result, a); - } - )? - ; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - - -equivalence_term returns [Term _equivalence_term = null] -@after{ _equivalence_term = a; } - : a=implication_term - (EQV a1=implication_term - { a = getTermFactory().createTerm(Equality.EQV, new Term[]{a, a1});} )* -; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -implication_term returns [Term _implication_term = null] -@after{ _implication_term = a; } - : a=disjunction_term - (IMP a1=implication_term - { a = getTermFactory().createTerm(Junctor.IMP, new Term[]{a, a1});} )? -; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -disjunction_term returns [Term _disjunction_term = null] -@after { _disjunction_term = a; } - : a=conjunction_term - (OR a1=conjunction_term - { a = getTermFactory().createTerm(Junctor.OR, new Term[]{a, a1});} )* -; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -conjunction_term returns [Term _conjunction_term = null] -@after { _conjunction_term = a; } - : a=term60 - (AND a1=term60 - { a = getTermFactory().createTerm(Junctor.AND, new Term[]{a, a1});} )* - -; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -term60 returns [Term _term_60 = null] -@after{ _term_60 = a; } - : - a = unary_formula - | a = equality_term -; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -unary_formula returns [Term _unary_formula = null] -@after{ _unary_formula = a; } - : - NOT a1 = term60 { a = getTermFactory().createTerm(Junctor.NOT,new Term[]{a1}); } - | a = quantifierterm - | a = modality_dl_term -; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - - -equality_term returns [Term _equality_term = null] -@init{ - boolean negated = false; -} -@after { _equality_term = a; } - : - a = logicTermReEntry // accessterm - // a term like {o:=u}x=y is parsed as {o:=u}(x=y) - ( (EQUALS | NOT_EQUALS) => - (EQUALS | NOT_EQUALS {negated = true;}) a1 = logicTermReEntry - { - if (a.sort() == Sort.FORMULA || - a1.sort() == Sort.FORMULA) { - String errorMessage = - "The term equality \'=\'/\'!=\' is not "+ - "allowed between formulas.\n Please use \'" + Equality.EQV + - "\' in combination with \'" + Junctor.NOT + "\' instead."; - if (a.op() == Junctor.TRUE || a.op() == Junctor.FALSE || - a1.op() == Junctor.TRUE || a1.op() == Junctor.FALSE) { - errorMessage += - " It seems as if you have mixed up the boolean " + - "constants \'TRUE\'/\'FALSE\' " + - "with the formulas \'true\'/\'false\'."; - } - semanticError(errorMessage); - } - a = getTermFactory().createTerm(Equality.EQUALS, a, a1); - - if (negated) { - a = getTermFactory().createTerm(Junctor.NOT, a); - } - })? - ; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -relation_op returns [Function op = null] -@init{ - String op_name = null; -} -: - ( - LESS { op_name = "lt"; } - | LESSEQUAL { op_name = "leq"; } - | GREATER { op_name = "gt"; } - | GREATEREQUAL { op_name = "geq"; } - ) { - op = (Function) functions().lookup(new Name(op_name)); - if(op == null) { - semanticError("Function symbol '"+op_name+"' not found."); - } - } -; - -weak_arith_op returns [Function op = null] -@init{ - String op_name = null; -} -: - ( - PLUS { op_name = "add"; } - | MINUS { op_name = "sub"; } - ) { - op = (Function) functions().lookup(new Name(op_name)); - if(op == null) { - semanticError("Function symbol '"+op_name+"' not found."); - } - } -; - -strong_arith_op returns [Function op = null] -@init{ - String op_name = null; -} -: - ( - STAR { op_name = "mul"; } - | SLASH { op_name = "div"; } - | PERCENT { op_name = "mod"; } - ) { - op = (Function) functions().lookup(new Name(op_name)); - if(op == null) { - semanticError("Function symbol '"+op_name+"' not found."); - } - } -; - -// term80 -logicTermReEntry returns [Term _logic_term_re_entry = null] -@after { _logic_term_re_entry = a; } -: - a = weak_arith_op_term ((relation_op) => op = relation_op a1=weak_arith_op_term { - a = getTermFactory().createTerm(op, a, a1); - })? -; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - - -weak_arith_op_term returns [Term _weak_arith_op_term = null] -@after { _weak_arith_op_term = a; } -: - a = strong_arith_op_term ((weak_arith_op)=> op = weak_arith_op a1=strong_arith_op_term { - a = getTermFactory().createTerm(op, a, a1); - })* -; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -strong_arith_op_term returns [Term _strong_arith_op_term = null] -@after { _strong_arith_op_term = a; } -: - a = term110 ( (strong_arith_op) => op = strong_arith_op a1=term110 { - a = getTermFactory().createTerm(op, a, a1); - })* -; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - - -/** - * helps to better distinguish if formulas are allowed or only term are - * accepted - * WATCHOUT: Woj: the check for Sort.FORMULA had to be removed to allow - * infix operators and the whole bunch of grammar rules above. - */ -term110 returns [Term _term110 = null] -@after { _term110 = result; } - : - ( - result = braces_term | - result = accessterm - ) - { - /* - if (result.sort() == Sort.FORMULA) { - semanticError("Only terms may stand here."); - } - */ - } - ; - -// WATCHOUT: Woj: not used anymore, but don't remove, -// very useful piece of code -/* -classReference returns [String classReference = ""] -@init{}: - - id=IDENT { - classReference = id.getText(); - while (isPackage(classReference)) { - match(input, DOT, null); - classReference += "." + input.LT(1).getText(); - match(input, IDENT, null); - } - KeYJavaType kjt = null; - kjt = getTypeByClassName(classReference); - if ( kjt == null) { - throw new NotDeclException - ("Class " + classReference + " is unknown.", - classReference, getSourceName(), getLine(), - getColumn()); - } - classReference = kjt.getFullName(); - } - ; -*/ - - - - -staticAttributeOrQueryReference returns [String attrReference = ""] -: - // attrReference=simple_ident_dots - id=IDENT - { - attrReference = id.getText(); - while (isPackage(attrReference) || input.LA(2)==NUM_LITERAL || - (input.LT(2).getText().charAt(0)<='Z' && input.LT(2).getText().charAt(0)>='A' && - (input.LT(2).getText().length()==1 || input.LT(2).getText().charAt(1)<='z' && input.LT(2).getText().charAt(1)>='a')) && - input.LA(1) == DOT) { - if(getTypeByClassName(attrReference)!=null){ - ProgramVariable maybeAttr = - getJavaInfo().getAttribute(input.LT(2).getText(), getTypeByClassName(attrReference)); - if(maybeAttr!=null){ - break; - } - } - - match(input, DOT, null); - attrReference += "." + input.LT(1).getText(); - if(input.LA(1)==NUM_LITERAL){ - match(input, NUM_LITERAL, null); - }else{ - match(input, IDENT, null); - } - } - } - (EMPTYBRACKETS {attrReference += "[]";})* - { KeYJavaType kjt = null; - kjt = getTypeByClassName(attrReference); - if (kjt == null) { - throw new NotDeclException(input, "Class", attrReference); - } - attrReference = kjt.getSort().name().toString(); - match(input, DOT, null); - attrReference += "::" + input.LT(1).getText(); - match(input, IDENT, null); - if(savedGuessing > -1) { - state.backtracking = savedGuessing; - savedGuessing = -1; - } - } - ; - -static_attribute_suffix returns [Term result = null] -@init{ - Operator v = null; - attributeName = ""; -} - : - attributeName = staticAttributeOrQueryReference - { - String className; - if(attributeName.indexOf(':')!=-1){ - className = - attributeName.substring(0, attributeName.indexOf(':')); - }else{ - className = - attributeName.substring(0, attributeName.lastIndexOf(".")); - } - v = getAttributeInPrefixSort(getTypeByClassName(className).getSort(), attributeName); - } - { result = createAttributeTerm(null, v); } - ; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -attribute_or_query_suffix[Term prefix] returns [Term _attribute_or_query_suffix = null] -@after { _attribute_or_query_suffix = result; } - : - DOT ( STAR { result = services.getTermBuilder().allFields(prefix); } - | ( memberName = attrid - (result = query_suffix[prefix, memberName] {assert result != null;})? - { - if(result == null) { - if(prefix.sort() == getServices().getTypeConverter().getSeqLDT().targetSort()) { - if("length".equals(memberName)) { - result = getServices().getTermBuilder().seqLen(prefix); - } else { - semanticError("There is no attribute '" + memberName + - "' for sequences (Seq), only 'length' is supported."); - } - } else { - Operator v = getAttributeInPrefixSort(prefix.sort(), memberName); - result = createAttributeTerm(prefix, v); - } - } - } ) ) - ; -catch [TermCreationException ex] { - raiseException(new KeYSemanticException(input, getSourceName(), ex)); -} - -attrid returns [String attr = "";] - : - // the o.f@(packagename.Classname) syntax has been dropped. - // instead, one can write o.(packagename.Classname::f) - id = simple_ident - { attr = id; } - | LPAREN clss = sort_name DOUBLECOLON id2 = simple_ident RPAREN - { attr = clss + "::" + id2; } - ; - -query_suffix [Term prefix, String memberName] returns [Term result = null] -@init{ - String classRef, name; - boolean brackets = false; -} - : - args = argument_list - { - // true in case class name is not explicitly mentioned as part of memberName - boolean implicitClassName = memberName.indexOf("::") == -1; - - if(implicitClassName) { - classRef = prefix.sort().name().toString(); - name = memberName; - } else { - String parts[] = memberName.split("::", 2); - classRef = parts[0]; - name = parts[1]; - } - KeYJavaType kjt = getTypeByClassName(classRef); - if(kjt == null) - throw new NotDeclException(input, "Class", classRef); - classRef = kjt.getFullName(); - - result = getServices().getJavaInfo().getProgramMethodTerm(prefix, name, args, classRef, implicitClassName); - } - ; -catch [TermCreationException ex] { - raiseException(new KeYSemanticException(input, getSourceName(), ex)); -} - -//term120 -accessterm returns [Term _accessterm = null] -@init{ int selectNestingDepth = globalSelectNestingDepth; } -@after { _accessterm = result; } - : - (MINUS ~NUM_LITERAL) => MINUS result = term110 - { - if (result.sort() != Sort.FORMULA) { - result = getTermFactory().createTerm - ((Function) functions().lookup(new Name("neg")), result); - } else { - semanticError("Formula cannot be prefixed with '-'"); - } - } - | - (LPAREN any_sortId_check[false] RPAREN term110)=> - LPAREN s = any_sortId_check[true] RPAREN result=term110 - { - final Sort objectSort = getServices().getJavaInfo().objectSort(); - if(s==null) { - semanticError("Tried to cast to unknown type."); - } else if (objectSort != null - && !s.extendsTrans(objectSort) - && result.sort().extendsTrans(objectSort)) { - semanticError("Illegal cast from " + result.sort() + - " to sort " + s + - ". Casts between primitive and reference types are not allowed. "); - } - result = getTermFactory().createTerm(s.getCastSymbol(getServices()), result); - } - | - ( {isStaticQuery()}? // look for package1.package2.Class.query( - result = static_query { selectNestingDepth++; } - | - {isStaticAttribute()}? // look for package1.package2.Class.attr - result = static_attribute_suffix { selectNestingDepth++; } - | - result = atom { selectNestingDepth = globalSelectNestingDepth; } - ) - - ( abs = accessterm_bracket_suffix[result] - { - result = $abs.result; - if($abs.increaseHeapSuffixCounter) selectNestingDepth++; - } - | result = attribute_or_query_suffix[result] { selectNestingDepth++; } - )* - - { globalSelectNestingDepth = selectNestingDepth; } - - // at most one heap selection suffix - ( result = heap_selection_suffix[result] )? // resets globalSelectNestingDepth to zero - ; -catch [TermCreationException ex] { - raiseException(new KeYSemanticException(input, getSourceName(), ex)); -} - -heap_selection_suffix [Term term] returns [Term result] - : - AT heap=accessterm - { result = heapSelectionSuffix(term, heap); } - ; - -accessterm_bracket_suffix[Term reference] returns [Term result, boolean increaseHeapSuffixCounter] -@init{ $increaseHeapSuffixCounter = false; } - : - { isHeapTerm(reference) }? tmp = heap_update_suffix[reference] { $result = tmp; } - | { isSequenceTerm(reference) }? tmp = seq_get_suffix[reference] { $result = tmp; } - | tmp = array_access_suffix[reference] { $result = tmp; $increaseHeapSuffixCounter = true; } - ; - -seq_get_suffix[Term reference] returns [Term result] - : - LBRACKET - indexTerm = logicTermReEntry - { - if(!isIntTerm(indexTerm)) semanticError("Expecting term of sort " + IntegerLDT.NAME + " as index of sequence " + reference + ", but found: " + indexTerm); - result = getServices().getTermBuilder().seqGet(Sort.ANY, reference, indexTerm); - } - RBRACKET - ; - -static_query returns [Term result = null] -@init{ - queryRef = ""; -} - : - queryRef = staticAttributeOrQueryReference args = argument_list - { - int index = queryRef.indexOf(':'); - String className = queryRef.substring(0, index); - String qname = queryRef.substring(index+2); - result = getServices().getJavaInfo().getStaticProgramMethodTerm(qname, args, className); - if(result == null && isTermParser()) { - final Sort sort = lookupSort(className); - if (sort == null) { - semanticError("Could not find matching sort for " + className); - } - KeYJavaType kjt = getServices().getJavaInfo().getKeYJavaType(sort); - if (kjt == null) { - semanticError("Found logic sort for " + className + - " but no corresponding java type!"); - } - } - - } - ; -catch [TermCreationException ex] { - raiseException(new KeYSemanticException(input, getSourceName(), ex)); -} - -heap_update_suffix [Term heap] returns [Term result=heap] - : // TODO find the right kind of non-terminal for "o.f" and "a[i]" - // and do not resign to parsing an arbitrary term - LBRACKET - ( (equivalence_term ASSIGN) => - target=equivalence_term ASSIGN val=equivalence_term - { // TODO at least make some check that it is a select term after all ... - Term objectTerm = target.sub(1); - Term fieldTerm = target.sub(2); - result = getServices().getTermBuilder().store(heap, objectTerm, fieldTerm, val); - } - | id=simple_ident args=argument_list - { - Function f = (Function)functions().lookup(new Name(id)); - if(f == null) { - semanticError("Unknown heap constructor " + id); - } - Term[] augmentedArgs = new Term[args.length+1]; - System.arraycopy(args, 0, augmentedArgs, 1, args.length); - augmentedArgs[0] = heap; - result = getTermFactory().createTerm(f, augmentedArgs); - if(!result.sort().name().toString().equals("Heap")) { - semanticError(id + " is not a heap constructor "); - } - } - ) - RBRACKET - ; -catch [TermCreationException ex] { - raiseException(new KeYSemanticException(input, getSourceName(), ex)); -} - -array_access_suffix [Term arrayReference] returns [Term _array_access_suffix = null] -@init{ - Term rangeFrom = null; - Term result = arrayReference; -} -@after{ _array_access_suffix = result; } - : - LBRACKET - ( STAR { - rangeFrom = toZNotation("0", functions()); - Term lt = getServices().getTermBuilder().dotLength(arrayReference); - Term one = toZNotation("1", functions()); - rangeTo = getTermFactory().createTerm - ((Function) functions().lookup(new Name("sub")), lt, one); - } - | indexTerm = logicTermReEntry - ((DOTRANGE) => DOTRANGE rangeTo = logicTermReEntry - {rangeFrom = indexTerm;})? - ) - RBRACKET - { - if(rangeTo != null) { - if(quantifiedArrayGuard == null) { - semanticError( - "Quantified array expressions are only allowed in locations."); - } - LogicVariable indexVar = new LogicVariable(new Name("i"), - (Sort) sorts().lookup(new Name("int"))); - indexTerm = getTermFactory().createTerm(indexVar); - - Function leq = (Function) functions().lookup(new Name("leq")); - Term fromTerm = getTermFactory().createTerm(leq, rangeFrom, indexTerm); - Term toTerm = getTermFactory().createTerm(leq, indexTerm, rangeTo); - Term guardTerm = getTermFactory().createTerm(Junctor.AND, fromTerm, toTerm); - quantifiedArrayGuard = getTermFactory().createTerm(Junctor.AND, quantifiedArrayGuard, guardTerm); - } - result = getServices().getTermBuilder().dotArr(result, indexTerm); - } - ; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - - - -accesstermlist returns [HashSet accessTerms = new LinkedHashSet()] : - (t=accessterm {accessTerms.add(t);} ( COMMA t=accessterm {accessTerms.add(t);})* )? ; - - -atom returns [Term _atom = null] -@after { _atom = a; } - : -( {isTermTransformer()}? a = specialTerm - | a = funcpredvarterm - | LPAREN a = term RPAREN - | TRUE { a = getTermFactory().createTerm(Junctor.TRUE); } - | FALSE { a = getTermFactory().createTerm(Junctor.FALSE); } - | a = ifThenElseTerm - | a = ifExThenElseTerm - | literal=STRING_LITERAL - { - String s = unescapeString(literal.getText()); - a = getServices().getTypeConverter().convertToLogicElement(new de.uka.ilkd.key.java.expression.literal.StringLiteral(s)); - } - ) (LGUILLEMETS labels = label {if (labels.size() > 0) {a = getServices().getTermBuilder().addLabel(a, labels);} } RGUILLEMETS)? - ; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -label returns [ImmutableArray labels = new ImmutableArray()] -@init { - ArrayList labelList = new ArrayList(); -} -: - l=single_label {labelList.add(l);} (COMMA l=single_label {labelList.add(l);})* - { - labels = new ImmutableArray((TermLabel[])labelList.toArray(new TermLabel[labelList.size()])); - } -; - -single_label returns [TermLabel label=null] -@init { - String labelName = ""; - TermLabel left = null; - TermLabel right = null; - List parameters = new LinkedList(); -} -: - (name=IDENT {labelName=name.getText();} | star=STAR {labelName=star.getText();} ) (LPAREN param1=STRING_LITERAL {parameters.add(param1.getText().substring(1,param1.getText().length()-1));} (COMMA param2=STRING_LITERAL {parameters.add(param2.getText().substring(1,param2.getText().length()-1));})* RPAREN)? - { - try { - if (inSchemaMode()) { - SchemaVariable var = schemaVariables().lookup(new Name(labelName)); - if (var instanceof TermLabel) { - label = (TermLabel)var; - } - } - if (label == null) { - label = getServices().getProfile() - .getTermLabelManager().parseLabel(labelName, parameters, getServices()); - } - } catch(TermLabelException ex) { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - } - ; - - -abbreviation returns [Term _abbreviation=null] -@init{ Term a = null; } -@after{ _abbreviation = a; } - : - ( sc = simple_ident - { - a = scm.getTerm(sc); - if(a==null){ - throw new NotDeclException(input, "abbreviation", sc); - } - } - ) - ; - - -ifThenElseTerm returns [Term _if_then_else_term = null] -@init{ Term result = null; } -@after{ _if_then_else_term = result; } - : - IF LPAREN condF = term RPAREN - { - if (condF.sort() != Sort.FORMULA) { - semanticError - ("Condition of an \\if-then-else term has to be a formula."); - } - } - THEN LPAREN thenT = term RPAREN - ELSE LPAREN elseT = term RPAREN - { - result = getTermFactory().createTerm ( IfThenElse.IF_THEN_ELSE, new Term[]{condF, thenT, elseT} ); - } - ; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - - -ifExThenElseTerm returns [Term _if_ex_then_else_term = null] -@init{ - exVars - = ImmutableSLList.nil(); - Namespace orig = variables(); - Term result = null; -} -@after{ _if_ex_then_else_term = result; } - : - IFEX exVars = bound_variables - LPAREN condF = term RPAREN - { - if (condF.sort() != Sort.FORMULA) { - semanticError - ("Condition of an \\ifEx-then-else term has to be a formula."); - } - } - THEN LPAREN thenT = term RPAREN - ELSE LPAREN elseT = term RPAREN - { - ImmutableArray exVarsArray - = new ImmutableArray( - exVars.toArray(new QuantifiableVariable[exVars.size()])); - result = getTermFactory().createTerm ( IfExThenElse.IF_EX_THEN_ELSE, - new Term[]{condF, thenT, elseT}, - exVarsArray, - null ); - if(!isGlobalDeclTermParser()) { - unbindVars(orig); - } - } - ; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - - -argument returns [Term _argument = null] -@init{ - ImmutableArray vars = null; -} -@after{ _argument = result; } -: - ( - // WATCHOUT Woj: can (should) this be unified to term60? - {isTermParser() || isGlobalDeclTermParser()}? - result = term - | - result = term60 - ) - ; - - -quantifierterm returns [Term _quantifier_term = null] -@init{ - Operator op = null; - Namespace orig = variables(); - Term a = null; -} -@after{ _quantifier_term = a; } -: - ( FORALL { op = Quantifier.ALL; } - | EXISTS { op = Quantifier.EX; }) - vs = bound_variables a1 = term60 - { - a = getTermFactory().createTerm((Quantifier)op, - new ImmutableArray(a1), - new ImmutableArray(vs.toArray(new QuantifiableVariable[vs.size()])), - null); - if(!isGlobalDeclTermParser()) - unbindVars(orig); - } -; - -/* - * A term that is surrounded by braces: {} - */ -braces_term returns [Term _update_or_substitution = null] -@after{ _update_or_substitution = result; } -: - (LBRACE SUBST) => result = substitutionterm - | (LBRACE (LPAREN | RBRACE)) => result = locset_term - | result = updateterm - ; - -locset_term returns [Term result = getServices().getTermBuilder().empty()] - : - LBRACE - ( l = location_term { $result = l; } - ( COMMA l = location_term { $result = getServices().getTermBuilder().union($result, l); } )* )? - RBRACE - ; - -location_term returns[Term result] - : - LPAREN obj=equivalence_term COMMA field=equivalence_term RPAREN - { $result = getServices().getTermBuilder().singleton(obj, field); } - ; - -substitutionterm returns [Term _substitution_term = null] -@init{ - SubstOp op = WarySubstOp.SUBST; - Namespace orig = variables(); - Term result = null; -} -@after{ _substitution_term = result; } -: - LBRACE SUBST - v = one_bound_variable SEMI - { // Tricky part, v cannot be bound while parsing a1 - if(!isGlobalDeclTermParser()) - unbindVars(orig); - } - a1=logicTermReEntry - { // The rest of the tricky part, bind it again - if(!isGlobalDeclTermParser()) - if(v instanceof LogicVariable) - bindVar((LogicVariable)v); - else - bindVar(); - } - RBRACE - ( a2 = term110 | a2 = unary_formula ) { - result = getServices().getTermBuilder().subst ( op, v, a1, a2 ); - if(!isGlobalDeclTermParser()) - unbindVars(orig); - } -; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - - -updateterm returns [Term _update_term = null] -@init{ Term result = null; } -@after{ _update_term = result; } -: - LBRACE u=term RBRACE - ( - a2=term110 - | - a2=unary_formula - ) - { - result = getTermFactory().createTerm(UpdateApplication.UPDATE_APPLICATION, u, a2); - } - ; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -bound_variables returns[ImmutableList list = ImmutableSLList.nil()] -: - var = one_bound_variable { list = list.append(var); } - ( - COMMA var = one_bound_variable { list = list.append(var); } - )* - SEMI -; - -one_bound_variable returns[QuantifiableVariable _one_bound_variable=null] -@after{ _one_bound_variable = v; } -: - {isGlobalDeclTermParser()}? v = one_logic_bound_variable_nosort - | - {inSchemaMode()}? v = one_schema_bound_variable - | - {!inSchemaMode()}? v = one_logic_bound_variable -; - -one_schema_bound_variable returns[QuantifiableVariable v=null] -@init{ - Operator ts = null; -} -: - id = simple_ident { - ts = schemaVariables().lookup(new Name(id)); - if ( ! (ts instanceof VariableSV)) { - semanticError(ts+" is not allowed in a quantifier. Note, that you can't " - + "use the normal syntax for quantifiers of the form \"\\exists int i;\"" - + " in taclets. You have to define the variable as a schema variable" - + " and use the syntax \"\\exists i;\" instead."); - } - v = (QuantifiableVariable) ts; - bindVar(); - } -; - -one_logic_bound_variable returns[QuantifiableVariable v=null] -: - s=sortId id=simple_ident { - v = bindVar(id, s); - } -; - -one_logic_bound_variable_nosort returns[QuantifiableVariable v=null] -: - id=simple_ident { - v = (LogicVariable)variables().lookup(new Name(id)); - } -; - -modality_dl_term returns [Term _modality_dl_term = null] -@init{ - Operator op = null; - PairOfStringAndJavaBlock sjb = null; - Term a = null; -} -@after{ _modality_dl_term = a; } - : - modality = MODALITY - { - sjb=getJavaBlock(modality); - Debug.out("op: ", sjb.opName); - Debug.out("program: ", sjb.javaBlock); - if(sjb.opName.charAt(0) == '#') { - if (!inSchemaMode()) { - semanticError - ("No schema elements allowed outside taclet declarations ("+sjb.opName+")"); - } - op = schemaVariables().lookup(new Name(sjb.opName)); - } else { - op = Modality.getModality(sjb.opName); - } - if(op == null) { - semanticError("Unknown modal operator: "+sjb.opName); - } - } - // CAREFUL here, op can be null during guessing stage (use lazy &&) - ({op != null && op.arity() == 1}? a1=term60 - // This here will accept both (1) \modality...\endmodality post and - // (2) \modality...\endmodality(post) - // so that it is consistent with pretty printer that prints (1). - // A term "(post)" seems to be parsed as "post" anyway - { - a = getTermFactory().createTerm(op, new Term[]{a1}, null, sjb.javaBlock); - } - ) - ; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - - -argument_list returns [Term[\] _argument_list = null] -@init{ - List args = new LinkedList(); - Term[] result = null; -} -@after{ _argument_list = result; } - : - LPAREN - (p1 = argument { args.add(p1); } - - (COMMA p2 = argument { args.add(p2); } )* )? - - RPAREN - { - result = args.toArray(new Term[0]); - } - - ; - -funcpredvarterm returns [Term _func_pred_var_term = null] -@init{ - String neg = ""; - boolean opSV = false; - Namespace orig = variables(); - boolean limited = false; -} -@after { _func_pred_var_term = a; } - : - ch=CHAR_LITERAL { - String s = ch.getText(); - int intVal = 0; - if (s.length()==3) { - intVal = (int)s.charAt(1); - } else { - try { - intVal = Integer.parseInt(s.substring(3,s.length()-1),16); - } catch (NumberFormatException ex) { - semanticError("'"+s+"' is not a valid character."); - } - } - a = getTermFactory().createTerm((Function) functions().lookup(new Name("C")), - toZNotation(""+intVal, functions()).sub(0)); - } - | - ((MINUS)? NUM_LITERAL) => (MINUS {neg = "-";})? number=NUM_LITERAL - { a = toZNotation(neg+number.getText(), functions());} - | AT a = abbreviation - | varfuncid = funcpred_name - ( (~LBRACE | LBRACE bound_variables) => - ( - LBRACE - boundVars = bound_variables - RBRACE - )? - - args = argument_list - )? - - //args==null indicates no argument list - //args.size()==0 indicates open-close-parens () - - { - if(varfuncid.equals("skip") && args == null) { - a = getTermFactory().createTerm(UpdateJunctor.SKIP); - } else { - Operator op; - if(varfuncid.endsWith(LIMIT_SUFFIX)) { - varfuncid = varfuncid.substring(0, varfuncid.length()-5); - op = lookupVarfuncId(varfuncid, args); - if(ObserverFunction.class.isAssignableFrom(op.getClass())) { - op = getServices().getSpecificationRepository() - .limitObs((ObserverFunction)op).first; - } else { - semanticError("Cannot can be limited: " + op); - } - } else { - op = lookupVarfuncId(varfuncid, args); - } - - if (op instanceof ParsableVariable) { - a = termForParsedVariable((ParsableVariable)op); - } else { - if (args==null) { - args = new Term[0]; - } - - if(boundVars == null) { - a = getTermFactory().createTerm(op, args); - } else { - //sanity check - assert op instanceof Function; - for(int i = 0; i < args.length; i++) { - if(i < op.arity() && !op.bindVarsAt(i)) { - for(QuantifiableVariable qv : args[i].freeVars()) { - if(boundVars.contains(qv)) { - semanticError("Building function term "+op+" with bound variables failed: " - + "Variable " + qv + " must not occur free in subterm " + args[i]); - } - } - } - } - - //create term - a = getTermFactory().createTerm(op, args, new ImmutableArray(boundVars.toArray(new QuantifiableVariable[boundVars.size()])), null); - } - } - } - - if(boundVars != null) { - unbindVars(orig); - } - } -; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -specialTerm returns [Term _special_term = null] -@init{ - Operator vf = null; -} -@after { _special_term = result; }: - {isTacletParser() || isProblemParser()}? - result = metaTerm - ; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -arith_op returns [String op = null] -: - PERCENT {op = "\%";} - | STAR {op = "*";} - | MINUS {op = "-";} - | SLASH {op = "/";} - | PLUS { op = "+";} -; - - -varId returns [ParsableVariable v = null] - : - id=IDENT - { - v = variables().lookup(new Name(id.getText())); - if (v == null) { - v = schemaVariables().lookup(new Name(id.getText())); - } - if (v == null) { - throw new NotDeclException(input, "variable", id.getText()); - } - } - ; - -varIds returns [LinkedList list = new LinkedList()] -@init{ - ParsableVariable v = null; -} - : - ids = simple_ident_comma_list { - Iterator it = ids.iterator(); - while(it.hasNext()) { - String id = it.next(); - v = (ParsableVariable) variables().lookup(new Name(id)); - if (v == null) { - v = schemaVariables().lookup(new Name(id)); - } - if (v == null) { - semanticError("Variable " +id + " not declared."); - } - list.add(v); - } - } - ; - -triggers[TacletBuilder b] -@init { - id = null; - t = null; - SchemaVariable triggerVar = null; - avoidCond = null; - ImmutableList avoidConditions = ImmutableSLList.nil(); -} : - TRIGGER - LBRACE id = simple_ident - { - triggerVar = schemaVariables().lookup(new Name(id)); - if (triggerVar == null) { - semanticError("Undeclared schemavariable: " + id); - } - } RBRACE - t=term (AVOID avoidCond=term {avoidConditions = avoidConditions.append(avoidCond);} - (COMMA avoidCond=term {avoidConditions = avoidConditions.append(avoidCond);})*)? SEMI - { - b.setTrigger(new Trigger(triggerVar, t, avoidConditions)); - } -; - -taclet[ImmutableSet choices, boolean axiomMode] returns [Taclet r] -@init{ - ifSeq = Sequent.EMPTY_SEQUENT; - TacletBuilder b = null; - int applicationRestriction = RewriteTaclet.NONE; - choices_ = choices; - switchToNormalMode(); - ImmutableSet tacletAnnotations = DefaultImmutableSet.nil(); -} - : - (LEMMA {tacletAnnotations = tacletAnnotations.add(de.uka.ilkd.key.rule.TacletAnnotation.LEMMA);})? - name=IDENT (choices_=option_list[choices_])? - LBRACE - ( (formula RBRACE) => /* check for rbrace needed to distinguish from "label" : goalspec*/ - { if(!axiomMode) { semanticError("formula rules are only permitted for \\axioms"); } } - form=formula { r = null; } - { b = createTacletBuilderFor(null, RewriteTaclet.NONE); - SequentFormula sform = new SequentFormula(form); - Semisequent semi = new Semisequent(sform); - Sequent addSeq = Sequent.createAnteSequent(semi); - ImmutableList noTaclets = ImmutableSLList.nil(); - DefaultImmutableSet noSV = DefaultImmutableSet.nil(); - addGoalTemplate(b, null, null, addSeq, noTaclets, noSV, null); - b.setName(new Name(name.getText())); - b.setChoices(choices_); - b.setAnnotations(tacletAnnotations); - r = b.getTaclet(); - taclet2Builder.put(r,b); - } - | - - { - switchToSchemaMode(); - // schema var decls - schemaVariablesNamespace = new Namespace(schemaVariables()); - } - ( SCHEMAVAR one_schema_var_decl ) * - ( ASSUMES LPAREN ifSeq=seq RPAREN ) ? - ( FIND LPAREN find = termorseq RPAREN - ( SAMEUPDATELEVEL { applicationRestriction |= RewriteTaclet.SAME_UPDATE_LEVEL; } - | INSEQUENTSTATE { applicationRestriction |= RewriteTaclet.IN_SEQUENT_STATE; } - | ANTECEDENTPOLARITY { applicationRestriction |= RewriteTaclet.ANTECEDENT_POLARITY; } - | SUCCEDENTPOLARITY { applicationRestriction |= RewriteTaclet.SUCCEDENT_POLARITY; } - )* - ) ? - { - b = createTacletBuilderFor(find, applicationRestriction); - b.setName(new Name(name.getText())); - b.setIfSequent(ifSeq); - } - ( VARCOND LPAREN varexplist[b] RPAREN ) ? - goalspecs[b, find != null] - modifiers[b] - { - b.setChoices(choices_); - b.setAnnotations(tacletAnnotations); - r = b.getTaclet(); - taclet2Builder.put(r,b); - // dump local schema var decls - schemaVariablesNamespace = schemaVariables().parent(); - } - ) - RBRACE - ; - -modifiers[TacletBuilder b] -: - ( rs = rulesets { - Iterator it = rs.iterator(); - while(it.hasNext()) - b.addRuleSet((RuleSet)it.next()); - } - | NONINTERACTIVE { b.addRuleSet((RuleSet)ruleSets().lookup(new Name("notHumanReadable"))); } - | DISPLAYNAME dname = string_literal - {b.setDisplayName(dname);} - | HELPTEXT htext = string_literal - {b.setHelpText(htext);} - | triggers[b] - ) * - ; - -seq returns [Sequent s] : - ant=semisequent SEQARROW suc=semisequent - { s = Sequent.createSequent(ant, suc); } - ; - catch [RuntimeException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -seqEOF returns [Sequent s] : - ss=seq EOF - {s = ss;} - ; - -termorseq returns [Object o] - : - head=term ( COMMA s=seq | SEQARROW ss=semisequent ) ? - { - if ( s == null ) { - if ( ss == null ) { - // Just a term - o = head; - } else { - // A sequent with only head in the antecedent. - Semisequent ant = Semisequent.EMPTY_SEMISEQUENT; - ant = ant.insertFirst( - new SequentFormula(head)).semisequent(); - o = Sequent.createSequent(ant,ss); - } - } else { - // A sequent. Prepend head to the antecedent. - Semisequent newAnt = s.antecedent(); - newAnt = newAnt .insertFirst( - new SequentFormula(head)).semisequent(); - o = Sequent.createSequent(newAnt,s.succedent()); - } - } - | - SEQARROW ss=semisequent - { - o = Sequent.createSequent(Semisequent.EMPTY_SEMISEQUENT,ss); - } - ; - -semisequent returns [Semisequent _semi_sequent] -@init{ - ss = Semisequent.EMPTY_SEMISEQUENT; -} -@after{ _semi_sequent = ss; } - : - /* empty */ | - head=term ( COMMA ss=semisequent) ? - { - ss = ss.insertFirst(new SequentFormula(head)).semisequent(); - } - ; - -varexplist[TacletBuilder b] : varexp[b] ( COMMA varexp[b] ) * ; - -varexp[TacletBuilder b] -@init{ - boolean negated = false; -} -: - ( varcond_applyUpdateOnRigid[b] - | varcond_dropEffectlessElementaries[b] - | varcond_dropEffectlessStores[b] - | varcond_enum_const[b] - | varcond_free[b] - | varcond_hassort[b] - | varcond_fieldtype[b] - | varcond_equalUnique[b] - | varcond_new[b] - | varcond_newlabel[b] - | varcond_observer[b] - | varcond_different[b] - | varcond_metadisjoint[b] - | varcond_simplifyIfThenElseUpdate[b] - | varcond_differentFields[b] - ) - | - ( (NOT_ {negated = true;} )? - ( varcond_abstractOrInterface[b, negated] - | varcond_array[b, negated] - | varcond_array_length[b, negated] - | varcond_enumtype[b, negated] - | varcond_freeLabelIn[b,negated] - | varcond_localvariable[b, negated] - | varcond_thisreference[b, negated] - | varcond_reference[b, negated] - | varcond_referencearray[b, negated] - | varcond_static[b,negated] - | varcond_staticmethod[b,negated] - | varcond_final[b,negated] - | varcond_typecheck[b, negated] - | varcond_constant[b, negated] - | varcond_label[b, negated] - | varcond_static_field[b, negated] - | varcond_subFormulas[b, negated] - | varcond_containsAssignment[b, negated] - ) - ) -; - - -varcond_applyUpdateOnRigid [TacletBuilder b] -: - APPLY_UPDATE_ON_RIGID LPAREN u=varId COMMA x=varId COMMA x2=varId RPAREN - { - b.addVariableCondition(new ApplyUpdateOnRigidCondition((UpdateSV)u, - (SchemaVariable)x, - (SchemaVariable)x2)); - } -; - -varcond_dropEffectlessElementaries[TacletBuilder b] -: - DROP_EFFECTLESS_ELEMENTARIES LPAREN u=varId COMMA x=varId COMMA result=varId RPAREN - { - b.addVariableCondition(new DropEffectlessElementariesCondition((UpdateSV)u, - (SchemaVariable)x, - (SchemaVariable)result)); - } -; - -varcond_dropEffectlessStores[TacletBuilder b] -: - DROP_EFFECTLESS_STORES LPAREN h=varId COMMA o=varId COMMA f=varId COMMA x=varId COMMA result=varId RPAREN - { - b.addVariableCondition(new DropEffectlessStoresCondition((TermSV)h, - (TermSV)o, - (TermSV)f, - (TermSV)x, - (TermSV)result)); - } -; - -varcond_differentFields [TacletBuilder b] -: - DIFFERENTFIELDS - LPAREN - x = varId COMMA y = varId - RPAREN - { - b.addVariableCondition(new DifferentFields((SchemaVariable)x, (SchemaVariable)y)); - } -; - - -varcond_simplifyIfThenElseUpdate[TacletBuilder b] -: - SIMPLIFY_IF_THEN_ELSE_UPDATE LPAREN phi=varId COMMA u1=varId COMMA u2=varId COMMA commonFormula=varId COMMA result=varId RPAREN - { - b.addVariableCondition(new SimplifyIfThenElseUpdateCondition((FormulaSV) phi, - (UpdateSV) u1, - (UpdateSV) u2, - (FormulaSV) commonFormula, - (SchemaVariable)result)); - } -; - -type_resolver returns [TypeResolver tr = null] -: - (s = any_sortId_check[true] - { - if ( s instanceof GenericSort ) { - tr = TypeResolver.createGenericSortResolver((GenericSort)s); - } else { - tr = TypeResolver.createNonGenericSortResolver(s); - } - } - ) - | - ( - TYPEOF LPAREN y = varId RPAREN - { - tr = TypeResolver.createElementTypeResolver((SchemaVariable)y); - } - ) - | - ( - CONTAINERTYPE LPAREN y = varId RPAREN - { - tr = TypeResolver.createContainerTypeResolver((SchemaVariable)y); - } - ) -; - -varcond_new [TacletBuilder b] -: - NEW LPAREN x=varId COMMA - ( - TYPEOF LPAREN y=varId RPAREN { - b.addVarsNew((SchemaVariable) x, (SchemaVariable) y); - } - | - DEPENDINGON LPAREN y=varId RPAREN { - b.addVarsNewDependingOn((SchemaVariable)x, (SchemaVariable)y); - } - | kjt=keyjavatype { - b.addVarsNew((SchemaVariable) x, kjt.getJavaType()); - } - ) - RPAREN - -; - -varcond_newlabel [TacletBuilder b] -: - NEWLABEL LPAREN x=varId RPAREN { - b.addVariableCondition(new NewJumpLabelCondition((SchemaVariable)x)); - } -; -varcond_typecheck [TacletBuilder b, boolean negated] -@init{ - TypeComparisonCondition.Mode mode = null; -} -: - ( SAME - { - mode = negated - ? TypeComparisonCondition.Mode.NOT_SAME - : TypeComparisonCondition.Mode.SAME; - } - | ISSUBTYPE - { - mode = negated - ? TypeComparisonCondition.Mode.NOT_IS_SUBTYPE - : TypeComparisonCondition.Mode.IS_SUBTYPE; - } - | STRICT ISSUBTYPE - { - if(negated) { - semanticError("A negated strict subtype check does not make sense."); - } - mode = TypeComparisonCondition.Mode.STRICT_SUBTYPE; - } - | DISJOINTMODULONULL - { - if(negated) { - semanticError("Negation not supported"); - } - mode = TypeComparisonCondition.Mode.DISJOINTMODULONULL; - } - ) - LPAREN fst = type_resolver COMMA snd = type_resolver RPAREN - { - b.addVariableCondition(new TypeComparisonCondition(fst, snd, mode)); - } -; - - -varcond_free [TacletBuilder b] -: - NOTFREEIN LPAREN x=varId COMMA ys=varIds RPAREN { - Iterator it = ys.iterator(); - while(it.hasNext()) { - b.addVarsNotFreeIn((SchemaVariable)x,(SchemaVariable)it.next()); - } - } -; - - -varcond_hassort [TacletBuilder b] -@init{ - boolean elemSort = false; -} -: - HASSORT - LPAREN - (x=varId | ELEMSORT LPAREN x=varId RPAREN {elemSort = true;}) - COMMA - s=any_sortId_check[true] - RPAREN - { - if(!(s instanceof GenericSort)) { - throw new GenericSortException("sort", - "Generic sort expected", - s, - getSourceName(), - getLine(), - getColumn()); - } else if (!JavaTypeToSortCondition.checkSortedSV((SchemaVariable)x)) { - semanticError("Expected schema variable of kind EXPRESSION or TYPE, " - + "but is " + x); - } else { - b.addVariableCondition(new JavaTypeToSortCondition((SchemaVariable)x, - (GenericSort)s, - elemSort)); - } - } -; - -varcond_fieldtype [TacletBuilder b] -: - FIELDTYPE - LPAREN - x=varId - COMMA - s=any_sortId_check[true] - RPAREN - { - if(!(s instanceof GenericSort)) { - throw new GenericSortException("sort", - "Generic sort expected", - s, - getSourceName(), - getLine(), - getColumn()); - } else if(!FieldTypeToSortCondition.checkSortedSV((SchemaVariable)x)) { - semanticError("Expected schema variable of kind EXPRESSION or TYPE, " - + "but is " + x); - } else { - b.addVariableCondition(new FieldTypeToSortCondition((SchemaVariable)x, - (GenericSort)s)); - } - } -; - -varcond_containsAssignment[TacletBuilder b, boolean negated] -: - CONTAINS_ASSIGNMENT LPAREN x=varId RPAREN - { - b.addVariableCondition(new ContainsAssignmentCondition((SchemaVariable)x, negated)); - } -; - -varcond_enumtype [TacletBuilder b, boolean negated] -: - ISENUMTYPE LPAREN tr = type_resolver RPAREN - { - b.addVariableCondition(new EnumTypeCondition(tr, negated)); - } -; - - -varcond_reference [TacletBuilder b, boolean isPrimitive] -@init{ - boolean nonNull = false; -} -: - ISREFERENCE (LBRACKET - id = simple_ident { - if ("non_null".equals(id)) { - nonNull = true; - } else { - semanticError(id + - " is not an allowed modifier for the \\isReference variable condition."); - } - } - RBRACKET)? - LPAREN - tr = type_resolver - RPAREN - { b.addVariableCondition(new TypeCondition(tr, !isPrimitive, nonNull)); } -; - -varcond_thisreference [TacletBuilder b, boolean negated] -@init { - x = null; - String id = null; - boolean nonNull = false; -} -: - ISTHISREFERENCE - LPAREN - x = varId - RPAREN - { b.addVariableCondition(new IsThisReference(x, negated)); } -; - - -varcond_staticmethod [TacletBuilder b, boolean negated] -: - STATICMETHODREFERENCE LPAREN x=varId COMMA y=varId COMMA z=varId RPAREN { - b.addVariableCondition(new StaticMethodCondition - (negated, (SchemaVariable)x, (SchemaVariable)y, (SchemaVariable)z)); - } -; - -varcond_referencearray [TacletBuilder b, boolean primitiveElementType] -: - ISREFERENCEARRAY LPAREN x=varId RPAREN { - b.addVariableCondition(new ArrayComponentTypeCondition( - (SchemaVariable)x, !primitiveElementType)); - } -; - -varcond_array [TacletBuilder b, boolean negated] -: - ISARRAY LPAREN x=varId RPAREN { - b.addVariableCondition(new ArrayTypeCondition( - (SchemaVariable)x, negated)); - } -; - -varcond_array_length [TacletBuilder b, boolean negated] -: - ISARRAYLENGTH LPAREN x=varId RPAREN { - b.addVariableCondition(new ArrayLengthCondition ( - (SchemaVariable)x, negated)); - } -; - - -varcond_abstractOrInterface [TacletBuilder b, boolean negated] -: - IS_ABSTRACT_OR_INTERFACE LPAREN tr=type_resolver RPAREN { - b.addVariableCondition(new AbstractOrInterfaceType(tr, negated)); - } -; - -varcond_enum_const [TacletBuilder b] -: - ENUM_CONST LPAREN x=varId RPAREN { - b.addVariableCondition(new EnumConstantCondition( - (SchemaVariable) x)); - } -; - -varcond_final [TacletBuilder b, boolean negated] -: - FINAL LPAREN x=varId RPAREN { - b.addVariableCondition(new FinalReferenceCondition( - (SchemaVariable) x, negated)); - } -; - -varcond_static [TacletBuilder b, boolean negated] -: - STATIC LPAREN x=varId RPAREN { - b.addVariableCondition(new StaticReferenceCondition( - (SchemaVariable) x, negated)); - } -; - -varcond_localvariable [TacletBuilder b, boolean negated] -: - ISLOCALVARIABLE - LPAREN x=varId RPAREN { - b.addVariableCondition(new LocalVariableCondition((SchemaVariable) x, negated)); - } -; - - -varcond_observer [TacletBuilder b] -: - ISOBSERVER - LPAREN obs=varId COMMA heap=varId RPAREN { - b.addVariableCondition(new ObserverCondition((TermSV)obs, - (TermSV)heap)); - } -; - - -varcond_different [TacletBuilder b] -: - DIFFERENT - LPAREN var1=varId COMMA var2=varId RPAREN { - b.addVariableCondition(new DifferentInstantiationCondition( - (SchemaVariable)var1, - (SchemaVariable)var2)); - } -; - - -varcond_metadisjoint [TacletBuilder b] -: - METADISJOINT - LPAREN var1=varId COMMA var2=varId RPAREN { - b.addVariableCondition(new MetaDisjointCondition( - (TermSV)var1, - (TermSV)var2)); - } -; - - - -varcond_equalUnique [TacletBuilder b] -: - EQUAL_UNIQUE - LPAREN t=varId COMMA t2=varId COMMA phi=varId RPAREN { - b.addVariableCondition(new EqualUniqueCondition((TermSV) t, - (TermSV) t2, - (FormulaSV) phi)); - } -; - - -varcond_freeLabelIn [TacletBuilder b, boolean negated] -: - - FREELABELIN - LPAREN l=varId COMMA statement=varId RPAREN { - b.addVariableCondition(new FreeLabelInVariableCondition((SchemaVariable) l, - (SchemaVariable) statement, negated )); - } -; - -varcond_constant [TacletBuilder b, boolean negated] -: - ISCONSTANT - LPAREN x=varId RPAREN { - if (x instanceof TermSV) { - b.addVariableCondition(new ConstantCondition((TermSV) x, negated )); - } else { - assert x instanceof FormulaSV; - b.addVariableCondition(new ConstantCondition((FormulaSV) x, negated )); - } - } -; - -varcond_label [TacletBuilder b, boolean negated] -: - HASLABEL - LPAREN l=varId COMMA name=simple_ident RPAREN { - b.addVariableCondition(new TermLabelCondition((TermLabelSV) l, name, negated )); - } -; - -varcond_static_field [TacletBuilder b, boolean negated] -: - ISSTATICFIELD - LPAREN field=varId RPAREN { - b.addVariableCondition(new StaticFieldCondition((SchemaVariable) field, negated )); - } -; - -varcond_subFormulas [TacletBuilder b, boolean negated] -: - HASSUBFORMULAS - LPAREN x=varId RPAREN { - b.addVariableCondition(new SubFormulaCondition((FormulaSV) x, negated )); - } -; - -goalspecs[TacletBuilder b, boolean ruleWithFind] : - CLOSEGOAL - | goalspecwithoption[b, ruleWithFind] ( SEMI goalspecwithoption[b, ruleWithFind] )* ; - -goalspecwithoption[TacletBuilder b, boolean ruleWithFind] -@init{ - soc = DefaultImmutableSet.nil(); -} : - (( soc = option_list[soc] - LBRACE - goalspec[b,soc,ruleWithFind] - RBRACE) - | - goalspec[b,null,ruleWithFind] - ) - ; - -option returns [Choice c=null] -: - cat=IDENT COLON choice_=IDENT - { - c = (Choice) choices().lookup(new Name(cat.getText()+":"+choice_.getText())); - if(c==null) { - throw new NotDeclException(input, "Option", choice_.getText()); - } - } - ; - -option_list[ImmutableSet soc] returns [ImmutableSet result = null] -: -LPAREN {result = soc; } - c = option {result = result.add(c);} - (COMMA c = option {result = result.add(c);})* -RPAREN -; - -goalspec[TacletBuilder b, ImmutableSet soc, boolean ruleWithFind] -@init{ - addSeq = Sequent.EMPTY_SEQUENT; - addRList = ImmutableSLList.nil(); - addpv = DefaultImmutableSet.nil(); -} - : - (name = string_literal COLON)? - ( ( rwObj = replacewith - (addSeq=add)? - (addRList=addrules)? - (addpv=addprogvar)? - ) - | ( addSeq=add (addRList=addrules)? ) - | ( addRList=addrules ) - ) - { - addGoalTemplate(b,name,rwObj,addSeq,addRList,addpv,soc); - } - - ; - -replacewith returns [Object _replace_with] -@after{ _replace_with = o; } -: - REPLACEWITH LPAREN o=termorseq RPAREN; - -add returns [Sequent _add] -@after{ _add = s; } -: - ADD LPAREN s=seq RPAREN; - -addrules returns [ImmutableList _add_rules] -@after{ _add_rules = lor; } -: - ADDRULES LPAREN lor=tacletlist RPAREN; - -addprogvar returns [ImmutableSet _add_prog_var] -@after{ _add_prog_var = pvs; } -: - ADDPROGVARS LPAREN pvs=pvset RPAREN; - -tacletlist returns [ImmutableList _taclet_list] -@init{ - lor = ImmutableSLList.nil(); -} -@after{ _taclet_list = lor; } - : - head=taclet[DefaultImmutableSet.nil(), false] - ( /*empty*/ | COMMA lor=tacletlist) { lor = lor.prepend(head); } - ; - -pvset returns [ImmutableSet _pv_set] -@init{ - pvs = DefaultImmutableSet.nil(); -} -@after{ _pv_set = pvs; } - : - pv=varId - ( /*empty*/ | COMMA pvs=pvset) { pvs = pvs.add - ((SchemaVariable)pv); }; - -rulesets returns [Vector rs = new Vector()] : - HEURISTICS LPAREN ruleset[rs] ( COMMA ruleset[rs] ) * RPAREN ; - -ruleset[Vector rs] -: - id=IDENT - { - RuleSet h = (RuleSet) ruleSets().lookup(new Name(id.getText())); - if (h == null) { - throw new NotDeclException(input, "ruleset", id.getText()); - } - rs.add(h); - } - ; - -metaId returns [TermTransformer v = null] -: - id = simple_ident { - v = AbstractTermTransformer.name2metaop(id); - if (v == null) - semanticError("Unknown metaoperator: "+id); - } -; - -metaTerm returns [Term result = null] -@init{ - LinkedList al = new LinkedList(); -} - : - (vf = metaId - ( LPAREN - t = term - { - al.add(t); - } - ( COMMA - t = term - { - al.add(t); - } - )* RPAREN )? - { - result = getTermFactory().createTerm(vf, (Term[])al.toArray(AN_ARRAY_OF_TERMS)); - } - ) - ; - catch [TermCreationException ex] { - raiseException - (new KeYSemanticException(input, getSourceName(), ex)); - } - -contracts -: - CONTRACTS - LBRACE { - switchToNormalMode(); - } - ( one_contract )* - RBRACE -; - -invariants -@init{ - Namespace orig = variables(); -} -: - INVARIANTS LPAREN selfVar=one_logic_bound_variable RPAREN - LBRACE { - switchToNormalMode(); - } - ( one_invariant[(ParsableVariable)selfVar] )* - RBRACE { - unbindVars(orig); - } -; - - -one_contract -@init{ - String displayName = null; - Vector rs = null; - NamespaceSet oldServicesNamespaces = null; -} -: - contractName = simple_ident LBRACE - { - //for program variable declarations - namespaces().setProgramVariables(new Namespace(programVariables())); - } - (prog_var_decls)? - fma = formula MODIFIES modifiesClause = term - { - DLSpecFactory dsf = new DLSpecFactory(getServices()); - try { - contracts = contracts.prepend(dsf.createDLOperationContract(contractName, - fma, - modifiesClause)); - } catch(ProofInputException e) { - semanticError(e.getMessage()); - } - } - RBRACE SEMI - { - //dump local program variable declarations - namespaces().setProgramVariables(programVariables().parent()); - } -; - -one_invariant[ParsableVariable selfVar] -: - invName = simple_ident LBRACE - fma = formula - (DISPLAYNAME displayName = string_literal)? - { - DLSpecFactory dsf = new DLSpecFactory(getServices()); - try { - invs = invs.add(dsf.createDLClassInvariant(invName, - displayName, - selfVar, - fma)); - } catch(ProofInputException e) { - semanticError(e.getMessage()); - } - } RBRACE SEMI -; - -problem returns [ Term _problem = null ] -@init { - boolean axiomMode = false; - int beginPos = 0; - choices=DefaultImmutableSet.nil(); - chooseContract = this.chooseContract; - proofObligation = this.proofObligation; -} -@after { - _problem = a; - this.chooseContract = chooseContract; - this.proofObligation = proofObligation; -} - : - - profile - - (pref = preferences) - { beginPos = input.index(); } - - string = bootClassPath - // the result is of no importance here (strange enough) - - stlist = classPaths - string = javaSource - - decls - { - if(parse_includes || onlyWith) return null; - switchToNormalMode(); - } - - // WATCHOUT: choices is always going to be an empty set here, - // isn't it? - ( contracts )* - ( invariants )* - ( ( RULES { axiomMode = false;} - | AXIOMS { axiomMode = true;} - ) - ( choices = option_list[choices] )? - LBRACE - { - switchToSchemaMode(); - } - ( - s = taclet[choices, axiomMode] SEMI - { - if (!skip_taclets) { - final RuleKey key = new RuleKey(s); - if (taclets.containsKey(key)) { - semanticError - ("Cannot add taclet \"" + s.name() + - "\" to rule base as a taclet with the same "+ - "name already exists."); - - } else { - taclets.put(key, s); - } - } - } - )* - RBRACE {choices=DefaultImmutableSet.nil();} - ) * - - { if(input.index() == 0) { - problemHeader = ""; - } else { - problemHeader = lexer.toString(beginPos, input.index()-1); - } } - - ((PROBLEM LBRACE - { switchToNormalMode(); } - a = formula - RBRACE) - | - CHOOSECONTRACT (chooseContract=string_literal SEMI)? - { - if(chooseContract == null) { - chooseContract = ""; - } - } - | - PROOFOBLIGATION (proofObligation=string_literal SEMI)? - { - if(proofObligation == null) { - proofObligation = ""; - } - } - )? - ; - -bootClassPath returns [String _boot_class_path = null] -@after{ _boot_class_path = id; } -: - ( BOOTCLASSPATH id=string_literal SEMI)? ; - -classPaths returns [ImmutableList ids = ImmutableSLList.nil()] -: - ( ( - CLASSPATH - s=string_literal - { - ids = ids.append(s); - } - (COMMA s=string_literal - { - ids = ids.append(s); - } - )* - - SEMI - ) - | - ( - NODEFAULTCLASSES { - throw new NoViableAltException("\\noDefaultClasses is no longer supported. Use \\bootclasspath. See docs/README.classpath", -1, -1, input); - } - SEMI - ) - )* - ; - -javaSource returns [String _java_source = null] -@after { _java_source = result; } -: - (JAVASOURCE - result = oneJavaSource - SEMI)? - ; - - -oneJavaSource returns [String s = null] -@init{ - StringBuffer b=new StringBuffer(); -} -: - ( l = string_literal { - b.append(l); - } - | - SLASH { b.append("/"); } - | - COLON {b.append(":");} - | - BACKSLASH {b.append("\\");} - )+ { - s = b.toString(); - } -; - - -profile: - (PROFILE profileName=string_literal { this.profileName = profileName; } SEMI)? -; - -preferences returns [String _preferences = null] -@after{ _preferences = s; }: - ( KEYSETTINGS LBRACE - (s = string_literal)? - RBRACE )? - ; - -// delivers: -proofScript returns [ Triple locatedString = null ] -: - PROOFSCRIPT ps = STRING_LITERAL - { int line = ps.getLine(); - // +1 for antlr starting at 0 - // +1 for removing the leading " - int col = ps.getCharPositionInLine() + 2; - String content = ps.getText().substring(1, ps.getText().length()-1); - locatedString = new Triple(content, line, col); - } - ; - -proof [IProofFileParser prl] : - ( PROOF proofBody[prl] )? - ; - - -proofBody [IProofFileParser prl] : - LBRACE - ( pseudosexpr[prl] )+ - RBRACE - ; - - -pseudosexpr [IProofFileParser prl] @init{ str = ""; } : - LPAREN (proofElementId=expreid - (str = string_literal )? - { prl.beginExpr(proofElementId,str); } - ( pseudosexpr[prl] )* ) ? - { prl.endExpr(proofElementId, stringLiteralLine); } - RPAREN - ; - -expreid returns [ IProofFileParser.ProofElementID proofElementId = null ] -: - id = simple_ident { - proofElementId = prooflabel2tag.get(id); - } -; diff --git a/key/key.core/src/main/antlr4/KeYLexer.g4 b/key/key.core/src/main/antlr4/KeYLexer.g4 index 2c13adc05a8..1bff17f7772 100644 --- a/key/key.core/src/main/antlr4/KeYLexer.g4 +++ b/key/key.core/src/main/antlr4/KeYLexer.g4 @@ -404,6 +404,9 @@ RGUILLEMETS WS: [ \t\n\r\u00a0]+ -> channel(HIDDEN); //U+00A0 = non breakable whitespace STRING_LITERAL:'"' ('\\' . | ~( '"' | '\\') )* '"' ; + +OPENTYPEPARAMS:'<' '['; +CLOSETYPEPARAMS:']' '>'; LESS: '<'; LESSEQUAL: '<' '=' | '\u2264'; LGUILLEMETS: '<' '<'; diff --git a/key/key.core/src/main/antlr4/KeYParser.g4 b/key/key.core/src/main/antlr4/KeYParser.g4 index 25fa181c83f..6bbc1de3107 100644 --- a/key/key.core/src/main/antlr4/KeYParser.g4 +++ b/key/key.core/src/main/antlr4/KeYParser.g4 @@ -109,14 +109,19 @@ one_sort_decl : doc=DOC_COMMENT? ( - GENERIC sortIds=simple_ident_dots_comma_list + GENERIC sortIds=sortList (ONEOF sortOneOf = oneof_sorts)? (EXTENDS sortExt = extends_sorts)? SEMI - | PROXY sortIds=simple_ident_dots_comma_list (EXTENDS sortExt=extends_sorts)? SEMI - | ABSTRACT? sortIds=simple_ident_dots_comma_list (EXTENDS sortExt=extends_sorts)? SEMI + | PROXY sortIds=sortList (EXTENDS sortExt=extends_sorts)? SEMI + | ABSTRACT? sortIds=sortList (EXTENDS sortExt=extends_sorts)? SEMI ) ; +sortList +: + sortId (COMMA sortId)* +; + simple_ident_dots : simple_ident (DOT simple_ident)* | NUM_LITERAL @@ -314,7 +319,21 @@ ruleset_decls sortId : - id=simple_ident_dots (EMPTYBRACKETS)* + id=simple_ident_dots (EMPTYBRACKETS)* formal_sort_parameters? +; + +formal_sort_variance +: + (PLUS | MINUS)? +; + +formal_sort_parameter: formal_sort_variance id=sortId; + +formal_sort_parameters +: + OPENTYPEPARAMS + formal_sort_parameter (COMMA formal_sort_parameter)* + CLOSETYPEPARAMS ; id_declaration diff --git a/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/AbstractSort.java b/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/AbstractSort.java index 37404b19a9c..b00d6964fcb 100644 --- a/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/AbstractSort.java +++ b/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/AbstractSort.java @@ -114,7 +114,7 @@ public final SortDependingFunction getExactInstanceofSymbol(TermServices service @Override - public final String toString() { + public String toString() { return name.toString(); } diff --git a/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSort.java b/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSort.java similarity index 98% rename from key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSort.java rename to key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSort.java index 20b5c95ae00..13e8f2f7617 100644 --- a/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSort.java +++ b/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSort.java @@ -8,6 +8,7 @@ import java.util.IdentityHashMap; import java.util.Map; import java.util.function.Function; +import java.util.stream.Collectors; /** * @@ -50,13 +51,12 @@ public class ParametricSort extends AbstractSort { - - public enum Variance { COVARIANT, CONTRAVARIANT, INVARIANT; } + private final ImmutableList parameters; private final ImmutableList covariances; diff --git a/key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java b/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java similarity index 100% rename from key/key.core/src/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java rename to key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java diff --git a/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ProgramSVSort.java b/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ProgramSVSort.java index b8e393b59c7..e6ac0c5dc25 100644 --- a/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ProgramSVSort.java +++ b/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ProgramSVSort.java @@ -13,19 +13,7 @@ package de.uka.ilkd.key.logic.sort; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.key_project.util.ExtList; -import org.key_project.util.collection.DefaultImmutableSet; - -import de.uka.ilkd.key.java.Expression; -import de.uka.ilkd.key.java.Label; -import de.uka.ilkd.key.java.NamedProgramElement; -import de.uka.ilkd.key.java.NonTerminalProgramElement; -import de.uka.ilkd.key.java.ProgramElement; -import de.uka.ilkd.key.java.Services; -import de.uka.ilkd.key.java.Statement; +import de.uka.ilkd.key.java.*; import de.uka.ilkd.key.java.abstraction.KeYJavaType; import de.uka.ilkd.key.java.abstraction.PrimitiveType; import de.uka.ilkd.key.java.abstraction.Type; @@ -36,31 +24,20 @@ import de.uka.ilkd.key.java.expression.ArrayInitializer; import de.uka.ilkd.key.java.expression.Literal; import de.uka.ilkd.key.java.expression.literal.StringLiteral; -import de.uka.ilkd.key.java.expression.operator.DLEmbeddedExpression; -import de.uka.ilkd.key.java.expression.operator.Instanceof; -import de.uka.ilkd.key.java.expression.operator.Intersect; -import de.uka.ilkd.key.java.expression.operator.Negative; -import de.uka.ilkd.key.java.expression.operator.New; -import de.uka.ilkd.key.java.expression.operator.NewArray; +import de.uka.ilkd.key.java.expression.operator.*; import de.uka.ilkd.key.java.expression.operator.adt.*; import de.uka.ilkd.key.java.reference.*; -import de.uka.ilkd.key.java.statement.Catch; -import de.uka.ilkd.key.java.statement.Ccatch; -import de.uka.ilkd.key.java.statement.For; -import de.uka.ilkd.key.java.statement.ForUpdates; -import de.uka.ilkd.key.java.statement.Guard; -import de.uka.ilkd.key.java.statement.LoopInit; -import de.uka.ilkd.key.java.statement.MethodBodyStatement; -import de.uka.ilkd.key.java.statement.Switch; -import de.uka.ilkd.key.logic.Name; -import de.uka.ilkd.key.logic.Named; -import de.uka.ilkd.key.logic.Namespace; -import de.uka.ilkd.key.logic.ProgramElementName; -import de.uka.ilkd.key.logic.Term; +import de.uka.ilkd.key.java.statement.*; +import de.uka.ilkd.key.logic.*; import de.uka.ilkd.key.logic.op.IProgramMethod; import de.uka.ilkd.key.logic.op.ProgramConstant; import de.uka.ilkd.key.logic.op.ProgramVariable; import de.uka.ilkd.key.logic.op.SchemaVariable; +import org.key_project.util.ExtList; +import org.key_project.util.collection.DefaultImmutableSet; + +import java.util.LinkedHashMap; +import java.util.Map; /** * Special "sorts" used for schema variables matching program constructs @@ -150,136 +127,136 @@ public abstract class ProgramSVSort extends AbstractSort { public static final ProgramSVSort JAVABOOLEANEXPRESSION = new ExpressionSpecialPrimitiveTypeSort( "JavaBooleanExpression", - new PrimitiveType[] { PrimitiveType.JAVA_BOOLEAN } - ); + new PrimitiveType[]{PrimitiveType.JAVA_BOOLEAN} + ); public static final ProgramSVSort SIMPLEJAVABYTEEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "JavaByteExpression", - new PrimitiveType[] { PrimitiveType.JAVA_BYTE } - ); + new PrimitiveType[]{PrimitiveType.JAVA_BYTE} + ); public static final ProgramSVSort SIMPLEJAVACHAREXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "JavaCharExpression", - new PrimitiveType[] { PrimitiveType.JAVA_CHAR } - ); + new PrimitiveType[]{PrimitiveType.JAVA_CHAR} + ); public static final ProgramSVSort SIMPLEJAVASHORTEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "JavaShortExpression", - new PrimitiveType[] { PrimitiveType.JAVA_SHORT } - ); + new PrimitiveType[]{PrimitiveType.JAVA_SHORT} + ); public static final ProgramSVSort SIMPLEJAVAINTEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "JavaIntExpression", - new PrimitiveType[] { PrimitiveType.JAVA_INT } - ); + new PrimitiveType[]{PrimitiveType.JAVA_INT} + ); public static final ProgramSVSort SIMPLEJAVALONGEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "JavaLongExpression", - new PrimitiveType[] { PrimitiveType.JAVA_LONG } - ); + new PrimitiveType[]{PrimitiveType.JAVA_LONG} + ); public static final ProgramSVSort SIMPLEJAVABYTESHORTEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "JavaByteShortExpression", - new PrimitiveType[] { - PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT + new PrimitiveType[]{ + PrimitiveType.JAVA_BYTE, + PrimitiveType.JAVA_SHORT } - ); + ); public static final ProgramSVSort SIMPLEJAVABYTESHORTINTEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "JavaByteShortIntExpression", - new PrimitiveType[] { - PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT + new PrimitiveType[]{ + PrimitiveType.JAVA_BYTE, + PrimitiveType.JAVA_SHORT, + PrimitiveType.JAVA_INT } - ); + ); public static final ProgramSVSort SIMPLEANYJAVATYPEEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "AnyJavaTypeExpression", - new PrimitiveType[] { - PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG + new PrimitiveType[]{ + PrimitiveType.JAVA_BYTE, + PrimitiveType.JAVA_SHORT, + PrimitiveType.JAVA_INT, + PrimitiveType.JAVA_LONG } - ); + ); public static final ProgramSVSort SIMPLEANYJAVANUMBERTYPEEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "AnyJavaNumberTypeExpression", - new PrimitiveType[] { - PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG, - PrimitiveType.JAVA_CHAR + new PrimitiveType[]{ + PrimitiveType.JAVA_BYTE, + PrimitiveType.JAVA_SHORT, + PrimitiveType.JAVA_INT, + PrimitiveType.JAVA_LONG, + PrimitiveType.JAVA_CHAR } - ); + ); public static final ProgramSVSort SIMPLEJAVASHORTINTLONGEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "JavaShortIntLongExpression", - new PrimitiveType[] { - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG + new PrimitiveType[]{ + PrimitiveType.JAVA_SHORT, + PrimitiveType.JAVA_INT, + PrimitiveType.JAVA_LONG } - ); + ); public static final ProgramSVSort SIMPLEJAVAINTLONGEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "JavaIntLongExpression", - new PrimitiveType[] { - PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG + new PrimitiveType[]{ + PrimitiveType.JAVA_INT, + PrimitiveType.JAVA_LONG } - ); + ); public static final ProgramSVSort SIMPLEJAVACHARBYTESHORTINTEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "JavaCharByteShortIntExpression", - new PrimitiveType[] { - PrimitiveType.JAVA_CHAR, - PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT + new PrimitiveType[]{ + PrimitiveType.JAVA_CHAR, + PrimitiveType.JAVA_BYTE, + PrimitiveType.JAVA_SHORT, + PrimitiveType.JAVA_INT } - ); + ); public static final ProgramSVSort SIMPLEJAVABIGINTEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "JavaBigintExpression", - new PrimitiveType[] { PrimitiveType.JAVA_BIGINT }); + new PrimitiveType[]{PrimitiveType.JAVA_BIGINT}); public static final ProgramSVSort SIMPLEANYNUMBERTYPEEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "AnyNumberTypeExpression", - new PrimitiveType[] { - PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG, - PrimitiveType.JAVA_CHAR, - PrimitiveType.JAVA_BIGINT + new PrimitiveType[]{ + PrimitiveType.JAVA_BYTE, + PrimitiveType.JAVA_SHORT, + PrimitiveType.JAVA_INT, + PrimitiveType.JAVA_LONG, + PrimitiveType.JAVA_CHAR, + PrimitiveType.JAVA_BIGINT } - ); + ); public static final ProgramSVSort SIMPLEJAVABOOLEANEXPRESSION = new SimpleExpressionSpecialPrimitiveTypeSort( "SimpleJavaBooleanExpression", - new PrimitiveType[] { PrimitiveType.JAVA_BOOLEAN }); + new PrimitiveType[]{PrimitiveType.JAVA_BOOLEAN}); public static final ProgramSVSort SIMPLESTRINGEXPRESSION = new SimpleExpressionStringSort("SimpleStringExpression"); @@ -288,7 +265,6 @@ public abstract class ProgramSVSort extends AbstractSort { new SimpleExpressionNonStringObjectSort("SimpleNonStringObjectExpression"); - //--------------- Specials that can be get rid of perhaps-------------- public static final ProgramSVSort LOOPINIT = new LoopInitSort(); @@ -317,12 +293,12 @@ public abstract class ProgramSVSort extends AbstractSort { public static final ProgramSVSort VARIABLEINIT = new ProgramSVSort(new Name("VariableInitializer")) { - @Override - public boolean canStandFor(ProgramElement pe, - Services services) { - return true; - } - }; + @Override + public boolean canStandFor(ProgramElement pe, + Services services) { + return true; + } + }; public static final ProgramSVSort NONSTRINGLITERAL = new NonStringLiteralSort(); public static final ProgramSVSort STRINGLITERAL = new StringLiteralSort(); @@ -353,11 +329,11 @@ public boolean canStandFor(ProgramElement check, protected abstract boolean canStandFor(ProgramElement check, - Services services); + Services services); public ProgramSVSort createInstance(String parameter) { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException(); } //-------------Now the inner classes representing the----------------------- @@ -395,7 +371,7 @@ protected boolean canStandFor(ProgramElement pe, } if (pe instanceof FieldReference) { - FieldReference fr = (FieldReference)pe; + FieldReference fr = (FieldReference) pe; // we allow only static field references with a // sequence of PVs or TypeRef @@ -436,7 +412,7 @@ protected boolean canStandFor(ProgramElement pe, Services services) { ProgramVariable accessedField = null; if (pe instanceof FieldReference) { - accessedField = ((FieldReference)pe).getProgramVariable(); + accessedField = ((FieldReference) pe).getProgramVariable(); } else if (pe instanceof ProgramVariable) { accessedField = (ProgramVariable) pe; } @@ -455,13 +431,13 @@ protected boolean canStandFor(ProgramElement pe, private static class StaticVariableSort extends LeftHandSideSort { public StaticVariableSort() { - super (new Name("StaticVariable")); + super(new Name("StaticVariable")); } @Override public boolean canStandFor(Term t) { return t.op() instanceof ProgramVariable - && ((ProgramVariable)t.op()).isStatic(); + && ((ProgramVariable) t.op()).isStatic(); } @Override @@ -469,7 +445,7 @@ protected boolean canStandFor(ProgramElement pe, Services services) { ProgramVariable accessedField = null; if (pe instanceof FieldReference) { - accessedField = ((FieldReference)pe).getProgramVariable(); + accessedField = ((FieldReference) pe).getProgramVariable(); } else if (pe instanceof ProgramVariable) { accessedField = (ProgramVariable) pe; } @@ -484,21 +460,21 @@ protected boolean canStandFor(ProgramElement pe, } private static class LocalVariableSort - extends LeftHandSideSort { + extends LeftHandSideSort { public LocalVariableSort() { - super (new Name("LocalVariable")); + super(new Name("LocalVariable")); } @Override public boolean canStandFor(Term t) { return t.op() instanceof ProgramVariable && - !((ProgramVariable)t.op()).isStatic(); + !((ProgramVariable) t.op()).isStatic(); } @Override protected boolean canStandFor(ProgramElement pe, - Services services) { + Services services) { return pe instanceof ProgramVariable && !((ProgramVariable) pe).isStatic(); } @@ -533,7 +509,7 @@ public boolean canStandFor(Term t) { protected boolean canStandFor(ProgramElement pe, Services services) { if (pe instanceof Negative) { - return ((Negative)pe).getChildAt(0) instanceof Literal; + return ((Negative) pe).getChildAt(0) instanceof Literal; } if (pe instanceof StringLiteral) { @@ -549,7 +525,7 @@ protected boolean canStandFor(ProgramElement pe, return VARIABLE.canStandFor(v, services); } - if(pe instanceof SetUnion + if (pe instanceof SetUnion || pe instanceof Singleton || pe instanceof Intersect || pe instanceof SetMinus @@ -724,7 +700,7 @@ protected boolean canStandFor(ProgramElement check, if (!(check instanceof New)) { return false; } - for (Expression arg : ((New)check).getArguments()) { + for (Expression arg : ((New) check).getArguments()) { if (NONSIMPLEEXPRESSION.canStandFor(arg, services)) { return false; } @@ -739,7 +715,7 @@ protected boolean canStandFor(ProgramElement check, * only on Class Instance Creation Expressions, new C(), where at * least one argument is a non-simple expression */ - private static class NonSimpleNewSVSort extends ProgramSVSort { + private static class NonSimpleNewSVSort extends ProgramSVSort { public NonSimpleNewSVSort() { super(new Name("NonSimpleInstanceCreation")); @@ -751,7 +727,7 @@ protected boolean canStandFor(ProgramElement check, if (!(check instanceof New)) { return false; } - for (Expression arg : ((New)check).getArguments()) { + for (Expression arg : ((New) check).getArguments()) { if (NONSIMPLEEXPRESSION.canStandFor(arg, services)) { return true; } @@ -764,7 +740,7 @@ protected boolean canStandFor(ProgramElement check, * This sort represents a type of program schema variables that match * only on Array Creation Expressions, new A[] */ - private static class NewArraySVSort extends ProgramSVSort{ + private static class NewArraySVSort extends ProgramSVSort { public NewArraySVSort() { super(new Name("ArrayCreation")); } @@ -818,7 +794,6 @@ public boolean canStandFor(Term t) { } - //----------- Types of Statement Program SVs ----------------------------- /** @@ -927,9 +902,9 @@ public NonSimpleMethodReferenceSort() { @Override protected boolean canStandFor(ProgramElement pe, - Services services) { + Services services) { if (pe instanceof MethodReference) { - MethodReference mr = (MethodReference)pe; + MethodReference mr = (MethodReference) pe; // FIX to bug #1223 (according to CS) /* if (mr.getReferencePrefix() instanceof SuperReference || @@ -946,7 +921,7 @@ protected boolean canStandFor(ProgramElement pe, } for (int i = 0; i < mr.getArguments().size(); i++) { if (NONSIMPLEEXPRESSION.canStandFor(mr.getArgumentAt(i), - services)) { + services)) { return true; } } @@ -966,14 +941,14 @@ public boolean canStandFor(Term t) { */ private static final class ProgramMethodSort extends ProgramSVSort { - public ProgramMethodSort() { - super(new Name("ProgramMethod")); - } + public ProgramMethodSort() { + super(new Name("ProgramMethod")); + } - @Override -protected boolean canStandFor(ProgramElement check, Services services) { - return (check instanceof IProgramMethod); - } + @Override + protected boolean canStandFor(ProgramElement check, Services services) { + return (check instanceof IProgramMethod); + } } //-----------Types-------------------------------------------------------- @@ -1016,14 +991,14 @@ protected boolean canStandFor(ProgramElement check, Services services) { if (!(check instanceof TypeReference)) { return false; } - if(((TypeReference)(check)).getKeYJavaType().getJavaType() + if (((TypeReference) (check)).getKeYJavaType().getJavaType() instanceof PrimitiveType) { return false; } - if(matchName != null) { + if (matchName != null) { return matchName.equals( - ((TypeReference)(check)).getKeYJavaType().getJavaType().getFullName() - ); + ((TypeReference) (check)).getKeYJavaType().getJavaType().getFullName() + ); } return true; } @@ -1056,7 +1031,7 @@ protected boolean canStandFor(ProgramElement check, Services services) { /** * This sort represents a type of program schema variables that match * on names of method references, i.e. the "m" of o.m(p1,pn). - * + *

    * It can also be made to match only specific method names * defined by the parameter "name". */ @@ -1133,7 +1108,7 @@ public boolean canStandFor(ProgramElement check, if (check instanceof ProgramVariable) { Namespace ns = services.getNamespaces().sorts(); Sort stringSort = ns.lookup(new Name("java.lang.String")); - return ((ProgramVariable)check).getKeYJavaType().getSort().equals(stringSort); + return ((ProgramVariable) check).getKeYJavaType().getSort().equals(stringSort); } return false; } @@ -1157,7 +1132,7 @@ public boolean canStandFor(ProgramElement check, return false; } if (check instanceof ProgramVariable) { - final Sort checkSort = ((ProgramVariable)check).sort(); + final Sort checkSort = ((ProgramVariable) check).sort(); Namespace ns = services.getNamespaces().sorts(); Sort stringSort = ns.lookup(new Name("java.lang.String")); return checkSort.extendsTrans(services.getJavaInfo().objectSort()) @@ -1270,6 +1245,7 @@ private static final class ForUpdatesSort extends ProgramSVSort { public ForUpdatesSort() { super(new Name("ForUpdates")); } + @Override protected boolean canStandFor(ProgramElement check, Services services) { return (check instanceof ForUpdates); @@ -1328,7 +1304,7 @@ protected boolean canStandFor(ProgramElement pe, return pe instanceof VariableDeclaration && ((VariableDeclaration) pe).getVariables().size() == 1 && ((VariableDeclaration) pe).getVariables(). - get(0).getDimensions() > 0; + get(0).getDimensions() > 0; } @@ -1350,7 +1326,7 @@ public ConstantProgramVariableSort(Name svSortName, boolean string) { @Override public boolean canStandFor(Term t) { - return t.op () instanceof ProgramConstant + return t.op() instanceof ProgramConstant && isString == t.sort().name().equals(type); } @@ -1369,7 +1345,7 @@ public ArrayLengthSort() { @Override protected boolean canStandFor(ProgramElement check, - Services services) { + Services services) { if (check instanceof ProgramVariable) { return check == services.getJavaInfo().getArrayLength(); } @@ -1401,7 +1377,7 @@ static boolean methodConstrReference(ProgramElement pe) { public ProgramElement getSVWithSort(ExtList l, Class alternative) { for (final Object o : l) { if (o instanceof SchemaVariable - && (((SchemaVariable)o).sort() == this)) { + && (((SchemaVariable) o).sort() == this)) { return (ProgramElement) o; } else if ((alternative.isInstance(o)) && (!(o instanceof SchemaVariable))) { @@ -1412,23 +1388,23 @@ public ProgramElement getSVWithSort(ExtList l, Class alternative) { } static KeYJavaType getKeYJavaType(ProgramElement pe, ExecutionContext ec, Services services) { - return services.getTypeConverter().getKeYJavaType((Expression)pe, ec); + return services.getTypeConverter().getKeYJavaType((Expression) pe, ec); } static boolean implicit(ProgramElement pe) { if (pe instanceof ProgramVariable) { - if (!((ProgramVariable)pe).isMember()) { + if (!((ProgramVariable) pe).isMember()) { return false; } } final String elemname; if (pe instanceof NamedProgramElement) { - elemname = ((NamedProgramElement)pe).getProgramElementName().getProgramName(); + elemname = ((NamedProgramElement) pe).getProgramElementName().getProgramName(); } else if (pe instanceof Named) { - final Name n = ((Named)pe).name(); + final Name n = ((Named) pe).name(); if (n instanceof ProgramElementName) { - elemname = ((ProgramElementName)n).getProgramName(); + elemname = ((ProgramElementName) n).getProgramName(); } else { elemname = n.toString(); } diff --git a/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/Sort.java b/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/Sort.java index d1973262534..3e7dfb310c1 100644 --- a/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/Sort.java +++ b/key/key.core/src/main/java/de/uka/ilkd/key/logic/sort/Sort.java @@ -27,28 +27,28 @@ public interface Sort extends Named { /** * Formulas are represented as "terms" of this sort. */ - public final Sort FORMULA = new SortImpl(new Name("Formula")); + Sort FORMULA = new SortImpl(new Name("Formula")); /** * Updates are represented as "terms" of this sort. */ - public final Sort UPDATE = new SortImpl(new Name("Update")); + Sort UPDATE = new SortImpl(new Name("Update")); /** * Term labels are represented as "terms" of this sort. */ - public final Sort TERMLABEL = new SortImpl(new Name("TermLabel")); + Sort TERMLABEL = new SortImpl(new Name("TermLabel")); /** * Any is a supersort of all sorts. */ - public final Sort ANY = new SortImpl(new Name("any")); + Sort ANY = new SortImpl(new Name("any")); /** * The base name for the cast function family. * Individual functions are called e.g. "C::cast" for sort C. */ - public final Name CAST_NAME = new Name("cast"); + Name CAST_NAME = new Name("cast"); /** * The base name for the instance (type membership) function family. diff --git a/key/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java b/key/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java index 5952cbd727d..cd0bb28f47c 100644 --- a/key/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java +++ b/key/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java @@ -8,14 +8,17 @@ import de.uka.ilkd.key.logic.sort.*; import de.uka.ilkd.key.nparser.KeYParser; import de.uka.ilkd.key.rule.RuleSet; +import de.uka.ilkd.key.util.Pair; import org.antlr.v4.runtime.Token; import org.key_project.util.collection.DefaultImmutableSet; +import org.key_project.util.collection.ImmutableList; +import org.key_project.util.collection.ImmutableSLList; import org.key_project.util.collection.ImmutableSet; +import org.key_project.util.java.StringUtil; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collector; +import java.util.stream.Collectors; /** * This visitor evaluates all basic (level 0) declarations. @@ -125,17 +128,33 @@ public Object visitSort_decls(KeYParser.Sort_declsContext ctx) { return null; } + @Override + public List>>> visitSortList(KeYParser.SortListContext ctx) { + List>>> seq = new ArrayList<>(); + for (KeYParser.SortIdContext context : ctx.sortId()) { + String sortName = context.simple_ident_dots().getText(); + String brackets = StringUtil.repeat("[]", context.EMPTYBRACKETS().size()); + List> typeParams = accept(context.formal_sort_parameters()); + seq.add(new Pair<>(sortName, typeParams != null ? typeParams : Collections.emptyList())); + } + return seq; + } + + @Override public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) { - List sortIds = accept(ctx.sortIds); + List>>> sortIds = accept(ctx.sortIds); List sortOneOf = accept(ctx.sortOneOf); List sortExt = accept(ctx.sortExt); boolean isGenericSort = ctx.GENERIC() != null; boolean isProxySort = ctx.PROXY() != null; boolean isAbstractSort = ctx.ABSTRACT() != null; List createdSorts = new LinkedList<>(); - for (String sortId : sortIds) { - Name sort_name = new Name(sortId); + assert sortIds != null; + + for (Pair>> sortId : sortIds) { + Name sortName = new Name(sortId.first); + boolean isParametricSort = !sortId.second.isEmpty(); ImmutableSet ext = sortExt == null ? ImmutableSet.empty() : @@ -145,23 +164,40 @@ public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) { DefaultImmutableSet.fromCollection(sortOneOf); // attention: no expand to java.lang here! - if (sorts().lookup(sort_name) == null) { + if (sorts().lookup(sortName) == null) { Sort s = null; - if (isGenericSort) { + if(isParametricSort) { + if(isGenericSort) { + semanticError(ctx, "Generic sorts are not allowed to have type parameters."); + } + + for (Pair param : sortId.second) { + if (!(param.second instanceof GenericSort)) { + semanticError(ctx, "Type parameters must be generic sorts. Given type '%s' is %s", + param.second.name(), param.second.getClass().getName()); + } + } + + ImmutableList> typeParams = + sortId.second.stream().map(it -> + new Pair<>((GenericSort) it.second, it.first)) + .collect(ImmutableSLList.toImmutableList()); + s = new ParametricSort(sortName, ext, isAbstractSort, typeParams); + }else if (isGenericSort) { int i; try { - s = new GenericSort(sort_name, ext, oneOf); + s = new GenericSort(sortName, ext, oneOf); } catch (GenericSupersortException e) { semanticError(ctx, "Illegal sort given"); } - } else if (new Name("any").equals(sort_name)) { + } else if (new Name("any").equals(sortName)) { s = Sort.ANY; } else { if (isProxySort) { - s = new ProxySort(sort_name, ext); + s = new ProxySort(sortName, ext); } else { - s = new SortImpl(sort_name, ext, isAbstractSort); + s = new SortImpl(sortName, ext, isAbstractSort); } } assert s != null; diff --git a/key/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java b/key/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java index 8db00479a62..edd7fe30eb7 100644 --- a/key/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java +++ b/key/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java @@ -9,13 +9,13 @@ import de.uka.ilkd.key.java.declaration.VariableDeclaration; import de.uka.ilkd.key.logic.*; import de.uka.ilkd.key.logic.op.*; -import de.uka.ilkd.key.logic.sort.ArraySort; -import de.uka.ilkd.key.logic.sort.NullSort; -import de.uka.ilkd.key.logic.sort.Sort; +import de.uka.ilkd.key.logic.sort.*; import de.uka.ilkd.key.nparser.KeYParser; import de.uka.ilkd.key.rule.RuleSet; import de.uka.ilkd.key.util.Pair; import org.antlr.v4.runtime.ParserRuleContext; +import org.key_project.util.collection.ImmutableList; +import org.key_project.util.collection.ImmutableSLList; import java.text.MessageFormat; import java.util.ArrayList; @@ -350,17 +350,67 @@ public Sort visitSortId(KeYParser.SortIdContext ctx) { t = PrimitiveType.JAVA_BIGINT; primitiveName = PrimitiveType.JAVA_BIGINT.getName(); } + + if (t != null && !ctx.formal_sort_parameters().formal_sort_parameter().isEmpty()) { + semanticError(ctx, "Combination of primitive type and type parameters."); + } + Sort s = lookupSort(primitiveName); if (s == null) { semanticError(ctx, "Could not find sort: %s", ctx.getText()); } + //parametric sorts should be instantiated + if (ctx.formal_sort_parameters() != null) { + if (s instanceof ParametricSort) { + ParametricSort ps = (ParametricSort) s; + ImmutableList parameters = getSorts(ctx.formal_sort_parameters()); + s = ParametricSortInstance.get(ps, parameters); + } else { + semanticError(ctx, "Not a polymorphic sort: %s", s); + } + } + + if (!ctx.EMPTYBRACKETS().isEmpty()) { return toArraySort(new Pair<>(s, t), ctx.EMPTYBRACKETS().size()); } return s; } + private ImmutableList getSorts(KeYParser.Formal_sort_parametersContext ctx) { + List> seq = accept(ctx); + assert seq != null; + for (Pair p : seq) { + if (p.first != ParametricSort.Variance.INVARIANT) { + addWarning(ctx, "Variance is ignored"); + } + } + return seq.stream().map(it -> it.second).collect(ImmutableSLList.toImmutableList()); + } + + @Override + public List> visitFormal_sort_parameters(KeYParser.Formal_sort_parametersContext ctx) { + return mapOf(ctx.formal_sort_parameter()); + } + + @Override + public Pair visitFormal_sort_parameter(KeYParser.Formal_sort_parameterContext ctx) { + Sort sort = sorts().lookup(ctx.id.getText()); + if (sort == null) { + semanticError(ctx.id, "Could not find sort '%s'. It was not previously defined.", ctx.id.getText()); + } + return new Pair<>(accept(ctx.formal_sort_variance()), sort); + } + + @Override + public Object visitFormal_sort_variance(KeYParser.Formal_sort_varianceContext ctx) { + if (ctx.PLUS() != null) return ParametricSort.Variance.COVARIANT; + if (ctx.MINUS() != null) return ParametricSort.Variance.CONTRAVARIANT; + return ParametricSort.Variance.INVARIANT; + } + + @Override public KeYJavaType visitKeyjavatype(KeYParser.KeyjavatypeContext ctx) { boolean array = false; diff --git a/key/key.core/src/main/java/de/uka/ilkd/key/proof/io/IProofFileParser.java b/key/key.core/src/main/java/de/uka/ilkd/key/proof/io/IProofFileParser.java index 4ca1df48454..23d0fac85d8 100644 --- a/key/key.core/src/main/java/de/uka/ilkd/key/proof/io/IProofFileParser.java +++ b/key/key.core/src/main/java/de/uka/ilkd/key/proof/io/IProofFileParser.java @@ -15,11 +15,8 @@ import java.util.List; -import de.uka.ilkd.key.logic.sort.Sort; -import de.uka.ilkd.key.parser.KeYParser; - /** - * Defines the required which a {@link KeYParser} needs to parse a *.proof file + * Defines the required which a needs to parse a *.proof file * and to apply the rules again. * * @author Martin Hentschel @@ -29,7 +26,7 @@ public interface IProofFileParser { /** * Enumeration of the different syntactic elements occurring in a saved * proof tree representation. - * + *

    * TODO: ProofSaver should not hardcode ids Enum names should be used * instead of rawnames (old proofs should be converted) * diff --git a/key/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java b/key/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java index c1a8e4d90e5..a9318ea7421 100644 --- a/key/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java +++ b/key/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java @@ -13,13 +13,6 @@ package de.uka.ilkd.key.parser; -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.antlr.runtime.RecognitionException; -import org.key_project.util.collection.DefaultImmutableSet; -import org.key_project.util.collection.ImmutableSet; - import de.uka.ilkd.key.java.Recoder2KeY; import de.uka.ilkd.key.java.Services; import de.uka.ilkd.key.logic.Name; @@ -27,11 +20,9 @@ import de.uka.ilkd.key.logic.Namespace; import de.uka.ilkd.key.logic.NamespaceSet; import de.uka.ilkd.key.logic.op.SchemaVariable; +import de.uka.ilkd.key.logic.op.SortDependingFunction; import de.uka.ilkd.key.logic.op.VariableSV; -import de.uka.ilkd.key.logic.sort.ArraySort; -import de.uka.ilkd.key.logic.sort.GenericSort; -import de.uka.ilkd.key.logic.sort.ProxySort; -import de.uka.ilkd.key.logic.sort.Sort; +import de.uka.ilkd.key.logic.sort.*; import de.uka.ilkd.key.nparser.KeyIO; import de.uka.ilkd.key.nparser.NamespaceBuilder; import de.uka.ilkd.key.proof.init.AbstractProfile; @@ -41,7 +32,9 @@ import org.junit.Test; import org.key_project.util.collection.DefaultImmutableSet; import org.key_project.util.collection.ImmutableSet; +import org.key_project.util.collection.Immutables; +import static de.uka.ilkd.key.logic.sort.ParametricSort.Variance.*; import static org.junit.Assert.*; @@ -96,6 +89,87 @@ public void testSortDecl() { nss.sorts().lookup(new Name("list")).name()); } + @Test + public void testSortDeclFail() { + try { + final String s = "\\sorts { X; X; }"; + evaluateDeclarations(s); + fail("Parsing " + s + " should have failed du to double definition."); + } catch (Exception ex) { + assertTrue(ex.getMessage().contains("already declared")); + } + + } + + @Test + public void testParametericSortDecl() { + evaluateDeclarations("\\sorts { \\generic E, F, G; " + + "coll<[E]>; list<[+E]> \\extends coll<[E]>;" + + "var<[-E, +F, G]>; }"); + + Sort e = nss.sorts().lookup("E"); + ParametricSort list = (ParametricSort) nss.sorts().lookup("list"); + ParametricSort coll = (ParametricSort) nss.sorts().lookup("coll"); + ParametricSort var = (ParametricSort) nss.sorts().lookup("var"); + + assertTrue(e instanceof GenericSort); + assertTrue(coll instanceof ParametricSort); + assertTrue(list instanceof ParametricSort); + + assertEquals( + Immutables.listOf(CONTRAVARIANT, COVARIANT, INVARIANT), + var.getCovariances()); + + assertEquals("{coll<[E]>}", list.extendsSorts().toString()); + + assertEquals("{any}", coll.extendsSorts().toString()); + } + + @Test + public void testParametericSortDeclFails0() { + try { + String s = "\\sorts { parametric<[E]>; }"; + evaluateDeclarations(s); + fail("Parsing " + s + " should have failed"); + } catch (Exception ex) { + assertTrue(ex.getMessage().contains("Formal type parameters must be (already declared) generic sorts")); + } + + } + + @Test + public void testParametericSortDeclFails1() { + try { + String s = "\\sorts { \\generic E; doubled<[E,E]>; }"; + evaluateDeclarations(s); + fail("Parsing " + s + " should have failed"); + } catch (Exception ex) { + assertTrue(ex.getMessage().contains("unique")); + } + } + + @Test + public void testParametericSortDeclFails2() { + try { + String s = "\\sorts { parametric<[int]>; }"; + evaluateDeclarations(s); + fail("Parsing " + s + " should have failed"); + } catch (Exception ex) { + assertTrue(ex.getMessage().contains("Formal type parameters must be (already declared) generic sorts")); + } + } + + @Test + public void testParametericSortDeclFails3() { + try { + String s = "\\sorts { \\generic E; int<[E]>; }"; + evaluateDeclarations(s); + fail("Parsing " + s + " should have failed"); + } catch (Exception ex) { + assertTrue(ex.getMessage().contains("already declared")); + } + } + private GenericSort checkGenericSort(Named name, ImmutableSet pExt, ImmutableSet pOneOf) { assertNotNull("Generic sort does not exist", name); @@ -220,7 +294,8 @@ public void testGenericSortDecl4() { } - @Test@Ignore + @Test + @Ignore //weigl: this test case seems not suitable anymore. // old parser throw an error message if generic sorts were used in normal mode. public void testGenericSortDecl5() { @@ -302,6 +377,28 @@ public void testArrayDecl() { cloneableSort.extendsSorts().contains(objectSort)); } + @Test + public void testFunctionPolymorphicDecl() { + evaluateDeclarations("\\sorts { \\generic elem; list<[+elem]>; }\n" + + "\\functions {\n" + + " elem elem::head(list<[elem]>);\n" + + " list<[elem]> elem::tail(list<[elem]>);\n" + + " list<[elem]> elem::nil;\n" + + " list<[elem]> elem::cons(elem, list<[elem]>);\n" + + "}\n"); + + + SortDependingFunction head = (SortDependingFunction) nss.functions().lookup("any::head"); + SortDependingFunction inthead = head.getInstanceFor(nss.sorts().lookup("int"), serv); + assertEquals("int", inthead.sort().toString()); + assertEquals("[list<[int]>]", inthead.argSorts().toString()); + + SortDependingFunction cons = (SortDependingFunction) nss.functions().lookup("any::cons"); + SortDependingFunction intcons = cons.getInstanceFor(nss.sorts().lookup("int"), serv); + assertEquals("list<[int]>", intcons.sort().toString()); + assertEquals("[int,list<[int]>]", intcons.argSorts().toString()); + } + @Test public void testFunctionDecl() { evaluateDeclarations("\\sorts { elem; list; }\n" + diff --git a/key/key.util.test/src/org/key_project/util/suite/AllCollectionTests.java b/key/key.util.test/src/org/key_project/util/suite/AllCollectionTests.java deleted file mode 100644 index 023425c8187..00000000000 --- a/key/key.util.test/src/org/key_project/util/suite/AllCollectionTests.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2014 Karlsruhe Institute of Technology, Germany - * Technical University Darmstadt, Germany - * Chalmers University of Technology, Sweden - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Technical University Darmstadt - initial API and implementation and/or initial documentation - *******************************************************************************/ - -package org.key_project.util.suite; - -import org.junit.runner.RunWith; -import org.junit.runners.Suite; -import org.key_project.util.collection.TestImmutables; -import org.key_project.util.collection.TestSLList; -import org.key_project.util.testcase.collection.TestLeftistHeapOfInteger; -import org.key_project.util.testcase.collection.TestMapAsListFromIntegerToString; -import org.key_project.util.testcase.collection.TestSLListOfString; -import org.key_project.util.testcase.collection.TestSetAsListOfString; - -/** - * Run all contained JUnit 4 test cases. - * @author Martin Hentschel - */ -@RunWith(Suite.class) -@Suite.SuiteClasses({ - TestLeftistHeapOfInteger.class, - TestMapAsListFromIntegerToString.class, - TestSetAsListOfString.class, - TestSLListOfString.class, - TestSLList.class, - TestImmutables.class -}) -public class AllCollectionTests { -} \ No newline at end of file diff --git a/key/key.util/src/main/java/org/key_project/util/collection/DefaultImmutableSet.java b/key/key.util/src/main/java/org/key_project/util/collection/DefaultImmutableSet.java index ad3acf1cfc8..01d811589b6 100644 --- a/key/key.util/src/main/java/org/key_project/util/collection/DefaultImmutableSet.java +++ b/key/key.util/src/main/java/org/key_project/util/collection/DefaultImmutableSet.java @@ -18,6 +18,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -89,9 +90,7 @@ private void complainAboutSize() { // } } - /** - * adds an element - * + /** adds an element * @param element of type that has to be added to this set */ @Override @@ -103,9 +102,7 @@ public ImmutableSet add(T element) { return new DefaultImmutableSet(elementList.prepend(element)); } - /** - * adds an element, barfs if the element is already present - * + /** adds an element, barfs if the element is already present * @param element of type that has to be added to this set * @throws NotUniqueException if the element is already present */ @@ -217,6 +214,11 @@ public boolean exists(Predicate predicate) { return elementList.exists(predicate); } + @Override + public ImmutableSet map(Function f) { + return new DefaultImmutableSet<>(elementList.map(f)); + } + /** @return int the cardinality of the set */ @Override public int size() { diff --git a/key/key.util/src/main/java/org/key_project/util/collection/ImmutableList.java b/key/key.util/src/main/java/org/key_project/util/collection/ImmutableList.java index e9600cce3d3..e3cde4d4721 100644 --- a/key/key.util/src/main/java/org/key_project/util/collection/ImmutableList.java +++ b/key/key.util/src/main/java/org/key_project/util/collection/ImmutableList.java @@ -14,6 +14,7 @@ package org.key_project.util.collection; import java.util.*; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collector; import java.util.stream.Stream; diff --git a/key/key.util/src/main/java/org/key_project/util/collection/ImmutableSet.java b/key/key.util/src/main/java/org/key_project/util/collection/ImmutableSet.java index d7e078c3490..13207682786 100644 --- a/key/key.util/src/main/java/org/key_project/util/collection/ImmutableSet.java +++ b/key/key.util/src/main/java/org/key_project/util/collection/ImmutableSet.java @@ -16,6 +16,7 @@ import javax.annotation.Nonnull; import java.util.*; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collector; import java.util.stream.Collector.Characteristics; @@ -109,6 +110,18 @@ static ImmutableSet fromCollection(@Nonnull Collection seq) { */ boolean exists(Predicate predicate); + /** + * Apply a function f to the elements of the set. + * If the set has an order: + * The result contains the elements in the same order, but after the + * application of f. + * + * @param f the function to apply to the elements + * @param result type of the mapping + * @return a new immutable list instance, not null. + */ + ImmutableSet map(Function f); + /** @return true iff obj in set */ boolean contains(T obj); diff --git a/key/key.util/src/org/key_project/util/collection/DefaultImmutableSet.java b/key/key.util/src/org/key_project/util/collection/DefaultImmutableSet.java deleted file mode 100644 index 65300b3814c..00000000000 --- a/key/key.util/src/org/key_project/util/collection/DefaultImmutableSet.java +++ /dev/null @@ -1,398 +0,0 @@ -// This file is part of KeY - Integrated Deductive Software Design -// -// Copyright (C) 2001-2011 Universitaet Karlsruhe (TH), Germany -// Universitaet Koblenz-Landau, Germany -// Chalmers University of Technology, Sweden -// Copyright (C) 2011-2014 Karlsruhe Institute of Technology, Germany -// Technical University Darmstadt, Germany -// Chalmers University of Technology, Sweden -// -// The KeY system is protected by the GNU General -// Public License. See LICENSE.TXT for details. -// - -package org.key_project.util.collection; - -import java.util.Iterator; -import java.util.Set; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - - -/** - * implementation of a persistent set using the SLListOf implementation - * with all its implications (means e.g. O(n) for adding an - * element and so on. - */ -public class DefaultImmutableSet implements ImmutableSet { - - /** - * - */ - private static final long serialVersionUID = -5000602574000532257L; - - /** - * Constant defining the set size at which an optimized union operation will be executed. - */ - public static final int UNION_OPTIMIZATION_SIZE = 100; - - /** list containing the elements */ - private final ImmutableList elementList; - - /** the empty set */ - @SuppressWarnings("unchecked") - public static final DefaultImmutableSet nil() { - return (DefaultImmutableSet) NILSet.NIL; - } - - - protected DefaultImmutableSet() { - elementList = ImmutableSLList.nil(); - } - - /** creates new set with one element - * @param element of type the new Set contains - */ - protected DefaultImmutableSet(T element) { - elementList = (ImmutableList) (ImmutableSLList.nil()).prepend(element); - } - - /** creates new set containg all elements from the elementList - * PRECONDITION: elementList has no duplicates - * @param elementList IList contains all elements of the new Set - */ - private DefaultImmutableSet(ImmutableList elementList) { - this.elementList=elementList; - } - - -// private static HashSet previousComplains = new HashSet<>(); - private void complainAboutSize() { -// // Immutable linear sets are very expensive with O(n) addition -// // and O(n) lookup. -// // To create a list with N entries O(N^2) comparisons need to be made -// // Better restrict this class to very small instances. -// // The following helps detecting "bad" usages. (MU 2016) -// if(elementList.size() > 20) { -// StackTraceElement[] st = new Throwable().getStackTrace(); -// String complain = "TOO LARGE: " + st[2]; -// if(previousComplains.add(complain)) { -// System.err.println(complain); -//// for (int i = 2; i < 6; i++) { -//// System.err.println(st[i]); -//// } -// } -// } - } - - /** adds an element - * @param element of type that has to be added to this set - */ - public ImmutableSet add(T element) { - complainAboutSize(); - if (elementList.contains(element)) { - return this; - } - return new DefaultImmutableSet(elementList.prepend(element)); - } - - /** adds an element, barfs if the element is already present - * @param element of type that has to be added to this set - * @throws org.key_project.utils.collection.NotUniqueException if the element is already present - */ - public ImmutableSet addUnique(T element) throws NotUniqueException { - complainAboutSize(); - if (elementList.contains(element)) { - throw new NotUniqueException(element); - } else { - return new DefaultImmutableSet(elementList.prepend(element)); - } - } - - /** @return union of this set with set */ - public ImmutableSet union(ImmutableSet set) { - if(set instanceof DefaultImmutableSet && size() * set.size() > UNION_OPTIMIZATION_SIZE) { - return newUnion((DefaultImmutableSet) set); - } - - return originalUnion(set); - } - - - private DefaultImmutableSet newUnion(DefaultImmutableSet set) { - ImmutableList otherList = set.elementList; - ImmutableList clean = Immutables.concatDuplicateFreeLists(this.elementList, otherList); - return new DefaultImmutableSet(clean); - } - - private DefaultImmutableSet originalUnion(ImmutableSet set) { - if (set.isEmpty()) { - return this; - } - - ImmutableList unionElements = this.elementList; - for (T otherEl : set) { - if (!contains(otherEl)) { - unionElements = unionElements.prepend(otherEl); - } - } - return new DefaultImmutableSet(unionElements); - } - - /** @return intersection of this set with set */ - public ImmutableSet intersect(ImmutableSet set) { - complainAboutSize(); - if (set.isEmpty()) { - return set; - } - - ImmutableList intersectElements = this.elementList; - for (T el : intersectElements) { - if (!set.contains(el)) { - intersectElements = intersectElements.removeFirst(el); - } - } - if(intersectElements.isEmpty()) { - return DefaultImmutableSet.nil(); - } else { - return new DefaultImmutableSet(intersectElements); - } - } - - /** @return Iterator of the set */ - public Iterator iterator() { - return elementList.iterator(); - } - - @Override - public Stream stream() { - return StreamSupport.stream(spliterator(), false); - } - - /** @return true iff obj in set */ - public boolean contains(T obj) { - complainAboutSize(); - return elementList.contains(obj); - } - - /** @return true iff this set is subset of set s */ - public boolean subset(ImmutableSet s) { - if (size() > s.size()) { - return false; - } else { - for (T el: this) { - if (!s.contains(el)) { - return false; - } - } - } - return true; - } - - /** - * return true if predicate is fullfilled for at least one element - * @param predicate the predicate - * @return true if predicate is fullfilled for at least one element - */ - public boolean exists(Predicate predicate) { - return elementList.exists(predicate); - } - - @Override - public ImmutableSet map(Function f) { - return new DefaultImmutableSet(elementList.map(f)); - } - - /** @return int the cardinality of the set */ - public int size() { - return elementList.size(); - } - - /** @return true iff the set is empty */ - public boolean isEmpty() { - return false; - } - - public ImmutableSet remove(T element) { - final ImmutableList list = elementList.removeFirst(element); - return (ImmutableSet) (list.isEmpty() ? DefaultImmutableSet.nil() : new DefaultImmutableSet(list)); - } - - - /** @return true iff the this set is subset of o and vice versa. - */ - public boolean equals(Object obj) { - if (obj==this) { - return true; - } - if (!(obj instanceof ImmutableSet)) { - return false; - } - @SuppressWarnings("unchecked") - ImmutableSet o=(ImmutableSet) obj; - return (o.subset(this) && this.subset(o)); - } - - /** - * Convert the set to a Java array (O(n)) - */ - public S[] toArray(S[] array) { - return elementList.toArray(array); - } - - public int hashCode() { - int hashCode = 0; - ImmutableList crt = this.elementList; - - while (!crt.isEmpty()) { - final T element = crt.head(); - hashCode = (element == null ? 0 : element.hashCode()) + hashCode; - crt = crt.tail(); - } - return hashCode; - } - - /** - * Get the underlying immutable list. - * - * @return an immutable list with the same iteration order as this set. - */ - public ImmutableList toImmutableList() { - return elementList; - } - - /** - * Create an immutable set from an immutable list. - * - * @param list - * a non-null immutable list - * @return a fresh immutable set with the same iteration order. - */ - public static ImmutableSet fromImmutableList(ImmutableList list) { - if(list.isEmpty()) { - return nil(); - } else { - return new DefaultImmutableSet(Immutables.removeDuplicates(list)); - } - } - - /** - * Create an immutable set from a mutable set - * - * @param set - * a non-null mutable set - * @return a fresh immutable set with all the elements in set - */ - public static ImmutableSet fromSet(Set set) { - if(set.isEmpty()) { - return nil(); - } else { - ImmutableList backerList = ImmutableSLList.nil(); - for (T element : set) { - backerList = backerList.prepend(element); - } - return new DefaultImmutableSet(backerList); - } - } - - public String toString() { - Iterator it=this.iterator(); - StringBuffer str=new StringBuffer("{"); - while (it.hasNext()) { - str.append(it.next()); - if (it.hasNext()) { - str.append(","); - } - } - str.append("}"); - return str.toString(); - } - - /** represents the empty set for elements of type */ - private static class NILSet extends DefaultImmutableSet { - - /** - * - */ - private static final long serialVersionUID = -8055357307337694419L; - static final NILSet NIL = new NILSet<>(); - - private NILSet() {} - - /** the NIL list is a singleton. Deserialization builds - * a new NIL object that has to be replaced by the singleton. - */ - private Object readResolve() - throws java.io.ObjectStreamException { - return NIL; - } - - - /** adds an element */ - public ImmutableSet add(T element) { - return new DefaultImmutableSet(element); - } - - /** adds an element (which is unique, since the set was empty) */ - public ImmutableSet addUnique(T element) { - return new DefaultImmutableSet(element); - } - - /** @return union of this set with set */ - public ImmutableSet union(ImmutableSet set) { - return set; - } - - /** @return true iff obj in set */ - public boolean contains(T obj) { - return false; - } - - /** @return Iterator of the set */ - public Iterator iterator() { - return ImmutableSLList.nil().iterator(); - } - - /** @return true iff this set is subset of set s */ - public boolean subset(ImmutableSet s) { - return true; - } - - /** @return int the cardinality of the set */ - public int size() { - return 0; - } - - /** @return true iff the set is empty */ - public boolean isEmpty() { - return true; - } - - /** @return true iff the this set is subset of o and vice versa. - */ - public boolean equals(Object o) { - return o instanceof NILSet; - } - - public int hashCode() { - return 23456; - } - - public String toString() { - return "{}"; - } - - public ImmutableSet remove(T element) { - return this; - } - - public S[] toArray(S[] array) { - return array; - } - - - } - -} diff --git a/key/key.util/src/org/key_project/util/collection/ImmutableSet.java b/key/key.util/src/org/key_project/util/collection/ImmutableSet.java deleted file mode 100644 index d1025d63a77..00000000000 --- a/key/key.util/src/org/key_project/util/collection/ImmutableSet.java +++ /dev/null @@ -1,97 +0,0 @@ -// This file is part of KeY - Integrated Deductive Software Design -// -// Copyright (C) 2001-2011 Universitaet Karlsruhe (TH), Germany -// Universitaet Koblenz-Landau, Germany -// Chalmers University of Technology, Sweden -// Copyright (C) 2011-2014 Karlsruhe Institute of Technology, Germany -// Technical University Darmstadt, Germany -// Chalmers University of Technology, Sweden -// -// The KeY system is protected by the GNU General -// Public License. See LICENSE.TXT for details. -// - -package org.key_project.util.collection; - -import java.util.Iterator; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.stream.Stream; - -/** interface implemented by non-destructive Sets. - * CONVENTION: Each SetOf implementation has to offer a public static - * final variable .nil() - */ - -public interface ImmutableSet extends Iterable, java.io.Serializable { - - /** adds an element */ - ImmutableSet add(T element); - - /** @return union of this set with set */ - ImmutableSet union(ImmutableSet set); - - /** @return intersection of this set with set */ - ImmutableSet intersect(ImmutableSet set); - - /** @return Iterator of the set */ - @Override - Iterator iterator(); - - /** @return Stream of the set */ - Stream stream(); - - /** - * return true if predicate is fullfilled for at least one element - * @param predicate the predicate - * @return true if predicate is fullfilled for at least one element - */ - boolean exists(Predicate predicate); - - /** - * Apply a function f to the elements of the set. - * If the set has an order: - * The result contains the elements in the same order, but after the - * application of f. - * - * @param f the function to apply to the elements - * @param result type of the mapping - * @return a new immutable list instance, not null. - */ - ImmutableSet map(Function f); - - /** @return true iff obj in set */ - boolean contains(T obj); - - /** @return true iff this set is subset of set s */ - boolean subset(ImmutableSet s); - - /** @return int the cardinality of the set */ - int size(); - - /** @return true iff the set is empty */ - boolean isEmpty(); - - /** @return set without element */ - ImmutableSet remove(T element); - - /** @return true iff the this set is subset of o and vice versa. - */ - @Override - public boolean equals(Object o); - - @Override - public int hashCode(); - - /** adds an element, barfs if the element is already present - * @param element of type that has to be added to this set - * @throws org.key_project.utils.collection.NotUniqueException if the element is already present - */ - ImmutableSet addUnique(T element) throws NotUniqueException; - - /** - * Convert the set to a Java array - */ - S[] toArray(S[] array); - -} From 50b18bbf26ca95247738141c90f0ca785df9df36 Mon Sep 17 00:00:00 2001 From: Alexander Weigl Date: Fri, 30 Jul 2021 12:04:37 +0200 Subject: [PATCH 06/13] fix NPE --- .../java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/key/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java b/key/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java index edd7fe30eb7..971389c1358 100644 --- a/key/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java +++ b/key/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java @@ -351,7 +351,9 @@ public Sort visitSortId(KeYParser.SortIdContext ctx) { primitiveName = PrimitiveType.JAVA_BIGINT.getName(); } - if (t != null && !ctx.formal_sort_parameters().formal_sort_parameter().isEmpty()) { + if (t != null + && ctx.formal_sort_parameters() != null + && !ctx.formal_sort_parameters().formal_sort_parameter().isEmpty()) { semanticError(ctx, "Combination of primitive type and type parameters."); } From 623b9417543ee9dad3ff2b3c5e27cdcdbe81851d Mon Sep 17 00:00:00 2001 From: Alexander Weigl Date: Fri, 12 Jan 2024 11:53:35 +0100 Subject: [PATCH 07/13] fixing merge errors --- .../ilkd/key/logic/sort/ParametricSort.java | 7 +- .../logic/sort/ParametricSortInstance.java | 17 +- .../nparser/builder/DeclarationBuilder.java | 39 +- .../key/nparser/builder/DefaultBuilder.java | 7 +- .../uka/ilkd/key/parser/TestDeclParser.java | 203 ++- .../util/collection/ImmutableList.java | 10 + .../util/collection/ImmutableSLList.java | 20 + .../util/collection/Immutables.java | 61 +- .../util/collection/TestSLList.java | 0 .../uka/ilkd/key/parser/TestDeclParser.java | 587 ------- .../ilkd/key/logic/sort/ProgramSVSort.java | 1367 ----------------- 11 files changed, 224 insertions(+), 2094 deletions(-) rename {key/key.util => key.util}/src/test/java/org/key_project/util/collection/TestSLList.java (100%) delete mode 100644 key/key.core.test/src/de/uka/ilkd/key/parser/TestDeclParser.java delete mode 100644 key/key.core/src/de/uka/ilkd/key/logic/sort/ProgramSVSort.java diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSort.java b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSort.java index 13e8f2f7617..f8ce9e53414 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSort.java +++ b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSort.java @@ -62,15 +62,16 @@ public enum Variance { private final ImmutableList covariances; public ParametricSort(Name name, ImmutableSet ext, boolean isAbstract, - ImmutableList parameters, ImmutableList covariances) { - super(name, ext, isAbstract); + ImmutableList parameters, ImmutableList covariances, + String documentation, String origin) { + super(name, ext, isAbstract, documentation, origin); this.parameters = parameters; this.covariances = covariances; } public ParametricSort(Name name, ImmutableSet ext, boolean isAbstract, ImmutableList> sortParams) { - this(name, ext, isAbstract, sortParams.map(x->x.first), sortParams.map(x->x.second)); + this(name, ext, isAbstract, sortParams.map(x -> x.first), sortParams.map(x -> x.second), null, null); } public Function getInstantiation(ImmutableList args) { diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java index e2912ac0c90..785fe2f9c26 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java +++ b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java @@ -1,6 +1,7 @@ package de.uka.ilkd.key.logic.sort; import de.uka.ilkd.key.logic.Name; +import org.jspecify.annotations.Nullable; import org.key_project.util.collection.DefaultImmutableSet; import org.key_project.util.collection.ImmutableList; import org.key_project.util.collection.ImmutableSet; @@ -18,8 +19,9 @@ public class ParametricSortInstance extends AbstractSort { private final ParametricSort base; - public static ParametricSortInstance get(ParametricSort base, ImmutableList parameters) { - ParametricSortInstance sort = new ParametricSortInstance(base, parameters); + public static ParametricSortInstance get(ParametricSort base, ImmutableList parameters, + @Nullable String documentation, @Nullable String origin) { + ParametricSortInstance sort = new ParametricSortInstance(base, parameters, documentation, origin); ParametricSortInstance cached = CACHE.get(sort); if (cached != null) { return cached; @@ -29,9 +31,10 @@ public static ParametricSortInstance get(ParametricSort base, ImmutableList parameters) { - super(makeName(base, parameters), - computeExt(base, parameters), base.isAbstract()); + private ParametricSortInstance(ParametricSort base, ImmutableList parameters, + String documentation, String origin) { + super(makeName(base, parameters), computeExt(base, parameters), base.isAbstract(), + documentation, origin); this.base = base; this.parameters = parameters; @@ -58,7 +61,7 @@ private static ImmutableSet computeExt(ParametricSort base, ImmutableList< // take all bases of that arg and add the modified sort as ext class for (Sort s : parameters.get(i).extendsSorts()) { ImmutableList newArgs = parameters.replace(i, s); - result = result.add(ParametricSortInstance.get(base, newArgs)); + result = result.add(ParametricSortInstance.get(base, newArgs, null, null)); } break; @@ -90,7 +93,7 @@ public ImmutableList getParameters() { public ParametricSortInstance map(Function f) { ImmutableList newParameters = parameters.map(f); // The cache ensures that no unnecessary duplicates are kept. - return get(base, newParameters); + return get(base, newParameters, null, null); } @Override diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java index b4d16b62170..4163ca4aa67 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java @@ -130,6 +130,7 @@ public Object visitSort_decls(KeYParser.Sort_declsContext ctx) { return null; } + @Override public List>>> visitSortList(KeYParser.SortListContext ctx) { List>>> seq = new ArrayList<>(); @@ -145,22 +146,23 @@ public List>>> visitSortLi @Override public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) { - List>>> sortIds = accept(ctx.sortIds); + //List>>> sortIds = accept(ctx.sortIds); List sortOneOf = accept(ctx.sortOneOf); List sortExt = accept(ctx.sortExt); boolean isGenericSort = ctx.GENERIC() != null; boolean isProxySort = ctx.PROXY() != null; boolean isAbstractSort = ctx.ABSTRACT() != null; List createdSorts = new LinkedList<>(); - assert sortIds != null; + //assert sortIds != null; - for (Pair>> sortId : sortIds) { - Name sortName = new Name(sortId.first); - boolean isParametricSort = !sortId.second.isEmpty(); var documentation = ParsingFacade.getValueDocumentation(ctx.DOC_COMMENT()); - for (var idCtx : ctx.sortIds.simple_ident_dots()) { - String sortId = accept(idCtx); - Name sortName = new Name(sortId); + for(var idCtx : ctx.sortIds.sortId()){ + //for (Pair>> sortId : sortIds) { + var name = idCtx.simple_ident_dots().getText(); + var brackets = StringUtil.repeat("[]", idCtx.EMPTYBRACKETS().size()); + List> typeParams = accept(idCtx.formal_sort_parameters()); + Name sortName = new Name(name); + boolean isParametricSort = typeParams != null && !typeParams.isEmpty(); ImmutableSet ext = sortExt == null ? ImmutableSet.empty() : DefaultImmutableSet.fromCollection(sortExt); @@ -175,25 +177,22 @@ public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) { semanticError(ctx, "Generic sorts are not allowed to have type parameters."); } - for (Pair param : sortId.second) { + for (Pair param : typeParams) { if (!(param.second instanceof GenericSort)) { semanticError(ctx, "Type parameters must be generic sorts. Given type '%s' is %s", param.second.name(), param.second.getClass().getName()); } } - ImmutableList> typeParams = - sortId.second.stream().map(it -> + ImmutableList> params = + typeParams.stream().map(it -> new Pair<>((GenericSort) it.second, it.first)) .collect(ImmutableSLList.toImmutableList()); - s = new ParametricSort(sortName, ext, isAbstractSort, typeParams); + s = new ParametricSort(sortName, ext, isAbstractSort, params); }else if (isGenericSort) { - int i; - try { - var gs = new GenericSort(sortName, ext, oneOf, documentation, - BuilderHelpers.getPosition(idCtx)); - s = gs; + s = new GenericSort(sortName, ext, oneOf, documentation, + BuilderHelpers.getPosition(ctx)); } catch (GenericSupersortException e) { semanticError(ctx, "Illegal sort given"); } @@ -201,13 +200,11 @@ public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) { s = Sort.ANY; } else { if (isProxySort) { - var ps = new ProxySort(sortName, ext, documentation, + s = new ProxySort(sortName, ext, documentation, BuilderHelpers.getPosition(idCtx)); - s = ps; } else { - var si = new SortImpl(sortName, ext, isAbstractSort, + s = new SortImpl(sortName, ext, isAbstractSort, documentation, BuilderHelpers.getPosition(idCtx)); - s = si; } } assert s != null; diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java index 1675573a557..89780ca5fa0 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java @@ -90,7 +90,7 @@ protected T doLookup(Name n, Namespace... lookups) { if (lookup != null && (l = lookup.lookup(n)) != null) { try { return (T) l; - } catch (ClassCastException e) { + } catch (ClassCastException ignored) { } } } @@ -353,10 +353,9 @@ public Sort visitSortId(KeYParser.SortIdContext ctx) { //parametric sorts should be instantiated if (ctx.formal_sort_parameters() != null) { - if (s instanceof ParametricSort) { - ParametricSort ps = (ParametricSort) s; + if (s instanceof ParametricSort ps) { ImmutableList parameters = getSorts(ctx.formal_sort_parameters()); - s = ParametricSortInstance.get(ps, parameters); + s = ParametricSortInstance.get(ps, parameters, null, null); } else { semanticError(ctx, "Not a polymorphic sort: %s", s); } diff --git a/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java b/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java index 1b1828a3bec..e58ee9a1f0b 100644 --- a/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java +++ b/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java @@ -11,21 +11,19 @@ import de.uka.ilkd.key.logic.NamespaceSet; import de.uka.ilkd.key.logic.op.SchemaVariable; import de.uka.ilkd.key.logic.op.VariableSV; -import de.uka.ilkd.key.logic.sort.ArraySort; -import de.uka.ilkd.key.logic.sort.GenericSort; -import de.uka.ilkd.key.logic.sort.ProxySort; -import de.uka.ilkd.key.logic.sort.Sort; +import de.uka.ilkd.key.logic.sort.*; import de.uka.ilkd.key.nparser.KeyIO; import de.uka.ilkd.key.nparser.NamespaceBuilder; import de.uka.ilkd.key.proof.init.AbstractProfile; - -import org.key_project.util.collection.DefaultImmutableSet; -import org.key_project.util.collection.ImmutableSet; - +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.key_project.util.collection.DefaultImmutableSet; +import org.key_project.util.collection.ImmutableSet; +import org.key_project.util.collection.Immutables; +import static de.uka.ilkd.key.logic.sort.ParametricSort.Variance.*; import static org.junit.jupiter.api.Assertions.*; @@ -70,16 +68,53 @@ private void evaluateDeclarations(String s) { public void testSortDecl() { evaluateDeclarations("\\sorts { elem; list; }"); assertEquals(new Name("elem"), nss.sorts().lookup(new Name("elem")).name(), - "find sort elem"); + "find sort elem"); assertEquals(new Name("list"), nss.sorts().lookup(new Name("list")).name(), - "find sort list"); + "find sort list"); + } + + + @Test + public void testSortDeclFail() { + evaluateDeclarations("\\sorts { X; X; }"); + } + + public void testParametericSortDecl() { + evaluateDeclarations("\\sorts { \\generic E, F, G; " + + "coll<[E]>; list<[+E]> \\extends coll<[E]>;" + + "var<[-E, +F, G]>; }"); + + Sort e = nss.sorts().lookup("E"); + ParametricSort list = (ParametricSort) nss.sorts().lookup("list"); + ParametricSort coll = (ParametricSort) nss.sorts().lookup("coll"); + ParametricSort var = (ParametricSort) nss.sorts().lookup("var"); + + assertInstanceOf(GenericSort.class, e); + assertInstanceOf(ParametricSort.class, coll); + assertInstanceOf(ParametricSort.class, list); + + assertEquals( + Immutables.listOf(CONTRAVARIANT, COVARIANT, INVARIANT), + var.getCovariances()); + + assertEquals("{coll<[E]>}", list.extendsSorts().toString()); + + assertEquals("{any}", coll.extendsSorts().toString()); + } + + @Test + public void testParametericSortDeclFails() { + Assertions.assertThrows(Exception.class, () -> evaluateDeclarations("\\sorts { parametric<[E]>; }")); + //assertTrue(ex.getMessage().contains("Formal type parameters must be (already declared) generic sorts")); + Assertions.assertThrows(Exception.class, () -> evaluateDeclarations("\\sorts { \\generic E; doubled<[E,E]>; }")); + Assertions.assertThrows(Exception.class, () -> evaluateDeclarations("\\sorts { parametric<[int]>; }")); + Assertions.assertThrows(Exception.class, () -> evaluateDeclarations("\\sorts { \\generic E; int<[E]>; }")); } private GenericSort checkGenericSort(Named name, ImmutableSet pExt, - ImmutableSet pOneOf) { + ImmutableSet pOneOf) { assertNotNull(name, "Generic sort does not exist"); - assertTrue(name instanceof GenericSort, - "Generic sort does not have type GenericSort, but " + name.getClass()); + assertInstanceOf(GenericSort.class, name, "Generic sort does not have type GenericSort, but " + name.getClass()); GenericSort gs = (GenericSort) name; assertEquals(pExt, gs.extendsSorts(), "Generic sort has wrong supersorts"); @@ -91,30 +126,30 @@ private GenericSort checkGenericSort(Named name, ImmutableSet pExt, private Sort checkSort(Named name) { assertNotNull(name, "Sort does not exist"); - assertTrue(name instanceof Sort, "Sort does not have type Sort, but " + name.getClass()); + assertInstanceOf(Sort.class, name, "Sort does not have type Sort, but " + name.getClass()); return (Sort) name; } @Test public void testProxySortDecl() { evaluateDeclarations( - "\\sorts { A; B; \\proxy P; \\proxy Q \\extends A,B; \\proxy R \\extends Q; }"); + "\\sorts { A; B; \\proxy P; \\proxy Q \\extends A,B; \\proxy R \\extends Q; }"); Sort P = nss.sorts().lookup(new Name("P")); assertNotNull(P); - assertTrue(P instanceof ProxySort); + assertInstanceOf(ProxySort.class, P); assertEquals("P", P.name().toString()); assertEquals(DefaultImmutableSet.nil().add(Sort.ANY), P.extendsSorts()); Sort A = nss.sorts().lookup(new Name("A")); Sort B = nss.sorts().lookup(new Name("B")); Sort Q = nss.sorts().lookup(new Name("Q")); - assertTrue(Q instanceof ProxySort); + assertInstanceOf(ProxySort.class, Q); assertEquals("Q", Q.name().toString()); assertEquals(DefaultImmutableSet.nil().add(A).add(B), Q.extendsSorts()); Sort R = nss.sorts().lookup(new Name("R")); - assertTrue(P instanceof ProxySort); + assertInstanceOf(ProxySort.class, P); assertEquals("R", R.name().toString()); assertEquals(DefaultImmutableSet.nil().add(Q), R.extendsSorts()); } @@ -127,9 +162,9 @@ public void testGenericSortDecl1() { evaluateDeclarations("\\sorts { \\generic G; \\generic H \\extends G; }"); G = checkGenericSort(nss.sorts().lookup(new Name("G")), - DefaultImmutableSet.nil().add(Sort.ANY), DefaultImmutableSet.nil()); + DefaultImmutableSet.nil().add(Sort.ANY), DefaultImmutableSet.nil()); H = checkGenericSort(nss.sorts().lookup(new Name("H")), - DefaultImmutableSet.nil().add(G), DefaultImmutableSet.nil()); + DefaultImmutableSet.nil().add(G), DefaultImmutableSet.nil()); } @Test @@ -138,9 +173,9 @@ public void testGenericSortDecl2() { Sort S = checkSort(nss.sorts().lookup(new Name("S"))); GenericSort G = checkGenericSort(nss.sorts().lookup(new Name("G")), - DefaultImmutableSet.nil().add(Sort.ANY), DefaultImmutableSet.nil()); + DefaultImmutableSet.nil().add(Sort.ANY), DefaultImmutableSet.nil()); GenericSort H = checkGenericSort(nss.sorts().lookup(new Name("H")), - DefaultImmutableSet.nil().add(S).add(G), DefaultImmutableSet.nil()); + DefaultImmutableSet.nil().add(S).add(G), DefaultImmutableSet.nil()); } @Test @@ -150,39 +185,39 @@ public void testGenericSortDecl3() { Sort S = checkSort(nss.sorts().lookup(new Name("S"))); Sort T = checkSort(nss.sorts().lookup(new Name("T"))); GenericSort H = checkGenericSort(nss.sorts().lookup(new Name("H")), - DefaultImmutableSet.nil().add(Sort.ANY), - DefaultImmutableSet.nil().add(S).add(T)); + DefaultImmutableSet.nil().add(Sort.ANY), + DefaultImmutableSet.nil().add(S).add(T)); } @Test public void testGenericSortDecl6() { evaluateDeclarations( - "\\sorts { S; T; \\generic G; \\generic H \\oneof {S} \\extends T, G; }"); + "\\sorts { S; T; \\generic G; \\generic H \\oneof {S} \\extends T, G; }"); Sort S = checkSort(nss.sorts().lookup(new Name("S"))); Sort T = checkSort(nss.sorts().lookup(new Name("T"))); GenericSort G = checkGenericSort(nss.sorts().lookup(new Name("G")), - DefaultImmutableSet.nil().add(Sort.ANY), DefaultImmutableSet.nil()); + DefaultImmutableSet.nil().add(Sort.ANY), DefaultImmutableSet.nil()); GenericSort H = checkGenericSort(nss.sorts().lookup(new Name("H")), - DefaultImmutableSet.nil().add(T).add(G), DefaultImmutableSet.nil().add(S)); + DefaultImmutableSet.nil().add(T).add(G), DefaultImmutableSet.nil().add(S)); } @Test public void testGenericSortDecl4() { evaluateDeclarations( - "\\sorts { S, T; \\generic G,G2; \\generic H,H2 \\oneof {S} \\extends T, G; }"); + "\\sorts { S, T; \\generic G,G2; \\generic H,H2 \\oneof {S} \\extends T, G; }"); Sort S = checkSort(nss.sorts().lookup(new Name("S"))); Sort T = checkSort(nss.sorts().lookup(new Name("T"))); GenericSort G = checkGenericSort(nss.sorts().lookup(new Name("G")), - DefaultImmutableSet.nil().add(Sort.ANY), DefaultImmutableSet.nil()); + DefaultImmutableSet.nil().add(Sort.ANY), DefaultImmutableSet.nil()); checkGenericSort(nss.sorts().lookup(new Name("G2")), - DefaultImmutableSet.nil().add(Sort.ANY), DefaultImmutableSet.nil()); + DefaultImmutableSet.nil().add(Sort.ANY), DefaultImmutableSet.nil()); GenericSort H = checkGenericSort(nss.sorts().lookup(new Name("H")), - DefaultImmutableSet.nil().add(T).add(G), DefaultImmutableSet.nil().add(S)); + DefaultImmutableSet.nil().add(T).add(G), DefaultImmutableSet.nil().add(S)); checkGenericSort(nss.sorts().lookup(new Name("H2")), - DefaultImmutableSet.nil().add(T).add(G), DefaultImmutableSet.nil().add(S)); + DefaultImmutableSet.nil().add(T).add(G), DefaultImmutableSet.nil().add(S)); } @@ -207,10 +242,10 @@ public void testGenericSortDecl5() { * QuantifiableVariable */ private void assertVariableSV(String msg, Object o) { - assertTrue(o instanceof SchemaVariable, "The named object: " + o + " is of type " - + o.getClass() + ", but the type SchemaVariable was expected"); + assertInstanceOf(SchemaVariable.class, o, "The named object: " + o + " is of type " + + o.getClass() + ", but the type SchemaVariable was expected"); - assertTrue(o instanceof VariableSV, msg); + assertInstanceOf(VariableSV.class, o, msg); } /** @@ -218,10 +253,10 @@ private void assertVariableSV(String msg, Object o) { */ private void assertTermSV(String msg, Object o) { - assertTrue(o instanceof SchemaVariable, "The named object: " + o + " is of type " - + o.getClass() + ", but the type SchemaVariable was expected"); + assertInstanceOf(SchemaVariable.class, o, "The named object: " + o + " is of type " + + o.getClass() + ", but the type SchemaVariable was expected"); assertNotSame(((SchemaVariable) o).sort(), Sort.FORMULA, - "Schemavariable is not allowed to match a term of sort FORMULA."); + "Schemavariable is not allowed to match a term of sort FORMULA."); } /** @@ -229,11 +264,11 @@ private void assertTermSV(String msg, Object o) { * Sort.FORMULA) */ private void assertFormulaSV(String msg, Object o) { - assertTrue(o instanceof SchemaVariable, "The named object: " + o + " is of type " - + o.getClass() + ", but the type SchemaVariable was expected"); + assertInstanceOf(SchemaVariable.class, o, "The named object: " + o + " is of type " + + o.getClass() + ", but the type SchemaVariable was expected"); assertSame(((SchemaVariable) o).sort(), Sort.FORMULA, - "Only matches to terms of sort FORMULA allowed. " + "But term has sort " - + ((SchemaVariable) o).sort()); + "Only matches to terms of sort FORMULA allowed. " + "But term has sort " + + ((SchemaVariable) o).sort()); } @@ -241,32 +276,32 @@ private void assertFormulaSV(String msg, Object o) { @Test public void testArrayDecl() { evaluateDeclarations( - """ - \\sorts { aSort;} - \\functions { - aSort[][] f(aSort); - } - """); + """ + \\sorts { aSort;} + \\functions { + aSort[][] f(aSort); + } + """); Sort aSort = nss.sorts().lookup(new Name("aSort")); Sort objectSort = serv.getJavaInfo().objectSort(); Sort cloneableSort = serv.getJavaInfo().cloneableSort(); Sort serializableSort = serv.getJavaInfo().serializableSort(); Sort aSortArr = ArraySort.getArraySort(aSort, objectSort, cloneableSort, serializableSort); Sort aSortArr2 = - ArraySort.getArraySort(aSortArr, objectSort, cloneableSort, serializableSort); + ArraySort.getArraySort(aSortArr, objectSort, cloneableSort, serializableSort); assertTrue(aSortArr.extendsSorts().contains(cloneableSort), - "aSort[] should extend Cloneable: " + aSortArr.extendsSorts()); + "aSort[] should extend Cloneable: " + aSortArr.extendsSorts()); assertTrue(aSortArr.extendsTrans(objectSort), "aSort[] should transitively extend Object "); assertTrue(aSortArr2.extendsTrans(objectSort), - "aSort[][] should transitively extend Object "); + "aSort[][] should transitively extend Object "); assertTrue(aSortArr2.extendsTrans(cloneableSort), - "aSort[][] should transitively extend Cloneable "); + "aSort[][] should transitively extend Cloneable "); assertTrue( - aSortArr2.extendsSorts().contains( - ArraySort.getArraySort(cloneableSort, objectSort, cloneableSort, serializableSort)), - "aSort[][] should extend Cloneable[] "); + aSortArr2.extendsSorts().contains( + ArraySort.getArraySort(cloneableSort, objectSort, cloneableSort, serializableSort)), + "aSort[][] should extend Cloneable[] "); assertTrue(cloneableSort.extendsSorts().contains(objectSort), - "Cloneable should extend Object "); + "Cloneable should extend Object "); } @Test @@ -290,28 +325,28 @@ public void testFunctionDecl() { Sort serializableSort = serv.getJavaInfo().serializableSort(); assertEquals(new Name("head"), nss.functions().lookup(new Name("head")).name(), - "find head function"); + "find head function"); assertEquals(1, nss.functions().lookup(new Name("head")).arity(), "head arity"); assertEquals(list, nss.functions().lookup(new Name("head")).argSort(0), "head arg sort 0"); assertEquals(elem, nss.functions().lookup(new Name("head")).sort(), "head return sort"); assertEquals(new Name("tail"), nss.functions().lookup(new Name("tail")).name(), - "find tail function"); + "find tail function"); assertEquals(1, nss.functions().lookup(new Name("tail")).arity(), "tail arity"); assertEquals(list, nss.functions().lookup(new Name("tail")).argSort(0), "tail arg sort 0"); assertEquals(list, nss.functions().lookup(new Name("tail")).sort(), "tail return sort"); assertEquals(ArraySort.getArraySort(elem, objectSort, cloneableSort, serializableSort), - nss.functions().lookup(new Name("tailarray")).argSort(0), "tailarray arg sort 0"); + nss.functions().lookup(new Name("tailarray")).argSort(0), "tailarray arg sort 0"); assertEquals(ArraySort.getArraySort(elem, objectSort, cloneableSort, serializableSort), - nss.functions().lookup(new Name("tailarray")).sort(), "tailarray return sort"); + nss.functions().lookup(new Name("tailarray")).sort(), "tailarray return sort"); assertEquals(new Name("nil"), nss.functions().lookup(new Name("nil")).name(), - "find nil function"); + "find nil function"); assertEquals(0, nss.functions().lookup(new Name("nil")).arity(), "nil arity"); assertEquals(list, nss.functions().lookup(new Name("nil")).sort(), "nil return sort"); assertEquals(new Name("cons"), nss.functions().lookup(new Name("cons")).name(), - "find cons function"); + "find cons function"); assertEquals(2, nss.functions().lookup(new Name("cons")).arity(), "cons arity"); assertEquals(elem, nss.functions().lookup(new Name("cons")).argSort(0), "cons arg sort 0"); assertEquals(list, nss.functions().lookup(new Name("cons")).argSort(1), "cons arg sort 1"); @@ -334,35 +369,35 @@ public void testPredicateDecl() { assertEquals(new Name("isEmpty"), nss.functions().lookup(new Name("isEmpty")).name(), - "find isEmpty predicate"); + "find isEmpty predicate"); assertEquals(1, nss.functions().lookup(new Name("isEmpty")).arity(), "isEmpty arity"); assertEquals(list, nss.functions().lookup(new Name("isEmpty")).argSort(0), - "isEmpty arg sort 0"); + "isEmpty arg sort 0"); assertEquals(Sort.FORMULA, nss.functions().lookup(new Name("isEmpty")).sort(), - "isEmpty return sort"); + "isEmpty return sort"); assertEquals(new Name("contains"), nss.functions().lookup(new Name("contains")).name(), - "find contains predicate"); + "find contains predicate"); assertEquals(2, nss.functions().lookup(new Name("contains")).arity(), "contains arity"); assertEquals(list, nss.functions().lookup(new Name("contains")).argSort(0), - "contains arg sort 0"); + "contains arg sort 0"); assertEquals(elem, nss.functions().lookup(new Name("contains")).argSort(1), - "contains arg sort 1"); + "contains arg sort 1"); assertEquals(Sort.FORMULA, nss.functions().lookup(new Name("contains")).sort(), - "contains return sort"); + "contains return sort"); assertEquals(new Name("maybe"), nss.functions().lookup(new Name("maybe")).name(), - "find maybe predicate"); + "find maybe predicate"); assertEquals(0, nss.functions().lookup(new Name("maybe")).arity(), "maybe arity"); assertEquals(Sort.FORMULA, nss.functions().lookup(new Name("maybe")).sort(), - "maybe return sort"); + "maybe return sort"); } @Test public void testSVDecl() { evaluateDeclarations( - "\\sorts { elem; list; } " + "\\schemaVariables {" + " \\program Statement #s ;" - + " \\term elem x,y ;" + " \\variables list lv;" + " \\formula b;}"); + "\\sorts { elem; list; } " + "\\schemaVariables {" + " \\program Statement #s ;" + + " \\term elem x,y ;" + " \\variables list lv;" + " \\formula b;}"); Sort elem = nss.sorts().lookup(new Name("elem")); @@ -393,15 +428,15 @@ public void testSVDecl() { public void testAmbiguousDecls() { try { evaluateDeclarations( - """ - \\sorts { elem; list; } - \\functions {elem x;elem fn;elem p;}\\predicates {fn(elem);y;p;}\\schemaVariables { - \\program Statement #s ;\s - \\term elem x,y ; - \\variables list lv ; - \\formula b; - } - """); + """ + \\sorts { elem; list; } + \\functions {elem x;elem fn;elem p;}\\predicates {fn(elem);y;p;}\\schemaVariables { + \\program Statement #s ;\s + \\term elem x,y ; + \\variables list lv ; + \\formula b; + } + """); fail("Ambiguous declaration successfully parsed. Error was expected."); // FIXME nparser It seems that the nparser does not check for conflicting declarations } catch (RuntimeException e) { @@ -413,8 +448,8 @@ public void testAmbiguousDecls() { public void testHeurDecl() { evaluateDeclarations("\\heuristicsDecl { bool; shoot_foot; }"); assertEquals(new Name("bool"), nss.ruleSets().lookup(new Name("bool")).name(), - "find heuristic bool"); + "find heuristic bool"); assertEquals(new Name("shoot_foot"), nss.ruleSets().lookup(new Name("shoot_foot")).name(), - "find heuristic shoot_foot"); + "find heuristic shoot_foot"); } } diff --git a/key.util/src/main/java/org/key_project/util/collection/ImmutableList.java b/key.util/src/main/java/org/key_project/util/collection/ImmutableList.java index 6fd1ec96f77..f70027c3475 100644 --- a/key.util/src/main/java/org/key_project/util/collection/ImmutableList.java +++ b/key.util/src/main/java/org/key_project/util/collection/ImmutableList.java @@ -367,4 +367,14 @@ default T get(int idx) { return take(idx).head(); } + /** + * Replace the element at position {@code pos} in the list + * by the value {@code t}. + * + * @param pos the position within the list {@code 0 <= pos && pos < size()} + * @param t the element to set, may be {@code null}. + * @return an immutable list in which only the element at pos has been replaced. + * @throws IndexOutOfBoundsException if pos is not a valid index in the list. + */ + ImmutableList replace(int pos, T t); } diff --git a/key.util/src/main/java/org/key_project/util/collection/ImmutableSLList.java b/key.util/src/main/java/org/key_project/util/collection/ImmutableSLList.java index 50106229327..6f470ee7877 100644 --- a/key.util/src/main/java/org/key_project/util/collection/ImmutableSLList.java +++ b/key.util/src/main/java/org/key_project/util/collection/ImmutableSLList.java @@ -165,6 +165,26 @@ public ImmutableList take(int n) { } + // Implemented imperatively to avoid arbitrarily deep recursion + @Override + public ImmutableList replace(int pos, T s) { + if(pos < 0 || pos >= size()) { + throw new IndexOutOfBoundsException(); + } + + ImmutableList already = nil(); + ImmutableList rest = this; + + while(pos > 0) { + already = already.prepend(rest.head()); + rest = rest.tail(); + pos --; + } + + return rest.tail().prepend(s).prepend(already.reverse()); + } + + private static class Cons extends ImmutableSLList { /** diff --git a/key.util/src/main/java/org/key_project/util/collection/Immutables.java b/key.util/src/main/java/org/key_project/util/collection/Immutables.java index 7c9cd4c3919..a2f198747cb 100644 --- a/key.util/src/main/java/org/key_project/util/collection/Immutables.java +++ b/key.util/src/main/java/org/key_project/util/collection/Immutables.java @@ -11,7 +11,7 @@ /** * This class is a collection of methods that operate on immutable collections, in particular * {@link ImmutableSet}s and {@link ImmutableList}s. - * + *

    * This class cannot be instantiated. * * @author Mattias Ulbrich @@ -24,11 +24,11 @@ private Immutables() { /** * Checks whether an immutable list is free of duplicates. - * + *

    * A list has a duplicate if it during iteration it visits two objects o1 and o2 such that * o1==null ? o2 == null : o1.equals(o2) is true. null may appear in * the list. - * + *

    * The implementation uses a hash set internally and thus runs in O(n). * * @param list any list, must not be null @@ -49,27 +49,26 @@ public static boolean isDuplicateFree(ImmutableList list) { /** * Removes duplicate entries from an immutable list. - * + *

    * A list has a duplicate if it during iteration it visits two objects o1 and o2 such that * o1==null ? o2 == null : o1.equals(o2) is true. null may appear in * the list. - * + *

    * If an element occurs duplicated, its first (in order of iteration) occurrence is kept, while * later occurrences are removeed. - * + *

    * If a list iterates "a", "b", "a" in this order, removeDuplicates returns a list iterating * "a", "b". - * + *

    * The implementation uses a hash set internally and thus runs in O(n). - * + *

    * It reuses as much created datastructure as possible. In particular, if the list is already * duplicate-fre, it does not allocate new memory (well, only temporarily) and returns the * argument. - * + *

    * Sidenote: Would that not make a nice KeY-Verification condition? Eat your own dogfood. * * @param list any list, must not be null - * * @return a duplicate-free version of the argument, never null */ public static ImmutableList removeDuplicates(ImmutableList list) { @@ -115,7 +114,7 @@ public static ImmutableList removeDuplicates(ImmutableList list) { } public static ImmutableList concatDuplicateFreeLists(ImmutableList l1, - ImmutableList l2) { + ImmutableList l2) { Set lookup = new HashSet<>(); for (T element : l1) { @@ -139,12 +138,11 @@ public static ImmutableSet createSetFrom(Iterable iterable) { /** * Returns an immutable list consisting of the elements of the * given iterable collection. - * + *

    * The iteration order of the result is identical to that of the argument. * * @param iterable the collection to iterate through to obtain the elements - * for the resulting list - * + * for the resulting list * @returns the view onto the iterable as an immutable list */ public static ImmutableList createListFrom(Iterable iterable) { @@ -159,12 +157,10 @@ public static ImmutableList createListFrom(Iterable iterable) { * Returns an immutable list consisting of the elements of the list that match * the given predicate. * - * @param ts non-null immutable list. - * + * @param ts non-null immutable list. * @param predicate a non-interfering, stateless - * predicate to apply to each element to determine if it - * should be included - * + * predicate to apply to each element to determine if it + * should be included * @returns the filtered list */ public static ImmutableList filter(ImmutableList ts, Predicate predicate) { @@ -185,8 +181,8 @@ public static ImmutableList filter(ImmutableList ts, Predicate pred * Returns an immutable list consisting of the results of applying the given * function to the elements of the list. * - * @param The element type of the result list - * @param ts ts non-null immutable list. + * @param The element type of the result list + * @param ts ts non-null immutable list. * @param function a non-interfering, stateless function to apply to each element * @return the mapped list of the same length as this */ @@ -201,4 +197,27 @@ public static ImmutableList map(ImmutableList ts, Function fu } return acc.reverse(); } + + public static ImmutableList listOf(T... elements) { + ImmutableList result = ImmutableSLList.nil(); + for (T t : elements) { + result = result.prepend(t); + } + return result.reverse(); + } + + public static ImmutableList listOf(T element) { + ImmutableList result = ImmutableSLList.nil(); + result = result.prepend(element); + return result.reverse(); + } + + public static ImmutableSet setOf(T... elements) { + return DefaultImmutableSet.fromImmutableList(listOf(elements)); + } + + public static ImmutableSet setOf(T element) { + return DefaultImmutableSet.fromImmutableList(listOf(element)); + } + } diff --git a/key/key.util/src/test/java/org/key_project/util/collection/TestSLList.java b/key.util/src/test/java/org/key_project/util/collection/TestSLList.java similarity index 100% rename from key/key.util/src/test/java/org/key_project/util/collection/TestSLList.java rename to key.util/src/test/java/org/key_project/util/collection/TestSLList.java diff --git a/key/key.core.test/src/de/uka/ilkd/key/parser/TestDeclParser.java b/key/key.core.test/src/de/uka/ilkd/key/parser/TestDeclParser.java deleted file mode 100644 index 5c8750b8e02..00000000000 --- a/key/key.core.test/src/de/uka/ilkd/key/parser/TestDeclParser.java +++ /dev/null @@ -1,587 +0,0 @@ -// This file is part of KeY - Integrated Deductive Software Design -// -// Copyright (C) 2001-2011 Universitaet Karlsruhe (TH), Germany -// Universitaet Koblenz-Landau, Germany -// Chalmers University of Technology, Sweden -// Copyright (C) 2011-2014 Karlsruhe Institute of Technology, Germany -// Technical University Darmstadt, Germany -// Chalmers University of Technology, Sweden -// -// The KeY system is protected by the GNU General -// Public License. See LICENSE.TXT for details. -// - -package de.uka.ilkd.key.parser; - -import java.io.PrintWriter; -import java.io.StringWriter; - -import de.uka.ilkd.key.logic.op.SortDependingFunction; -import de.uka.ilkd.key.logic.sort.*; -import junit.framework.TestCase; - -import org.antlr.runtime.RecognitionException; -import org.key_project.util.collection.DefaultImmutableSet; -import org.key_project.util.collection.ImmutableSet; - -import de.uka.ilkd.key.java.Recoder2KeY; -import de.uka.ilkd.key.java.Services; -import de.uka.ilkd.key.logic.Name; -import de.uka.ilkd.key.logic.Named; -import de.uka.ilkd.key.logic.Namespace; -import de.uka.ilkd.key.logic.NamespaceSet; -import de.uka.ilkd.key.logic.op.Function; -import de.uka.ilkd.key.logic.op.SchemaVariable; -import de.uka.ilkd.key.logic.op.VariableSV; -import de.uka.ilkd.key.logic.sort.ParametricSort; -import static de.uka.ilkd.key.logic.sort.ParametricSort.Variance.*; -import de.uka.ilkd.key.proof.init.AbstractProfile; -import org.key_project.util.collection.Immutables; - - -public class TestDeclParser extends TestCase { - - NamespaceSet nss; - Services serv; - private Namespace parsedSchemaVars; - - public TestDeclParser(String name) { - super(name); - } - - public void setUp() { - serv = new Services(AbstractProfile.getDefaultProfile()); - nss = serv.getNamespaces(); - - String sorts = "\\sorts{boolean;int;LocSet;}"; - KeYParserF basicSortsParser = new KeYParserF(ParserMode.DECLARATION, - new KeYLexerF(sorts, - "No file. Call of parser from logic/TestClashFreeSubst.java"), - serv, nss); - try { - basicSortsParser.parseSorts(); - } catch(Exception e) { - throw new RuntimeException(e); - } - - Recoder2KeY r2k = new Recoder2KeY(serv, nss); - r2k.parseSpecialClasses(); - } - - private KeYParserF stringParser(String s) { - return new KeYParserF(ParserMode.DECLARATION, - new KeYLexerF(s, - "No file. Call of parser from parser/TestDeclParser.java"), - serv, nss); - } - - private void parseDecls(String s) { - try { - KeYParserF p = stringParser(s); - p.decls(); - this.parsedSchemaVars = p.schemaVariables(); - } catch (Exception e) { - StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw); - e.printStackTrace(pw); - throw new RuntimeException("Exc while Parsing:\n" + sw ); - } - } - - public void testSortDecl() { - - - parseDecls("\\sorts { elem; list; }"); - assertEquals("find sort elem", new Name("elem"), - nss.sorts().lookup(new Name("elem")).name()); - assertEquals("find sort list", new Name("list"), - nss.sorts().lookup(new Name("list")).name()); - } - - public void testSortDeclFail() { - try { - String s = "\\sorts { X; X; }"; - KeYParserF p = stringParser(s); - p.decls(); - fail("Parsing " + s + " should have failed"); - } catch (Exception ex) { - assertTrue(ex.getMessage().contains("already declared")); - } - - } - - public void testParametericSortDecl() { - parseDecls("\\sorts { \\generic E, F, G; " + - "coll<[E]>; list<[+E]> \\extends coll<[E]>;" + - "var<[-E, +F, G]>; }"); - - Sort e = nss.sorts().lookup("E"); - ParametricSort list = (ParametricSort) nss.sorts().lookup("list"); - ParametricSort coll = (ParametricSort) nss.sorts().lookup("coll"); - ParametricSort var = (ParametricSort) nss.sorts().lookup("var"); - - assertTrue(e instanceof GenericSort); - assertTrue(coll instanceof ParametricSort); - assertTrue(list instanceof ParametricSort); - - assertEquals( - Immutables.listOf(CONTRAVARIANT, COVARIANT, INVARIANT), - var.getCovariances()); - - assertEquals("{coll<[E]>}", list.extendsSorts().toString()); - - assertEquals("{any}", coll.extendsSorts().toString()); - } - - public void testParametericSortDeclFails() { - try { - String s = "\\sorts { parametric<[E]>; }"; - KeYParserF p = stringParser(s); - p.decls(); - fail("Parsing " + s + " should have failed"); - } catch (Exception ex) { - assertTrue(ex.getMessage().contains("Formal type parameters must be (already declared) generic sorts")); - } - - try { - String s = "\\sorts { \\generic E; doubled<[E,E]>; }"; - KeYParserF p = stringParser(s); - p.decls(); - fail("Parsing " + s + " should have failed"); - } catch (Exception ex) { - assertTrue(ex.getMessage().contains("unique")); - } - - - try { - String s = "\\sorts { parametric<[int]>; }"; - KeYParserF p = stringParser(s); - p.decls(); - fail("Parsing " + s + " should have failed"); - } catch (Exception ex) { - assertTrue(ex.getMessage().contains("Formal type parameters must be (already declared) generic sorts")); - } - - try { - String s = "\\sorts { \\generic E; int<[E]>; }"; - KeYParserF p = stringParser(s); - p.decls(); - fail("Parsing " + s + " should have failed"); - } catch (Exception ex) { - assertTrue(ex.getMessage().contains("already declared")); - } - } - - - protected GenericSort checkGenericSort ( Named p_n, - ImmutableSet p_ext, - ImmutableSet p_oneof ) { - assertTrue ( "Generic sort does not exist", p_n != null ); - assertTrue ( "Generic sort does not have type GenericSort, but " + p_n.getClass(), - p_n instanceof GenericSort ); - - GenericSort gs = (GenericSort)p_n; - - assertEquals ( "Generic sort has wrong supersorts", - p_ext, - gs.extendsSorts () ); - assertEquals ( "Generic sort has wrong oneof-list", - p_oneof, - gs.getOneOf () ); - - return gs; - } - - protected Sort checkSort ( Named p_n ) { - assertTrue ( "Sort does not exist", p_n != null ); - assertTrue ( "Sort does not have type Sort, but " + p_n.getClass(), - p_n instanceof Sort ); - - return (Sort)p_n; - } - - public void testProxySortDecl() { - nss = new NamespaceSet (); - parseDecls("\\sorts { A; B; \\proxy P; \\proxy Q \\extends A,B; \\proxy R \\extends Q; }"); - - Sort P = (Sort) nss.sorts().lookup(new Name("P")); - assertTrue(P instanceof ProxySort); - assertEquals("P", P.name().toString()); - assertEquals(DefaultImmutableSet.nil().add(Sort.ANY), P.extendsSorts()); - - Sort A = (Sort) nss.sorts().lookup(new Name("A")); - Sort B = (Sort) nss.sorts().lookup(new Name("B")); - Sort Q = (Sort) nss.sorts().lookup(new Name("Q")); - assertTrue(Q instanceof ProxySort); - assertEquals("Q", Q.name().toString()); - assertEquals(DefaultImmutableSet.nil().add(A).add(B), Q.extendsSorts()); - - Sort R = (Sort) nss.sorts().lookup(new Name("R")); - assertTrue(P instanceof ProxySort); - assertEquals("R", R.name().toString()); - assertEquals(DefaultImmutableSet.nil().add(Q), R.extendsSorts()); - } - - - public void testGenericSortDecl() { - GenericSort G, H; - Sort S, T; - - nss = new NamespaceSet (); - parseDecls("\\sorts { \\generic G; \\generic H \\extends G; }"); - - G = checkGenericSort ( nss.sorts().lookup(new Name("G")), - DefaultImmutableSet.nil().add(Sort.ANY), - DefaultImmutableSet.nil() ); - H = checkGenericSort ( nss.sorts().lookup(new Name("H")), - DefaultImmutableSet.nil().add ( G ), - DefaultImmutableSet.nil() ); - - - nss = new NamespaceSet (); - parseDecls("\\sorts { S; \\generic G; \\generic H \\extends G, S; }"); - - S = checkSort ( nss.sorts().lookup(new Name("S")) ); - G = checkGenericSort ( nss.sorts().lookup(new Name("G")), - DefaultImmutableSet.nil().add(Sort.ANY), - DefaultImmutableSet.nil() ); - H = checkGenericSort ( nss.sorts().lookup(new Name("H")), - DefaultImmutableSet.nil().add ( S ).add ( G ), - DefaultImmutableSet.nil() ); - - - nss = new NamespaceSet (); - parseDecls("\\sorts { S; T; \\generic H \\oneof {S, T}; }"); - - S = checkSort ( nss.sorts().lookup(new Name("S")) ); - T = checkSort ( nss.sorts().lookup(new Name("T")) ); - H = checkGenericSort ( nss.sorts().lookup(new Name("H")), - DefaultImmutableSet.nil().add(Sort.ANY), - DefaultImmutableSet.nil().add ( S ).add ( T ) ); - - - nss = new NamespaceSet (); - parseDecls("\\sorts { S; T; \\generic G; \\generic H \\oneof {S} \\extends T, G; }"); - - S = checkSort ( nss.sorts().lookup(new Name("S")) ); - T = checkSort ( nss.sorts().lookup(new Name("T")) ); - G = checkGenericSort ( nss.sorts().lookup(new Name("G")), - DefaultImmutableSet.nil().add(Sort.ANY), - DefaultImmutableSet.nil() ); - H = checkGenericSort ( nss.sorts().lookup(new Name("H")), - DefaultImmutableSet.nil().add ( T ).add ( G ), - DefaultImmutableSet.nil().add ( S ) ); - - - nss = new NamespaceSet (); - parseDecls("\\sorts { S, T; \\generic G,G2; \\generic H,H2 \\oneof {S} \\extends T, G; }"); - - S = checkSort ( nss.sorts().lookup(new Name("S")) ); - T = checkSort ( nss.sorts().lookup(new Name("T")) ); - G = checkGenericSort ( nss.sorts().lookup(new Name("G")), - DefaultImmutableSet.nil().add(Sort.ANY), - DefaultImmutableSet.nil() ); - checkGenericSort ( nss.sorts().lookup(new Name("G2")), - DefaultImmutableSet.nil().add(Sort.ANY), - DefaultImmutableSet.nil() ); - H = checkGenericSort ( nss.sorts().lookup(new Name("H")), - DefaultImmutableSet.nil().add ( T ).add ( G ), - DefaultImmutableSet.nil().add ( S ) ); - checkGenericSort ( nss.sorts().lookup(new Name("H2")), - DefaultImmutableSet.nil().add ( T ).add ( G ), - DefaultImmutableSet.nil().add ( S ) ); - - - nss = new NamespaceSet (); - String str = "\\sorts { \\generic G; \\generic H \\oneof {G}; }"; - try { - KeYParserF p = stringParser(str); - p.decls(); - - fail ( "Expected an GenericSortException" ); - } catch ( Exception e ) { - assertTrue ( "Expected a GenericSortException", - e instanceof de.uka.ilkd.key.parser.GenericSortException || e.getCause() instanceof de.uka.ilkd.key.parser.GenericSortException); - } - } - - /** asserts that the found object is a schemavariable and - * that the allowed macthing type is QuantifiableVariable - */ - public void assertVariableSV(String msg, - Object o) { - assertTrue("The named object: "+o+" is of type "+o.getClass()+ - ", but the type SchemaVariable was expected", - o instanceof SchemaVariable); - - assertTrue(msg, o instanceof VariableSV); - } - - /** asserts that the SchemaVariable matches to term but not to a - * formula - */ - public void assertTermSV(String msg, - Object o) { - - assertTrue("The named object: "+o+" is of type "+o.getClass()+ - ", but the type SchemaVariable was expected", - o instanceof SchemaVariable); - assertTrue("Schemavariable is not allowed to match a term of sort FORMULA.", - ((SchemaVariable)o).sort() != Sort.FORMULA); - } - - /** asserts that the SchemaVariable matches to a formula - * and not to a term (of sort != Sort.FORMULA) - */ - public void assertFormulaSV(String msg, - Object o) { - assertTrue("The named object: "+o+" is of type "+o.getClass()+ - ", but the type SchemaVariable was expected", - o instanceof SchemaVariable); - assertSame("Only matches to terms of sort FORMULA allowed. "+ - "But term has sort "+((SchemaVariable)o).sort(), - ((SchemaVariable)o).sort(), Sort.FORMULA); - - - } - - public void testArrayDecl() { - parseDecls("\\sorts { aSort;}\n" + - "\\functions {\n" + - " aSort[][] f(aSort);\n" + - "}\n"); - Sort aSort = nss.sorts().lookup(new Name("aSort")); - Sort objectSort = serv.getJavaInfo().objectSort(); - Sort cloneableSort = serv.getJavaInfo().cloneableSort(); - Sort serializableSort = serv.getJavaInfo().serializableSort(); - Sort aSortArr = ArraySort.getArraySort(aSort, objectSort, cloneableSort, serializableSort); - Sort aSortArr2 = ArraySort.getArraySort(aSortArr, objectSort, cloneableSort, serializableSort); - assertTrue("aSort[] should extend Cloneable: " + aSortArr.extendsSorts(), - aSortArr.extendsSorts().contains(cloneableSort)); - assertTrue("aSort[] should transitively extend Object ", - aSortArr.extendsTrans(objectSort)); - assertTrue("aSort[][] should transitively extend Object ", - aSortArr2.extendsTrans(objectSort)); - assertTrue("aSort[][] should transitively extend Cloneable ", - aSortArr2.extendsTrans(cloneableSort)); - assertTrue("aSort[][] should extend Cloneable[] ", - aSortArr2.extendsSorts().contains - (ArraySort.getArraySort(cloneableSort, objectSort, cloneableSort, serializableSort))); - assertTrue("Cloneable should extend Object ", - cloneableSort.extendsSorts().contains(objectSort)); - } - - public void testFunctionPolymorphicDecl() { - parseDecls("\\sorts { \\generic elem; list<[+elem]>; }\n" + - "\\functions {\n" + - " elem elem::head(list<[elem]>);\n" + - " list<[elem]> elem::tail(list<[elem]>);\n" + - " list<[elem]> elem::nil;\n" + - " list<[elem]> elem::cons(elem, list<[elem]>);\n" + - "}\n"); - - - SortDependingFunction head = (SortDependingFunction) nss.functions().lookup("any::head"); - SortDependingFunction inthead = head.getInstanceFor(nss.sorts().lookup("int"), serv); - assertEquals("int", inthead.sort().toString()); - assertEquals("[list<[int]>]", inthead.argSorts().toString()); - - SortDependingFunction cons = (SortDependingFunction) nss.functions().lookup("any::cons"); - SortDependingFunction intcons = cons.getInstanceFor(nss.sorts().lookup("int"), serv); - assertEquals("list<[int]>", intcons.sort().toString()); - assertEquals("[int,list<[int]>]", intcons.argSorts().toString()); - - } - - public void testFunctionDecl() { - parseDecls("\\sorts { elem; list; }\n" + - "\\functions {\n" + - " elem head(list);\n" + - " list tail(list);\n" + - " elem[] tailarray(elem[]);\n" + - " list nil;\n" + - " list cons(elem,list);\n" + - "}\n"); - - Sort elem = nss.sorts().lookup(new Name("elem")); - Sort list = nss.sorts().lookup(new Name("list")); - - Sort objectSort = serv.getJavaInfo().objectSort(); - Sort cloneableSort = serv.getJavaInfo().cloneableSort(); - Sort serializableSort = serv.getJavaInfo().serializableSort(); - - assertEquals("find head function", new Name("head"), - nss.functions().lookup(new Name("head")).name()); - assertEquals("head arity", 1, - ((Function)nss.functions().lookup(new Name("head"))).arity()); - assertEquals("head arg sort 0", list, - ((Function)nss.functions().lookup(new Name("head"))).argSort(0)); - assertEquals("head return sort", elem, - ((Function)nss.functions().lookup(new Name("head"))).sort()); - - assertEquals("find tail function", new Name("tail"), - nss.functions().lookup(new Name("tail")).name()); - assertEquals("tail arity", 1, - ((Function)nss.functions().lookup(new Name("tail"))).arity()); - assertEquals("tail arg sort 0", list, - ((Function)nss.functions().lookup(new Name("tail"))).argSort(0)); - assertEquals("tail return sort", list, - ((Function)nss.functions().lookup(new Name("tail"))).sort()); - assertEquals("tailarray arg sort 0", - ArraySort.getArraySort(elem, objectSort, cloneableSort, serializableSort), - - ((Function)nss.functions().lookup(new Name("tailarray"))).argSort(0)); - assertEquals("tailarray return sort", ArraySort.getArraySort(elem, - objectSort, cloneableSort, serializableSort), - ((Function)nss.functions().lookup(new Name("tailarray"))).sort()); - - assertEquals("find nil function", new Name("nil"), - nss.functions().lookup(new Name("nil")).name()); - assertEquals("nil arity", 0, - ((Function)nss.functions().lookup(new Name("nil"))).arity()); - assertEquals("nil return sort", list, - ((Function)nss.functions().lookup(new Name("nil"))).sort()); - - assertEquals("find cons function", new Name("cons"), - nss.functions().lookup(new Name("cons")).name()); - assertEquals("cons arity", 2, - ((Function)nss.functions().lookup(new Name("cons"))).arity()); - assertEquals("cons arg sort 0", elem, - ((Function)nss.functions().lookup(new Name("cons"))).argSort(0)); - assertEquals("cons arg sort 1", list, - ((Function)nss.functions().lookup(new Name("cons"))).argSort(1)); - assertEquals("cons return sort", list, - ((Function)nss.functions().lookup(new Name("cons"))).sort()); - } - - public void testPredicateDecl() { - parseDecls("\\sorts { elem; list; }\n" + - "\\predicates {\n" + - " isEmpty(list);\n" + - " contains(list,elem);\n" + - " maybe;\n" + - "}\n"); - - Sort elem = nss.sorts().lookup(new Name("elem")); - Sort list = nss.sorts().lookup(new Name("list")); - - - assertEquals("find isEmpty predicate", new Name("isEmpty"), - nss.functions().lookup(new Name("isEmpty")).name()); - assertEquals("isEmpty arity", 1, - ((Function)nss.functions().lookup(new Name("isEmpty"))).arity()); - assertEquals("isEmpty arg sort 0", list, - ((Function)nss.functions().lookup(new Name("isEmpty"))).argSort(0)); - assertEquals("isEmpty return sort", Sort.FORMULA, - ((Function)nss.functions().lookup(new Name("isEmpty"))).sort()); - - assertEquals("find contains predicate", new Name("contains"), - nss.functions().lookup(new Name("contains")).name()); - assertEquals("contains arity", 2, - ((Function)nss.functions().lookup(new Name("contains"))).arity()); - assertEquals("contains arg sort 0", list, - ((Function)nss.functions().lookup(new Name("contains"))).argSort(0)); - assertEquals("contains arg sort 1", elem, - ((Function)nss.functions().lookup(new Name("contains"))).argSort(1)); - assertEquals("contains return sort", Sort.FORMULA, - ((Function)nss.functions().lookup(new Name("contains"))).sort()); - - assertEquals("find maybe predicate", new Name("maybe"), - nss.functions().lookup(new Name("maybe")).name()); - assertEquals("maybe arity", 0, - ((Function)nss.functions().lookup(new Name("maybe"))).arity()); - assertEquals("maybe return sort", Sort.FORMULA, - ((Function)nss.functions().lookup(new Name("maybe"))).sort()); - } - - public void testSVDecl() { - parseDecls("\\sorts { elem; list; }\n" + - "\\schemaVariables {\n" + - " \\program Statement #s ; \n"+ - " \\term elem x,y ;\n" + - " \\variables list lv ;\n" + - " \\formula b;\n" + - "}\n"); - - - Sort elem = nss.sorts().lookup(new Name("elem")); - Sort list = nss.sorts().lookup(new Name("list")); - - Namespace variables = parsedSchemaVars; - - assertEquals("find SV x", new Name("x"), - variables.lookup(new Name("x")).name()); - assertTermSV("SV x type", - variables.lookup(new Name("x"))); - assertEquals("SV x sort", elem, - ((SchemaVariable)variables.lookup(new Name("x"))).sort()); - - assertEquals("find SV ", new Name("y"), - variables.lookup(new Name("y")).name()); - assertTermSV("SV y type", - variables.lookup(new Name("y"))); - assertEquals("SV y sort", elem, - ((SchemaVariable)variables.lookup(new Name("y"))).sort()); - - assertEquals("find SV ", new Name("lv"), - variables.lookup(new Name("lv")).name()); - assertVariableSV("SV lv type", - variables.lookup(new Name("lv"))); - assertEquals("SV lv sort", list, - ((SchemaVariable)variables.lookup(new Name("lv"))).sort()); - - assertEquals("find SV ", new Name("b"), - variables.lookup(new Name("b")).name()); - assertFormulaSV("SV b type", - variables.lookup(new Name("b"))); - assertEquals("SV b sort", Sort.FORMULA, - ((SchemaVariable)variables.lookup(new Name("b"))).sort()); - } - - - public void testAmbigiousDecls() { - try { - stringParser - ("\\sorts { elem; list; }\n" + - "\\functions {" + - "elem x;"+ - "elem fn;"+ - "elem p;" + - "}" + - "\\predicates {" + - "fn(elem);"+ - "y;" + - "p;" + - "}" + - "\\schemaVariables {\n" + - " \\program Statement #s ; \n"+ - " \\term elem x,y ;\n" + - " \\variables list lv ;\n" + - " \\formula b;\n" + - "}\n").decls(); - fail("Parsed in ambigious declaration"); - } catch(RuntimeException e){ - if(!(e.getCause() instanceof AmbigiousDeclException)){ - e.printStackTrace(); - fail("Unexpected excpetion. Testcase failed." +e); - } - } catch(RecognitionException re) { - if(!(re instanceof AmbigiousDeclException)) { - re.printStackTrace(); - fail("Unexpected recognition excpetion. Testcase failed." + re); - } - } - - } - - - public void testHeurDecl() { - parseDecls("\\heuristicsDecl { bool; shoot_foot; }"); - assertEquals("find heuristic bool", new Name("bool"), - nss.ruleSets().lookup(new Name("bool")).name()); - assertEquals("find heuristic shoot_foot", new Name("shoot_foot"), - nss.ruleSets().lookup(new Name("shoot_foot")).name()); - } - - -} \ No newline at end of file diff --git a/key/key.core/src/de/uka/ilkd/key/logic/sort/ProgramSVSort.java b/key/key.core/src/de/uka/ilkd/key/logic/sort/ProgramSVSort.java deleted file mode 100644 index da6f56f5902..00000000000 --- a/key/key.core/src/de/uka/ilkd/key/logic/sort/ProgramSVSort.java +++ /dev/null @@ -1,1367 +0,0 @@ -// This file is part of KeY - Integrated Deductive Software Design -// -// Copyright (C) 2001-2011 Universitaet Karlsruhe (TH), Germany -// Universitaet Koblenz-Landau, Germany -// Chalmers University of Technology, Sweden -// Copyright (C) 2011-2014 Karlsruhe Institute of Technology, Germany -// Technical University Darmstadt, Germany -// Chalmers University of Technology, Sweden -// -// The KeY system is protected by the GNU General -// Public License. See LICENSE.TXT for details. -// - -package de.uka.ilkd.key.logic.sort; - -import java.util.LinkedHashMap; -import java.util.Map; - -import org.key_project.util.ExtList; -import org.key_project.util.collection.DefaultImmutableSet; - -import de.uka.ilkd.key.java.*; -import de.uka.ilkd.key.java.abstraction.KeYJavaType; -import de.uka.ilkd.key.java.abstraction.PrimitiveType; -import de.uka.ilkd.key.java.abstraction.Type; -import de.uka.ilkd.key.java.declaration.ConstructorDeclaration; -import de.uka.ilkd.key.java.declaration.MethodDeclaration; -import de.uka.ilkd.key.java.declaration.VariableDeclaration; -import de.uka.ilkd.key.java.declaration.VariableSpecification; -import de.uka.ilkd.key.java.expression.ArrayInitializer; -import de.uka.ilkd.key.java.expression.Literal; -import de.uka.ilkd.key.java.expression.literal.StringLiteral; -import de.uka.ilkd.key.java.expression.operator.DLEmbeddedExpression; -import de.uka.ilkd.key.java.expression.operator.Instanceof; -import de.uka.ilkd.key.java.expression.operator.Intersect; -import de.uka.ilkd.key.java.expression.operator.Negative; -import de.uka.ilkd.key.java.expression.operator.New; -import de.uka.ilkd.key.java.expression.operator.NewArray; -import de.uka.ilkd.key.java.expression.operator.adt.*; -import de.uka.ilkd.key.java.reference.ConstructorReference; -import de.uka.ilkd.key.java.reference.ExecutionContext; -import de.uka.ilkd.key.java.reference.FieldReference; -import de.uka.ilkd.key.java.reference.MetaClassReference; -import de.uka.ilkd.key.java.reference.MethodName; -import de.uka.ilkd.key.java.reference.MethodReference; -import de.uka.ilkd.key.java.reference.ReferencePrefix; -import de.uka.ilkd.key.java.reference.SpecialConstructorReference; -import de.uka.ilkd.key.java.reference.SuperReference; -import de.uka.ilkd.key.java.reference.ThisReference; -import de.uka.ilkd.key.java.reference.TypeReference; -import de.uka.ilkd.key.java.statement.Catch; -import de.uka.ilkd.key.java.statement.For; -import de.uka.ilkd.key.java.statement.ForUpdates; -import de.uka.ilkd.key.java.statement.Guard; -import de.uka.ilkd.key.java.statement.LoopInit; -import de.uka.ilkd.key.java.statement.MethodBodyStatement; -import de.uka.ilkd.key.java.statement.Switch; -import de.uka.ilkd.key.logic.Name; -import de.uka.ilkd.key.logic.Named; -import de.uka.ilkd.key.logic.Namespace; -import de.uka.ilkd.key.logic.ProgramElementName; -import de.uka.ilkd.key.logic.Term; -import de.uka.ilkd.key.logic.op.IProgramMethod; -import de.uka.ilkd.key.logic.op.ProgramConstant; -import de.uka.ilkd.key.logic.op.ProgramVariable; -import de.uka.ilkd.key.logic.op.SchemaVariable; - -/** - * Special "sorts" used for schema variables matching program constructs - * (class ProgramSV). Not really sorts in the theoretical meaning of the word. - */ -public abstract class ProgramSVSort extends AbstractSort { - - // Keeps the mapping of ProgramSVSort names to - // ProgramSVSort instances (helpful in parsing - // schema variable declarations) - private static final Map name2sort = - new LinkedHashMap(60); - - //----------- Types of Expression Program SVs ---------------------------- - - public static final ProgramSVSort LEFTHANDSIDE - = new LeftHandSideSort(); - - public static final ProgramSVSort VARIABLE - = new ProgramVariableSort(); - - public static final ProgramSVSort STATICVARIABLE - = new StaticVariableSort(); - - public static final ProgramSVSort LOCALVARIABLE - = new LocalVariableSort(); - - public static final ProgramSVSort SIMPLEEXPRESSION - = new SimpleExpressionSort(); - - public static final ProgramSVSort NONSIMPLEEXPRESSION - = new NonSimpleExpressionSort(); - - public static final ProgramSVSort NONSIMPLEEXPRESSIONNOCLASSREFERENCE - = new NonSimpleExpressionNoClassReferenceSort(); - - public static final ProgramSVSort EXPRESSION - = new ExpressionSort(); - - - //----------- Initialisation and Creation expressions ------------------- - - public static final ProgramSVSort SIMPLE_NEW = new SimpleNewSVSort(); - - public static final ProgramSVSort NONSIMPLE_NEW = new NonSimpleNewSVSort(); - - public static final ProgramSVSort NEWARRAY = new NewArraySVSort(); - - public static final ProgramSVSort ARRAYINITIALIZER - = new ArrayInitializerSVSort(); - - public static final ProgramSVSort SPECIALCONSTRUCTORREFERENCE - = new SpecialConstructorReferenceSort(); - - - //----------- Expressions with restrictions on kind of type ------------- - - public static final NonSimpleMethodReferenceSort NONSIMPLEMETHODREFERENCE - = new NonSimpleMethodReferenceSort(); - - - //----------- Types of Statement Program SVs ----------------------------- - - public static final ProgramSVSort STATEMENT - = new StatementSort(); - - public static final ProgramSVSort CATCH - = new CatchSort(); - - public static final ProgramSVSort METHODBODY - = new MethodBodySort(); - - public static final ProgramSVSort NONMODELMETHODBODY - = new NonModelMethodBodySort(); - - public static final ProgramSVSort PROGRAMMETHOD - = new ProgramMethodSort(); - - //-----------Types-------------------------------------------------------- - - public static final ProgramSVSort TYPE - = new TypeReferenceSort(); - - public static final ProgramSVSort TYPENOTPRIMITIVE - = new TypeReferenceNotPrimitiveSort(); - - public static final ProgramSVSort CLASSREFERENCE - = new MetaClassReferenceSort(); - - - //-----------Others------------------------------------------------------- - - public static final ProgramSVSort METHODNAME - = new MethodNameSort(); - - public static final ProgramSVSort LABEL - = new LabelSort(); - - - //-----------Specials for primitive types--------------------------------- - - public static final ProgramSVSort JAVABOOLEANEXPRESSION - = new ExpressionSpecialPrimitiveTypeSort - ("JavaBooleanExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BOOLEAN}); - - public static final ProgramSVSort SIMPLEJAVABYTEEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaByteExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BYTE}); - - public static final ProgramSVSort SIMPLEJAVACHAREXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaCharExpression", new - PrimitiveType[]{PrimitiveType.JAVA_CHAR}); - - public static final ProgramSVSort SIMPLEJAVASHORTEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaShortExpression", new - PrimitiveType[]{PrimitiveType.JAVA_SHORT}); - - public static final ProgramSVSort SIMPLEJAVAINTEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaIntExpression", new - PrimitiveType[]{PrimitiveType.JAVA_INT}); - - public static final ProgramSVSort SIMPLEJAVALONGEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaLongExpression", new - PrimitiveType[]{PrimitiveType.JAVA_LONG}); - - public static final ProgramSVSort SIMPLEJAVABYTESHORTEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaByteShortExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT}); - - public static final ProgramSVSort SIMPLEJAVABYTESHORTINTEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaByteShortIntExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT}); - - - public static final ProgramSVSort SIMPLEANYJAVATYPEEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("AnyJavaTypeExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG}); - - - public static final ProgramSVSort SIMPLEANYJAVANUMBERTYPEEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("AnyJavaNumberTypeExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG, - PrimitiveType.JAVA_CHAR}); - - public static final ProgramSVSort SIMPLEJAVASHORTINTLONGEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaShortIntLongExpression", new - PrimitiveType[]{PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG}); - - public static final ProgramSVSort SIMPLEJAVAINTLONGEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaIntLongExpression", new - PrimitiveType[]{PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG}); - - public static final ProgramSVSort SIMPLEJAVACHARBYTESHORTINTEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaCharByteShortIntExpression", new - PrimitiveType[]{PrimitiveType.JAVA_CHAR, - PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT}); - - public static final ProgramSVSort SIMPLEJAVABIGINTEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("JavaBigintExpression", new PrimitiveType[]{PrimitiveType.JAVA_BIGINT}); - - - public static final ProgramSVSort SIMPLEANYNUMBERTYPEEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("AnyNumberTypeExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BYTE, - PrimitiveType.JAVA_SHORT, - PrimitiveType.JAVA_INT, - PrimitiveType.JAVA_LONG, - PrimitiveType.JAVA_CHAR, - PrimitiveType.JAVA_BIGINT}); - - public static final ProgramSVSort SIMPLEJAVABOOLEANEXPRESSION - = new SimpleExpressionSpecialPrimitiveTypeSort - ("SimpleJavaBooleanExpression", new - PrimitiveType[]{PrimitiveType.JAVA_BOOLEAN}); - - public static final ProgramSVSort SIMPLESTRINGEXPRESSION - = new SimpleExpressionStringSort("SimpleStringExpression"); - - public static final ProgramSVSort SIMPLENONSTRINGOBJECTEXPRESSION - = new SimpleExpressionNonStringObjectSort("SimpleNonStringObjectExpression"); - - - //--------------- Specials that can be get rid of perhaps-------------- - - public static final ProgramSVSort LOOPINIT = new LoopInitSort(); - - public static final ProgramSVSort GUARD = new GuardSort(); - - public static final ProgramSVSort FORUPDATES = new ForUpdatesSort(); - - public static final ProgramSVSort FORLOOP = new ForLoopSort(); - - public static final ProgramSVSort MULTIPLEVARDECL - = new MultipleVariableDeclarationSort(); - - public static final ProgramSVSort ARRAYPOSTDECL - = new ArrayPostDeclarationSort(); - - public static final ProgramSVSort SWITCH - = new SwitchSVSort(); - - public static final ProgramSVSort CONSTANT_PRIMITIVE_TYPE_VARIABLE - = new ConstantProgramVariableSort(new Name("ConstantPrimitiveTypeVariable"), false); - - public static final ProgramSVSort CONSTANT_STRING_VARIABLE - = new ConstantProgramVariableSort(new Name("ConstantStringVariable"), true); - - - public static final ProgramSVSort VARIABLEINIT - = new ProgramSVSort(new Name("VariableInitializer")) { - public boolean canStandFor(ProgramElement pe, - Services services) { - return true; - } - }; - - public static final ProgramSVSort NONSTRINGLITERAL = new NonStringLiteralSort(); - public static final ProgramSVSort STRINGLITERAL = new StringLiteralSort(); - - //--------------- Specials that match on certain names----------------- - - public static final ProgramSVSort ARRAYLENGTH - = new ArrayLengthSort(); - - //---------------REFERENCE SORTS ------------------------ - public static final ProgramSVSort EXECUTIONCONTEXT = new ExecutionContextSort(); - - - //-------------------------------------------------------------------------- - - public ProgramSVSort(Name name) { - super(name, DefaultImmutableSet.nil(), false); - name2sort.put(name, this); - } - - public boolean canStandFor(Term t) { - return true; - } - - public boolean canStandFor(ProgramElement check, - ExecutionContext ec, - Services services) { - return canStandFor(check, services); - } - - - protected abstract boolean canStandFor(ProgramElement check, - Services services); - - - public ProgramSVSort createInstance(String parameter) { - throw new UnsupportedOperationException(); - } - - //-------------Now the inner classes representing the----------------------- - //-------------different kinds of program SVs------------------------------- - - /** - * This sort represents a type of program schema variables that match - * only on

    • program variables or
    • static field references with - * a prefix that consists of
      • a program variable followed by a - * sequence of attribute accesses or
      • of a type reference followed by - * a sequence of attribute accesses
    - */ - private static class LeftHandSideSort extends ProgramSVSort { - - public LeftHandSideSort() { - super(new Name("LeftHandSide")); - } - - public LeftHandSideSort(Name name) { - super(name); - } - - public boolean canStandFor(Term t) { - return t.op() instanceof ProgramVariable; - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - - if (pe instanceof ProgramVariable || - pe instanceof ThisReference || - pe instanceof VariableSpecification) { - return true; - } - - if (pe instanceof FieldReference) { - FieldReference fr = (FieldReference) pe; - // we allow only static field references with a - // sequence of PVs or TypeRef - ReferencePrefix rp = fr.getReferencePrefix(); - if ((fr.getProgramVariable()).isStatic()) { - return (rp == null || - rp instanceof ThisReference || - rp instanceof TypeReference || - canStandFor(rp, services)); - } - } - - return false; - } - } - - /** - * This sort represents a type of program schema variables that match - * only on
    • program variables or
    • static field references with - * a prefix that consists of
      • a program variable followed by a - * sequence of attribute accesses or
      • of a type reference followed by - * a sequence of attribute accesses
    . In opposite to its - * super class it matches only if the field reference does not - * trigger static initialisation (i.e. if it is no active reference) - */ - private static class ProgramVariableSort - extends LeftHandSideSort { - - public ProgramVariableSort() { - super(new Name("Variable")); - } - - public boolean canStandFor(Term t) { - return t.op() instanceof ProgramVariable; - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - - ProgramVariable accessedField = null; - if (pe instanceof FieldReference) { - accessedField = ((FieldReference) pe).getProgramVariable(); - } else if (pe instanceof ProgramVariable) { - accessedField = (ProgramVariable) pe; - } - - if (accessedField != null && - accessedField.isStatic() && - !(accessedField instanceof ProgramConstant)) { - return false; - } - - return super.canStandFor(pe, services); - } - - } - - - private static class StaticVariableSort - extends LeftHandSideSort { - - public StaticVariableSort() { - super(new Name("StaticVariable")); - } - - public boolean canStandFor(Term t) { - return t.op() instanceof ProgramVariable && - ((ProgramVariable) t.op()).isStatic(); - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - - ProgramVariable accessedField = null; - if (pe instanceof FieldReference) { - accessedField = ((FieldReference) pe).getProgramVariable(); - } else if (pe instanceof ProgramVariable) { - accessedField = (ProgramVariable) pe; - } - if (accessedField != null) { - return - accessedField.isStatic() && - !(accessedField instanceof ProgramConstant) && - super.canStandFor(pe, services); - } - return false; - } - - } - - private static class LocalVariableSort - extends LeftHandSideSort { - - public LocalVariableSort() { - super(new Name("LocalVariable")); - } - - public boolean canStandFor(Term t) { - return t.op() instanceof ProgramVariable && - !((ProgramVariable) t.op()).isStatic(); - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - return pe instanceof ProgramVariable && !((ProgramVariable) pe).isStatic(); - } - - } - - - /** - * This sort represents a type of program schema variables that match - * only on
    • program variables or
    • static field references with - * a prefix that consists of
      • a program variable followed by a - * sequence of attribute accesses or
      • of a type reference followed by - * a sequence of attribute accesses
    • (negated) literal - * expressions or
    • instanceof expressions v instanceof T with an - * expression v that matches on a program variable SV
    - */ - private static class SimpleExpressionSort extends ProgramSVSort { - - public SimpleExpressionSort() { - super(new Name("SimpleExpression")); - } - - protected SimpleExpressionSort(Name n) { - super(n); - } - - public boolean canStandFor(Term t) { - return true; - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - if (pe instanceof Negative) { - return ((Negative) pe).getChildAt(0) instanceof Literal; - } - - if (pe instanceof StringLiteral) - return false; - - if (pe instanceof Literal) { - return true; - } - - if (pe instanceof Instanceof) { - ProgramElement v = ((Instanceof) pe).getChildAt(0); - return VARIABLE.canStandFor(v, services); - } - - if (pe instanceof SetUnion - || pe instanceof Singleton - || pe instanceof Intersect - || pe instanceof SetMinus - || pe instanceof AllFields - || pe instanceof SeqSingleton - || pe instanceof SeqConcat - || pe instanceof SeqLength - || pe instanceof SeqGet - || pe instanceof SeqIndexOf - || pe instanceof SeqConcat - || pe instanceof SeqSub - || pe instanceof SeqReverse) { - if (pe instanceof NonTerminalProgramElement) { - final NonTerminalProgramElement npe = (NonTerminalProgramElement) pe; - for (int i = 0, childCount = npe.getChildCount(); i < childCount; i++) { - if (!canStandFor(npe.getChildAt(i), services)) { - return false; - } - } - } - return true; - } else if (pe instanceof DLEmbeddedExpression) { - // this is a not so nice special case (all expressiosn within embedded expressions are considered to - // be side effect free; to handle it properly we need some meta constructs to decompose these expressions - return true; - } - return VARIABLE.canStandFor(pe, services); - } - } - - - private static class NonSimpleExpressionNoClassReferenceSort extends NonSimpleExpressionSort { - - public NonSimpleExpressionNoClassReferenceSort() { - super(new Name("NonSimpleExpressionNoClassReference")); - } - - /* Will not match on MetaClassReference variables */ - public boolean canStandFor(ProgramElement check, - Services services) { - if (!super.canStandFor(check, services) - || CLASSREFERENCE.canStandFor(check, services)) { - return false; - } - return true; - } - } - - - /** - * This sort represents a type of program schema variables that match - * only on all expressions which are not matched by simple expression - * SVs. - */ - private static class NonSimpleExpressionSort extends ProgramSVSort { - - public NonSimpleExpressionSort() { - super(new Name("NonSimpleExpression")); - } - - protected NonSimpleExpressionSort(Name n) { - super(n); - } - - protected boolean canStandFor(ProgramElement check, - Services services) { - if (!(check instanceof Expression) - || check instanceof SuperReference) { - return false; - } - return !SIMPLEEXPRESSION.canStandFor(check, services); - } - } - - /** - * This sort represents a type of program schema variables that match on - * all expressions only. - */ - private static class ExpressionSort extends ProgramSVSort { - - public ExpressionSort() { - super(new Name("Expression")); - } - - protected ExpressionSort(Name n) { - super(n); - } - - protected boolean canStandFor(ProgramElement pe, Services services) { - return (pe instanceof Expression); - } - - } - - /** - * This sort represents a type of program schema variables that match - * only string literals, e.g. "abc" - */ - private static class StringLiteralSort extends ProgramSVSort { - public StringLiteralSort() { - super(new Name("StringLiteral")); - } - - protected StringLiteralSort(Name n) { - super(n); - } - - // do not match a term - public boolean canStandFor(Term t) { - return false; - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - return (pe instanceof StringLiteral); - } - } - - /** - * This sort represents a type of program schema variables that match - * only on non-string literals - */ - private static class NonStringLiteralSort extends ProgramSVSort { - - public NonStringLiteralSort() { - super(new Name("NonStringLiteral")); - } - - protected NonStringLiteralSort(Name n) { - super(n); - } - - // not designed to match on terms - public boolean canStandFor(Term t) { - return false; - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - return (pe instanceof Literal - && !(pe instanceof StringLiteral)); - } - } - - - //----------- Initialisation and Creation expressions ------------------- - - - /** - * This sort represents a type of program schema variables that match - * only on Class Instance Creation Expressions, new C(), where all - * arguments are simple expressions. - */ - private static class SimpleNewSVSort extends ProgramSVSort { - - public SimpleNewSVSort() { - super(new Name("SimpleInstanceCreation")); - } - - protected boolean canStandFor(ProgramElement check, - Services services) { - if (!(check instanceof New)) { - return false; - } - for (Expression arg : ((New) check).getArguments()) { - if (NONSIMPLEEXPRESSION.canStandFor(arg, services)) { - return false; - } - } - return true; - } - } - - - /** - * This sort represents a type of program schema variables that match - * only on Class Instance Creation Expressions, new C(), where at - * least one argument is a non-simple expression - */ - private static class NonSimpleNewSVSort extends ProgramSVSort { - - public NonSimpleNewSVSort() { - super(new Name("NonSimpleInstanceCreation")); - } - - protected boolean canStandFor(ProgramElement check, - Services services) { - if (!(check instanceof New)) { - return false; - } - for (Expression arg : ((New) check).getArguments()) { - if (NONSIMPLEEXPRESSION.canStandFor(arg, services)) { - return true; - } - } - return false; - } - } - - /** - * This sort represents a type of program schema variables that match - * only on Array Creation Expressions, new A[] - */ - private static class NewArraySVSort extends ProgramSVSort { - public NewArraySVSort() { - super(new Name("ArrayCreation")); - } - - protected boolean canStandFor(ProgramElement check, - Services services) { - return (check instanceof NewArray); - } - } - - /** - * This sort represents a type of program schema variables that - * match only on Array Initializers. - */ - private static final class ArrayInitializerSVSort extends ProgramSVSort { - - public ArrayInitializerSVSort() { - super(new Name("ArrayInitializer")); - } - - protected boolean canStandFor(ProgramElement check, - Services services) { - return (check instanceof ArrayInitializer); - } - } - - - /** - * This sort represents a type of program schema variables that - * match only on Special Constructor References. - */ - private static class SpecialConstructorReferenceSort - extends ProgramSVSort { - - public SpecialConstructorReferenceSort() { - super(new Name("SpecialConstructorReference")); - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - return (pe instanceof SpecialConstructorReference); - } - - public boolean canStandFor(Term t) { - return (t.op() instanceof IProgramMethod && - !((IProgramMethod) t.op()).isModel()); - } - } - - - //----------- Types of Statement Program SVs ----------------------------- - - /** - * This sort represents a type of program schema variables that - * match only on statements - */ - private static class StatementSort extends ProgramSVSort { - - public StatementSort() { - super(new Name("Statement")); - } - - protected boolean canStandFor(ProgramElement pe, Services services) { - return (pe instanceof Statement); - } - - } - - /** - * This sort represents a type of program schema variables that - * match only on catch branches of try-catch-finally blocks - */ - private static final class CatchSort extends ProgramSVSort { - - public CatchSort() { - super(new Name("Catch")); - } - - protected boolean canStandFor(ProgramElement pe, Services services) { - return (pe instanceof Catch); - } - } - - /** - * This sort represents a type of program schema variables that - * match only on method body statements - */ - private static final class MethodBodySort extends ProgramSVSort { - - public MethodBodySort() { - super(new Name("MethodBody")); - } - - protected boolean canStandFor(ProgramElement check, Services services) { - return (check instanceof MethodBodyStatement); - } - } - - /** - * This sort represents a type of program schema variables that - * match only on method body statements for nonmodel methods for which - * an implementation is present. - */ - private static final class NonModelMethodBodySort extends ProgramSVSort { - - public NonModelMethodBodySort() { - super(new Name("NonModelMethodBody")); - } - - protected boolean canStandFor(ProgramElement pe, Services services) { - if (!(pe instanceof MethodBodyStatement)) { - return false; - } - - final IProgramMethod pm = - ((MethodBodyStatement) pe).getProgramMethod(services); - if (pm == null) { - return false; - } - final MethodDeclaration methodDeclaration = pm.getMethodDeclaration(); - - return !(//pm.isModel() || - methodDeclaration.getBody() == null) || - (methodDeclaration instanceof ConstructorDeclaration); - } - - } - - /** - * This sort represents a type of program schema variables that - * match on a method call with SIMPLE PREFIX and AT LEAST a - * NONSIMPLE expression in the ARGUMENTS. - */ - private static final class NonSimpleMethodReferenceSort extends ProgramSVSort { - - public NonSimpleMethodReferenceSort() { - super(new Name("NonSimpleMethodReference")); - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - if (pe instanceof MethodReference) { - MethodReference mr = (MethodReference) pe; - // FIX to bug #1223 (according to CS) - /* - if (mr.getReferencePrefix() instanceof SuperReference || - mr.getReferencePrefix() instanceof TypeReference) { - return false; - } - */ - if (mr.getReferencePrefix() != null && - NONSIMPLEEXPRESSION.canStandFor - (mr.getReferencePrefix(), services)) { - return false; - } - if (mr.getArguments() == null) { - return false; - } - for (int i = 0; i < mr.getArguments().size(); i++) { - if (NONSIMPLEEXPRESSION.canStandFor(mr.getArgumentAt(i), - services)) { - return true; - } - } - } - return false; - } - - public boolean canStandFor(Term t) { - return (t.op() instanceof IProgramMethod); - } - } - - /** - * This sort represents a type of program schema variables that - * match only on program methods - */ - private static final class ProgramMethodSort extends ProgramSVSort { - - public ProgramMethodSort() { - super(new Name("ProgramMethod")); - } - - protected boolean canStandFor(ProgramElement check, Services services) { - return (check instanceof IProgramMethod); - } - } - - //-----------Types-------------------------------------------------------- - - /** - * This sort represents a type of program schema variables that - * match only on type references. - */ - private static final class TypeReferenceSort extends ProgramSVSort { - - public TypeReferenceSort() { - super(new Name("Type")); - } - - protected boolean canStandFor(ProgramElement check, Services services) { - return (check instanceof TypeReference); - } - } - - - /** - * This sort represents a type of program schema variables that - * match anything except byte, char, short, int, and long. - */ - private static final class TypeReferenceNotPrimitiveSort extends ProgramSVSort { - - private final String matchName; - - public TypeReferenceNotPrimitiveSort() { - super(new Name("NonPrimitiveType")); - this.matchName = null; - } - - public TypeReferenceNotPrimitiveSort(String name) { - super(new Name("NonPrimitiveType" + (name != null ? "[name=" + name + "]" : ""))); - this.matchName = name; - } - - protected boolean canStandFor(ProgramElement check, Services services) { - if (!(check instanceof TypeReference)) return false; - if (((TypeReference) (check)).getKeYJavaType().getJavaType() - instanceof PrimitiveType) return false; - if (matchName != null) { - return matchName.equals(((TypeReference) (check)).getKeYJavaType().getJavaType().getFullName()); - } - return true; - } - - public ProgramSVSort createInstance(String parameter) { - return new TypeReferenceNotPrimitiveSort(parameter); - } - } - - /** - * This sort represents a type of program schema variables that - * match only on meta class references. - */ - private static final class MetaClassReferenceSort extends ProgramSVSort { - - public MetaClassReferenceSort() { - super(new Name("ClassReference")); - } - - protected boolean canStandFor(ProgramElement check, Services services) { - return (check instanceof MetaClassReference); - } - } - - - //-----------Names-------------------------------------------------------- - - /** - * This sort represents a type of program schema variables that match - * on names of method references, i.e. the "m" of o.m(p1,pn). - *

    - * It can also be made to match only specific method names - * defined by the parameter "name". - */ - private static class MethodNameSort extends ProgramSVSort { - private final ProgramElementName methodName; - - public MethodNameSort() { - super(new Name("MethodName")); - this.methodName = null; - } - - public MethodNameSort(ProgramElementName name) { - super(new Name("MethodName" + (name != null ? "[name=" + name + "]" : ""))); - this.methodName = name; - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - if (pe instanceof MethodName) { - return methodName == null || pe.equals(methodName); - } - return false; - } - - public ProgramSVSort createInstance(String parameter) { - return new MethodNameSort(new ProgramElementName(parameter)); - } - - } - - /** - * This sort represents a type of program schema variables that match - * on labels. - */ - private static final class LabelSort extends ProgramSVSort { - - public LabelSort() { - super(new Name("Label")); - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - return (pe instanceof Label); - } - } - - - /** - * This sort represents a type of program schema variables that match - * on string literals and string variables. - */ - public static final class SimpleExpressionStringSort - extends SimpleExpressionSort { - - public SimpleExpressionStringSort(String name) { - super(new Name(name)); - } - - /* Will only match on String variables */ - public boolean canStandFor(ProgramElement check, - ExecutionContext ec, - Services services) { - if (!super.canStandFor(check, ec, services)) { - return false; - } - //String Literal has SideEffects, but SimpleExpressionSort will not match - //if (check instanceof StringLiteral) return false; - if (check instanceof ProgramVariable) { - Namespace ns = services.getNamespaces().sorts(); - Sort stringSort = ns.lookup(new Name("java.lang.String")); - return ((ProgramVariable) check).getKeYJavaType().getSort().equals(stringSort); - } - return false; - } - } - - - public static class SimpleExpressionNonStringObjectSort - extends SimpleExpressionSort { - - public SimpleExpressionNonStringObjectSort(String name) { - super(new Name(name)); - } - - public boolean canStandFor(ProgramElement check, - ExecutionContext ec, - Services services) { - if (!super.canStandFor(check, ec, services)) { - return false; - } - if (check instanceof ProgramVariable) { - final Sort checkSort = ((ProgramVariable) check).sort(); - Namespace ns = services.getNamespaces().sorts(); - Sort stringSort = ns.lookup(new Name("java.lang.String")); - return checkSort.extendsTrans(services.getJavaInfo().objectSort()) - && !checkSort.equals(stringSort); - } - return false; - } - } - - //-----------Specials for primitive types--------------------------------- - - - /** - * This sort represents a type of program schema variables that match - * on simple expressions which have a special primitive type. - */ - private static final class SimpleExpressionSpecialPrimitiveTypeSort - extends SimpleExpressionSort { - - private final PrimitiveType[] allowed_types; - - public SimpleExpressionSpecialPrimitiveTypeSort - (String name, PrimitiveType[] allowed_types) { - - super(new Name(name)); - this.allowed_types = allowed_types; - } - - public boolean canStandFor(ProgramElement check, - ExecutionContext ec, - Services services) { - if (!super.canStandFor(check, ec, services)) { - return false; - } - final KeYJavaType kjt = getKeYJavaType(check, ec, services); - if (kjt != null) { - final Type type = kjt.getJavaType(); - for (PrimitiveType allowed_type : allowed_types) { - if (type == allowed_type) - return true; - } - } - return false; - } - } - - /** - * This sort represents a type of program schema variables that match - * on simple expressions which have a special primitive type. - */ - private static final class ExpressionSpecialPrimitiveTypeSort - extends ExpressionSort { - - private final PrimitiveType[] allowed_types; - - public ExpressionSpecialPrimitiveTypeSort - (String name, PrimitiveType[] allowed_types) { - - super(new Name(name)); - this.allowed_types = allowed_types; - } - - public boolean canStandFor(ProgramElement check, - ExecutionContext ec, - Services services) { - if (!super.canStandFor(check, ec, services)) { - return false; - } - - final KeYJavaType kjt = getKeYJavaType(check, ec, services); - if (kjt != null) { - final Type type = kjt.getJavaType(); - - for (PrimitiveType allowed_type : allowed_types) { - if (type == allowed_type) - return true; - } - } - return false; - } - } - - //-----------Specials (unnecessary?)-------------------------------------- - - - private static final class LoopInitSort extends ProgramSVSort { - - public LoopInitSort() { - super(new Name("LoopInit")); - } - - protected boolean canStandFor(ProgramElement check, Services services) { - return (check instanceof LoopInit); - } - } - - private static final class GuardSort extends ProgramSVSort { - public GuardSort() { - super(new Name("Guard")); - } - - protected boolean canStandFor(ProgramElement check, Services services) { - return (check instanceof Guard); - } - } - - private static final class ForUpdatesSort extends ProgramSVSort { - public ForUpdatesSort() { - super(new Name("ForUpdates")); - } - - protected boolean canStandFor(ProgramElement check, Services services) { - return (check instanceof ForUpdates); - - } - } - - private static final class ForLoopSort extends ProgramSVSort { - public ForLoopSort() { - super(new Name("ForLoop")); - } - - protected boolean canStandFor(ProgramElement check, Services services) { - return (check instanceof For); - } - } - - private static final class SwitchSVSort extends ProgramSVSort { - public SwitchSVSort() { - super(new Name("Switch")); - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - return (pe instanceof Switch); - } - } - - private static final class MultipleVariableDeclarationSort extends ProgramSVSort { - - public MultipleVariableDeclarationSort() { - super(new Name("MultipleVariableDeclaration")); - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - return pe instanceof VariableDeclaration && - ((VariableDeclaration) pe).getVariables().size() > 1; - } - - } - - private static final class ArrayPostDeclarationSort extends ProgramSVSort { - - public ArrayPostDeclarationSort() { - super(new Name("ArrayPostDeclaration")); - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - return pe instanceof VariableDeclaration && - ((VariableDeclaration) pe).getVariables().size() == 1 && - ((VariableDeclaration) pe).getVariables(). - get(0).getDimensions() > 0; - - } - - } - - - //------------------ stuff concerned with explicit and implicit elements---- - - - private static final class ConstantProgramVariableSort - extends ProgramSVSort { - - private final Name type = new Name("java.lang.String"); - private final boolean isString; - - public ConstantProgramVariableSort(Name svSortName, boolean string) { - super(svSortName); - isString = string; - } - - - public boolean canStandFor(Term t) { - return t.op() instanceof ProgramConstant && - isString == t.sort().name().equals(type); - } - - protected boolean canStandFor(ProgramElement pe, - Services services) { - return false; - } - } - - private static final class ArrayLengthSort extends ProgramSVSort { - - public ArrayLengthSort() { - super(new Name("ArrayLength")); - } - - protected boolean canStandFor(ProgramElement check, - Services services) { - if (check instanceof ProgramVariable) { - return check == services.getJavaInfo().getArrayLength(); - } - return false; - } - } - - private static final class ExecutionContextSort extends ProgramSVSort { - - public ExecutionContextSort() { - super(new Name("ExecutionContext")); - } - - protected boolean canStandFor(ProgramElement check, - Services services) { - return (check instanceof ExecutionContext); - } - } - - - //-------------------helper methods ------------------------------------ - - static boolean methodConstrReference(ProgramElement pe) { - return (pe instanceof MethodReference) - || (pe instanceof ConstructorReference); - } - - public ProgramElement getSVWithSort(ExtList l, Class alternative) { - for (final Object o : l) { - if (o instanceof SchemaVariable - && (((SchemaVariable) o).sort() == this)) { - return (ProgramElement) o; - } else if ((alternative.isInstance(o)) - && (!(o instanceof SchemaVariable))) { - return (ProgramElement) o; - } - } - return null; - } - - static KeYJavaType getKeYJavaType(ProgramElement pe, ExecutionContext ec, Services services) { - return services.getTypeConverter().getKeYJavaType((Expression) pe, ec); - } - - static boolean implicit(ProgramElement pe) { - if (pe instanceof ProgramVariable) { - if (!((ProgramVariable) pe).isMember()) return false; - } - - final String elemname; - if (pe instanceof NamedProgramElement) { - elemname = ((NamedProgramElement) pe).getProgramElementName().getProgramName(); - } else if (pe instanceof Named) { - final Name n = ((Named) pe).name(); - if (n instanceof ProgramElementName) { - elemname = ((ProgramElementName) n).getProgramName(); - } else { - elemname = n.toString(); - } - } else { - System.err.println("Please check implicit in ProgramSVSort"); - return false; - } - return elemname.charAt(0) == '<'; - } - - public static Map name2sort() { - return name2sort; - } - -} From f3a2f9027711769b8d813786f6c9095dd586621a Mon Sep 17 00:00:00 2001 From: Alexander Weigl Date: Sat, 13 Jan 2024 16:13:38 +0100 Subject: [PATCH 08/13] support for polymorphic datatypes --- key.core/src/main/antlr4/KeYParser.g4 | 2 +- .../nparser/builder/DeclarationBuilder.java | 46 +++++++++---------- .../key/nparser/builder/TacletPBuilder.java | 2 +- .../uka/ilkd/key/parser/TestDeclParser.java | 5 ++ 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/key.core/src/main/antlr4/KeYParser.g4 b/key.core/src/main/antlr4/KeYParser.g4 index 8db7fa302a9..61afb1fe1bf 100644 --- a/key.core/src/main/antlr4/KeYParser.g4 +++ b/key.core/src/main/antlr4/KeYParser.g4 @@ -248,7 +248,7 @@ datatype_decl: doc=DOC_COMMENT? // weigl: all datatypes are free! // FREE? - name=simple_ident + name=simple_ident formal_sort_parameters? EQUALS datatype_constructor (OR datatype_constructor)* SEMI diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java index 4163ca4aa67..bdd3dd7dc69 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java @@ -3,11 +3,6 @@ * SPDX-License-Identifier: GPL-2.0-only */ package de.uka.ilkd.key.nparser.builder; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - import de.uka.ilkd.key.java.Services; import de.uka.ilkd.key.java.abstraction.KeYJavaType; import de.uka.ilkd.key.logic.*; @@ -17,7 +12,6 @@ import de.uka.ilkd.key.nparser.KeYParser; import de.uka.ilkd.key.nparser.ParsingFacade; import de.uka.ilkd.key.rule.RuleSet; - import de.uka.ilkd.key.util.Pair; import org.antlr.v4.runtime.Token; import org.key_project.util.collection.DefaultImmutableSet; @@ -26,10 +20,7 @@ import org.key_project.util.collection.ImmutableSet; import org.key_project.util.java.StringUtil; -import org.antlr.v4.runtime.Token; import java.util.*; -import java.util.stream.Collector; -import java.util.stream.Collectors; /** * This visitor evaluates all basic (level 0) declarations. This includes: @@ -57,21 +48,30 @@ public DeclarationBuilder(Services services, NamespaceSet nss) { @Override public Object visitDecls(KeYParser.DeclsContext ctx) { mapMapOf(ctx.option_decls(), ctx.options_choice(), ctx.ruleset_decls(), ctx.sort_decls(), - ctx.datatype_decls(), - ctx.prog_var_decls(), ctx.schema_var_decls()); + ctx.datatype_decls(), + ctx.prog_var_decls(), ctx.schema_var_decls()); return null; } @Override public Object visitDatatype_decl(KeYParser.Datatype_declContext ctx) { - // boolean freeAdt = ctx.FREE() != null; var name = ctx.name.getText(); + List> typeParameters = accept(ctx.formal_sort_parameters()); var doc = ctx.DOC_COMMENT() != null ? ctx.DOC_COMMENT().getText() : null; var origin = BuilderHelpers.getPosition(ctx); - var s = new SortImpl(new Name(name), ImmutableSet.empty(), false, doc, origin); - sorts().add(s); + if (typeParameters == null) { + var s = new SortImpl(new Name(name), ImmutableSet.empty(), false, doc, origin); + sorts().add(s); + } else { + var tp = typeParameters.stream().map(it -> (GenericSort) it.second).collect(ImmutableList.collector()); + var variance = typeParameters.stream().map(it -> it.first).collect(ImmutableList.collector()); + var s = new ParametricSort( + new Name(name), ImmutableSet.empty(), false, tp, variance, + doc, origin); + sorts().add(s); + } return null; } @@ -156,8 +156,8 @@ public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) { //assert sortIds != null; var documentation = ParsingFacade.getValueDocumentation(ctx.DOC_COMMENT()); - for(var idCtx : ctx.sortIds.sortId()){ - //for (Pair>> sortId : sortIds) { + for (var idCtx : ctx.sortIds.sortId()) { + //for (Pair>> sortId : sortIds) { var name = idCtx.simple_ident_dots().getText(); var brackets = StringUtil.repeat("[]", idCtx.EMPTYBRACKETS().size()); List> typeParams = accept(idCtx.formal_sort_parameters()); @@ -172,8 +172,8 @@ public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) { // attention: no expand to java.lang here! if (sorts().lookup(sortName) == null) { Sort s = null; - if(isParametricSort) { - if(isGenericSort) { + if (isParametricSort) { + if (isGenericSort) { semanticError(ctx, "Generic sorts are not allowed to have type parameters."); } @@ -186,13 +186,13 @@ public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) { ImmutableList> params = typeParams.stream().map(it -> - new Pair<>((GenericSort) it.second, it.first)) + new Pair<>((GenericSort) it.second, it.first)) .collect(ImmutableSLList.toImmutableList()); s = new ParametricSort(sortName, ext, isAbstractSort, params); - }else if (isGenericSort) { + } else if (isGenericSort) { try { s = new GenericSort(sortName, ext, oneOf, documentation, - BuilderHelpers.getPosition(ctx)); + BuilderHelpers.getPosition(ctx)); } catch (GenericSupersortException e) { semanticError(ctx, "Illegal sort given"); } @@ -201,10 +201,10 @@ public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) { } else { if (isProxySort) { s = new ProxySort(sortName, ext, documentation, - BuilderHelpers.getPosition(idCtx)); + BuilderHelpers.getPosition(idCtx)); } else { s = new SortImpl(sortName, ext, isAbstractSort, - documentation, BuilderHelpers.getPosition(idCtx)); + documentation, BuilderHelpers.getPosition(idCtx)); } } assert s != null; diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/TacletPBuilder.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/TacletPBuilder.java index f58f7a4615f..5024a2b3441 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/TacletPBuilder.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/TacletPBuilder.java @@ -328,7 +328,7 @@ private Term createQuantifiedFormula(KeYParser.Datatype_constructorContext conte var argSort = context.argSort.stream() - .map(it -> sorts().lookup(it.getText())) + .map(it -> (Sort) accept(it)) .toList(); var argNames = context.argName.stream() diff --git a/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java b/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java index e58ee9a1f0b..06b9efec44a 100644 --- a/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java +++ b/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java @@ -102,6 +102,11 @@ public void testParametericSortDecl() { assertEquals("{any}", coll.extendsSorts().toString()); } + @Test + public void testParametricDatatype() { + evaluateDeclarations("\\sorts{\\generic E;} \\datatypes { List<[E]> = Nil | Cons(E obj, List<[E]> tail); }"); + } + @Test public void testParametericSortDeclFails() { Assertions.assertThrows(Exception.class, () -> evaluateDeclarations("\\sorts { parametric<[E]>; }")); From 2ca3631b6bff190bc01f1ba61bdcbe377e2d1f25 Mon Sep 17 00:00:00 2001 From: Alexander Weigl Date: Sun, 5 May 2024 18:50:22 +0200 Subject: [PATCH 09/13] fix merge error, reformat --- .../de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java index a736fd8ebe9..a5096fde679 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java @@ -3,10 +3,7 @@ * SPDX-License-Identifier: GPL-2.0-only */ package de.uka.ilkd.key.nparser.builder; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; import de.uka.ilkd.key.java.Services; import de.uka.ilkd.key.java.abstraction.KeYJavaType; @@ -23,7 +20,6 @@ import org.key_project.logic.Name; import org.key_project.logic.Named; import org.key_project.logic.sort.Sort; -import org.key_project.util.collection.DefaultImmutableSet; import org.key_project.util.collection.ImmutableList; import org.key_project.util.collection.ImmutableSLList; import org.key_project.util.collection.ImmutableSet; From a21dded74a8ba0c75088e8cdb6478a43d18a3c38 Mon Sep 17 00:00:00 2001 From: Alexander Weigl Date: Thu, 23 May 2024 18:35:21 +0200 Subject: [PATCH 10/13] fix merge errors --- .../key/nparser/builder/DefaultBuilder.java | 1 + .../uka/ilkd/key/parser/TestDeclParser.java | 62 ++----------------- 2 files changed, 7 insertions(+), 56 deletions(-) diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java index 42bafd95666..0668b132bff 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java @@ -29,6 +29,7 @@ import org.key_project.logic.Name; import org.key_project.logic.Named; +import org.key_project.logic.ParsableVariable; import org.key_project.logic.sort.Sort; import org.key_project.util.collection.ImmutableList; import org.key_project.util.collection.ImmutableSLList; diff --git a/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java b/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java index 022dbffc47a..fbbbd5ebf6d 100644 --- a/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java +++ b/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java @@ -11,7 +11,6 @@ import de.uka.ilkd.key.logic.op.*; import de.uka.ilkd.key.logic.sort.ArraySort; import de.uka.ilkd.key.logic.sort.GenericSort; -import de.uka.ilkd.key.logic.sort.ParametricSort; import de.uka.ilkd.key.logic.sort.ProxySort; import de.uka.ilkd.key.nparser.KeyIO; import de.uka.ilkd.key.nparser.NamespaceBuilder; @@ -22,9 +21,7 @@ import org.key_project.logic.sort.Sort; import org.key_project.util.collection.DefaultImmutableSet; import org.key_project.util.collection.ImmutableSet; -import org.key_project.util.collection.Immutables; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -80,53 +77,6 @@ public void testSortDecl() { } - @Test - public void testSortDeclFail() { - evaluateDeclarations("\\sorts { X; X; }"); - } - - public void testParametericSortDecl() { - evaluateDeclarations("\\sorts { \\generic E, F, G; " + - "coll<[E]>; list<[+E]> \\extends coll<[E]>;" + - "var<[-E, +F, G]>; }"); - - Sort e = nss.sorts().lookup("E"); - ParametricSort list = (ParametricSort) nss.sorts().lookup("list"); - ParametricSort coll = (ParametricSort) nss.sorts().lookup("coll"); - ParametricSort var = (ParametricSort) nss.sorts().lookup("var"); - - assertInstanceOf(GenericSort.class, e); - assertInstanceOf(ParametricSort.class, coll); - assertInstanceOf(ParametricSort.class, list); - - assertEquals( - Immutables.listOf(CONTRAVARIANT, COVARIANT, INVARIANT), - var.getCovariances()); - - assertEquals("{coll<[E]>}", list.extendsSorts().toString()); - - assertEquals("{any}", coll.extendsSorts().toString()); - } - - @Test - public void testParametricDatatype() { - evaluateDeclarations( - "\\sorts{\\generic E;} \\datatypes { List<[E]> = Nil | Cons(E obj, List<[E]> tail); }"); - } - - @Test - public void testParametericSortDeclFails() { - Assertions.assertThrows(Exception.class, - () -> evaluateDeclarations("\\sorts { parametric<[E]>; }")); - // assertTrue(ex.getMessage().contains("Formal type parameters must be (already declared) - // generic sorts")); - Assertions.assertThrows(Exception.class, - () -> evaluateDeclarations("\\sorts { \\generic E; doubled<[E,E]>; }")); - Assertions.assertThrows(Exception.class, - () -> evaluateDeclarations("\\sorts { parametric<[int]>; }")); - Assertions.assertThrows(Exception.class, - () -> evaluateDeclarations("\\sorts { \\generic E; int<[E]>; }")); - } private GenericSort checkGenericSort(Named name, ImmutableSet pExt, ImmutableSet pOneOf) { @@ -271,7 +221,7 @@ private void assertVariableSV(String msg, Object o) { */ private void assertTermSV(String msg, Object o) { assertInstanceOf(TermSV.class, o, "The named object: " + o + " is of type " - + o.getClass() + ", but the type SchemaVariable was expected"); + + o.getClass() + ", but the type SchemaVariable was expected"); assertNotSame(((TermSV) o).sort(), JavaDLTheory.FORMULA, "Schemavariable is not allowed to match a term of sort FORMULA."); } @@ -282,7 +232,7 @@ private void assertTermSV(String msg, Object o) { */ private void assertFormulaSV(String msg, Object o) { assertInstanceOf(FormulaSV.class, o, "The named object: " + o + " is of type " - + o.getClass() + ", but the type SchemaVariable was expected"); + + o.getClass() + ", but the type SchemaVariable was expected"); assertSame(((FormulaSV) o).sort(), JavaDLTheory.FORMULA, "Only matches to terms of sort FORMULA allowed. " + "But term has sort " + ((FormulaSV) o).sort()); @@ -424,19 +374,19 @@ public void testSVDecl() { assertEquals(new Name("x"), variables.lookup(new Name("x")).name(), "find SV x"); assertTermSV("SV x type", variables.lookup(new Name("x"))); - assertEquals(elem, variables.lookup(new Name("x")).sort(), "SV x sort"); + assertEquals(elem, ((TermSV) variables.lookup(new Name("x"))).sort(), "SV x sort"); assertEquals(new Name("y"), variables.lookup(new Name("y")).name(), "find SV "); assertTermSV("SV y type", variables.lookup(new Name("y"))); - assertEquals(elem, variables.lookup(new Name("y")).sort(), "SV y sort"); + assertEquals(elem, ((TermSV) variables.lookup(new Name("y"))).sort(), "SV y sort"); assertEquals(new Name("lv"), variables.lookup(new Name("lv")).name(), "find SV "); assertVariableSV("SV lv type", variables.lookup(new Name("lv"))); - assertEquals(list, variables.lookup(new Name("lv")).sort(), "SV lv sort"); + assertEquals(list, ((VariableSV) variables.lookup(new Name("lv"))).sort(), "SV lv sort"); assertEquals(new Name("b"), variables.lookup(new Name("b")).name(), "find SV "); assertFormulaSV("SV b type", variables.lookup(new Name("b"))); - assertEquals(JavaDLTheory.FORMULA, variables.lookup(new Name("b")).sort(), + assertEquals(JavaDLTheory.FORMULA, ((FormulaSV) variables.lookup(new Name("b"))).sort(), "SV b sort"); } From 7b72f7185ec5ad9072274091c77cbf33adacb432 Mon Sep 17 00:00:00 2001 From: Alexander Weigl Date: Wed, 26 Jun 2024 18:30:33 +0200 Subject: [PATCH 11/13] fix junit4 class --- .../util/collection/TestSLList.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/key.util/src/test/java/org/key_project/util/collection/TestSLList.java b/key.util/src/test/java/org/key_project/util/collection/TestSLList.java index b0935bc1221..d198eddefda 100644 --- a/key.util/src/test/java/org/key_project/util/collection/TestSLList.java +++ b/key.util/src/test/java/org/key_project/util/collection/TestSLList.java @@ -3,9 +3,10 @@ * SPDX-License-Identifier: GPL-2.0-only */ package org.key_project.util.collection; -import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.assertEquals; public class TestSLList { @@ -32,19 +33,23 @@ public void testReplace() { assertEquals("[1,2,3,0]", l.replace(3, 0).toString()); } - @Test(expected = IndexOutOfBoundsException.class) + @Test public void testReplaceBounds1() { - ImmutableList l = ImmutableSLList.nil().prepend(1, 2, 3, 4); + Assertions.assertThrows(IndexOutOfBoundsException.class, () -> { + ImmutableList l = ImmutableSLList.nil().prepend(1, 2, 3, 4); - System.out.println(l.replace(-1, 0)); + System.out.println(l.replace(-1, 0)); + }); } // revealed a bug - @Test(expected = IndexOutOfBoundsException.class) + @Test public void testReplaceBounds2() { - ImmutableList l = ImmutableSLList.nil().prepend(1, 2, 3, 4); + Assertions.assertThrows(IndexOutOfBoundsException.class, () -> { + ImmutableList l = ImmutableSLList.nil().prepend(1, 2, 3, 4); - System.out.println(l.replace(4, 0)); + System.out.println(l.replace(4, 0)); + }); } } From 62383042b4f213318302d06fd063075503c35f13 Mon Sep 17 00:00:00 2001 From: Mattias Ulbrich Date: Tue, 4 Mar 2025 16:42:53 +0100 Subject: [PATCH 12/13] further towards polymorphic sorts --- .../de/uka/ilkd/key/logic/NamespaceSet.java | 33 +++- .../ilkd/key/logic/sort/ParametricSort.java | 151 ------------------ .../logic/sort/ParametricSortInstance.java | 57 +++---- .../de/uka/ilkd/key/logic/sort/SortImpl.java | 26 +-- .../nparser/builder/DeclarationBuilder.java | 18 ++- .../key/nparser/builder/DefaultBuilder.java | 27 ++-- .../ilkd/key/parser/DefaultTermParser.java | 11 +- .../proof/io/IntermediateProofReplayer.java | 2 +- .../util/collection/Immutables.java | 15 ++ 9 files changed, 106 insertions(+), 234 deletions(-) delete mode 100644 key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSort.java diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/NamespaceSet.java b/key.core/src/main/java/de/uka/ilkd/key/logic/NamespaceSet.java index 8b6771b1b6c..257e116b269 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/logic/NamespaceSet.java +++ b/key.core/src/main/java/de/uka/ilkd/key/logic/NamespaceSet.java @@ -7,6 +7,8 @@ import de.uka.ilkd.key.logic.op.IProgramVariable; import de.uka.ilkd.key.logic.op.JFunction; import de.uka.ilkd.key.logic.op.QuantifiableVariable; +import de.uka.ilkd.key.logic.sort.ParametricSortDeclaration; +import de.uka.ilkd.key.logic.sort.ParametricSortInstance; import de.uka.ilkd.key.rule.RuleSet; import org.key_project.logic.Name; @@ -21,6 +23,7 @@ public class NamespaceSet { private Namespace funcNS = new Namespace<>(); private Namespace ruleSetNS = new Namespace<>(); private Namespace sortNS = new Namespace<>(); + private Namespace parametricSortNS = new Namespace<>(); private Namespace choiceNS = new Namespace<>(); public NamespaceSet() { @@ -28,32 +31,35 @@ public NamespaceSet() { public NamespaceSet(Namespace varNS, Namespace funcNS, - Namespace sortNS, Namespace ruleSetNS, Namespace choiceNS, + Namespace sortNS, + Namespace parametricSortNS, + Namespace ruleSetNS, Namespace choiceNS, Namespace programVarNS) { this.varNS = varNS; this.progVarNS = programVarNS; this.funcNS = funcNS; this.sortNS = sortNS; + this.parametricSortNS = parametricSortNS; this.ruleSetNS = ruleSetNS; this.choiceNS = choiceNS; } public NamespaceSet copy() { return new NamespaceSet(variables().copy(), functions().copy(), - sorts().copy(), + sorts().copy(), parametricSorts().copy(), ruleSets().copy(), choices().copy(), programVariables().copy()); } public NamespaceSet shallowCopy() { - return new NamespaceSet(variables(), functions(), sorts(), ruleSets(), - choices(), - programVariables()); + return new NamespaceSet(variables(), functions(), sorts(), parametricSorts(), ruleSets(), + choices(), programVariables()); } // TODO MU: Rename into sth with wrap or similar public NamespaceSet copyWithParent() { return new NamespaceSet(new Namespace<>(variables()), new Namespace<>(functions()), new Namespace<>(sorts()), + new Namespace<>(parametricSorts()), new Namespace<>(ruleSets()), new Namespace<>(choices()), new Namespace<>(programVariables())); } @@ -98,6 +104,14 @@ public void setSorts(Namespace sortNS) { this.sortNS = sortNS; } + public Namespace parametricSorts() { + return parametricSortNS; + } + + public void setParametricSorts(Namespace parametricSortNS) { + this.parametricSortNS = parametricSortNS; + } + public Namespace choices() { return choiceNS; } @@ -110,6 +124,7 @@ public void add(NamespaceSet ns) { variables().add(ns.variables()); programVariables().add(ns.programVariables()); sorts().add(ns.sorts()); + parametricSorts().add(ns.parametricSorts()); ruleSets().add(ns.ruleSets()); functions().add(ns.functions()); choices().add(ns.choices()); @@ -119,7 +134,7 @@ public void add(NamespaceSet ns) { * returns all namespaces in an array */ private Namespace[] asArray() { - return new Namespace[] { variables(), programVariables(), sorts(), ruleSets(), functions(), + return new Namespace[] { variables(), programVariables(), sorts(), parametricSorts(), ruleSets(), functions(), choices() }; } @@ -190,23 +205,26 @@ public void seal() { funcNS.seal(); ruleSetNS.seal(); sortNS.seal(); + parametricSortNS.seal(); choiceNS.seal(); } public boolean isEmpty() { return varNS.isEmpty() && programVariables().isEmpty() && funcNS.isEmpty() - && ruleSetNS.isEmpty() && sortNS.isEmpty() && choiceNS.isEmpty(); + && ruleSetNS.isEmpty() && sortNS.isEmpty() && parametricSortNS.isEmpty() && choiceNS.isEmpty(); } // create a namespace public NamespaceSet simplify() { return new NamespaceSet(varNS.simplify(), funcNS.simplify(), sortNS.simplify(), + parametricSortNS.simplify(), ruleSetNS.simplify(), choiceNS.simplify(), progVarNS.simplify()); } public NamespaceSet getCompression() { return new NamespaceSet(varNS.compress(), funcNS.compress(), sortNS.compress(), + parametricSortNS.compress(), ruleSetNS.compress(), choiceNS.compress(), progVarNS.compress()); } @@ -218,6 +236,7 @@ public void flushToParent() { public NamespaceSet getParent() { return new NamespaceSet(varNS.parent(), funcNS.parent(), sortNS.parent(), + parametricSortNS.parent(), ruleSetNS.parent(), choiceNS.parent(), progVarNS.parent()); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSort.java b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSort.java deleted file mode 100644 index 7d07844ecc8..00000000000 --- a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSort.java +++ /dev/null @@ -1,151 +0,0 @@ -/* This file is part of KeY - https://key-project.org - * KeY is licensed under the GNU General Public License Version 2 - * SPDX-License-Identifier: GPL-2.0-only */ -package de.uka.ilkd.key.logic.sort; - -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.function.Function; - -import de.uka.ilkd.key.ldt.JavaDLTheory; - -import org.key_project.logic.Name; -import org.key_project.logic.sort.AbstractSort; -import org.key_project.logic.sort.Sort; -import org.key_project.util.collection.ImmutableList; -import org.key_project.util.collection.ImmutableSet; - -/** - * Here is a short class diagram, written for PlantUML. - * You can create the PNG file by feeding this SourceFile into PlantUML or - * by entering the text into https://www.planttext.com/, e.g. - * - * @startuml interface Sort - * abstract class AbstractSort - * class SortImpl - *

    - * class PolymorphicSort - * class PolymorphicSortInstance - * class NullSort - * class GenericSort - *

    - * Sort <|-- AbstractSort - * AbstractSort <|-- SortImpl - * AbstractSort <|-- PolymorphicSort - * AbstractSort <|-- GenericSort - * Sort <|-- PolymorphicSortInstance - * Sort <|-- NullSort - *

    - * PolymorphicSortInstance --> "1" PolymorphicSort : base - * PolymorphicSortInstance --> "*" Sort :args - * PolymorphicSort --> "*" GenericSort : typeParameters - *

    - *

    - * PolymorphicSort : bounds : List[Variance] - *

    - * enum Variance { - * COVARIANT - * CONTRAVARIANT - * INVARIANT - * } - * @enduml - */ - -public class ParametricSort extends AbstractSort { - public enum Variance { - COVARIANT, - CONTRAVARIANT, - INVARIANT; - } - - private final ImmutableList parameters; - - private final ImmutableList covariances; - - private final ImmutableSet extendsSorts; - - public ParametricSort(Name name, ImmutableSet ext, boolean isAbstract, - ImmutableList parameters, ImmutableList covariances, - String documentation, String origin) { - super(name, isAbstract, origin, documentation); - this.extendsSorts = ext; - this.parameters = parameters; - this.covariances = covariances; - } - - public record SortParameter(GenericSort first, Variance second) { - } - - public ParametricSort(Name name, ImmutableSet ext, boolean isAbstract, - ImmutableList sortParams) { - this(name, ext, isAbstract, sortParams.map(x -> x.first), sortParams.map(x -> x.second), - null, null); - } - - public Function getInstantiation(ImmutableList args) { - IdentityHashMap map = new IdentityHashMap<>(); - - if (args.size() != parameters.size()) { - throw new IllegalArgumentException("Parametric type " + name() + - " expected " + parameters.size() + " arguments, but received " + - args); - } - - ImmutableList p = parameters; - while (!args.isEmpty()) { - map.put(p.head(), args.head()); - p = p.tail(); - args = args.tail(); - } - - return new SortInstantiator(map); - } - - public static class SortInstantiator implements Function { - private final Map map; - - public SortInstantiator(Map map) { - this.map = map; - } - - @Override - public Sort apply(Sort sort) { - Sort mapped = map.get(sort); - if (mapped != null) { - return mapped; - } - if (sort instanceof ParametricSortInstance psi) { - return psi.map(this); - } else { - return sort; - } - } - } - - public ImmutableList getParameters() { - return parameters; - } - - public ImmutableList getCovariances() { - return covariances; - } - - @Override - public ImmutableSet extendsSorts() { - return extendsSorts; - } - - @Override - public boolean extendsTrans(Sort sort) { - if (sort == this) { - return true; - } else if (this == JavaDLTheory.FORMULA || this == JavaDLTheory.UPDATE) { - return false; - } else if (sort == JavaDLTheory.ANY) { - return true; - } - - return extendsSorts() - .exists((Sort superSort) -> superSort == sort || superSort.extendsTrans(sort)); - } -} diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java index 0c9c72b6921..b65695dbc57 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java +++ b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java @@ -8,6 +8,7 @@ import java.util.WeakHashMap; import java.util.function.Function; +import org.jspecify.annotations.NullMarked; import org.key_project.logic.Name; import org.key_project.logic.sort.AbstractSort; import org.key_project.logic.sort.Sort; @@ -17,20 +18,21 @@ import org.jspecify.annotations.Nullable; +@NullMarked public class ParametricSortInstance extends AbstractSort { private static final Map CACHE = new WeakHashMap<>(); private final ImmutableList parameters; - private final ParametricSort base; + private final ParametricSortDeclaration base; private final ImmutableSet extendsSorts; - public static ParametricSortInstance get(ParametricSort base, ImmutableList parameters, - @Nullable String documentation, @Nullable String origin) { + public static ParametricSortInstance get(ParametricSortDeclaration base, + ImmutableList parameters) { ParametricSortInstance sort = - new ParametricSortInstance(base, parameters, documentation, origin); + new ParametricSortInstance(base, parameters); ParametricSortInstance cached = CACHE.get(sort); if (cached != null) { return cached; @@ -40,55 +42,56 @@ public static ParametricSortInstance get(ParametricSort base, ImmutableList parameters, - String documentation, String origin) { - super(makeName(base, parameters), base.isAbstract(), documentation, origin); + // This must only be called in #get, which ensures that the cache is used. + private ParametricSortInstance(ParametricSortDeclaration base, ImmutableList parameters) { + super(makeName(base, parameters), base.isAbstract(), base.getDocumentation(), base.getOrigin()); this.extendsSorts = computeExt(base, parameters); this.base = base; this.parameters = parameters; } - private static ImmutableSet computeExt(ParametricSort base, + private static ImmutableSet computeExt(ParametricSortDeclaration base, ImmutableList parameters) { ImmutableSet result = DefaultImmutableSet.nil(); // 1. extensions by base sort - ImmutableSet baseExt = base.extendsSorts(); + ImmutableSet baseExt = base.getExtendedSorts(); if (!baseExt.isEmpty()) { - Function inster = base.getInstantiation(parameters); + Function inster = base.getInstantiator(parameters); for (Sort s : baseExt) { result = result.add(inster.apply(s)); } } // 2. extensions by variances - ImmutableList cov = base.getCovariances(); - for (int i = 0; !cov.isEmpty(); i++, cov = cov.tail()) { - switch (cov.head()) { - case COVARIANT -> { - // take all bases of that arg and add the modified sort as ext class - for (Sort s : parameters.get(i).extendsSorts()) { - ImmutableList newArgs = parameters.replace(i, s); - result = result.add(ParametricSortInstance.get(base, newArgs, null, null)); + ImmutableList cov = base.getParameters(); + int number = 0; + for (ParametricSortDeclaration.SortParameter parameter : base.getParameters()) { + switch(parameter.variance()) { + case COVARIANT -> { + // take all bases of that arg and add the modified sort as ext class + for (Sort s : parameter.genericSort().extendsSorts()) { + ImmutableList newArgs = parameters.replace(number, s); + result = result.add(ParametricSortInstance.get(base, newArgs)); + } } - } - case CONTRAVARIANT -> throw new UnsupportedOperationException( - "Contravariance can currently not be supported"); + case CONTRAVARIANT -> throw new UnsupportedOperationException( + "Contravariance currently not supported"); - case INVARIANT -> { - /* Nothing to be done */} + case INVARIANT -> { + /* Nothing to be done */} } } return result; } - private static Name makeName(Sort base, ImmutableList parameters) { - return new Name(base + "<" + parameters + ">"); + private static Name makeName(ParametricSortDeclaration base, ImmutableList parameters) { + return new Name(base.name() + "<[" + parameters + "]>"); } - public Sort getBase() { + public ParametricSortDeclaration getBase() { return base; } @@ -99,7 +102,7 @@ public ImmutableList getParameters() { public ParametricSortInstance map(Function f) { ImmutableList newParameters = parameters.map(f); // The cache ensures that no unnecessary duplicates are kept. - return get(base, newParameters, null, null); + return get(base, newParameters); } @Override diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/SortImpl.java b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/SortImpl.java index b65f32b59d3..b1952fb84ca 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/SortImpl.java +++ b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/SortImpl.java @@ -11,29 +11,17 @@ import org.key_project.util.collection.DefaultImmutableSet; import org.key_project.util.collection.ImmutableSet; -import org.jspecify.annotations.Nullable; - /** * Abstract base class for implementations of the Sort interface. */ public class SortImpl extends AbstractSort { - /** - * Documentation for this sort given by the associated documentation comment. - * - * @see de.uka.ilkd.key.nparser.KeYParser.One_sort_declContext#doc - */ - private final String documentation; - - /** Information of the origin of this sort */ - private final String origin; + private ImmutableSet ext; public SortImpl(Name name, ImmutableSet ext, boolean isAbstract, String documentation, String origin) { - super(name, isAbstract); + super(name, isAbstract, documentation, origin); this.ext = ext; - this.documentation = documentation; - this.origin = origin; } public SortImpl(Name name, ImmutableSet ext, String documentation, String origin) { @@ -88,16 +76,6 @@ public String declarationString() { return name().toString(); } - @Override - public @Nullable String getDocumentation() { - return documentation; - } - - @Override - public @Nullable String getOrigin() { - return origin; - } - @Override public boolean equals(Object o) { if (o instanceof SortImpl) { diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java index 95cb61525d0..da597757ff2 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java @@ -12,7 +12,7 @@ import de.uka.ilkd.key.logic.op.LocationVariable; import de.uka.ilkd.key.logic.op.ProgramVariable; import de.uka.ilkd.key.logic.sort.*; -import de.uka.ilkd.key.logic.sort.ParametricSort.SortParameter; +import de.uka.ilkd.key.logic.sort.ParametricSortDeclaration.SortParameter; import de.uka.ilkd.key.nparser.KeYParser; import de.uka.ilkd.key.nparser.ParsingFacade; import de.uka.ilkd.key.rule.RuleSet; @@ -78,10 +78,10 @@ public Object visitDatatype_decl(KeYParser.Datatype_declContext ctx) { var variance = typeParameters.stream().map(FormalSortParameter::first) .collect(ImmutableList.collector()); - var s = new ParametricSort( + var s = new ParametricSortDeclaration( new Name(name), ImmutableSet.empty(), false, tp, variance, doc, origin); - sorts().add(s); + namespaces().parametricSorts().add(s); } return null; } @@ -210,7 +210,8 @@ public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) { typeParams.stream() .map(it -> new SortParameter((GenericSort) it.second(), it.first())) .collect(ImmutableSLList.toImmutableList()); - s = new ParametricSort(sortName, ext, isAbstractSort, params); + var sortDecl = new ParametricSortDeclaration(sortName, ext, isAbstractSort, params, documentation, BuilderHelpers.getPosition(idCtx)); + namespaces().parametricSorts().add(sortDecl); } else if (isGenericSort) { try { s = new GenericSort(sortName, ext, oneOf, documentation, @@ -229,9 +230,12 @@ public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) { documentation, BuilderHelpers.getPosition(idCtx)); } } - assert s != null; - sorts().add(s); - createdSorts.add(s); + if(!isParametricSort) { + // parametric sort declarations are not sorts themselves. + assert s != null; + sorts().add(s); + createdSorts.add(s); + } } else { // weigl: agreement on KaKeY meeting: this should be ignored until we finally have // local namespaces for generic sorts diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java index 0668b132bff..f09551e22a4 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java @@ -21,8 +21,8 @@ import de.uka.ilkd.key.logic.op.QuantifiableVariable; import de.uka.ilkd.key.logic.sort.ArraySort; import de.uka.ilkd.key.logic.sort.NullSort; -import de.uka.ilkd.key.logic.sort.ParametricSort; -import de.uka.ilkd.key.logic.sort.ParametricSort.Variance; +import de.uka.ilkd.key.logic.sort.ParametricSortDeclaration; +import de.uka.ilkd.key.logic.sort.ParametricSortDeclaration.Variance; import de.uka.ilkd.key.logic.sort.ParametricSortInstance; import de.uka.ilkd.key.nparser.KeYParser; import de.uka.ilkd.key.rule.RuleSet; @@ -359,18 +359,19 @@ public Sort visitSortId(KeYParser.SortIdContext ctx) { semanticError(ctx, "Combination of primitive type and type parameters."); } - Sort s = lookupSort(primitiveName); - if (s == null) { - semanticError(ctx, "Could not find sort: %s", ctx.getText()); - } - - // parametric sorts should be instantiated + Sort s; if (ctx.formal_sort_parameters() != null) { - if (s instanceof ParametricSort ps) { - ImmutableList parameters = getSorts(ctx.formal_sort_parameters()); - s = ParametricSortInstance.get(ps, parameters, null, null); - } else { - semanticError(ctx, "Not a polymorphic sort: %s", s); + // parametric sorts should be instantiated + ParametricSortDeclaration sortDecl = services.getNamespaces().parametricSorts().lookup(primitiveName); + if (sortDecl == null) { + semanticError(ctx, "Could not find polymorphic sort: %s", primitiveName); + } + ImmutableList parameters = getSorts(ctx.formal_sort_parameters()); + s = ParametricSortInstance.get(sortDecl, parameters); + } else { + s = lookupSort(primitiveName); + if (s == null) { + semanticError(ctx, "Could not find sort: %s", ctx.getText()); } } diff --git a/key.core/src/main/java/de/uka/ilkd/key/parser/DefaultTermParser.java b/key.core/src/main/java/de/uka/ilkd/key/parser/DefaultTermParser.java index 6e6ffda4e91..3c6857e6584 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/parser/DefaultTermParser.java +++ b/key.core/src/main/java/de/uka/ilkd/key/parser/DefaultTermParser.java @@ -14,6 +14,7 @@ import de.uka.ilkd.key.logic.op.IProgramVariable; import de.uka.ilkd.key.logic.op.JFunction; import de.uka.ilkd.key.logic.op.QuantifiableVariable; +import de.uka.ilkd.key.logic.sort.ParametricSortDeclaration; import de.uka.ilkd.key.nparser.KeyIO; import de.uka.ilkd.key.pp.AbbrevMap; @@ -43,11 +44,13 @@ public final class DefaultTermParser { * correctly or the term has an invalid sort. */ public Term parse(Reader in, Sort sort, Services services, - Namespace var_ns, - Namespace func_ns, - Namespace sort_ns, Namespace progVar_ns, AbbrevMap scm) + Namespace var_ns, + Namespace func_ns, + Namespace sort_ns, + Namespace paramSort_ns, + Namespace progVar_ns, AbbrevMap scm) throws ParserException { - return parse(in, sort, services, new NamespaceSet(var_ns, func_ns, sort_ns, + return parse(in, sort, services, new NamespaceSet(var_ns, func_ns, sort_ns, paramSort_ns, new Namespace<>(), new Namespace<>(), progVar_ns), scm); } diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/io/IntermediateProofReplayer.java b/key.core/src/main/java/de/uka/ilkd/key/proof/io/IntermediateProofReplayer.java index b40ef0409c1..9baaaccb09a 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/proof/io/IntermediateProofReplayer.java +++ b/key.core/src/main/java/de/uka/ilkd/key/proof/io/IntermediateProofReplayer.java @@ -939,7 +939,7 @@ public static Term parseTerm(String value, Proof proof, Namespace progVarNS, Namespace functNS) { try { return new DefaultTermParser().parse(new StringReader(value), null, proof.getServices(), - varNS, functNS, proof.getNamespaces().sorts(), + varNS, functNS, proof.getNamespaces().sorts(), proof.getNamespaces().parametricSorts(), progVarNS, new AbbrevMap()); } catch (ParserException e) { throw new RuntimeException( diff --git a/key.util/src/main/java/org/key_project/util/collection/Immutables.java b/key.util/src/main/java/org/key_project/util/collection/Immutables.java index a0dd9497c92..b5d78d316f9 100644 --- a/key.util/src/main/java/org/key_project/util/collection/Immutables.java +++ b/key.util/src/main/java/org/key_project/util/collection/Immutables.java @@ -4,6 +4,7 @@ package org.key_project.util.collection; import java.util.HashSet; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Predicate; @@ -239,4 +240,18 @@ public static ImmutableSet setOf(T element) { return DefaultImmutableSet.fromImmutableList(listOf(element)); } + public static ImmutableList zip(ImmutableList list1, ImmutableList list2, BiFunction zipper) { + ImmutableList result = ImmutableSLList.nil(); + while (!list1.isEmpty() && !list2.isEmpty()) { + result = result.prepend(zipper.apply(list1.head(), list2.head())); + list1 = list1.tail(); + list2 = list2.tail(); + } + return result.reverse(); + } + + @Deprecated + public static ImmutableList> zip(ImmutableList list1, ImmutableList list2) { + return zip(list1, list2, Pair::new); + } } From 65006b4975caa4e793d318340c692813c6828658 Mon Sep 17 00:00:00 2001 From: Mattias Ulbrich Date: Tue, 4 Mar 2025 20:38:41 +0100 Subject: [PATCH 13/13] more on parameterised types ... --- key.core/src/main/antlr4/KeYParser.g4 | 31 ++-- .../key/logic/op/SortDependingFunction.java | 14 +- .../logic/sort/ParametricSortDeclaration.java | 160 ++++++++++++++++ .../logic/sort/ParametricSortInstance.java | 27 ++- .../nparser/builder/DeclarationBuilder.java | 174 ++++++++++-------- .../key/nparser/builder/DefaultBuilder.java | 48 +---- .../key/nparser/builder/TacletPBuilder.java | 2 +- .../de/uka/ilkd/key/proof/io/KeYFile.java | 4 +- .../key/logic/sort/TestParametricSorts.java | 95 ++++++++++ .../uka/ilkd/key/parser/TestDeclParser.java | 51 ++++- .../quantifierHeuristics/TestTriggersSet.java | 4 +- .../java/org/key_project/logic/sort/Sort.java | 18 +- .../util/collection/ImmutableSet.java | 2 +- .../util/collection/Immutables.java | 7 +- .../key_project/util/java/CollectionUtil.java | 21 +++ 15 files changed, 503 insertions(+), 155 deletions(-) create mode 100644 key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortDeclaration.java create mode 100644 key.core/src/test/java/de/uka/ilkd/key/logic/sort/TestParametricSorts.java diff --git a/key.core/src/main/antlr4/KeYParser.g4 b/key.core/src/main/antlr4/KeYParser.g4 index 08b6e287272..6fe081dcb7e 100644 --- a/key.core/src/main/antlr4/KeYParser.g4 +++ b/key.core/src/main/antlr4/KeYParser.g4 @@ -90,17 +90,28 @@ one_sort_decl : doc=DOC_COMMENT? ( - GENERIC sortIds=sortList + GENERIC sortIds=simple_ident_dots_comma_list (ONEOF sortOneOf = oneof_sorts)? (EXTENDS sortExt = extends_sorts)? SEMI - | PROXY sortIds=sortList (EXTENDS sortExt=extends_sorts)? SEMI - | ABSTRACT? sortIds=sortList (EXTENDS sortExt=extends_sorts)? SEMI + | PROXY sortIds=simple_ident_dots_comma_list (EXTENDS sortExt=extends_sorts)? SEMI + | ABSTRACT? (sortIds=simple_ident_dots_comma_list | + parametric_sort_decl) (EXTENDS sortExt=extends_sorts)? SEMI ) ; -sortList +// TODO currently you are not allowed to commatise parametric_sort_decl. Is this severe? + +parametric_sort_decl : - sortId (COMMA sortId)* + simple_ident_dots + OPENTYPEPARAMS + formal_sort_param_decl (COMMA formal_sort_param_decl)* + CLOSETYPEPARAMS +; + +formal_sort_param_decl +: + (PLUS | MINUS)? simple_ident ; simple_ident_dots @@ -113,7 +124,6 @@ simple_ident_dots_comma_list simple_ident_dots (COMMA simple_ident_dots)* ; - extends_sorts : sortId (COMMA sortId)* @@ -334,17 +344,10 @@ sortId id=simple_ident_dots (EMPTYBRACKETS)* formal_sort_parameters? ; -formal_sort_variance -: - (PLUS | MINUS)? -; - -formal_sort_parameter: formal_sort_variance id=sortId; - formal_sort_parameters : OPENTYPEPARAMS - formal_sort_parameter (COMMA formal_sort_parameter)* + sortId (COMMA sortId)* CLOSETYPEPARAMS ; diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/op/SortDependingFunction.java b/key.core/src/main/java/de/uka/ilkd/key/logic/op/SortDependingFunction.java index bd675d35d89..dc1f204e80c 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/logic/op/SortDependingFunction.java +++ b/key.core/src/main/java/de/uka/ilkd/key/logic/op/SortDependingFunction.java @@ -9,6 +9,7 @@ import de.uka.ilkd.key.logic.NamespaceSet; import de.uka.ilkd.key.logic.TermServices; import de.uka.ilkd.key.logic.sort.GenericSort; +import de.uka.ilkd.key.logic.sort.ParametricSortInstance; import de.uka.ilkd.key.logic.sort.ProgramSVSort; import org.key_project.logic.Name; @@ -39,7 +40,7 @@ public final class SortDependingFunction extends JFunction { private SortDependingFunction(SortDependingFunctionTemplate template, Sort sortDependingOn) { super(instantiateName(template.kind, sortDependingOn), - instantiateResultSort(template, sortDependingOn), + instantiateSort(template.sortDependingOn, sortDependingOn, template.sort), instantiateArgSorts(template, sortDependingOn), null, template.unique, false); this.template = template; this.sortDependingOn = Qualifier.create(sortDependingOn); @@ -55,9 +56,10 @@ private static Name instantiateName(Name kind, Sort sortDependingOn) { } - private static Sort instantiateResultSort(SortDependingFunctionTemplate template, - Sort sortDependingOn) { - return template.sort == template.sortDependingOn ? sortDependingOn : template.sort; + private static Sort instantiateSort(GenericSort genericSort, Sort instanatiation, + Sort toInstantiate) { + // Replaces the generic sort and all occurrences in parametric sorts + return ParametricSortInstance.instantiate(genericSort, instanatiation, toInstantiate); } @@ -65,13 +67,11 @@ private static ImmutableArray instantiateArgSorts(SortDependingFunctionTem Sort sortDependingOn) { Sort[] result = new Sort[template.argSorts.size()]; for (int i = 0; i < result.length; i++) { - result[i] = (template.argSorts.get(i) == template.sortDependingOn ? sortDependingOn - : template.argSorts.get(i)); + result[i] = ParametricSortInstance.instantiate(template.sortDependingOn, sortDependingOn, template.argSorts.get(i)); } return new ImmutableArray<>(result); } - // ------------------------------------------------------------------------- // public interface // ------------------------------------------------------------------------- diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortDeclaration.java b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortDeclaration.java new file mode 100644 index 00000000000..01c489ac6d4 --- /dev/null +++ b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortDeclaration.java @@ -0,0 +1,160 @@ +/* This file is part of KeY - https://key-project.org + * KeY is licensed under the GNU General Public License Version 2 + * SPDX-License-Identifier: GPL-2.0-only */ +package de.uka.ilkd.key.logic.sort; + +import java.util.IdentityHashMap; +import java.util.Map; +import java.util.function.Function; + +import de.uka.ilkd.key.ldt.JavaDLTheory; + +import org.jspecify.annotations.NonNull; +import org.jspecify.annotations.NullMarked; +import org.key_project.logic.Name; +import org.key_project.logic.Named; +import org.key_project.logic.sort.Sort; +import org.key_project.util.collection.ImmutableList; +import org.key_project.util.collection.ImmutableSet; +import org.key_project.util.collection.Immutables; + +/** + * Here is a short class diagram, written for PlantUML. + * You can create the PNG file by feeding this SourceFile into PlantUML or + * by entering the text into https://www.planttext.com/, e.g. + @formatter:off + @startuml + interface Sort + abstract class AbstractSort + class SortImpl + + class ParametricSortDeclaration + class ParametricSortInstance + class NullSort + class GenericSort + + Sort <|-- AbstractSort + AbstractSort <|-- SortImpl + AbstractSort <|-- ParametricSortInstance + AbstractSort <|-- GenericSort + Sort <|-- NullSort + + ParametricSortInstance --> ParametricSortDeclaration : base + ParametricSortInstance --> "*" Sort :args + ParametricSortDeclaration --> "n" GenericSort : typeParameters + ParametricSortDeclaration --> "*" Sort : extendsDecl + ParametricSortDeclaration --> "n" Variance : variances + + enum Variance { + COVARIANT + CONTRAVARIANT + INVARIANT + } + @enduml + @formatter:on + */ + +@NullMarked +public class ParametricSortDeclaration implements Named { + + private final Name name; + private final boolean isAbstract; + private final String documentation; + private final String origin; + + public enum Variance { + COVARIANT, + CONTRAVARIANT, + INVARIANT; + } + + public record SortParameter(@NonNull GenericSort genericSort, @NonNull Variance variance) { + } + + private final ImmutableList parameters; + + private final ImmutableSet extendedSorts; + + public ParametricSortDeclaration(Name name, ImmutableSet ext, boolean isAbstract, + ImmutableList parameters, ImmutableList covariances, + String documentation, String origin) { + this(name, ext, isAbstract, Immutables.zip(parameters, covariances, SortParameter::new), documentation, origin); + } + + public ParametricSortDeclaration(Name name, ImmutableSet ext, boolean isAbstract, + ImmutableList sortParams, String documentation, String origin) { + this.name = name; + this.extendedSorts = ext.isEmpty() ? Immutables.setOf(JavaDLTheory.ANY) : ext; + this.isAbstract = isAbstract; + this.documentation = documentation; + this.origin = origin; + this.parameters = sortParams; + assert Immutables.isDuplicateFree(parameters.map(SortParameter::genericSort)) : + "The caller should have made sure that generic sorts are not duplicated"; + } + + public Function getInstantiator(ImmutableList args) { + IdentityHashMap map = new IdentityHashMap<>(); + + if (args.size() != parameters.size()) { + throw new IllegalArgumentException("Parametric type " + name + + " expected " + parameters.size() + " arguments, but received " + + args); + } + + ImmutableList p = parameters; + while (!args.isEmpty()) { + map.put(p.head().genericSort(), args.head()); + p = p.tail(); + args = args.tail(); + } + + return new SortInstantiator(map); + } + + public static class SortInstantiator implements Function { + private final Map map; + + public SortInstantiator(Map map) { + this.map = map; + } + + @Override + public Sort apply(Sort sort) { + Sort mapped = map.get(sort); + if (mapped != null) { + return mapped; + } + if (sort instanceof ParametricSortInstance psi) { + return psi.map(this); + } else { + return sort; + } + } + } + + public ImmutableList getParameters() { + return parameters; + } + + public ImmutableSet getExtendedSorts() { + return extendedSorts; + } + + @Override + public Name name() { + return name; + } + + public boolean isAbstract() { + return isAbstract; + } + + public String getDocumentation() { + return documentation; + } + + public String getOrigin() { + return origin; + } +} diff --git a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java index b65695dbc57..68d86c3e605 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java +++ b/key.core/src/main/java/de/uka/ilkd/key/logic/sort/ParametricSortInstance.java @@ -71,10 +71,12 @@ private static ImmutableSet computeExt(ParametricSortDeclaration base, switch(parameter.variance()) { case COVARIANT -> { // take all bases of that arg and add the modified sort as ext class - for (Sort s : parameter.genericSort().extendsSorts()) { + /* for (Sort s : parameter.genericSort().extendsSorts()) { ImmutableList newArgs = parameters.replace(number, s); result = result.add(ParametricSortInstance.get(base, newArgs)); - } + } */ +// throw new UnsupportedOperationException( +// "Covariance currently not supported"); } case CONTRAVARIANT -> throw new UnsupportedOperationException( @@ -88,7 +90,8 @@ private static ImmutableSet computeExt(ParametricSortDeclaration base, } private static Name makeName(ParametricSortDeclaration base, ImmutableList parameters) { - return new Name(base.name() + "<[" + parameters + "]>"); + // The [ ] are produced by the list's toString method. + return new Name(base.name() + "<" + parameters + ">"); } public ParametricSortDeclaration getBase() { @@ -128,6 +131,22 @@ public ImmutableSet extendsSorts() { @Override public boolean extendsTrans(Sort sort) { - return false; + return sort == this || extendsSorts() + .exists((Sort superSort) -> superSort == sort || superSort.extendsTrans(sort)); + } + + public static Sort instantiate(GenericSort genericSort, Sort instantiation, Sort toInstantiate) { + if(genericSort == toInstantiate) { + return instantiation; + } else if(toInstantiate instanceof ParametricSortInstance psort) { + return psort.instantiate(genericSort, instantiation); + } else { + return toInstantiate; + } + } + + public Sort instantiate(GenericSort template, Sort instantiation) { + ImmutableList newParameters = parameters.map(s -> instantiate(template, instantiation, s)); + return get(base, newParameters); } } diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java index da597757ff2..f6a06fb15ca 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DeclarationBuilder.java @@ -20,12 +20,10 @@ import org.key_project.logic.Name; import org.key_project.logic.Named; import org.key_project.logic.sort.Sort; -import org.key_project.util.collection.ImmutableList; -import org.key_project.util.collection.ImmutableSLList; -import org.key_project.util.collection.ImmutableSet; -import org.key_project.util.collection.Immutables; +import org.key_project.util.collection.*; import org.antlr.v4.runtime.Token; +import org.key_project.util.java.CollectionUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -64,7 +62,7 @@ public Object visitDecls(KeYParser.DeclsContext ctx) { @Override public Object visitDatatype_decl(KeYParser.Datatype_declContext ctx) { var name = ctx.name.getText(); - List typeParameters = accept(ctx.formal_sort_parameters()); + List typeParameters = accept(ctx.formal_sort_parameters()); var doc = ctx.DOC_COMMENT() != null ? ctx.DOC_COMMENT().getText() : null; @@ -73,10 +71,15 @@ public Object visitDatatype_decl(KeYParser.Datatype_declContext ctx) { var s = new SortImpl(new Name(name), ImmutableSet.empty(), false, doc, origin); sorts().addSafely(s); } else { - var tp = typeParameters.stream().map(it -> (GenericSort) it.second()) + var tp = typeParameters.stream().map(SortParameter::genericSort) .collect(ImmutableList.collector()); + var doubled = CollectionUtil.findDuplicates(tp); + if (!doubled.isEmpty()) { + semanticError(ctx.formal_sort_parameters(), + "Type parameters must be unique within a declaration. Found duplicate: %s", doubled.getFirst()); + } var variance = - typeParameters.stream().map(FormalSortParameter::first) + typeParameters.stream().map(SortParameter::variance) .collect(ImmutableList.collector()); var s = new ParametricSortDeclaration( new Name(name), ImmutableSet.empty(), false, tp, variance, @@ -146,20 +149,20 @@ public Object visitSort_decls(KeYParser.Sort_declsContext ctx) { } - public record NamedFormalSortParameter(String name, List parameters) {} + public record NamedFormalSortParameter(String name, List parameters) {} - @Override - public List visitSortList(KeYParser.SortListContext ctx) { - List seq = new ArrayList<>(); - for (KeYParser.SortIdContext context : ctx.sortId()) { - String sortName = context.simple_ident_dots().getText(); - // String brackets = StringUtil.repeat("[]", context.EMPTYBRACKETS().size()); - List typeParams = accept(context.formal_sort_parameters()); - seq.add(new NamedFormalSortParameter(sortName, - typeParams != null ? typeParams : Collections.emptyList())); - } - return seq; - } +// @Override +// public List visitSortList(KeYParser.SortListContext ctx) { +// List seq = new ArrayList<>(); +// for (KeYParser.SortIdContext context : ctx.sortId()) { +// String sortName = context.simple_ident_dots().getText(); +// // String brackets = StringUtil.repeat("[]", context.EMPTYBRACKETS().size()); +// List typeParams = accept(context.formal_sort_parameters()); +// seq.add(new NamedFormalSortParameter(sortName, +// typeParams != null ? typeParams : Collections.emptyList())); +// } +// return seq; +// } @Override @@ -174,80 +177,95 @@ public Object visitOne_sort_decl(KeYParser.One_sort_declContext ctx) { List createdSorts = new LinkedList<>(); // assert sortIds != null; + ImmutableSet ext = sortExt == null ? ImmutableSet.empty() + : Immutables.setOf(sortExt); + ImmutableSet oneOf = sortOneOf == null ? ImmutableSet.empty() + : Immutables.setOf(sortOneOf); + var documentation = ParsingFacade.getValueDocumentation(ctx.DOC_COMMENT()); - for (var idCtx : ctx.sortIds.sortId()) { - // for (Pair>> sortId : sortIds) { - var name = idCtx.simple_ident_dots().getText(); - // var brackets = StringUtil.repeat("[]", idCtx.EMPTYBRACKETS().size()); - List typeParams = accept(idCtx.formal_sort_parameters()); + + if(ctx.sortIds == null) { + // parametrised sorts + var declCtx = ctx.parametric_sort_decl(); + assert declCtx != null : "One of the two must be present"; + List typeParams = mapOf(declCtx.formal_sort_param_decl()); + ImmutableList params = Immutables.listOf(typeParams); + var doubled = CollectionUtil.findDuplicates(params.map(SortParameter::genericSort)); + if (!doubled.isEmpty()) { + semanticError(declCtx, + "Type parameters must be unique within a declaration. Found duplicate: %s", doubled.getFirst()); + } + String name = declCtx.simple_ident_dots().getText(); Name sortName = new Name(name); - boolean isParametricSort = typeParams != null && !typeParams.isEmpty(); - - ImmutableSet ext = sortExt == null ? ImmutableSet.empty() - : Immutables.createSetFrom(sortExt); - ImmutableSet oneOf = sortOneOf == null ? ImmutableSet.empty() - : Immutables.createSetFrom(sortOneOf); - - // attention: no expand to java.lang here! - Sort existingSort = sorts().lookup(sortName); - if (existingSort == null) { - Sort s = null; - if (isParametricSort) { - if (isGenericSort) { - semanticError(ctx, - "Generic sorts are not allowed to have type parameters."); - } + var sortDecl = new ParametricSortDeclaration(sortName, ext, isAbstractSort, params, documentation, BuilderHelpers.getPosition(declCtx)); + namespaces().parametricSorts().add(sortDecl); - for (FormalSortParameter param : typeParams) { - if (!(param.second() instanceof GenericSort)) { - semanticError(ctx, - "Type parameters must be generic sorts. Given type '%s' is %s", - param.second().name(), param.second().getClass().getName()); - } - } + } else { + for (var idCtx : ctx.sortIds.simple_ident_dots()) { + var name = idCtx.getText(); + Name sortName = new Name(name); - ImmutableList params = - typeParams.stream() - .map(it -> new SortParameter((GenericSort) it.second(), it.first())) - .collect(ImmutableSLList.toImmutableList()); - var sortDecl = new ParametricSortDeclaration(sortName, ext, isAbstractSort, params, documentation, BuilderHelpers.getPosition(idCtx)); - namespaces().parametricSorts().add(sortDecl); - } else if (isGenericSort) { - try { - s = new GenericSort(sortName, ext, oneOf, documentation, - BuilderHelpers.getPosition(ctx)); - } catch (GenericSupersortException e) { - semanticError(ctx, "Illegal sort given"); - } - } else if (new Name("any").equals(sortName)) { - s = JavaDLTheory.ANY; - } else { - if (isProxySort) { - s = new ProxySort(sortName, ext, documentation, - BuilderHelpers.getPosition(idCtx)); + // attention: no expand to java.lang here! + Sort existingSort = sorts().lookup(sortName); + if (existingSort == null) { + Sort s = null; + if (isGenericSort) { + try { + s = new GenericSort(sortName, ext, oneOf, documentation, + BuilderHelpers.getPosition(ctx)); + } catch (GenericSupersortException e) { + semanticError(ctx, "Illegal sort given"); + } + } else if (new Name("any").equals(sortName)) { + s = JavaDLTheory.ANY; } else { - s = new SortImpl(sortName, ext, isAbstractSort, - documentation, BuilderHelpers.getPosition(idCtx)); + if (isProxySort) { + s = new ProxySort(sortName, ext, documentation, + BuilderHelpers.getPosition(idCtx)); + } else { + s = new SortImpl(sortName, ext, isAbstractSort, + documentation, BuilderHelpers.getPosition(idCtx)); + } } - } - if(!isParametricSort) { // parametric sort declarations are not sorts themselves. assert s != null; sorts().add(s); createdSorts.add(s); + } else { + // weigl: agreement on KaKeY meeting: this should be ignored until we finally have + // local namespaces for generic sorts + // addWarning(ctx, "Sort declaration is ignored, due to collision."); + LOGGER.debug("Sort declaration of {} in {} is ignored due to collision (already " + + "present in {}).", sortName, BuilderHelpers.getPosition(ctx), + existingSort.getOrigin()); } - } else { - // weigl: agreement on KaKeY meeting: this should be ignored until we finally have - // local namespaces for generic sorts - // addWarning(ctx, "Sort declaration is ignored, due to collision."); - LOGGER.debug("Sort declaration of {} in {} is ignored due to collision (already " - + "present in {}).", sortName, BuilderHelpers.getPosition(ctx), - existingSort.getOrigin()); } } return createdSorts; } + @Override + public SortParameter visitFormal_sort_param_decl(KeYParser.Formal_sort_param_declContext ctx) { + ParametricSortDeclaration.Variance variance; + if (ctx.PLUS() != null) + variance = ParametricSortDeclaration.Variance.COVARIANT; + else if (ctx.MINUS() != null) + variance = ParametricSortDeclaration.Variance.CONTRAVARIANT; + else + variance = ParametricSortDeclaration.Variance.INVARIANT; + + var name = ctx.simple_ident().getText(); + Sort paramSort = sorts().lookup(name); + if(paramSort == null) { + semanticError(ctx, "Parameter sort %s not found", name); + } + if(!(paramSort instanceof GenericSort)) { + semanticError(ctx, "Parameter sort %s is not a generic sort", name); + } + + return new SortParameter((GenericSort) paramSort, variance); + } + @Override public Object visitOption_decls(KeYParser.Option_declsContext ctx) { return mapOf(ctx.choice()); diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java index f09551e22a4..95689f600bd 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/DefaultBuilder.java @@ -19,11 +19,9 @@ import de.uka.ilkd.key.logic.*; import de.uka.ilkd.key.logic.op.*; import de.uka.ilkd.key.logic.op.QuantifiableVariable; -import de.uka.ilkd.key.logic.sort.ArraySort; -import de.uka.ilkd.key.logic.sort.NullSort; -import de.uka.ilkd.key.logic.sort.ParametricSortDeclaration; +import de.uka.ilkd.key.logic.sort.*; import de.uka.ilkd.key.logic.sort.ParametricSortDeclaration.Variance; -import de.uka.ilkd.key.logic.sort.ParametricSortInstance; +import de.uka.ilkd.key.logic.sort.ParametricSortDeclaration.SortParameter; import de.uka.ilkd.key.nparser.KeYParser; import de.uka.ilkd.key.rule.RuleSet; @@ -353,9 +351,7 @@ public Sort visitSortId(KeYParser.SortIdContext ctx) { primitiveName = PrimitiveType.JAVA_BIGINT.getName(); } - if (t != null - && ctx.formal_sort_parameters() != null - && !ctx.formal_sort_parameters().formal_sort_parameter().isEmpty()) { + if (t != null && ctx.formal_sort_parameters() != null) { semanticError(ctx, "Combination of primitive type and type parameters."); } @@ -381,48 +377,18 @@ public Sort visitSortId(KeYParser.SortIdContext ctx) { return s; } - public record FormalSortParameter(Variance first, Sort second) {} - - private ImmutableList getSorts(KeYParser.Formal_sort_parametersContext ctx) { - List seq = accept(ctx); + List seq = accept(ctx); assert seq != null; - for (var p : seq) { - if (p.first() != Variance.INVARIANT) { - addWarning(ctx, "Variance is ignored"); - } - } - return seq.stream().map(FormalSortParameter::second) - .collect(ImmutableSLList.toImmutableList()); + return ImmutableList.fromList(seq); } @Override - public List visitFormal_sort_parameters( + public List visitFormal_sort_parameters( KeYParser.Formal_sort_parametersContext ctx) { - return mapOf(ctx.formal_sort_parameter()); - } - - @Override - public FormalSortParameter visitFormal_sort_parameter( - KeYParser.Formal_sort_parameterContext ctx) { - Sort sort = sorts().lookup(ctx.id.getText()); - if (sort == null) { - semanticError(ctx.id, "Could not find sort '%s'. It was not previously defined.", - ctx.id.getText()); - } - return new FormalSortParameter(accept(ctx.formal_sort_variance()), sort); - } - - @Override - public Object visitFormal_sort_variance(KeYParser.Formal_sort_varianceContext ctx) { - if (ctx.PLUS() != null) - return Variance.COVARIANT; - if (ctx.MINUS() != null) - return Variance.CONTRAVARIANT; - return Variance.INVARIANT; + return mapOf(ctx.sortId()); } - @Override public KeYJavaType visitKeyjavatype(KeYParser.KeyjavatypeContext ctx) { boolean array = false; diff --git a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/TacletPBuilder.java b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/TacletPBuilder.java index f78e5a87a7b..40494c1784a 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/TacletPBuilder.java +++ b/key.core/src/main/java/de/uka/ilkd/key/nparser/builder/TacletPBuilder.java @@ -748,7 +748,7 @@ public Object visitAddrules(KeYParser.AddrulesContext ctx) { @Override public ImmutableSet visitAddprogvar(KeYParser.AddprogvarContext ctx) { final Collection accept = accept(ctx.pvs); - return Immutables.createSetFrom(Objects.requireNonNull(accept)); + return Immutables.setOf(Objects.requireNonNull(accept)); } @Override diff --git a/key.core/src/main/java/de/uka/ilkd/key/proof/io/KeYFile.java b/key.core/src/main/java/de/uka/ilkd/key/proof/io/KeYFile.java index 63ebbb3a3f8..0580fd5a410 100644 --- a/key.core/src/main/java/de/uka/ilkd/key/proof/io/KeYFile.java +++ b/key.core/src/main/java/de/uka/ilkd/key/proof/io/KeYFile.java @@ -332,8 +332,8 @@ public ImmutableSet readContracts() { ContractsAndInvariantsFinder cinvs = new ContractsAndInvariantsFinder(initConfig.getServices(), initConfig.namespaces()); getParseContext().accept(cinvs); - specRepos.addContracts(Immutables.createSetFrom(cinvs.getContracts())); - specRepos.addClassInvariants(Immutables.createSetFrom(cinvs.getInvariants())); + specRepos.addContracts(Immutables.setOf(cinvs.getContracts())); + specRepos.addClassInvariants(Immutables.setOf(cinvs.getInvariants())); return DefaultImmutableSet.nil(); } diff --git a/key.core/src/test/java/de/uka/ilkd/key/logic/sort/TestParametricSorts.java b/key.core/src/test/java/de/uka/ilkd/key/logic/sort/TestParametricSorts.java new file mode 100644 index 00000000000..119837ec4ba --- /dev/null +++ b/key.core/src/test/java/de/uka/ilkd/key/logic/sort/TestParametricSorts.java @@ -0,0 +1,95 @@ +package de.uka.ilkd.key.logic.sort; + +import de.uka.ilkd.key.java.Recoder2KeY; +import de.uka.ilkd.key.java.Services; +import de.uka.ilkd.key.logic.NamespaceSet; +import de.uka.ilkd.key.logic.op.JFunction; +import de.uka.ilkd.key.logic.op.SortDependingFunction; +import de.uka.ilkd.key.nparser.KeyIO; +import de.uka.ilkd.key.nparser.NamespaceBuilder; +import de.uka.ilkd.key.proof.init.AbstractProfile; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.key_project.logic.Name; +import org.key_project.logic.sort.Sort; +import org.key_project.util.collection.ImmutableList; +import org.key_project.util.collection.ImmutableSet; + +import static org.junit.jupiter.api.Assertions.*; + +class TestParametricSorts { + + private NamespaceSet nss; + private Services services; + private KeyIO io; + private GenericSort g1; + + @BeforeEach + public void setUp() { + this.services = new Services(AbstractProfile.getDefaultProfile()); + this.nss = services.getNamespaces(); + this.io = new KeyIO(services, nss); + + nss.sorts().add(g1 = new GenericSort(new Name("G1"))); + nss.sorts().add(new GenericSort(new Name("G2"))); + nss.sorts().add(new GenericSort(new Name("G3"))); + nss.sorts().add(new GenericSort(new Name("G4"))); + + NamespaceBuilder nb = new NamespaceBuilder(nss); + nb.addSort("boolean").addSort("int").addSort("Seq").addSort("LocSet").addSort("double") + .addSort("float"); + + Recoder2KeY r2k = new Recoder2KeY(services, nss); + r2k.parseSpecialClasses(); + } + + private ParametricSortDeclaration addParametricSort(String name, ParametricSortDeclaration.Variance... variance) { + ImmutableList params = ImmutableList.of(); + for (int i = 0; i < variance.length; i++) { + ParametricSortDeclaration.Variance varia = variance[i]; + GenericSort genSort = (GenericSort) nss.sorts().lookup("G" + (i + 1)); + params = params.prepend(new ParametricSortDeclaration.SortParameter(genSort, varia)); + } + ParametricSortDeclaration psd = new ParametricSortDeclaration(new Name(name), ImmutableSet.empty(), false, + params, "", ""); + nss.parametricSorts().add(psd); + return psd; + } + + + @Test + public void testParametricSortIdentical() { + ParametricSortDeclaration psd = addParametricSort("List", ParametricSortDeclaration.Variance.COVARIANT); + var sdf = SortDependingFunction.createFirstInstance(g1, new Name("someConst"), g1, new Sort[0], false); + nss.functions().add(sdf); + + var term = io.parseExpression("List<[int]>::someConst = List<[int]>::someConst"); + assertEquals(term.sub(0), term.sub(1)); + assertSame(term.sub(0).sort(), term.sub(1).sort()); + } + + @Test + public void testParametricSortDependentFunctionInstantiation() { + ParametricSortDeclaration psd = addParametricSort("List", ParametricSortDeclaration.Variance.COVARIANT); + Sort intSort = nss.sorts().lookup("int"); + + var someConst = SortDependingFunction.createFirstInstance(g1, new Name("someConst"), g1, new Sort[0], false); + nss.functions().add(someConst); + + var listOfInt = ParametricSortInstance.get(psd, ImmutableList.of(intSort)); + var listOfG1 = ParametricSortInstance.get(psd, ImmutableList.of(g1)); + var sdf = SortDependingFunction.createFirstInstance(g1, new Name("head"), g1, new Sort[] {listOfG1}, false); + nss.functions().add(sdf); + + SortDependingFunction sdfInst = sdf.getInstanceFor(intSort, services); + assertEquals(intSort, sdfInst.sort()); + assertEquals(listOfInt, sdfInst.argSort(0)); + + var term = io.parseExpression("int::head(List<[int]>::someConst) = int::someConst"); + assertEquals("List<[int]>", term.sub(0).sub(0).sort().toString()); + assertEquals("List<[int]>", ((JFunction)term.sub(0).op()).argSorts().get(0).toString()); + assertEquals("int", term.sub(0).op().sort(null).toString()); + assertSame(term.sub(0).sort(), term.sub(1).sort()); + } + +} \ No newline at end of file diff --git a/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java b/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java index fbbbd5ebf6d..60f5791fbdd 100644 --- a/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java +++ b/key.core/src/test/java/de/uka/ilkd/key/parser/TestDeclParser.java @@ -16,6 +16,7 @@ import de.uka.ilkd.key.nparser.NamespaceBuilder; import de.uka.ilkd.key.proof.init.AbstractProfile; +import de.uka.ilkd.key.util.parsing.BuildingException; import org.key_project.logic.Name; import org.key_project.logic.Named; import org.key_project.logic.sort.Sort; @@ -26,7 +27,8 @@ import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; -import static de.uka.ilkd.key.logic.sort.ParametricSort.Variance.*; +import java.io.IOException; + import static org.junit.jupiter.api.Assertions.*; @@ -205,6 +207,53 @@ public void testGenericSortDecl5() { } } + + @Test + public void testParametrisedSortDecls() { + evaluateDeclarations("\\sorts { \\generic G, H; ADT<[+G]>; Fun<[-G,-H]>; Invar<[G]>; }"); + var adt = serv.getNamespaces().parametricSorts().lookup("ADT"); + assertNotNull(adt); + assertEquals("ADT", adt.name().toString()); + assertEquals("[SortParameter[genericSort=G, variance=COVARIANT]]", adt.getParameters().toString()); + + var fun = serv.getNamespaces().parametricSorts().lookup("Fun"); + assertNotNull(fun); + assertEquals("Fun", fun.name().toString()); + assertEquals("[SortParameter[genericSort=G, variance=CONTRAVARIANT]," + + "SortParameter[genericSort=H, variance=CONTRAVARIANT]]", fun.getParameters().toString()); + + var invar = serv.getNamespaces().parametricSorts().lookup("Invar"); + assertNotNull(invar); + assertEquals("Invar", invar.name().toString()); + assertEquals("[SortParameter[genericSort=G, variance=INVARIANT]]", invar.getParameters().toString()); + + var exc = assertThrowsExactly(BuildingException.class, () -> { + KeyIO.Loader l = io.load("\\sorts { \\generic G; ADT<[+G,G]>; }"); + l.parseFile().loadDeclarations().loadSndDegreeDeclarations().loadTaclets(); + }); + assertTrue(exc.getMessage().contains("Type parameters must be unique within a declaration")); + + exc = assertThrowsExactly(BuildingException.class, () -> { + KeyIO.Loader l = io.load("\\sorts { X; ADT<[X]>; }"); + l.parseFile().loadDeclarations().loadSndDegreeDeclarations().loadTaclets(); + }); + + assertTrue(exc.getMessage().contains("Sort 'X' is not a generic sort")); + + exc = assertThrowsExactly(BuildingException.class, () -> { + KeyIO.Loader l = io.load("\\sorts { ADT<[Y]>; }"); + l.parseFile().loadDeclarations().loadSndDegreeDeclarations().loadTaclets(); + }); + assertTrue(exc.getMessage().contains("Could not find sort 'Y'.")); + } + + @Test + public void testParametrisedFunDecls() throws IOException { + KeyIO.Loader l = io.load("\\sorts { \\generic A; \\generic G; ADT<[+G]>; } " + + "\\functions { int f(ADT<[int]>); A A::g(ADT<[A]>); }"); + l.parseFile().loadDeclarations().loadSndDegreeDeclarations().loadTaclets(); + } + /** * asserts that the found object is a schemavariable and that the allowed macthing type is * QuantifiableVariable diff --git a/key.core/src/test/java/de/uka/ilkd/key/strategy/quantifierHeuristics/TestTriggersSet.java b/key.core/src/test/java/de/uka/ilkd/key/strategy/quantifierHeuristics/TestTriggersSet.java index 47f83efdec1..fe70256c639 100644 --- a/key.core/src/test/java/de/uka/ilkd/key/strategy/quantifierHeuristics/TestTriggersSet.java +++ b/key.core/src/test/java/de/uka/ilkd/key/strategy/quantifierHeuristics/TestTriggersSet.java @@ -192,13 +192,13 @@ public void setUp() { proof.add(g); proof.setNamespaces(new NamespaceSet(variables, functions, sorts, new Namespace<>(), - new Namespace<>(), new Namespace<>())); + new Namespace<>(), new Namespace<>(), new Namespace<>())); } private Term parseTerm(String termstr) { return TacletForTests.parseTerm(termstr, new NamespaceSet(variables, functions, sorts, - new Namespace<>(), new Namespace<>(), new Namespace<>())); + new Namespace<>(), new Namespace<>(), new Namespace<>(), new Namespace<>())); } @Test diff --git a/key.ncore/src/main/java/org/key_project/logic/sort/Sort.java b/key.ncore/src/main/java/org/key_project/logic/sort/Sort.java index 562e35157a6..074ef954059 100644 --- a/key.ncore/src/main/java/org/key_project/logic/sort/Sort.java +++ b/key.ncore/src/main/java/org/key_project/logic/sort/Sort.java @@ -12,15 +12,31 @@ public interface Sort extends Named, HasOrigin { /** - * @return the direct supersorts of this sort. Not supported by {@code NullSort}. + * Gives the set of sorts that are direct super-sorts of this sort. + * + * The NullSort implementation fails on this method. + * + * @return a non-null set of sorts. */ ImmutableSet extendsSorts(); + /** + * Gives the set of sorts that are direct super-sorts of this sort. + * + * The NullSort implementation does not fail on this method. + * + * By default, this method calls {@link #extendsSorts()}. + * + * @param services the logic services to use for computing super-sorts. + * @return a non-null set of sorts. + */ default ImmutableSet extendsSorts(Services services) { return extendsSorts(); } /** + * Check whether this sort is a direct or indirect subsort of the given sort. + * * @param sort some sort. * @return whether the given sort is a reflexive, transitive subsort of this sort. */ diff --git a/key.util/src/main/java/org/key_project/util/collection/ImmutableSet.java b/key.util/src/main/java/org/key_project/util/collection/ImmutableSet.java index 07a42b7240c..c607a421ed5 100644 --- a/key.util/src/main/java/org/key_project/util/collection/ImmutableSet.java +++ b/key.util/src/main/java/org/key_project/util/collection/ImmutableSet.java @@ -29,7 +29,7 @@ public interface ImmutableSet return Collector.of(HashSet::new, Set::add, (set1, set2) -> { set1.addAll(set2); return set1; - }, Immutables::createSetFrom, Characteristics.UNORDERED); + }, Immutables::setOf, Characteristics.UNORDERED); } /** diff --git a/key.util/src/main/java/org/key_project/util/collection/Immutables.java b/key.util/src/main/java/org/key_project/util/collection/Immutables.java index b5d78d316f9..eca21e7a6f7 100644 --- a/key.util/src/main/java/org/key_project/util/collection/Immutables.java +++ b/key.util/src/main/java/org/key_project/util/collection/Immutables.java @@ -147,9 +147,9 @@ private Immutables() { * * @return the view onto the iterable as an immutable set */ - public static ImmutableSet createSetFrom( + public static ImmutableSet setOf( Iterable iterable) { - return DefaultImmutableSet.fromImmutableList(createListFrom(iterable)); + return DefaultImmutableSet.fromImmutableList(listOf(iterable)); } /** @@ -163,7 +163,7 @@ private Immutables() { * * @return the view onto the iterable as an immutable list */ - public static ImmutableList createListFrom(Iterable iterable) { + public static ImmutableList listOf(Iterable iterable) { ImmutableList result = ImmutableSLList.nil(); for (T t : iterable) { result = result.prepend(t); @@ -254,4 +254,5 @@ public static ImmutableList zip(ImmutableList list1, ImmutableList public static ImmutableList> zip(ImmutableList list1, ImmutableList list2) { return zip(list1, list2, Pair::new); } + } diff --git a/key.util/src/main/java/org/key_project/util/java/CollectionUtil.java b/key.util/src/main/java/org/key_project/util/java/CollectionUtil.java index baa70c6c94f..e78ccec4c7b 100644 --- a/key.util/src/main/java/org/key_project/util/java/CollectionUtil.java +++ b/key.util/src/main/java/org/key_project/util/java/CollectionUtil.java @@ -305,4 +305,25 @@ public static void addAll(Collection collection, Iterable iterable) { list.add(index, toInsert); } } + + /** + * Finds all duplicated elements in the given collection. + * + * The order of reported elements is in order of appearance in the collection. + * They are reported on the second and subsequent occurrences. + * + * @param collection The collection to search for duplicates. + * @return A list of all duplicated elements. + */ + public static List findDuplicates(Iterable collection) { + List result = new ArrayList<>(); + Set alreadySeen = new HashSet<>(); + for (T element : collection) { + if (!alreadySeen.add(element)) { + result.add(element); + } + } + return result; + } + }