Search in sources :

Example 1 with BLangMatch

use of org.wso2.ballerinalang.compiler.tree.statements.BLangMatch in project ballerina by ballerina-lang.

the class CodeAnalyzer method visit.

@Override
public void visit(BLangMatch matchStmt) {
    this.returnWithintransactionCheckStack.push(true);
    boolean unmatchedExprTypesAvailable = false;
    analyzeExpr(matchStmt.expr);
    // TODO Handle **any** as a expr type.. special case it..
    // TODO Complete the exhaustive tests with any, struct and connector types
    // TODO Handle the case where there are incompatible types. e.g. input string : pattern int and pattern string
    List<BType> unmatchedExprTypes = new ArrayList<>();
    for (BType exprType : matchStmt.exprTypes) {
        boolean assignable = false;
        for (BLangMatchStmtPatternClause pattern : matchStmt.patternClauses) {
            BType patternType = pattern.variable.type;
            if (exprType.tag == TypeTags.ERROR || patternType.tag == TypeTags.ERROR) {
                return;
            }
            assignable = this.types.isAssignable(exprType, patternType);
            if (assignable) {
                pattern.matchedTypesDirect.add(exprType);
                break;
            } else if (exprType.tag == TypeTags.ANY) {
                pattern.matchedTypesIndirect.add(exprType);
            } else if (exprType.tag == TypeTags.JSON && this.types.isAssignable(patternType, exprType)) {
                pattern.matchedTypesIndirect.add(exprType);
            } else if (exprType.tag == TypeTags.STRUCT && this.types.isAssignable(patternType, exprType)) {
                pattern.matchedTypesIndirect.add(exprType);
            } else {
            // TODO Support other assignable types
            }
        }
        if (!assignable) {
            unmatchedExprTypes.add(exprType);
        }
    }
    if (!unmatchedExprTypes.isEmpty()) {
        unmatchedExprTypesAvailable = true;
        dlog.error(matchStmt.pos, DiagnosticCode.MATCH_STMT_CANNOT_GUARANTEE_A_MATCHING_PATTERN, unmatchedExprTypes);
    }
    boolean matchedPatternsAvailable = false;
    for (int i = matchStmt.patternClauses.size() - 1; i >= 0; i--) {
        BLangMatchStmtPatternClause pattern = matchStmt.patternClauses.get(i);
        if (pattern.matchedTypesDirect.isEmpty() && pattern.matchedTypesIndirect.isEmpty()) {
            if (matchedPatternsAvailable) {
                dlog.error(pattern.pos, DiagnosticCode.MATCH_STMT_UNMATCHED_PATTERN);
            } else {
                dlog.error(pattern.pos, DiagnosticCode.MATCH_STMT_UNREACHABLE_PATTERN);
            }
        } else {
            matchedPatternsAvailable = true;
        }
    }
    // Execute the following block if there are no unmatched expression types
    if (!unmatchedExprTypesAvailable) {
        this.checkStatementExecutionValidity(matchStmt);
        boolean matchStmtReturns = true;
        for (BLangMatchStmtPatternClause patternClause : matchStmt.patternClauses) {
            patternClause.body.accept(this);
            matchStmtReturns = matchStmtReturns && this.statementReturns;
            this.resetStatementReturns();
        }
        this.statementReturns = matchStmtReturns;
    }
    this.returnWithintransactionCheckStack.pop();
}
Also used : BType(org.wso2.ballerinalang.compiler.semantics.model.types.BType) ArrayList(java.util.ArrayList) BLangMatchStmtPatternClause(org.wso2.ballerinalang.compiler.tree.statements.BLangMatch.BLangMatchStmtPatternClause) BLangEndpoint(org.wso2.ballerinalang.compiler.tree.BLangEndpoint)

Example 2 with BLangMatch

use of org.wso2.ballerinalang.compiler.tree.statements.BLangMatch in project ballerina by ballerina-lang.

the class ASTBuilderUtil method createMatchStatement.

static BLangMatch createMatchStatement(DiagnosticPos pos, BLangExpression expr, List<BLangMatchStmtPatternClause> patternClauses) {
    BLangMatch matchStmt = (BLangMatch) TreeBuilder.createMatchStatement();
    matchStmt.pos = pos;
    matchStmt.expr = expr;
    matchStmt.patternClauses = patternClauses;
    return matchStmt;
}
Also used : BLangMatch(org.wso2.ballerinalang.compiler.tree.statements.BLangMatch)

Example 3 with BLangMatch

