diff --git a/SyntaxTree/tree/TreeHelper.cs b/SyntaxTree/tree/TreeHelper.cs index 1b618420c..dff8e7c7d 100644 --- a/SyntaxTree/tree/TreeHelper.cs +++ b/SyntaxTree/tree/TreeHelper.cs @@ -33,6 +33,8 @@ namespace PascalABCCompiler.SyntaxTree DirectDescendants } + public enum SugaredExpressionType { MatchedExpression } + public partial class syntax_tree_node { diff --git a/SyntaxVisitors/SugarVisitors/PatternsDesugaringVisitor.cs b/SyntaxVisitors/SugarVisitors/PatternsDesugaringVisitor.cs index 25c5a1dd7..21d797a21 100644 --- a/SyntaxVisitors/SugarVisitors/PatternsDesugaringVisitor.cs +++ b/SyntaxVisitors/SugarVisitors/PatternsDesugaringVisitor.cs @@ -111,8 +111,9 @@ namespace SyntaxVisitors.SugarVisitors public override void visit(is_pattern_expr isPatternExpr) { - // TODO Patterns: convert to compilation error - Debug.Assert(GetLocation(isPatternExpr) != PatternLocation.Unknown, "Is-pattern expression is in an unknown context"); + if (GetLocation(isPatternExpr) == PatternLocation.Unknown) + throw new SyntaxVisitorError("PATTERN_MATHING_IS_NOT_SUPPORTED_IN_THIS_CONTEXT", isPatternExpr.source_context); + Debug.Assert(GetAscendant(isPatternExpr) != null, "Couldn't find statement list in upper nodes"); DesugarIsExpression(isPatternExpr); @@ -235,6 +236,7 @@ namespace SyntaxVisitors.SugarVisitors ReplaceUsingParent(isExpression, desugaringResult.SuccessVariable); var statementsToAdd = desugaringResult.GetDeconstructionDefinitions(pattern.source_context); + statementsToAdd.Add(GetMatchedExpressionCheck(isExpression.left)); statementsToAdd.Add(desugaringResult.GetPatternCheckWithDeconstrunctorCall()); AddDefinitionsInUpperStatementList(isExpression, statementsToAdd); @@ -247,11 +249,12 @@ namespace SyntaxVisitors.SugarVisitors ReplaceUsingParent(isExpression, desugaringResult.SuccessVariable); var statementsToAdd = desugaringResult.GetDeconstructionDefinitions(pattern.source_context); + statementsToAdd.Add(GetMatchedExpressionCheck(isExpression.left)); statementsToAdd.Add(desugaringResult.GetPatternCheckWithDeconstrunctorCall()); var enclosingIf = GetAscendant(isExpression); // Если уже обрабатывался ранее (второй встретившийся в том же условии is), то не изменяем if - if (processedIfNodes.Contains(enclosingIf)) + if (processedIfNodes.Contains(enclosingIf)) AddDefinitionsInUpperStatementList(isExpression, statementsToAdd); // Иначе помещаем определения и if-then в отдельный блок, а else после этого блока else @@ -267,6 +270,9 @@ namespace SyntaxVisitors.SugarVisitors } } + private semantic_check_sugared_statement_node GetMatchedExpressionCheck(expression matchedExpression) + => new semantic_check_sugared_statement_node(SugaredExpressionType.MatchedExpression, new List() { matchedExpression }); + private statement_list ConvertIfNode(if_node ifNode, List statementsBeforeIf, out statement elseBody) { // if e then else diff --git a/TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Patterns.cs b/TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Patterns.cs index 484aa216e..859349bbe 100644 --- a/TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Patterns.cs +++ b/TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Patterns.cs @@ -211,5 +211,16 @@ namespace PascalABCCompiler.TreeConverter if (parameter.parameter_type != SemanticTree.parameter_type.var && parameter is common_parameter p) AddError(p.loc, "DECONSTRUCTION_PARAMETERS_SHOULD_HAVE_VAR_MODIFIER"); } + + /// + /// Проверяет выражение, сопоставляемое с образцом + /// + /// + private void CheckMatchedExpression(expression matchedExpression) + { + var convertedExpression = convert_strong(matchedExpression); + if (convertedExpression.type.IsPointer) + AddError(get_location(matchedExpression), "PATTERN_MATCHING_DOESNT_SUPPORT_POINTERS"); + } } } diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 8cb4005b3..279e172e8 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -12276,8 +12276,7 @@ namespace PascalABCCompiler.TreeConverter commonNode.name.ToLower() == compiler_string_consts.deconstruct_method_name) { var deconstructor = commonNode; - - // TODO Patterns: add warning for non-extension deconstruct + if (!deconstructor.is_extension_method) { //AddWarning(); @@ -19413,6 +19412,13 @@ namespace PascalABCCompiler.TreeConverter var expr = st.lst[0] as SyntaxTree.expression; semantic_check_loop_stmt(expr); } + // Patterns + else if (st.typ is SugaredExpressionType.MatchedExpression) + { + var expr = st.lst[0] as expression; + CheckMatchedExpression(expr); + } + // !Patterns else { AddError(get_location(st), "MISSED_SEMANTIC_CHECK_FOR_SUGARED_NODE_{0}", (st.typ as System.Type)?.Name??"Unknown");