From 748bf89911359bffbfafe354e522f7d656488146 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Tue, 13 Sep 2022 20:39:27 +0200 Subject: refactor(language): clarify containment hierarchy --- .../java/tools/refinery/language/Problem.xtext | 27 ++++++++++++---- .../java/tools/refinery/language/ProblemUtil.java | 37 ++++++++++++++++++++-- .../tools/refinery/language/builtin.problem | 19 +++++++++++ 3 files changed, 74 insertions(+), 9 deletions(-) (limited to 'subprojects/language') diff --git a/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext b/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext index f7b86dca..2a5af628 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext +++ b/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext @@ -26,15 +26,23 @@ EnumDeclaration: EnumLiteral returns Node: name=Identifier; +enum ReferenceKind: + REFERENCE="refers" | CONTAINMENT="contains" | CONTAINER="container"; + ReferenceDeclaration: - (containment?="contains" | "refers")? - referenceType=[Relation|QualifiedName] + ( + kind=ReferenceKind referenceType=[Relation|QualifiedName] | + referenceType=[Relation|NonRelationKindQualifiedName] + ) ("[" multiplicity=Multiplicity "]")? name=Identifier ("opposite" opposite=[ReferenceDeclaration|QualifiedName])?; +enum PredicateKind: + ERROR="error" | CONTAINED="contained" | CONTAINMENT="containment"; + PredicateDefinition: - (error?="error" "pred"? | "pred") + (kind=PredicateKind "pred"? | "pred") name=Identifier "(" (parameters+=Parameter ("," parameters+=Parameter)*)? ")" ("<->" bodies+=Conjunction (";" bodies+=Conjunction)*)? @@ -150,7 +158,7 @@ ScopeDeclaration: "scope" typeScopes+=TypeScope ("," typeScopes+=TypeScope)* "."; TypeScope: - targetType=[ClassDeclaration|QualifiedName] + targetType=[Relation|QualifiedName] (increment?="+=" | "=") multiplicity=DefiniteMultiplicity; @@ -175,12 +183,19 @@ IndividualDeclaration: UpperBound returns ecore::EInt: INT | "*"; +NonRelationKindQualifiedName hidden(): + NonRelationKindIdentifier ("::" Identifier)*; + QualifiedName hidden(): Identifier ("::" Identifier)*; +NonRelationKindIdentifier: + ID | "true" | "false" | "unknown" | "error" | "class" | "abstract" | "extends" | "enum" | + "pred" | "indiv" | "problem" | "new" | "delete" | "rule" | "may" | "must" | "current" | + "count" | "default" | "scope" | "contained" | "containment"; + Identifier: - ID | "true" | "false" | "unknown" | "error" | "class" | "abstract" | "extends" | "enum" | "pred" | - "indiv" | "problem" | "new" | "delete" | "rule" | "may" | "must" | "current" | "count"; + NonRelationKindIdentifier | "refers" | "contains" | "container"; Integer returns ecore::EInt hidden(): "-"? INT; diff --git a/subprojects/language/src/main/java/tools/refinery/language/ProblemUtil.java b/subprojects/language/src/main/java/tools/refinery/language/ProblemUtil.java index b1e39176..0be296fd 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/ProblemUtil.java +++ b/subprojects/language/src/main/java/tools/refinery/language/ProblemUtil.java @@ -27,6 +27,10 @@ public final class ProblemUtil { public static final String NODE_CLASS_NAME = "node"; + public static final String DOMAIN_CLASS_NAME = "domain"; + + public static final String DATA_CLASS_NAME = "data"; + private ProblemUtil() { throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); } @@ -80,15 +84,15 @@ public final class ProblemUtil { return false; } - public static Optional getNodeClassDeclaration(EObject context) { + public static Optional getBuiltinClassDeclaration(EObject context, String name) { return getBuiltInLibrary(context).flatMap(problem -> problem.getStatements().stream() .filter(ClassDeclaration.class::isInstance).map(ClassDeclaration.class::cast) - .filter(declaration -> NODE_CLASS_NAME.equals(declaration.getName())).findFirst()); + .filter(declaration -> name.equals(declaration.getName())).findFirst()); } public static Collection getSuperclassesAndSelf(ClassDeclaration classDeclaration) { Set found = new HashSet<>(); - getNodeClassDeclaration(classDeclaration).ifPresent(found::add); + getBuiltinClassDeclaration(classDeclaration, NODE_CLASS_NAME).ifPresent(found::add); Deque queue = new ArrayDeque<>(); queue.addLast(classDeclaration); while (!queue.isEmpty()) { @@ -102,6 +106,11 @@ public final class ProblemUtil { } } } + getBuiltinClassDeclaration(classDeclaration, DATA_CLASS_NAME).ifPresent((dataClassDelcaration) -> { + if (!found.contains(dataClassDelcaration)) { + getBuiltinClassDeclaration(classDeclaration, DOMAIN_CLASS_NAME).ifPresent(found::add); + } + }); return found; } @@ -113,6 +122,28 @@ public final class ProblemUtil { return referenceDeclarations; } + public static boolean isDataClass(Relation relation) { + if (relation instanceof ClassDeclaration classDeclaration) { + var supertypes = getSuperclassesAndSelf(classDeclaration); + return getBuiltinClassDeclaration(classDeclaration, DATA_CLASS_NAME).map(supertypes::contains) + .orElse(false); + } + return false; + } + + public static boolean isContainmentReference(ReferenceDeclaration referenceDeclaration) { + switch (referenceDeclaration.getKind()) { + case REFERENCE, CONTAINER: + return false; + case CONTAINMENT: + return true; + case DEFAULT: + return isDataClass(referenceDeclaration.getReferenceType()); + default: + throw new IllegalArgumentException("Unknown reference kind " + referenceDeclaration.getKind()); + } + } + private static URI getLibraryUri(String libraryName) { return URI.createURI(ProblemUtil.class.getClassLoader() .getResource("tools/refinery/language/%s.problem".formatted(libraryName)).toString()); diff --git a/subprojects/language/src/main/resources/tools/refinery/language/builtin.problem b/subprojects/language/src/main/resources/tools/refinery/language/builtin.problem index 323e03f1..e39ff1a3 100644 --- a/subprojects/language/src/main/resources/tools/refinery/language/builtin.problem +++ b/subprojects/language/src/main/resources/tools/refinery/language/builtin.problem @@ -19,3 +19,22 @@ class real extends data. class int extends data. class string extends data. + +pred contained(node node). + +pred contains(node container, node contained). + +pred root(node node). + +% error missingContainer(contained node) <-> +% !contains(node, _), !root(node). +% +% error tooManyContainers(contained node) <-> +% count contains(_, node) > 1 +% ; +% contains(_, node), root(node) +% ; +% contains(_, node), !contained(node). +% +% error containmentCycle(node node) <-> +% contains+(node, node). -- cgit v1.2.3-54-g00ecf