use of org.wso2.ballerinalang.compiler.tree.statements.BLangMatch in project ballerina by ballerina-lang.

the class Desugar method visit.

@Override
public void visit(BLangAssignment assignNode) {
    if (assignNode.expr.type.tag == TypeTags.STREAM && assignNode.varRefs.get(0) instanceof BLangSimpleVarRef) {
        ((BLangRecordLiteral) assignNode.expr).name = ((BLangSimpleVarRef) assignNode.varRefs.get(0)).variableName;
    }
    assignNode.varRefs = rewriteExprs(assignNode.varRefs);
    assignNode.expr = rewriteExpr(assignNode.expr);
    result = assignNode;
    if (!assignNode.safeAssignment) {
        return;
    }
    // Desugar the =? operator with the match statement
    // 
    // e.g.
    // File f;
    // .....
    // f =? openFile("/tmp/foo.txt"); // openFile: () -> (File | error)
    // 
    // {
    // match openFile("/tmp/foo.txt") {
    // File _$_f1 => f = _$_f1;
    // error e => throw e | return e
    // }
    // }
    BLangBlockStmt safeAssignmentBlock = ASTBuilderUtil.createBlockStmt(assignNode.pos, new ArrayList<>());
    BLangExpression lhsExpr = assignNode.varRefs.get(0);
    BLangMatchStmtPatternClause patternSuccessCase;
    if (assignNode.declaredWithVar) {
        BVarSymbol varSymbol = ((BLangSimpleVarRef) lhsExpr).symbol;
        BLangVariable variable = ASTBuilderUtil.createVariable(assignNode.pos, "", lhsExpr.type, null, varSymbol);
        BLangVariableDef variableDef = ASTBuilderUtil.createVariableDef(assignNode.pos, variable);
        safeAssignmentBlock.stmts.add(variableDef);
        patternSuccessCase = getSafeAssignSuccessPattern(assignNode.pos, lhsExpr.type, true, varSymbol, null);
    } else {
        patternSuccessCase = getSafeAssignSuccessPattern(assignNode.pos, lhsExpr.type, false, null, lhsExpr);
    }
    // Create the pattern to match the success case
    BLangMatchStmtPatternClause patternErrorCase = getSafeAssignErrorPattern(assignNode.pos, this.env.enclInvokable.symbol);
    // Create the match statement
    BLangMatch matchStmt = ASTBuilderUtil.createMatchStatement(assignNode.pos, assignNode.expr, new ArrayList<BLangMatchStmtPatternClause>() {

        {
            add(patternSuccessCase);
            add(patternErrorCase);
        }
    });
    // var f =? foo() -> var f;
    assignNode.expr = null;
    assignNode.safeAssignment = false;
    safeAssignmentBlock.stmts.add(matchStmt);
    result = rewrite(safeAssignmentBlock, this.env);
}
Also used : BLangBlockStmt(org.wso2.ballerinalang.compiler.tree.statements.BLangBlockStmt) BLangSimpleVarRef(org.wso2.ballerinalang.compiler.tree.expressions.BLangSimpleVarRef) BLangMatch(org.wso2.ballerinalang.compiler.tree.statements.BLangMatch) BLangMatchStmtPatternClause(org.wso2.ballerinalang.compiler.tree.statements.BLangMatch.BLangMatchStmtPatternClause) BLangVariableDef(org.wso2.ballerinalang.compiler.tree.statements.BLangVariableDef) BLangExpression(org.wso2.ballerinalang.compiler.tree.expressions.BLangExpression) BVarSymbol(org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol) BLangVariable(org.wso2.ballerinalang.compiler.tree.BLangVariable)

Example 4 with BLangMatch

use of org.wso2.ballerinalang.compiler.tree.statements.BLangMatch in project ballerina by ballerina-lang.

the class MatchStatementScopeResolver method isCursorBeforeNode.

/**
 * Check whether the cursor is positioned before the given node start.
 *
 * @param nodePosition          Position of the node
 * @param node                  Node
 * @param treeVisitor           {@link TreeVisitor} current tree visitor instance
 * @param completionContext     Completion operation context
 * @return {@link Boolean}      Whether the cursor is before the node start or not
 */
