Search in sources :

Example 21 with AstNode

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);
}
Also used : ExpressionResult(nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult) AbstractType(nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType) AstNode(com.sonar.sslr.api.AstNode)

Example 22 with AstNode

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);
}
Also used : ExpressionResult(nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult) AbstractType(nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType) Method(nl.ramsolutions.sw.magik.analysis.typing.types.Method) AstNode(com.sonar.sslr.api.AstNode) MethodInvocationNodeHelper(nl.ramsolutions.sw.magik.analysis.helpers.MethodInvocationNodeHelper)

Example 23 with AstNode

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);
        }
    }
}
Also used : ScopeEntry(nl.ramsolutions.sw.magik.analysis.scope.ScopeEntry) GlobalScope(nl.ramsolutions.sw.magik.analysis.scope.GlobalScope) Scope(nl.ramsolutions.sw.magik.analysis.scope.Scope) ExpressionResult(nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult) AbstractType(nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType) AstNode(com.sonar.sslr.api.AstNode)

Example 24 with AstNode

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);
}
Also used : AstNode(com.sonar.sslr.api.AstNode)

Example 25 with AstNode

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);
    }
}
Also used : ScopeEntry(nl.ramsolutions.sw.magik.analysis.scope.ScopeEntry) GlobalScope(nl.ramsolutions.sw.magik.analysis.scope.GlobalScope) Scope(nl.ramsolutions.sw.magik.analysis.scope.Scope) ExpressionResult(nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult) AbstractType(nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType) AstNode(com.sonar.sslr.api.AstNode)

Aggregations

AstNode (com.sonar.sslr.api.AstNode)491 Test (org.junit.Test)108 Test (org.junit.jupiter.api.Test)91 ExpressionResult (nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult)71 Token (com.sonar.sslr.api.Token)50 AbstractType (nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType)49 Token (org.sonar.plugins.python.api.tree.Token)46 MagikTypedFile (nl.ramsolutions.sw.magik.MagikTypedFile)41 YieldExpression (org.sonar.plugins.python.api.tree.YieldExpression)40 FormattedExpression (org.sonar.plugins.python.api.tree.FormattedExpression)39 QualifiedExpression (org.sonar.plugins.python.api.tree.QualifiedExpression)39 AssignmentExpression (org.sonar.plugins.python.api.tree.AssignmentExpression)38 ComprehensionExpression (org.sonar.plugins.python.api.tree.ComprehensionExpression)38 ConditionalExpression (org.sonar.plugins.python.api.tree.ConditionalExpression)38 Expression (org.sonar.plugins.python.api.tree.Expression)38 LambdaExpression (org.sonar.plugins.python.api.tree.LambdaExpression)38 List (java.util.List)35 RuleTest (org.sonar.python.parser.RuleTest)34 ArrayList (java.util.ArrayList)33 MagikType (nl.ramsolutions.sw.magik.analysis.typing.types.MagikType)33