Skip to content

Commit

Permalink
Merge pull request #50 from MontiCore/STExpr-source-info
Browse files Browse the repository at this point in the history
SymTypeSourceInfo
  • Loading branch information
SE-FDr authored Nov 12, 2024
2 parents 4c145a7 + afca4bc commit 6761e4f
Show file tree
Hide file tree
Showing 8 changed files with 443 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import de.monticore.symbols.basicsymbols._symboltable.VariableSymbol;
import de.monticore.symbols.oosymbols.OOSymbolsMill;
import de.monticore.symbols.oosymbols._symboltable.*;
import de.monticore.symboltable.ISymbol;
import de.monticore.symboltable.modifiers.AccessModifier;
import de.monticore.types3.ISymTypeVisitor;
import de.monticore.types3.util.SymTypeDeepCloneVisitor;
Expand Down Expand Up @@ -624,7 +625,7 @@ public boolean hasTypeInfo() {

/**
* Returns an TypeSymbol representing the type
* Only to be called according to {@link SymTypeExpression::hasTypeInfo}
* Only to be called according to {@link #hasTypeInfo()}
*/
public TypeSymbol getTypeInfo() {
//support deprecated behaviour
Expand All @@ -636,6 +637,25 @@ public TypeSymbol getTypeInfo() {
return null;
}

protected SymTypeSourceInfo sourceInfo = new SymTypeSourceInfo();

/**
* Contains information where this SymTypeExpression comes from.
* Used in CoCos, code-generation, etc.
* <p>
* not considered during {@link #deepEquals(SymTypeExpression)}.
*/
public SymTypeSourceInfo getSourceInfo() {
return this.sourceInfo;
}

/**
* used during deep-cloning, clones the SymTypeSourceInfo
*/
public void _internal_setSourceInfo(SymTypeSourceInfo sourceInfo) {
this.sourceInfo = new SymTypeSourceInfo(sourceInfo);
}

public void accept(ISymTypeVisitor visitor) {
// not abstract to support legacy typecheck subclasses
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// (c) https://github.com/MontiCore/monticore
package de.monticore.types.check;

import de.monticore.ast.ASTNode;
import de.monticore.symboltable.ISymbol;

import java.lang.ref.WeakReference;
import java.util.Optional;

/**
* Stores information where a SymTypeExpression comes from.
* This additional information can be used in CoCos/code-generation, etc.
* <p>
* There will be no info available if using TypeCheck1.
*/
public class SymTypeSourceInfo {

protected Optional<ISymbol> sourceSymbol;

/**
* Usage of a WeakReference over an Optional is mostly symbolic;
* NEVER rely on this information, but if it is available, it may be of use.
*/
protected WeakReference<ASTNode> sourceNode;

public SymTypeSourceInfo() {
this.sourceSymbol = Optional.empty();
this.sourceNode = new WeakReference<>(null);
}

/**
* deep clone
*/
public SymTypeSourceInfo(SymTypeSourceInfo other) {
this.sourceSymbol = other.sourceSymbol;
this.sourceNode = other.sourceNode;
}

/**
* Source symbol of the SymTypeExpression, e.g.,
* if a variable "int x" is resolved, the type symbol will be int,
* but the source symbol will be the variable symbol x.
* <p>
* This information can be used for CoCos, code generators, etc.
* <p>
* WARNING: modifying the SymTypeExpression (e.g., normalization)
* can remove this information. This is deliberate.
* <p>
* This replaces getDefiningSymbol() of TypeCheck1.
*/
public Optional<ISymbol> getSourceSymbol() {
return this.sourceSymbol;
}

public void setSourceSymbol(ISymbol source) {
this.sourceSymbol = Optional.of(source);
}

/**
* Source ASTNode of the SymTypeExpression, e.g.,
* if the SymTypeExpression has been calculated as the type of a specific ASTNode,
* this ASTNode may(!) be returned (no other ASTNode is returned).
* <p>
* This is ONLY meant to be used to create better log messages!
* As (especially during type inference) SymTypeExpressions
* are moved around, cloned, and modified A LOT,
* therefore, it cannot be assumed that this holds reliable information.
* The information should still be useful in most cases, though.
*/
public Optional<ASTNode> getSourceNode() {
return Optional.ofNullable(this.sourceNode.get());
}

/**
* first and foremost called in Type4Ast
*/
public void _internal_setSourceNode(ASTNode source) {
this.sourceNode = new WeakReference<>(source);
}

}
30 changes: 16 additions & 14 deletions monticore-grammar/src/main/java/de/monticore/types3/Type4Ast.java
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ protected void internal_setTypeOfExpression(
+ typeExpr.printFullName(),
LOG_NAME
);
typeExpr.getSourceInfo()._internal_setSourceNode(node);
getExpression2Type().put(node, typeExpr);
}
else {
Expand Down Expand Up @@ -488,6 +489,7 @@ protected void internal_setTypeOfTypeIdentifier(
+ typeExpr.printFullName(),
LOG_NAME
);
typeExpr.getSourceInfo()._internal_setSourceNode(node);
getTypeIdentifier2Type().put(node, typeExpr);
}
else {
Expand All @@ -513,20 +515,20 @@ protected void internal_setTypeOfTypeIdentifier(
protected void assertNoInferenceVars(ASTNode node, SymTypeExpression type) {
// todo reenable after https://git.rwth-aachen.de/monticore/monticore/-/issues/4268
if (false)
if (TypeParameterRelations.hasInferenceVariables(type)) {
Log.info("0xFD777 internal error: "
+ "(this is going to be considered an error, currently(!) "
+ "only ignored for legacy reasons) " + System.lineSeparator()
+ "tried storing a type with inference variables ("
+ type.printFullName() + ") in Type4Ast."
+ " This can occur due to: " + System.lineSeparator()
+ "1. The TypeCheck of this language does not support"
+ " type inference and a symbol has been used which requires "
+ "type inference (in this context)." + System.lineSeparator()
+ "2. Or, a programming error.",
LOG_NAME
);
}
if (TypeParameterRelations.hasInferenceVariables(type)) {
Log.info("0xFD777 internal error: "
+ "(this is going to be considered an error, currently(!) "
+ "only ignored for legacy reasons) " + System.lineSeparator()
+ "tried storing a type with inference variables ("
+ type.printFullName() + ") in Type4Ast."
+ " This can occur due to: " + System.lineSeparator()
+ "1. The TypeCheck of this language does not support"
+ " type inference and a symbol has been used which requires "
+ "type inference (in this context)." + System.lineSeparator()
+ "2. Or, a programming error.",
LOG_NAME
);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@
import de.se_rwth.commons.logging.Log;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
* resolves within a type,
Expand All @@ -34,7 +34,7 @@ public List<SymTypeOfFunction> resolveConstructors(
SymTypeExpression thisType,
AccessModifier accessModifier,
Predicate<FunctionSymbol> predicate) {
List<SymTypeOfFunction> resolvedSymTypes = new ArrayList<>();
List<SymTypeOfFunction> resolvedSymTypes;
Optional<IBasicSymbolsScope> spannedScopeOpt = getSpannedScope(thisType);
if (spannedScopeOpt.isEmpty()) {
resolvedSymTypes = new ArrayList<>();
Expand All @@ -47,26 +47,26 @@ public List<SymTypeOfFunction> resolveConstructors(
accessModifier,
predicate
);
List<SymTypeOfFunction> resolvedTypesUnmodified = resolvedSymbols.stream()
.map(FunctionSymbol::getFunctionType)
.collect(Collectors.toList());
// checking for broken symbol table
if (resolvedTypesUnmodified.stream().anyMatch(f ->
!f.getType().hasTypeInfo() ||
!f.getType().getTypeInfo().getFullName()
.equals(thisType.getTypeInfo().getFullName())
)) {
Log.error("0xFDCC2 unexpected constructor return type(s) of type "
+ thisType.printFullName()
+ ", constructors are " + System.lineSeparator()
+ resolvedTypesUnmodified.stream()
.map(SymTypeOfFunction::printFullName)
.collect(Collectors.joining(System.lineSeparator()))
);
resolvedSymTypes = new ArrayList<>(resolvedSymbols.size());
for (FunctionSymbol funcSym : resolvedSymbols) {
SymTypeOfFunction funcTypeUnmodified = funcSym.getFunctionType();
// checking for broken symbol table
if (!funcTypeUnmodified.getType().hasTypeInfo() ||
!funcTypeUnmodified.getType().getTypeInfo().getFullName().equals(
thisType.getTypeInfo().getFullName()
)) {
Log.error("0xFDCC2 unexpected constructor return type(s) of type "
+ thisType.printFullName()
+ ", constructor is " + System.lineSeparator()
+ funcTypeUnmodified.printFullName()
);
}
SymTypeOfFunction funcType = replaceVariablesIfNecessary(
thisType, funcTypeUnmodified
).asFunctionType();
funcType.getSourceInfo().setSourceSymbol(funcSym);
resolvedSymTypes.add(funcType);
}
resolvedSymTypes = resolvedTypesUnmodified.stream()
.map(f -> (SymTypeOfFunction) replaceVariablesIfNecessary(thisType, f))
.collect(Collectors.toList());
}

// do not search super types for constructors
Expand Down
Loading

0 comments on commit 6761e4f

Please sign in to comment.