@Override
public boolean isCursorBeforeNode(DiagnosticPos nodePosition, Node node, TreeVisitor treeVisitor, TextDocumentServiceContext completionContext) {
    if (!(treeVisitor.getBlockOwnerStack().peek() instanceof BLangMatch)) {
        // In the ideal case, this will not get triggered
        return false;
    }
    BLangMatch matchNode = (BLangMatch) treeVisitor.getBlockOwnerStack().peek();
    DiagnosticPos matchNodePos = CommonUtil.toZeroBasedPosition(matchNode.getPosition());
    DiagnosticPos nodePos = CommonUtil.toZeroBasedPosition((DiagnosticPos) node.getPosition());
    List<BLangMatch.BLangMatchStmtPatternClause> patternClauseList = matchNode.getPatternClauses();
    int line = completionContext.get(DocumentServiceKeys.POSITION_KEY).getPosition().getLine();
    int col = completionContext.get(DocumentServiceKeys.POSITION_KEY).getPosition().getCharacter();
    int nodeLine = nodePos.getStartLine();
    int nodeCol = nodePos.getStartColumn();
    boolean isBeforeNode = false;
    if ((line < nodeLine) || (line == nodeLine && col < nodeCol)) {
        isBeforeNode = true;
    } else if (patternClauseList.indexOf(node) == patternClauseList.size() - 1) {
        isBeforeNode = (line < matchNodePos.getEndLine()) || (line == matchNodePos.getEndLine() && col < matchNodePos.getEndColumn());
    }
    if (isBeforeNode) {
        Map<Name, Scope.ScopeEntry> visibleSymbolEntries = treeVisitor.resolveAllVisibleSymbols(treeVisitor.getSymbolEnv());
        SymbolEnv matchEnv = createMatchEnv(matchNode, treeVisitor.getSymbolEnv());
        treeVisitor.populateSymbols(visibleSymbolEntries, matchEnv);
        treeVisitor.setTerminateVisitor(true);
    }
    return isBeforeNode;
}
Also used : DiagnosticPos(org.wso2.ballerinalang.compiler.util.diagnotic.DiagnosticPos) BLangMatch(org.wso2.ballerinalang.compiler.tree.statements.BLangMatch) SymbolEnv(org.wso2.ballerinalang.compiler.semantics.model.SymbolEnv) Name(org.wso2.ballerinalang.compiler.util.Name)

Example 5 with BLangMatch

use of org.wso2.ballerinalang.compiler.tree.statements.BLangMatch in project ballerina by ballerina-lang.

the class MatchStatementScopeResolver method createMatchEnv.

private static SymbolEnv createMatchEnv(BLangMatch match, SymbolEnv env) {
    SymbolEnv symbolEnv = new SymbolEnv(match, null);
    env.copyTo(symbolEnv);
    return symbolEnv;
}
Also used : SymbolEnv(org.wso2.ballerinalang.compiler.semantics.model.SymbolEnv)

Aggregations

BLangMatch (org.wso2.ballerinalang.compiler.tree.statements.BLangMatch)7 BLangMatchStmtPatternClause (org.wso2.ballerinalang.compiler.tree.statements.BLangMatch.BLangMatchStmtPatternClause)4 BType (org.wso2.ballerinalang.compiler.semantics.model.types.BType)3 BLangVariable (org.wso2.ballerinalang.compiler.tree.BLangVariable)3 BLangBlockStmt (org.wso2.ballerinalang.compiler.tree.statements.BLangBlockStmt)3 ArrayList (java.util.ArrayList)2 SymbolEnv (org.wso2.ballerinalang.compiler.semantics.model.SymbolEnv)2 BVarSymbol (org.wso2.ballerinalang.compiler.semantics.model.symbols.BVarSymbol)2 BUnionType (org.wso2.ballerinalang.compiler.semantics.model.types.BUnionType)2 BLangEndpoint (org.wso2.ballerinalang.compiler.tree.BLangEndpoint)2 BLangVariableDef (org.wso2.ballerinalang.compiler.tree.statements.BLangVariableDef)2 List (java.util.List)1 SymbolInfo (org.ballerinalang.langserver.completions.SymbolInfo)1 CompletionItem (org.eclipse.lsp4j.CompletionItem)1 BStructSymbol (org.wso2.ballerinalang.compiler.semantics.model.symbols.BStructSymbol)1 BSymbol (org.wso2.ballerinalang.compiler.semantics.model.symbols.BSymbol)1 BTypeSymbol (org.wso2.ballerinalang.compiler.semantics.model.symbols.BTypeSymbol)1 BJSONType (org.wso2.ballerinalang.compiler.semantics.model.types.BJSONType)1 BStructType (org.wso2.ballerinalang.compiler.semantics.model.types.BStructType)1 BLangNode (org.wso2.ballerinalang.compiler.tree.BLangNode)1