Type check for constant matching.
This commit is contained in:
parent
1d6c0e334a
commit
b4b4e8c4fd
|
|
@ -33,7 +33,7 @@ namespace PascalABCCompiler.SyntaxTree
|
|||
DirectDescendants
|
||||
}
|
||||
|
||||
public enum SemanticCheckType { MatchedExpression, MatchedExpressionAndType }
|
||||
public enum SemanticCheckType { MatchedExpression, MatchedExpressionAndType, MatchedExpressionAndExpression }
|
||||
|
||||
public partial class syntax_tree_node
|
||||
{
|
||||
|
|
|
|||
|
|
@ -74,9 +74,11 @@ namespace SyntaxVisitors.SugarVisitors
|
|||
|
||||
private if_node _previousIf;
|
||||
private statement desugaredMatchWith;
|
||||
|
||||
private List<if_node> processedIfNodes = new List<if_node>();
|
||||
|
||||
//const matching
|
||||
private List<statement> typeChecks = new List<statement>();
|
||||
|
||||
public static PatternsDesugaringVisitor New => new PatternsDesugaringVisitor();
|
||||
|
||||
public override void visit(match_with matchWith)
|
||||
|
|
@ -129,6 +131,11 @@ namespace SyntaxVisitors.SugarVisitors
|
|||
if (desugaredMatchWith == null)
|
||||
desugaredMatchWith = new empty_statement();
|
||||
|
||||
if (typeChecks.Count != 0)
|
||||
{
|
||||
typeChecks.Add(desugaredMatchWith);
|
||||
desugaredMatchWith = new statement_list(typeChecks);
|
||||
}
|
||||
// Замена выражения match with на новое несахарное поддерево и его обход
|
||||
ReplaceUsingParent(matchWith, desugaredMatchWith);
|
||||
visit(desugaredMatchWith);
|
||||
|
|
@ -162,6 +169,7 @@ namespace SyntaxVisitors.SugarVisitors
|
|||
var patternExpressionNode = patternCase.pattern as const_pattern;
|
||||
//var tuple_pattern_case = patternExpressionNode.pattern_expression as method_call;
|
||||
|
||||
var statementsToAdd = new List<statement>();
|
||||
var equalCalls = new List<method_call>();
|
||||
foreach (var patternExpression in patternExpressionNode.pattern_expressions.expressions)
|
||||
{
|
||||
|
|
@ -179,7 +187,9 @@ namespace SyntaxVisitors.SugarVisitors
|
|||
patternCase.source_context
|
||||
)
|
||||
);
|
||||
statementsToAdd.Add(GetTypeCompatibilityCheck(matchingExpression, patternExpression));
|
||||
}
|
||||
typeChecks.AddRange(statementsToAdd);
|
||||
expression orPatternCases = equalCalls[0];
|
||||
for (int i = 1; i < equalCalls.Count; ++i)
|
||||
{
|
||||
|
|
@ -187,7 +197,18 @@ namespace SyntaxVisitors.SugarVisitors
|
|||
}
|
||||
var ifCondition = patternCase.condition == null ? orPatternCases : bin_expr.LogicalAnd(orPatternCases, patternCase.condition);
|
||||
var ifCheck = SubtreeCreator.CreateIf(ifCondition, patternCase.case_action);
|
||||
|
||||
/*
|
||||
if (_previousIf != null)
|
||||
{
|
||||
AddDefinitionsInUpperStatementList(ifCheck, statementsToAdd);
|
||||
}
|
||||
else
|
||||
{
|
||||
statement emptySt = new empty_statement();
|
||||
ConvertIfNode(ifCheck, statementsToAdd, out emptySt);
|
||||
ifCheck = processedIfNodes[0];
|
||||
}
|
||||
*/
|
||||
// Добавляем полученные statements в результат
|
||||
AddDesugaredCaseToResult(ifCheck, ifCheck);
|
||||
}
|
||||
|
|
@ -341,6 +362,9 @@ namespace SyntaxVisitors.SugarVisitors
|
|||
private semantic_check_sugared_statement_node GetTypeCompatibilityCheck(is_pattern_expr expression) =>
|
||||
new semantic_check_sugared_statement_node(SemanticCheckType.MatchedExpressionAndType, new List<syntax_tree_node>() { expression.left, (expression.right as deconstructor_pattern).type });
|
||||
|
||||
private semantic_check_sugared_statement_node GetTypeCompatibilityCheck(expression expression1, expression expression2) =>
|
||||
new semantic_check_sugared_statement_node(SemanticCheckType.MatchedExpressionAndExpression, new List<syntax_tree_node>() { expression1, expression2 });
|
||||
|
||||
private statement_list ConvertIfNode(if_node ifNode, List<statement> statementsBeforeIf, out statement elseBody)
|
||||
{
|
||||
// if e then <then> else <else>
|
||||
|
|
|
|||
|
|
@ -261,5 +261,22 @@ namespace PascalABCCompiler.TreeConverter
|
|||
|
||||
AddError(get_location(matchedExpression), "EXPRESSION_OF_TYPE_{0}_CANNOT_BE_MATCHED_AGAINST_PATTERN_WITH_TYPE_{1}", expression.name, type.name);
|
||||
}
|
||||
|
||||
private void CheckIfCanBeMatched(expression matchedExpression, expression patternExpression)
|
||||
{
|
||||
var patternType = convert_strong(patternExpression).type;
|
||||
var expressionType = convert_strong(matchedExpression).type;
|
||||
|
||||
var expressionTypeName = expressionType.name;
|
||||
var patternTypeName = patternType.name;
|
||||
|
||||
if (type_table.is_derived(patternType, expressionType) ||
|
||||
type_table.is_derived(expressionType, patternType) ||
|
||||
AreTheSameType(patternType, expressionType) ||
|
||||
(expressionTypeName.StartsWith("Tuple") && patternTypeName.StartsWith("Tuple")))
|
||||
return;
|
||||
|
||||
AddError(get_location(matchedExpression), "EXPRESSION_OF_TYPE_{0}_CANNOT_BE_MATCHED_AGAINST_PATTERN_WITH_TYPE_{1}", expressionType.name, patternType.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20012,6 +20012,12 @@ namespace PascalABCCompiler.TreeConverter
|
|||
var type = st.lst[1] as type_definition;
|
||||
CheckIfCanBeMatched(expr, type);
|
||||
}
|
||||
else if (st.typ is SemanticCheckType.MatchedExpressionAndExpression)
|
||||
{
|
||||
var matchedExpr = st.lst[0] as expression;
|
||||
var patternExpr = st.lst[1] as expression;
|
||||
CheckIfCanBeMatched(matchedExpr, patternExpr);
|
||||
}
|
||||
// !Patterns
|
||||
else
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue