use of nl.ramsolutions.sw.magik.analysis.scope.ScopeEntry in project magik-tools by StevenLooman.
the class LocalTypeReasoner method walkPostIdentifier.
@Override
protected void walkPostIdentifier(final AstNode node) {
final AstNode parent = node.getParent();
if (!parent.is(MagikGrammar.ATOM)) {
return;
}
final Scope scope = this.globalScope.getScopeForNode(node);
Objects.requireNonNull(scope);
String identifier = node.getTokenValue();
final ScopeEntry scopeEntry = scope.getScopeEntry(identifier);
Objects.requireNonNull(scopeEntry);
if (scopeEntry.isType(ScopeEntry.Type.GLOBAL) || scopeEntry.isType(ScopeEntry.Type.DYNAMIC)) {
final String packageName = this.currentPackage.getName();
final GlobalReference globalRef = identifier.contains(":") ? GlobalReference.of(identifier) : GlobalReference.of(packageName, identifier);
this.assignAtom(node, globalRef);
} else if (scopeEntry.isType(ScopeEntry.Type.IMPORT)) {
final ScopeEntry parentScopeEntry = scopeEntry.getImportedEntry();
final AstNode lastNodeType = this.currentScopeEntryNodes.get(parentScopeEntry);
final ExpressionResult result = this.getNodeType(lastNodeType);
this.assignAtom(node, result);
} else if (scopeEntry.isType(ScopeEntry.Type.PARAMETER)) {
final AstNode parameterNode = scopeEntry.getNode();
final ExpressionResult result = this.getNodeType(parameterNode);
this.assignAtom(node, result);
} else {
final AstNode lastNodeType = this.currentScopeEntryNodes.get(scopeEntry);
if (lastNodeType != null) {
final ExpressionResult result = this.getNodeType(lastNodeType);
this.assignAtom(node, result);
}
}
}
use of nl.ramsolutions.sw.magik.analysis.scope.ScopeEntry in project magik-tools by StevenLooman.
the class LocalTypeReasoner method walkPostVariableDefinitionMulti.
@Override
protected void walkPostVariableDefinitionMulti(final AstNode node) {
final AbstractType unsetType = this.typeKeeper.getType(SW_UNSET);
// Take result for right hand.
final AstNode rightNode = node.getFirstChild(MagikGrammar.TUPLE);
final ExpressionResult result = this.getNodeType(rightNode);
// Assign to all left hands.
final List<AstNode> identifierNodes = node.getFirstChild(MagikGrammar.IDENTIFIERS_WITH_GATHER).getChildren(MagikGrammar.IDENTIFIER);
for (int i = 0; i < identifierNodes.size(); ++i) {
// TODO: Does this work with gather?
final AstNode identifierNode = identifierNodes.get(i);
final ExpressionResult partialResult = new ExpressionResult(result.get(i, unsetType));
this.setNodeType(identifierNode, partialResult);
// Store 'active' type for future reference.
final Scope scope = this.globalScope.getScopeForNode(node);
Objects.requireNonNull(scope);
final String identifier = identifierNode.getTokenValue();
final ScopeEntry scopeEntry = scope.getScopeEntry(identifier);
// TODO: Test if it isn't a slot node
this.currentScopeEntryNodes.put(scopeEntry, identifierNode);
}
}
use of nl.ramsolutions.sw.magik.analysis.scope.ScopeEntry in project magik-tools by StevenLooman.
the class LocalTypeReasoner method walkPostIterableExpression.
@Override
protected void walkPostIterableExpression(final AstNode node) {
final AbstractType unsetType = this.typeKeeper.getType(SW_UNSET);
// Bind to identifiers, if any.
final AstNode overNode = node.getParent();
final AstNode forNode = overNode.getParent();
if (forNode.is(MagikGrammar.FOR)) {
final AstNode loopNode = overNode.getFirstChild(MagikGrammar.LOOP);
final AstNode bodyNode = loopNode.getFirstChild(MagikGrammar.BODY);
final List<AstNode> identifierNodes = AstQuery.getChildrenFromChain(forNode, MagikGrammar.FOR_VARIABLES, MagikGrammar.IDENTIFIERS_WITH_GATHER, MagikGrammar.IDENTIFIER);
for (int i = 0; i < identifierNodes.size(); ++i) {
final AstNode identifierNode = identifierNodes.get(i);
final AstNode identifierPreviousNode = identifierNode.getPreviousSibling();
final AbstractType type = identifierPreviousNode != null && identifierPreviousNode.getTokenValue().equalsIgnoreCase("_gather") ? this.typeKeeper.getType(SW_SIMPLE_VECTOR) : this.getIteratorType().get(i, unsetType);
final ExpressionResult result = new ExpressionResult(type);
this.setNodeType(identifierNode, result);
final Scope scope = this.globalScope.getScopeForNode(bodyNode);
Objects.requireNonNull(scope);
final String identifier = identifierNode.getTokenValue();
final ScopeEntry scopeEntry = scope.getScopeEntry(identifier);
this.currentScopeEntryNodes.put(scopeEntry, identifierNode);
}
}
}
use of nl.ramsolutions.sw.magik.analysis.scope.ScopeEntry in project magik-tools by StevenLooman.
the class LocalTypeReasoner method walkPostAugmentedAssignmentExpression.
@Override
protected void walkPostAugmentedAssignmentExpression(final AstNode node) {
final AbstractType unsetType = this.typeKeeper.getType(SW_UNSET);
final AbstractType falseType = this.typeKeeper.getType(SW_FALSE);
// Take result from right hand.
final AstNode rightNode = node.getLastChild();
final ExpressionResult rightResult = this.getNodeType(rightNode);
// Get left hand result.
final AstNode assignedNode = node.getFirstChild();
final ExpressionResult leftResult = this.getNodeType(assignedNode);
// Get operator.
final AstNode operatorNode = node.getChildren().get(1);
final String operatorStr = operatorNode.getTokenValue();
// Evaluate binary operator.
final AbstractType leftType = leftResult.get(0, unsetType);
final AbstractType rightType = rightResult.get(0, unsetType);
final ExpressionResult result;
switch(operatorStr.toLowerCase()) {
case "_is":
case "_isnt":
result = new ExpressionResult(falseType);
break;
// TODO: Not entirely true.
case "_andif":
case // TODO: Not entirely true.
"_orif":
result = new ExpressionResult(falseType);
break;
default:
final BinaryOperator.Operator operator = BinaryOperator.Operator.valueFor(operatorStr);
final BinaryOperator binaryOperator = this.typeKeeper.getBinaryOperator(operator, leftType, rightType);
final AbstractType resultingType = binaryOperator != null ? binaryOperator.getResultType() : UndefinedType.INSTANCE;
result = new ExpressionResult(resultingType);
break;
}
// Store result of expression.
this.setNodeType(node, result);
if (assignedNode.is(MagikGrammar.ATOM)) {
// Store 'active' type for future reference.
final Scope scope = this.globalScope.getScopeForNode(assignedNode);
Objects.requireNonNull(scope);
final String identifier = assignedNode.getTokenValue();
final ScopeEntry scopeEntry = scope.getScopeEntry(identifier);
this.currentScopeEntryNodes.put(scopeEntry, assignedNode);
this.setNodeType(assignedNode, result);
}
}
use of nl.ramsolutions.sw.magik.analysis.scope.ScopeEntry in project magik-tools by StevenLooman.
the class ImportMissingDefinitionCheck method walkPreVariableDefinitionStatement.
@Override
protected void walkPreVariableDefinitionStatement(AstNode node) {
// Ensure it is an _import (and not a _dynamic _import).
final boolean isImport = node.getChildren(MagikGrammar.VARIABLE_DEFINITION_MODIFIER).stream().allMatch(modifierNode -> modifierNode.getTokenValue().equalsIgnoreCase("_import"));
if (!isImport) {
return;
}
// Ready the scope.
final MagikFile magikFile = this.getMagikFile();
final GlobalScope globalScope = magikFile.getGlobalScope();
final Scope scope = globalScope.getScopeForNode(node);
// Iterate over all defined variables and check if parent definition exists.
node.getChildren(MagikGrammar.VARIABLE_DEFINITION).stream().map(variableDefinitionNode -> variableDefinitionNode.getFirstChild(MagikGrammar.IDENTIFIER)).forEach(identifierNode -> {
final String identifier = identifierNode.getTokenValue();
final ScopeEntry scopeEntry = scope.getScopeEntry(identifier);
if (scopeEntry.isType(Type.IMPORT) && scopeEntry.getImportedEntry() == null) {
final String originalIdentifier = identifierNode.getTokenOriginalValue();
final String message = String.format(MESSAGE, originalIdentifier);
this.addIssue(identifierNode, message);
}
});
}
Aggregations