use of com.sonar.sslr.api.AstNode in project magik-tools by StevenLooman.
the class LocalTypeReasoner method applyUnaryOperator.
/**
* Apply a unary operator.
* @param node Node to evaluate.
*/
private void applyUnaryOperator(final AstNode node) {
final AbstractType unsetType = this.typeKeeper.getType(SW_UNSET);
// Get operand.
final AstNode operatedNode = node.getLastChild();
final ExpressionResult operatedResult = this.getNodeType(operatedNode);
final AbstractType type = operatedResult.get(0, unsetType);
// Get operator.
final String operatorStr = node.getTokenValue();
final UnaryOperator.Operator operator = UnaryOperator.Operator.valueFor(operatorStr);
final UnaryOperator unaryOperator = this.typeKeeper.getUnaryOperator(operator, type);
// Apply opertor to operand and store result.
final AbstractType resultingType = unaryOperator != null ? unaryOperator.getResultType() : UndefinedType.INSTANCE;
final ExpressionResult result = new ExpressionResult(resultingType);
this.setNodeType(node, result);
}
use of com.sonar.sslr.api.AstNode in project magik-tools by StevenLooman.
the class LocalTypeReasoner method walkPostMethodInvocation.
@Override
protected void walkPostMethodInvocation(final AstNode node) {
final AbstractType unsetType = this.typeKeeper.getType(SW_UNSET);
// Get called type for method.
final AstNode calledNode = node.getPreviousSibling();
final ExpressionResult calledResult = this.getNodeType(calledNode);
final AbstractType originalCalledType = calledResult.get(0, unsetType);
final AbstractType calledType = calledResult.get(0, unsetType) == SelfType.INSTANCE ? this.getMethodOwnerType(node) : calledResult.get(0, unsetType);
// Clear iterator results.
this.setIteratorType(null);
// Perform method call and store iterator result(s).
final MethodInvocationNodeHelper helper = new MethodInvocationNodeHelper(node);
final String methodName = helper.getMethodName();
final Collection<Method> methods = calledType.getMethods(methodName);
ExpressionResult callResult = null;
if (methods.isEmpty()) {
// Method not found, we cannot known what the results will be.
callResult = ExpressionResult.UNDEFINED;
this.setIteratorType(ExpressionResult.UNDEFINED);
} else {
for (final Method method : methods) {
// Call.
if (callResult == null) {
callResult = method.getCallResult();
} else {
final ExpressionResult methodResult = method.getCallResult();
callResult = new ExpressionResult(callResult, methodResult, unsetType);
}
if (originalCalledType != SelfType.INSTANCE) {
callResult = callResult.substituteType(SelfType.INSTANCE, calledType);
}
// Iterator.
final ExpressionResult loopbodyResult = method.getLoopbodyResult();
if (this.getIteratorType() == null) {
this.setIteratorType(loopbodyResult);
} else {
final ExpressionResult iterResult = new ExpressionResult(this.iteratorType, loopbodyResult, unsetType);
this.setIteratorType(iterResult);
}
if (originalCalledType != SelfType.INSTANCE) {
final ExpressionResult subbedResult = this.getIteratorType().substituteType(SelfType.INSTANCE, calledType);
this.setIteratorType(subbedResult);
}
}
}
// Store it!
// Keep linters happy.
Objects.requireNonNull(callResult);
this.setNodeType(node, callResult);
}
use of com.sonar.sslr.api.AstNode 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 com.sonar.sslr.api.AstNode in project magik-tools by StevenLooman.
the class LocalTypeReasoner method walkPostPackageSpecification.
@Override
protected void walkPostPackageSpecification(final AstNode node) {
final AstNode identifierNode = node.getFirstChild(MagikGrammar.IDENTIFIER);
final String name = identifierNode.getTokenValue();
if (!this.typeKeeper.hasPackage(name)) {
LOGGER.warn("Package not found: {}", name);
}
// Package is created on demand.
this.currentPackage = this.typeKeeper.getPackage(name);
}
use of com.sonar.sslr.api.AstNode 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);
}
}
Aggregations