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();
}
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;
}
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);
}
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;
}
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;
}
Aggregations