diff --git a/CodeExamples/Patterns/patterns-switch.pas b/CodeExamples/Patterns/patterns-switch.pas index 3f3686e4f..d9fd0471b 100644 --- a/CodeExamples/Patterns/patterns-switch.pas +++ b/CodeExamples/Patterns/patterns-switch.pas @@ -3,6 +3,6 @@ match a with integer(var c): write(1); boolean(var s): write(2); - List(var l) when l.Count > 0 :write(3) + List(var l) when l.Count > 0 : write(3) end; end. \ No newline at end of file diff --git a/CodeExamples/Patterns/patterns-user-defined.pas b/CodeExamples/Patterns/patterns-user-defined.pas index ec4598d05..6b23c6f5c 100644 --- a/CodeExamples/Patterns/patterns-user-defined.pas +++ b/CodeExamples/Patterns/patterns-user-defined.pas @@ -20,5 +20,5 @@ begin var p := new Person('Петр', 25); if p is Person(var name, var age) then - Print(name, age); + Println(name, age); end. \ No newline at end of file diff --git a/InstallerSamples/LanguageFeatures/Pattern Matching/MatchDelegate.pas b/InstallerSamples/LanguageFeatures/Pattern Matching/MatchDelegate.pas new file mode 100644 index 000000000..72da62353 --- /dev/null +++ b/InstallerSamples/LanguageFeatures/Pattern Matching/MatchDelegate.pas @@ -0,0 +1,12 @@ +begin + var s: real->real := x -> x * x; + var add: (real,real)->real := (x, y)-> x + y; + + // Делегат может хранить процедурную переменную любого типа! + var d: System.Delegate := s; + d := add; + match d with + Func(var i): Print(i(2)); + Func2(var i): Print(i(2,3)); + end; +end. \ No newline at end of file diff --git a/InstallerSamples/LanguageFeatures/Pattern Matching/UserDefinedDeconstruct.pas b/InstallerSamples/LanguageFeatures/Pattern Matching/UserDefinedDeconstruct.pas new file mode 100644 index 000000000..044339b2a --- /dev/null +++ b/InstallerSamples/LanguageFeatures/Pattern Matching/UserDefinedDeconstruct.pas @@ -0,0 +1,27 @@ +type + Person = class + name: string; + age: integer; + + constructor(name: string; age: integer); + begin + self.name := name; + self.age := age; + end; + + procedure Deconstruct(var name: string; var age: integer); + begin + name := self.name; + age := self.age; + end; + end; + +begin + var p := new Person('Петр', 25); + if p is Person(var name, var age) then + Println(name, age); + + match p with + Person(name,age): Println(name,age); + end; +end. \ No newline at end of file diff --git a/InstallerSamples/LanguageFeatures/Pattern Matching/UserDefinedDeconstructAsExtension.pas b/InstallerSamples/LanguageFeatures/Pattern Matching/UserDefinedDeconstructAsExtension.pas new file mode 100644 index 000000000..89b4878c4 --- /dev/null +++ b/InstallerSamples/LanguageFeatures/Pattern Matching/UserDefinedDeconstructAsExtension.pas @@ -0,0 +1,20 @@ +// Деконструктор как метод расширения + +procedure Deconstruct(Self: integer; var a: integer; var b: integer); extensionmethod; +begin + a := Self div 10; + b := Self mod 10; +end; + + +begin + var i := 25; + if i is integer(var a, var b) then + Println(a,b); + + i := 9; + match i with + integer(a,b) when i>=10: Println(a,b); + integer(a): Println(a); // деконструктор по умолчанию + end; +end. \ No newline at end of file diff --git a/SyntaxTreeConverters/StandardSyntaxConverter.cs b/SyntaxTreeConverters/StandardSyntaxConverter.cs index 8180bdee1..b6ce19c9e 100644 --- a/SyntaxTreeConverters/StandardSyntaxConverter.cs +++ b/SyntaxTreeConverters/StandardSyntaxConverter.cs @@ -55,7 +55,7 @@ namespace PascalABCCompiler.SyntaxTreeConverters DoubleQuestionDesugarVisitor.New.ProcessNode(root); // Patterns - SingleDeconstructChecker.New.ProcessNode(root); + // SingleDeconstructChecker.New.ProcessNode(root); // SSM 21.10.18 - пока разрешил множественные деконструкторы. Если будут проблемы - запретить PatternsDesugaringVisitor.New.ProcessNode(root); // Всё, связанное с yield diff --git a/TestSuite/errors/err0292.pas b/TestSuite/errors/err0292.pas new file mode 100644 index 000000000..b6e67063c --- /dev/null +++ b/TestSuite/errors/err0292.pas @@ -0,0 +1,17 @@ +type + Person = auto class + name: string; + age: integer; + + class procedure Deconstruct(var age: integer); + begin + age := 666; + end; + end; + + +begin + var p := new Person('Иванов',20); + if p is Person(var age: integer) then + Print(name); +end. \ No newline at end of file diff --git a/TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Patterns.cs b/TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Patterns.cs index 1558fa1cc..a3260092b 100644 --- a/TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Patterns.cs +++ b/TreeConverter/TreeConversion/SyntaxTreeVisitorNodes/Patterns.cs @@ -225,8 +225,10 @@ namespace PascalABCCompiler.TreeConverter /// private void ExecuteCommonChecks(common_function_node deconstructor) { + if ((deconstructor as common_method_node).IsStatic) + AddError(deconstructor.loc, "DECONSTRUCTOR_SHOULD_NOT_BE_STATIC"); if (deconstructor.return_value_type != null) - AddError(deconstructor.loc, "DECONSTRUCTOR_SOULD_BE_A_PROCEDURE"); + AddError(deconstructor.loc, "DECONSTRUCTOR_SHOULD_BE_A_PROCEDURE"); foreach (var parameter in deconstructor.parameters.Where(x => !IsSelfParameter(x))) if (parameter.parameter_type != SemanticTree.parameter_type.var && parameter is common_parameter p) diff --git a/bin/Lng/Eng/SemanticErrors_nv.dat b/bin/Lng/Eng/SemanticErrors_nv.dat index 53fc82d94..777568eed 100644 --- a/bin/Lng/Eng/SemanticErrors_nv.dat +++ b/bin/Lng/Eng/SemanticErrors_nv.dat @@ -30,7 +30,7 @@ DUPLICATE_FUNCTION_DEFINITION=Duplicate function definition THIS_EXPRESSION_CAN_NOT_BE_PASSED_BY_ADDRESS=A var or const argument must be an assignable variable MEMBER_{0}_IS_NOT_DECLARED_IN_TYPE_{1}=The type '{1}' does not contain a definition for '{0}' MEMBER_{0}_IS_NOT_DECLARED_IN_NAMESPACE_{1}=The namespace '{0}' does not contaion definition for '{1}' -CAN_NOT_CALL_STATIC_MEMBER_{0}_WITH_EXPRESSION=Static member '{0}' cannot be accessed with an instance reference +CAN_NOT_CALL_STATIC_MEMBER_{0}_WITH_EXPRESSION=Static member '{0}' cannot be accessed wia an instance reference CAN_NOT_CALL_NON_STATIC_MEMBER_{0}_WITH_TYPE_{1}=An object reference is required for the nonstatic field, method, or property '{0}' CAN_NOT_REFERENCE_TO_STATIC_FIELD_{0}_WITH_EXPRESSION=Static field '{0}' cannot be accessed with an instance reference CAN_NOT_REFERENCE_TO_NONSTATIC_FIELD_{0}_WITH_TYPE=An object reference is required for the nonstatic field '{0}' diff --git a/bin/Lng/Eng/SemanticErrors_ws.dat b/bin/Lng/Eng/SemanticErrors_ws.dat index 0347b9652..c6c3ab4b7 100644 --- a/bin/Lng/Eng/SemanticErrors_ws.dat +++ b/bin/Lng/Eng/SemanticErrors_ws.dat @@ -4,7 +4,8 @@ INSTANCE_DECONSTRUCTORS_CANNOT_BE_GENERIC=Instance deconstructors cannot be gene NO_SUITABLE_DECONSTRUCT_FOUND=Couldn't find suitable deconstructor for given parameters NO_DECONSTRUCT_FOUND=Couldn't find deconstructor for this type DECONSTRUCTOR_METHOD_AMBIGUITY=Ambiguity between deconstructor methods -DECONSTRUCTOR_SOULD_BE_A_PROCEDURE=Deconstruct should be a procedure +DECONSTRUCTOR_SHOULD_BE_A_PROCEDURE=Deconstruct should be a procedure DECONSTRUCTION_PARAMETERS_SHOULD_HAVE_VAR_MODIFIER=Deconstructor's parameters should have 'var' modifier PATTERN_MATCHING_DOESNT_SUPPORT_POINTERS=Pattern matching doesn't support pointers in current compiler version EXPRESSION_OF_TYPE_{0}_CANNOT_BE_MATCHED_AGAINST_PATTERN_WITH_TYPE_{1}=Expression of type {0} cannot be matched against pattern with type {1} +DECONSTRUCTOR_SHOULD_NOT_BE_STATIC=Deconstructor should not be static diff --git a/bin/Lng/Eng/SyntaxTreeVisitorsErrors.dat b/bin/Lng/Eng/SyntaxTreeVisitorsErrors.dat index cddb0b59c..328c893b2 100644 --- a/bin/Lng/Eng/SyntaxTreeVisitorsErrors.dat +++ b/bin/Lng/Eng/SyntaxTreeVisitorsErrors.dat @@ -14,6 +14,7 @@ YIELDS_INSIDE_WITH_ARE_ILLEGAL=with statement cannot contain yields LAMBDA_EXPRESSIONS_CANNOT_CONTAIN_YIELD=Lambda-expressions cannot contain yields PATTERN_MATHING_IS_NOT_SUPPORTED_IN_THIS_CONTEXT=Pattern matching is not supported in this context +ONLY_ONE_DECONSTRUCT_ALLOWED=Only one user deconstructor is allowed Var_{0}_is_already_defined=Variable {0} is already defined diff --git a/bin/Lng/Rus/SemanticErrors_nv.dat b/bin/Lng/Rus/SemanticErrors_nv.dat index 6dd70333f..7ad1e2bdf 100644 --- a/bin/Lng/Rus/SemanticErrors_nv.dat +++ b/bin/Lng/Rus/SemanticErrors_nv.dat @@ -32,7 +32,7 @@ DUPLICATE_FUNCTION_DEFINITION=Повторное объявление подпр THIS_EXPRESSION_CAN_NOT_BE_PASSED_BY_ADDRESS=Данный объект не может быть передан как var-параметр MEMBER_{0}_IS_NOT_DECLARED_IN_TYPE_{1}={0} не объявлен в типе {1} MEMBER_{0}_IS_NOT_DECLARED_IN_NAMESPACE_{1}={0} не объявлен в пространстве имен {1} -CAN_NOT_CALL_STATIC_MEMBER_{0}_WITH_EXPRESSION=Нельзя вызвать статический метод {0} с выражением +CAN_NOT_CALL_STATIC_MEMBER_{0}_WITH_EXPRESSION=Нельзя вызвать статический метод {0} через ссылку на экземпляр CAN_NOT_CALL_NON_STATIC_MEMBER_{0}_WITH_TYPE_{1}=Mетод {0} не является статическим для типа {1} CAN_NOT_REFERENCE_TO_STATIC_FIELD_{0}_WITH_EXPRESSION=Нельзя обратиться к статическому полю {0} через объект CAN_NOT_REFERENCE_TO_NONSTATIC_FIELD_{0}_WITH_TYPE=Нельзя обратиться к экземплярному полю {0} через тип @@ -82,7 +82,7 @@ CASE_DIAPASON_VARIANT_INTERSECTION=Пересечение диапазонов CAN_NOT_INCREMENT_ORDINAL_TYPE_VALUE=Невозможно увеличить значение перечислимого типа (возможно, происходит выход за верхнюю границу типа) CAN_NOT_DECREMENT_ORDINAL_TYPE_VALUE=Невозможно уменьшить значение перечислимого типа (возможно, происходит выход за нижнюю границу типа) EXPECTED_DELEGATE=Ожидалось имя процедуры или функции -EXPECTED_STATIC_METHOD=Ожидался классовый метод +EXPECTED_STATIC_METHOD=Ожидался статический метод EXPECTED_NON_STATIC_METHOD=Ожидался экземплярный метод CAN_NOT_EXPLICITLY_CONVERT_TYPE_{0}_TO_TYPE_{1}=Невозможно явно преобразовать тип {0} к типу {1} ONLY_ONE_PARAMETER_OF_TYPE_CONVERSION_ALLOWED=У операции преобразования типов допустим только один параметр diff --git a/bin/Lng/Rus/SemanticErrors_ws.dat b/bin/Lng/Rus/SemanticErrors_ws.dat index 4862f66e9..adb55f0ff 100644 --- a/bin/Lng/Rus/SemanticErrors_ws.dat +++ b/bin/Lng/Rus/SemanticErrors_ws.dat @@ -4,7 +4,8 @@ INSTANCE_DECONSTRUCTORS_CANNOT_BE_GENERIC=Экземплярные деконс NO_SUITABLE_DECONSTRUCT_FOUND=Не удалось найти подходящий деконструктор NO_DECONSTRUCT_FOUND=В типе отсутствуют деконструкторы DECONSTRUCTOR_METHOD_AMBIGUITY=Неоднозначный вызов деконструктора -DECONSTRUCTOR_SOULD_BE_A_PROCEDURE=Деконструктор должен быть процедурой +DECONSTRUCTOR_SHOULD_BE_A_PROCEDURE=Деконструктор должен быть процедурой DECONSTRUCTION_PARAMETERS_SHOULD_HAVE_VAR_MODIFIER=Параметры деконструктора должны иметь модификатор 'var' PATTERN_MATCHING_DOESNT_SUPPORT_POINTERS=Сопоставление с образцом не поддерживает указатели в данной версии компилятора EXPRESSION_OF_TYPE_{0}_CANNOT_BE_MATCHED_AGAINST_PATTERN_WITH_TYPE_{1}= Выражение типа {0} не может быть сопоставлено с образцом типа {1} +DECONSTRUCTOR_SHOULD_NOT_BE_STATIC=Деконструктор не может быть статическим diff --git a/bin/Lng/Rus/SyntaxTreeVisitorsErrors.dat b/bin/Lng/Rus/SyntaxTreeVisitorsErrors.dat index f7e4a07af..b5a348048 100644 --- a/bin/Lng/Rus/SyntaxTreeVisitorsErrors.dat +++ b/bin/Lng/Rus/SyntaxTreeVisitorsErrors.dat @@ -14,6 +14,7 @@ YIELDS_INSIDE_WITH_ARE_ILLEGAL=Оператор yield запрещен внут LAMBDA_EXPRESSIONS_CANNOT_CONTAIN_YIELD=Лямбда-выражения не могут содержать yield PATTERN_MATHING_IS_NOT_SUPPORTED_IN_THIS_CONTEXT=Сопоставление с образцом не поддерживается в данном контексте +ONLY_ONE_DECONSTRUCT_ALLOWED=Можно определить только один пользовательский деконструктор Var_{0}_is_already_defined=Переменная {0} уже определена