Search in sources :

Example 1 with ScopeEntry

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

Example 2 with ScopeEntry

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);
    }
}
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 3 with ScopeEntry

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);
        }
    }
}
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 4 with ScopeEntry

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);
    }
}
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 5 with ScopeEntry

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);
        }
    });
}
Also used : GlobalScope(nl.ramsolutions.sw.magik.analysis.scope.GlobalScope) AstNode(com.sonar.sslr.api.AstNode) MagikCheck(nl.ramsolutions.sw.magik.checks.MagikCheck) MagikFile(nl.ramsolutions.sw.magik.MagikFile) ScopeEntry(nl.ramsolutions.sw.magik.analysis.scope.ScopeEntry) Scope(nl.ramsolutions.sw.magik.analysis.scope.Scope) Type(nl.ramsolutions.sw.magik.analysis.scope.ScopeEntry.Type) Rule(org.sonar.check.Rule) MagikGrammar(nl.ramsolutions.sw.magik.api.MagikGrammar) GlobalScope(nl.ramsolutions.sw.magik.analysis.scope.GlobalScope) ScopeEntry(nl.ramsolutions.sw.magik.analysis.scope.ScopeEntry) GlobalScope(nl.ramsolutions.sw.magik.analysis.scope.GlobalScope) Scope(nl.ramsolutions.sw.magik.analysis.scope.Scope) MagikFile(nl.ramsolutions.sw.magik.MagikFile)

Aggregations

ScopeEntry (nl.ramsolutions.sw.magik.analysis.scope.ScopeEntry)24 AstNode (com.sonar.sslr.api.AstNode)23 GlobalScope (nl.ramsolutions.sw.magik.analysis.scope.GlobalScope)22 Scope (nl.ramsolutions.sw.magik.analysis.scope.Scope)21 ExpressionResult (nl.ramsolutions.sw.magik.analysis.typing.types.ExpressionResult)10 AbstractType (nl.ramsolutions.sw.magik.analysis.typing.types.AbstractType)8 GlobalReference (nl.ramsolutions.sw.magik.analysis.typing.types.GlobalReference)4 MagikGrammar (nl.ramsolutions.sw.magik.api.MagikGrammar)4 List (java.util.List)3 Collectors (java.util.stream.Collectors)3 MagikFile (nl.ramsolutions.sw.magik.MagikFile)3 ArrayList (java.util.ArrayList)2 Map (java.util.Map)2 Objects (java.util.Objects)2 Stream (java.util.stream.Stream)2 Range (nl.ramsolutions.sw.magik.analysis.Range)2 MethodInvocationNodeHelper (nl.ramsolutions.sw.magik.analysis.helpers.MethodInvocationNodeHelper)2 PackageNodeHelper (nl.ramsolutions.sw.magik.analysis.helpers.PackageNodeHelper)2 ITypeKeeper (nl.ramsolutions.sw.magik.analysis.typing.ITypeKeeper)2 MagikCheck (nl.ramsolutions.sw.magik.checks.MagikCheck)2