Skip to content

Commit

Permalink
Merge branch 'TypeParameters-after-LQT' into 'dev'
Browse files Browse the repository at this point in the history
Type parameters

See merge request monticore/monticore!1034
  • Loading branch information
SE-FDr committed Oct 1, 2024
2 parents cdab9d2 + e7c65f8 commit 0acfb7a
Show file tree
Hide file tree
Showing 19 changed files with 626 additions and 6 deletions.
7 changes: 7 additions & 0 deletions monticore-grammar/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ def grammarDependencies = ext {
SIUnitLiterals = ["MCCommonLiterals", "SIUnits"]
SIUnitTypes4Math = ["MCBasicTypes", "SIUnits"]
SIUnitTypes4Computing = ["MCBasicTypes", "SIUnitTypes4Math"]
TypeParameters = ["BasicSymbols", "MCBasicTypes"]

// three dependencies
LambdaExpressions = ["BasicSymbols", "MCBasicTypes", "ExpressionsBasis"]
Expand Down Expand Up @@ -372,6 +373,9 @@ checkArtifactsMCFullGenericTypes.dependsOn(checkArtifactsMCSimpleGenericTypes)

checkArtifactsMCSimpleGenericTypes.dependsOn(checkArtifactsMCCollectionTypes)

checkArtifactsTypeParameters.dependsOn(checkArtifactsBasicSymbols)
checkArtifactsTypeParameters.dependsOn(checkArtifactsMCBasicTypes)

checkArtifactsCardinality.dependsOn(checkArtifactsMCBasics)
checkArtifactsCardinality.dependsOn(checkArtifactsMCCommonLiterals)

Expand Down Expand Up @@ -503,6 +507,9 @@ showArtifactsMCFullGenericTypes.dependsOn(showArtifactsMCSimpleGenericTypes)

showArtifactsMCSimpleGenericTypes.dependsOn(showArtifactsMCCollectionTypes)

showArtifactsTypeParameters.dependsOn(showArtifactsBasicSymbols)
showArtifactsTypeParameters.dependsOn(showArtifactsMCBasicTypes)

showArtifactsCardinality.dependsOn(showArtifactsMCBasics)
showArtifactsCardinality.dependsOn(showArtifactsMCCommonLiterals)

Expand Down
12 changes: 12 additions & 0 deletions monticore-grammar/src/main/grammars/de/monticore/Grammars.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,18 @@ be issued (instead of runtime errors only).
* `String` could be treated identical to `R".*"`, but it may be that
the chosen typecheck wants to enforce explicit coercion.

### [TypeParameters.mc4](types/TypeParameters.mc4) (alpha)

This grammar offers ways to define type parameters for,
e.g., classes or functions.
Modeling elements with type parameters represent
type-level functions that take type arguments;
For Example, the generic type `List<T>` has one type parameter `T`
and therefore takes one type argument.
`List<T>` or `List` cannot be used directly in a model,
instead, providing a type argument (e.g., `int`)
yields a type `List<int>` that can be used.

## Symbols: List of Grammars in package `de.monticore.symbols`

These two grammars do not provide syntax themselves, but
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ component grammar JavaLight extends AssignmentExpressions,
JavaClassExpressions,
MCCommonStatements,
MCArrayStatements,
MCReturnStatements {
MCReturnStatements,
TypeParameters {

interface ClassBodyDeclaration;

Expand All @@ -45,12 +46,12 @@ symbolrule JavaMethod =
isDefault: boolean;

MethodDeclaration implements JavaMethod, ClassBodyDeclaration, InterfaceBodyDeclaration
= MCModifier* ("<"(MCTypeArgument||",")+">")?
= MCModifier* TypeParameters?
MCReturnType Name FormalParameters (dim:"[" "]")*
("throws" Throws)? (MCJavaBlock | ";");

ConstructorDeclaration implements JavaMethod, ClassBodyDeclaration
= MCModifier* ("<"(MCTypeArgument||",")+">")? Name FormalParameters
= MCModifier* TypeParameters? Name FormalParameters
("throws" Throws)? MCJavaBlock;

ConstDeclaration extends LocalVariableDeclarationStatement
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ mlc JavaLight {
mlc "de.monticore.statements.MCCommonStatements";
mlc "de.monticore.statements.MCArrayStatements";
mlc "de.monticore.statements.MCReturnStatements";
mlc "de.monticore.types.TypeParameters";
}

uses {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* (c) https://github.com/MontiCore/monticore */
package de.monticore.types;

/* Beta-version: This is intended to become a MontiCore stable grammar. */

import de.monticore.symbols.BasicSymbols;

/**
* This grammar introduces type parameters such as T, U extends Set<int>,
* and type parameter lists such as <T, S extends T>
* that can be used to declare generic model elements
* such as generic classes and functions.
*
* Like Java, each type parameter can have an upper bound
* consisting of an arbitrary number of types.
*/

component grammar TypeParameters
extends BasicSymbols,
MCBasicTypes {

/**
* ASTTypeParameters are type parameter lists that are can be used to
* declare generic model elements.
* Each type parameter lists contains at least one type parameter.
* Example:
* <T>
* <T, U extends T & Comparable<U>>
*/
TypeParameters =
"<" (TypeParameter || ",")+ ">"
;

/**
* ASTTypeParameter represents one type parameter.
* It itself is represented in the symbol table as a TypeVarSymbol.
* Each type parameter has a name
* and can have an optional list of upper type bounds.
* Each bound list consists of an arbitrary positive number of types.
* Each of those types is a supertype of the corresponding type parameter.
* Example:
* T
* U extends T & Comparable<U>
*/
TypeParameter implements TypeVar =
Name
("extends" (MCType || "&")+)?
;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package de.monticore.types;

mlc TypeParameters {

//export the grammar
export "$projectDir/src/main/grammars" {
include "de/monticore/types/TypeParameters.mc4";
}

//export handwritten code
export "$projectDir/src/main/java" {
include "de/monticore/types/typeparameters/**.java";
}

// export all Java files generated from the grammar
export "$projectDir/target/generated-sources/monticore/sourcecode" {
include "de/monticore/types/typeparameters/**.java";
}

promote {
include "$projectDir/src/main/java/de/monticore/types3/*.java";
}

promote {
mlc "de.monticore.symbols.BasicSymbols";
mlc "de.monticore.types.MCBasicTypes";
}

}
12 changes: 12 additions & 0 deletions monticore-grammar/src/main/grammars/de/monticore/types/Types.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ the following language components:
* [`MCArrayTypes`](MCArrayTypes.mc4)
* [`MCFunctionTypes`](MCFunctionTypes.mc4)
* [`MCStructuralTypes`](MCStructuralTypes.mc4)
* [`TypeParameters`](TypeParameters.mc4)
* [`SIUnitTypes4Math`](../siunit/SIUnitTypes4Math.mc4)
* [`SIUnitTypes4Computing`](../siunit/SIUnitTypes4Computing.mc4)
* [`RegExType`](../regex/RegExType.mc4)
Expand Down Expand Up @@ -65,6 +66,17 @@ arguments including wild card types. When using this language component,
types such as `Person<?>`, `Map<Person<String>, ? extends Person>`, and
`a.b.C<D>.E.F<G>.H` are expressible.

## [`TypeParameters`](TypeParameters.mc4)

This language component offers ways to define type parameter lists
for generic model elements, e.g., generic classes such as `Map<K, V>`.
The resulting Symbols can than be used with, e.g.,
[`MCSimpleGenericTypes`](MCSimpleGenericTypes.mc4), or
[`MCFullGenericTypes`](MCFullGenericTypes.mc4)
to define types by providing the corresponding type arguments.
Additionally, type parameters may optionally have upper bounds,
e.g., `T extends Person`, `U extends T & Comparable<U>`.

## [`MCArrayTypes`](MCArrayTypes.mc4)

This language component allows to express array types like `Person[]` or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ public interface IBasicSymbolsScope extends IBasicSymbolsScopeTOP {
* e.g. class C<T> {} // T is bound within the class
*/
default boolean isTypeVariableBound(TypeVarSymbol typeVar) {
if (getLocalTypeVarSymbols().stream()
List<TypeVarSymbol> localVars = resolveTypeVarLocallyMany(
false, typeVar.getName(),
AccessModifier.ALL_INCLUSION, (tv) -> true
);
if (localVars.stream()
.anyMatch(otherTypeVar -> otherTypeVar == typeVar)) {
return true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,14 +320,16 @@ public boolean deepEquals(SymTypeExpression sym) {
return true;
}
SymTypeVariable symVar = (SymTypeVariable) sym;
if (!denotesSameVar(symVar)) {
return false;
}
if (!getUpperBound().deepEquals(symVar.getUpperBound())) {
return false;
}
else if (!getLowerBound().deepEquals(symVar.getLowerBound())) {
return false;
}
// cannot identify without a name at this point
return denotesSameVar(symVar);
return true;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package de.monticore.types.typeparameters._symboltable;

import de.monticore.types.check.SymTypeExpression;
import de.monticore.types.mcbasictypes._ast.ASTMCType;
import de.monticore.types.typeparameters._ast.ASTTypeParameter;
import de.monticore.types.typeparameters._visitor.TypeParametersVisitor2;
import de.monticore.types3.ITypeCalculator;

import java.util.ArrayList;
import java.util.List;

/**
* Sets the superTypes of the type parameter symbols.
*/
public class TypeParametersSTCompleteTypes implements TypeParametersVisitor2 {

ITypeCalculator tc;

public TypeParametersSTCompleteTypes(ITypeCalculator tc) {
this.tc = tc;
}

@Override
public void visit(ASTTypeParameter node) {
List<SymTypeExpression> bounds = new ArrayList<>();
for (ASTMCType astTypeBound : node.getMCTypeList()) {
bounds.add(tc.symTypeFromAST(astTypeBound));
}
// error logged if obscure
node.getSymbol().setSuperTypesList(bounds);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* (c) https://github.com/MontiCore/monticore */
package de.monticore.types.typeparameters.cocos;

import de.monticore.types.check.SymTypeExpression;
import de.monticore.types.check.SymTypeVariable;
import de.monticore.types.typeparameters._ast.ASTTypeParameter;
import de.monticore.types.typeparameters._cocos.TypeParametersASTTypeParameterCoCo;
import de.monticore.types3.SymTypeRelations;
import de.se_rwth.commons.logging.Log;

import java.util.ArrayList;
import java.util.List;

import static de.monticore.types.check.SymTypeExpressionFactory.createTypeVariable;

/**
* Finds instances of circular inheritance,
* e.g., <T extends U, U extends Person & T>
*/
public class TypeParameterNoCyclicInheritance
implements TypeParametersASTTypeParameterCoCo {

@Override
public void check(ASTTypeParameter node) {
SymTypeVariable thisVar = createTypeVariable(node.getSymbol());
checkForCircularInheritance(List.of(thisVar), node);
}

protected boolean checkForCircularInheritance(
List<SymTypeExpression> currentInheritanceList,
ASTTypeParameter node
) {
List<SymTypeExpression> superTypes = SymTypeRelations.getNominalSuperTypes(
currentInheritanceList.get(currentInheritanceList.size() - 1)
);
for (SymTypeExpression superType : superTypes) {
if (currentInheritanceList.stream().anyMatch(superType::deepEquals)) {
Log.error("0xFDC12 Checked supertypes of type variable \""
+ node.getName()
+ "\" and found circular inheritance of type "
+ superType.printFullName(),
node.get_SourcePositionStart(),
node.get_SourcePositionEnd()
);
return false;
}
else {
List<SymTypeExpression> nextInheritanceList = new ArrayList<>();
nextInheritanceList.addAll(currentInheritanceList);
nextInheritanceList.add(superType);
if (!checkForCircularInheritance(nextInheritanceList, node)) {
return false;
}
}
}
return true;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* (c) https://github.com/MontiCore/monticore */
package de.monticore.types.typeparameters.cocos;

import de.monticore.symbols.basicsymbols._symboltable.TypeSymbolTOP;
import de.monticore.types.typeparameters._ast.ASTTypeParameter;
import de.monticore.types.typeparameters._ast.ASTTypeParameters;
import de.monticore.types.typeparameters._cocos.TypeParametersASTTypeParametersCoCo;
import de.se_rwth.commons.logging.Log;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class TypeParametersHaveUniqueNames
implements TypeParametersASTTypeParametersCoCo {

@Override
public void check(ASTTypeParameters node) {
List<String> names = node.getTypeParameterList().stream()
.map(ASTTypeParameter::getSymbol)
.map(TypeSymbolTOP::getName)
.collect(Collectors.toList());
Set<String> duplicates = findDuplicates(names);
for (String dupName : duplicates) {
Log.error("0xFDC14 The same name \"" + dupName
+ "\" has been used for multiple type parameters."
);
}
}

// Helper

protected Set<String> findDuplicates(List<String> listContainingDuplicates) {
final Set<String> setToReturn = new HashSet<>();
final Set<String> set1 = new HashSet<>();

for (String modifierName : listContainingDuplicates) {
if (!set1.add(modifierName)) {
setToReturn.add(modifierName);
}
}
return setToReturn;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ grammar CombineExpressionsWithLiterals extends
de.monticore.types.MCArrayTypes,
de.monticore.types.MCFunctionTypes,
de.monticore.types.MCStructuralTypes,
de.monticore.types.TypeParameters,
de.monticore.regex.RegExType,
de.monticore.siunit.SIUnitTypes4Math,
de.monticore.siunit.SIUnitTypes4Computing,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/* (c) https://github.com/MontiCore/monticore */
package de.monticore.types;

grammar TypeParametersTest extends
de.monticore.types.TypeParameters,
de.monticore.types.MCFullGenericTypes,
de.monticore.types.MCArrayTypes,
de.monticore.types.MCFunctionTypes,
de.monticore.types.MCStructuralTypes {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* (c) https://github.com/MontiCore/monticore */
package de.monticore.types;

grammar TypeParametersWithoutIntersectionTypesTest extends
de.monticore.types.TypeParameters,
de.monticore.types.MCFullGenericTypes,
de.monticore.types.MCArrayTypes,
de.monticore.types.MCFunctionTypes {
}
Loading

0 comments on commit 0acfb7a

Please sign in to comment.