From 460247ccc6afb0bdd226854aaad65b5879efe887 Mon Sep 17 00:00:00 2001 From: Ivan Bondarev Date: Sun, 27 Dec 2020 12:18:28 +0100 Subject: [PATCH] fix #2330 --- Compiler/PCU/PCUFileFormatVersion.cs | 2 +- Compiler/PCU/PCUReader.cs | 9 +- Compiler/PCU/PCUWriter.cs | 10 +- NETGenerator/NETGenerator.cs | 51 ++++++++ SemanticTree/AbstractVisitor.cs | 5 + SemanticTree/IVisitor.cs | 4 +- SemanticTree/SemanticTree.cs | 15 ++- .../DoubleQuestionDesugarVisitor.cs | 4 +- TestSuite/CompilationSamples/PABCSystem.pas | 67 ++++++----- TestSuite/double_question1.pas | 10 ++ TestSuite/errors/err0382.pas | 3 + TestSuite/errors/err0383.pas | 3 + TestSuite/errors/err0384.pas | 3 + TestSuite/units/u_doublequestion1.pas | 12 ++ TestSuite/usesunits/use_doublequestion1.pas | 2 + .../TreeConversion/syntax_tree_visitor.cs | 109 ++++++++++++++++++ TreeConverter/TreeRealization/Expressions.cs | 62 +++++++++- TreeConverter/TreeRealization/base_nodes.cs | 2 +- .../LanguageConverter/Source/Visitor.cs | 5 + .../Source/Visitor.cs | 5 + 20 files changed, 347 insertions(+), 36 deletions(-) create mode 100644 TestSuite/double_question1.pas create mode 100644 TestSuite/errors/err0382.pas create mode 100644 TestSuite/errors/err0383.pas create mode 100644 TestSuite/errors/err0384.pas create mode 100644 TestSuite/units/u_doublequestion1.pas create mode 100644 TestSuite/usesunits/use_doublequestion1.pas diff --git a/Compiler/PCU/PCUFileFormatVersion.cs b/Compiler/PCU/PCUFileFormatVersion.cs index e8fce5107..adb82a0e1 100644 --- a/Compiler/PCU/PCUFileFormatVersion.cs +++ b/Compiler/PCU/PCUFileFormatVersion.cs @@ -6,6 +6,6 @@ namespace PascalABCCompiler.PCU { public static class PCUFileFormatVersion { - public static System.Int16 Version = 116; + public static System.Int16 Version = 117; } } diff --git a/Compiler/PCU/PCUReader.cs b/Compiler/PCU/PCUReader.cs index 8576860e9..02dbdc62e 100644 --- a/Compiler/PCU/PCUReader.cs +++ b/Compiler/PCU/PCUReader.cs @@ -3502,7 +3502,12 @@ namespace PascalABCCompiler.PCU { return new question_colon_expression(CreateExpression(), CreateExpression(), CreateExpression(), null); } - + + private double_question_colon_expression CreateDoubleQuestionColonExpression() + { + return new double_question_colon_expression(CreateExpression(), CreateExpression(), null); + } + private statements_expression_node CreateStatementsExpressionNode() { statement_node_list sl = new statement_node_list(); @@ -3551,6 +3556,8 @@ namespace PascalABCCompiler.PCU return CreateStatementsExpressionNode(); case semantic_node_type.question_colon_expression: return CreateQuestionColonExpression(); + case semantic_node_type.double_question_colon_expression: + return CreateDoubleQuestionColonExpression(); case semantic_node_type.sizeof_operator: return CreateSizeOfOperator(); case semantic_node_type.is_node: diff --git a/Compiler/PCU/PCUWriter.cs b/Compiler/PCU/PCUWriter.cs index f238838a2..ef87071ac 100644 --- a/Compiler/PCU/PCUWriter.cs +++ b/Compiler/PCU/PCUWriter.cs @@ -3634,7 +3634,13 @@ namespace PascalABCCompiler.PCU VisitExpression(node.internal_ret_if_true); VisitExpression(node.internal_ret_if_false); } - + + private void VisitDoubleQuestionColonExpression(double_question_colon_expression node) + { + VisitExpression(node.internal_condition); + VisitExpression(node.internal_ret_if_null); + } + private void VisitStatementsExpressionNode(statements_expression_node node) { bw.Write(node.internal_statements.Count); @@ -3677,6 +3683,8 @@ namespace PascalABCCompiler.PCU VisitStatementsExpressionNode((statements_expression_node)en); break; case semantic_node_type.question_colon_expression: VisitQuestionColonExpression((question_colon_expression)en); break; + case semantic_node_type.double_question_colon_expression: + VisitDoubleQuestionColonExpression((double_question_colon_expression)en); break; case semantic_node_type.sizeof_operator: VisitSizeOfOperator((sizeof_operator)en); break; case semantic_node_type.is_node: diff --git a/NETGenerator/NETGenerator.cs b/NETGenerator/NETGenerator.cs index 417e879d9..31a77ffbe 100644 --- a/NETGenerator/NETGenerator.cs +++ b/NETGenerator/NETGenerator.cs @@ -10411,6 +10411,57 @@ namespace PascalABCCompiler.NETGenerator } + public override void visit(IDoubleQuestionColonExpressionNode value) + { + Label EndLabel = il.DefineLabel(); + Label NullLabel = il.DefineLabel(); + bool tmp_is_dot_expr = is_dot_expr; + bool tmp_is_addr = is_addr; + is_dot_expr = false;//don't box the condition expression + is_addr = false; + LocalBuilder tmp_lb = null; + if (value.condition is IBasicFunctionCallNode && + (value.condition as IBasicFunctionCallNode).real_parameters[0].type.IsDelegate && + (value.condition as IBasicFunctionCallNode).real_parameters[1] is INullConstantNode && + (value.condition as IBasicFunctionCallNode).basic_function.basic_function_type == basic_function_type.objeq) + { + IBasicFunctionCallNode eq = (value.condition as IBasicFunctionCallNode); + tmp_lb = il.DeclareLocal(helper.GetTypeReference((value.condition as IBasicFunctionCallNode).real_parameters[0].type).tp); + eq.real_parameters[0].visit(this); + il.Emit(OpCodes.Stloc, tmp_lb); + il.Emit(OpCodes.Ldloc, tmp_lb); + il.Emit(OpCodes.Ldnull); + il.Emit(OpCodes.Ceq); + + } + else + { + value.condition.visit(this); + tmp_lb = il.DeclareLocal(helper.GetTypeReference(value.type).tp); + il.Emit(OpCodes.Stloc, tmp_lb); + il.Emit(OpCodes.Ldloc, tmp_lb); + il.Emit(OpCodes.Ldnull); + il.Emit(OpCodes.Ceq); + } + + + is_dot_expr = tmp_is_dot_expr; + is_addr = tmp_is_addr; + il.Emit(OpCodes.Brtrue, NullLabel); + il.Emit(OpCodes.Ldloc, tmp_lb); + TypeInfo ti = helper.GetTypeReference(value.condition.type); + if (ti != null) + EmitBox(value.condition, ti.tp); + il.Emit(OpCodes.Br, EndLabel); + il.MarkLabel(NullLabel); + value.ret_if_null.visit(this); + ti = helper.GetTypeReference(value.ret_if_null.type); + if (ti != null) + EmitBox(value.ret_if_null, ti.tp); + il.MarkLabel(EndLabel); + + } + private Hashtable range_stmts_labels = new Hashtable(); //перевод селекторов-диапазонов case diff --git a/SemanticTree/AbstractVisitor.cs b/SemanticTree/AbstractVisitor.cs index 3c1a6acf8..9ac335081 100644 --- a/SemanticTree/AbstractVisitor.cs +++ b/SemanticTree/AbstractVisitor.cs @@ -646,6 +646,11 @@ namespace PascalABCCompiler.SemanticTree { } + + public virtual void visit(IDoubleQuestionColonExpressionNode value) + { + + } } } diff --git a/SemanticTree/IVisitor.cs b/SemanticTree/IVisitor.cs index e2c822126..09679e948 100644 --- a/SemanticTree/IVisitor.cs +++ b/SemanticTree/IVisitor.cs @@ -299,6 +299,8 @@ namespace PascalABCCompiler.SemanticTree void visit(ICommonNamespaceEventNode value); void visit(IDefaultOperatorNodeAsConstant value); - } + + void visit(IDoubleQuestionColonExpressionNode value); + } } diff --git a/SemanticTree/SemanticTree.cs b/SemanticTree/SemanticTree.cs index 82c2068e5..c3ef40bf0 100644 --- a/SemanticTree/SemanticTree.cs +++ b/SemanticTree/SemanticTree.cs @@ -2241,7 +2241,20 @@ namespace PascalABCCompiler.SemanticTree } } - public interface ILabelNode : IDefinitionNode, ILocated + public interface IDoubleQuestionColonExpressionNode : IExpressionNode + { + IExpressionNode condition + { + get; + } + + IExpressionNode ret_if_null + { + get; + } + } + + public interface ILabelNode : IDefinitionNode, ILocated { //Имя метки. Для языков не чувствительных к регистрам хранит имя в том виде, в каком тип объявлен. string name diff --git a/SyntaxVisitors/SugarVisitors/DoubleQuestionDesugarVisitor.cs b/SyntaxVisitors/SugarVisitors/DoubleQuestionDesugarVisitor.cs index d4beae951..40fe7c031 100644 --- a/SyntaxVisitors/SugarVisitors/DoubleQuestionDesugarVisitor.cs +++ b/SyntaxVisitors/SugarVisitors/DoubleQuestionDesugarVisitor.cs @@ -22,7 +22,7 @@ namespace SyntaxVisitors.SugarVisitors return num.ToString(); } - public override void visit(double_question_node dqn) + /*public override void visit(double_question_node dqn) { var st = dqn.Parent; while (!(st is statement)) @@ -42,6 +42,6 @@ namespace SyntaxVisitors.SugarVisitors visit(qce); ReplaceStatementUsingParent(st as statement, l); visit(tt); - } + }*/ } } \ No newline at end of file diff --git a/TestSuite/CompilationSamples/PABCSystem.pas b/TestSuite/CompilationSamples/PABCSystem.pas index 847f34b09..6b00332c4 100644 --- a/TestSuite/CompilationSamples/PABCSystem.pas +++ b/TestSuite/CompilationSamples/PABCSystem.pas @@ -67,6 +67,9 @@ const /// Константа перехода на новую строку /// !! The newline string defined for this environment. NewLine = System.Environment.NewLine; + /// Константа - символы-разделители слов + /// !! symbols - word delimiters + AllDelimiters = ' <>=^`|~$№§!"#%&''()*,+-./:;?@[\]_{}«­·»'#9#10#13; //{{{--doc: Конец секции стандартных констант для документации }}} @@ -4064,20 +4067,25 @@ function CharRange.Reverse: sequence of char := Range(l,h).Reverse; //------------------------------------------------------------------------------ // Операции для string и char //------------------------------------------------------------------------------ +///-- procedure string.operator+=(var left: string; right: string); begin left := left + right; end; +///-- function string.operator<(left, right: string) := string.CompareOrdinal(left, right) < 0; +///-- function string.operator<=(left, right: string) := string.CompareOrdinal(left, right) <= 0; +///-- function string.operator>(left, right: string) := string.CompareOrdinal(left, right) > 0; +///-- function string.operator>=(left, right: string) := string.CompareOrdinal(left, right) >= 0; -/// Повторяет строку str n раз +///-- function string.operator*(str: string; n: integer): string; begin var sb := new StringBuilder; @@ -4086,7 +4094,7 @@ begin Result := sb.ToString; end; -/// Повторяет строку str n раз +///-- function string.operator*(n: integer; str: string): string; begin var sb := new StringBuilder; @@ -4095,7 +4103,7 @@ begin Result := sb.ToString; end; -/// Повторяет символ c n раз +///-- function char.operator*(c: char; n: integer): string; begin if n <= 0 then @@ -4109,7 +4117,7 @@ begin Result := sb.ToString; end; -/// Повторяет символ c n раз +///-- function char.operator*(n: integer; c: char): string; begin if n <= 0 then @@ -4123,18 +4131,23 @@ begin Result := sb.ToString; end; -/// Добавляет к строке str строковое представление числа n +// Добавляет к строке str строковое представление числа n +///-- function string.operator+(str: string; n: integer) := str + n.ToString; -/// Добавляет к строке str строковое представление числа n +// Добавляет к строке str строковое представление числа n +///-- function string.operator+(n: integer; str: string) := n.ToString + str; -/// Добавляет к строке str строковое представление числа r +// Добавляет к строке str строковое представление числа r +///-- function string.operator+(str: string; r: real) := str + r.ToString(nfi); -/// Добавляет к строке str строковое представление числа r +// Добавляет к строке str строковое представление числа r +///-- function string.operator+(r: real; str: string) := r.ToString(nfi) + str; +///-- procedure string.operator+=(var left: string; right: integer); begin left := left + right.ToString; @@ -12349,10 +12362,10 @@ begin Result := Self.Split(delim, System.StringSplitOptions.RemoveEmptyEntries); end; -const AllWordDelimiters = ' <>=^`|~$№§!"#%&''()*,+-./:;?@[\]_{}«­·»'#9#10#13; +const SpaceDelimiters = ' '+#9#10#13; /// Преобразует строку в массив слов, используя в качестве разделителей символы из строки delim -function ToWords(Self: string; delim: string := AllWordDelimiters): array of string; extensionmethod; +function ToWords(Self: string; delim: string := SpaceDelimiters): array of string; extensionmethod; begin Result := Self.Split(delim.ToCharArray, System.StringSplitOptions.RemoveEmptyEntries); end; @@ -12859,59 +12872,59 @@ function operator>=(Self: (T1, T2, T3, T4,T5,T6,T7); v: (T // ------------------------------------------- // Дополнения февраль 2016 -// Добавляет поле к кортежу +/// Добавляет поле к кортежу function Add(Self: (T1, T2); v: T3): (T1, T2, T3); extensionmethod; begin Result := (Self[0], Self[1], v); end; -// Добавляет поле к кортежу +/// Добавляет поле к кортежу function Add(Self: (T1, T2, T3); v: T4): (T1, T2, T3, T4); extensionmethod; begin Result := (Self[0], Self[1], Self[2], v); end; -// Добавляет поле к кортежу +/// Добавляет поле к кортежу function Add(Self: (T1, T2, T3, T4); v: T5): (T1, T2, T3, T4, T5); extensionmethod; begin Result := (Self[0], Self[1], Self[2], Self[3], v); end; -// Добавляет поле к кортежу +/// Добавляет поле к кортежу function Add(Self: (T1, T2, T3, T4, T5); v: T6): (T1, T2, T3, T4, T5, T6); extensionmethod; begin Result := (Self[0], Self[1], Self[2], Self[3], Self[4], v); end; -// Добавляет поле к кортежу +/// Добавляет поле к кортежу function Add(Self: (T1, T2, T3, T4, T5, T6); v: T7): (T1, T2, T3, T4, T5, T6, T7); extensionmethod; begin Result := (Self[0], Self[1], Self[2], Self[3], Self[4], Self[5], v); end; -// Выводит кортеж +/// Выводит кортеж procedure Print(Self: (T1, T2)); extensionmethod := Print(Self); -// Выводит кортеж +/// Выводит кортеж procedure Print(Self: (T1, T2, T3)); extensionmethod := Print(Self); -// Выводит кортеж +/// Выводит кортеж procedure Print(Self: (T1, T2, T3, T4)); extensionmethod := Print(Self); -// Выводит кортеж +/// Выводит кортеж procedure Print(Self: (T1, T2, T3, T4, T5)); extensionmethod := Print(Self); -// Выводит кортеж +/// Выводит кортеж procedure Print(Self: (T1, T2, T3, T4, T5, T6)); extensionmethod := Print(Self); -// Выводит кортеж +/// Выводит кортеж procedure Print(Self: (T1, T2, T3, T4, T5, T6, T7)); extensionmethod := Print(Self); -// Выводит кортеж и переходит на новую строку +/// Выводит кортеж и переходит на новую строку procedure Println(Self: (T1, T2)); extensionmethod := Println(Self); -// Выводит кортеж и переходит на новую строку +/// Выводит кортеж и переходит на новую строку procedure Println(Self: (T1, T2, T3)); extensionmethod := Println(Self); -// Выводит кортеж и переходит на новую строку +/// Выводит кортеж и переходит на новую строку procedure Println(Self: (T1, T2, T3, T4)); extensionmethod := Println(Self); -// Выводит кортеж и переходит на новую строку +/// Выводит кортеж и переходит на новую строку procedure Println(Self: (T1, T2, T3, T4, T5)); extensionmethod := Println(Self); -// Выводит кортеж и переходит на новую строку +/// Выводит кортеж и переходит на новую строку procedure Println(Self: (T1, T2, T3, T4, T5, T6)); extensionmethod := Println(Self); -// Выводит кортеж и переходит на новую строку +/// Выводит кортеж и переходит на новую строку procedure Println(Self: (T1, T2, T3, T4, T5, T6, T7)); extensionmethod := Println(Self); diff --git a/TestSuite/double_question1.pas b/TestSuite/double_question1.pas new file mode 100644 index 000000000..a86b5a6ed --- /dev/null +++ b/TestSuite/double_question1.pas @@ -0,0 +1,10 @@ +begin + var o := new object; + var s := o ?? nil; + assert(s = o); + o := nil; + s := o ?? new object; + assert(s <> nil); + var x := nil ?? 'abc'; + assert(x = 'abc'); +end. \ No newline at end of file diff --git a/TestSuite/errors/err0382.pas b/TestSuite/errors/err0382.pas new file mode 100644 index 000000000..fb33b0bdc --- /dev/null +++ b/TestSuite/errors/err0382.pas @@ -0,0 +1,3 @@ +begin + var x := 'aaa'??2; +end. \ No newline at end of file diff --git a/TestSuite/errors/err0383.pas b/TestSuite/errors/err0383.pas new file mode 100644 index 000000000..1f2e271e1 --- /dev/null +++ b/TestSuite/errors/err0383.pas @@ -0,0 +1,3 @@ +begin + var x := 3??2; +end. \ No newline at end of file diff --git a/TestSuite/errors/err0384.pas b/TestSuite/errors/err0384.pas new file mode 100644 index 000000000..fbf6c1630 --- /dev/null +++ b/TestSuite/errors/err0384.pas @@ -0,0 +1,3 @@ +begin + var x := nil??nil; +end. \ No newline at end of file diff --git a/TestSuite/units/u_doublequestion1.pas b/TestSuite/units/u_doublequestion1.pas new file mode 100644 index 000000000..d5a8beeec --- /dev/null +++ b/TestSuite/units/u_doublequestion1.pas @@ -0,0 +1,12 @@ +unit u_doublequestion1; + +begin + var o := new object; + var s := o ?? nil; + assert(s = o); + o := nil; + s := o ?? new object; + assert(s <> nil); + var x := nil ?? 'abc'; + assert(x = 'abc'); +end. \ No newline at end of file diff --git a/TestSuite/usesunits/use_doublequestion1.pas b/TestSuite/usesunits/use_doublequestion1.pas new file mode 100644 index 000000000..9c68fa81e --- /dev/null +++ b/TestSuite/usesunits/use_doublequestion1.pas @@ -0,0 +1,2 @@ +//winonly +uses u_doublequestion1; begin end. \ No newline at end of file diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 5403f3ef0..d09185672 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -18059,6 +18059,115 @@ namespace PascalABCCompiler.TreeConverter throw new NotSupportedError(get_location(_template_param_list)); } + public override void visit(double_question_node node) + { + expression_node condition = convert_strong(node.left); + + convertion_data_and_alghoritms.convert_type(new null_const_node(null_type_node.get_type_node(), condition.location), condition.type); + expression_node left = condition; + expression_node right = convert_strong(node.right); + if (condition is null_const_node) + convertion_data_and_alghoritms.convert_type(new null_const_node(null_type_node.get_type_node(), right.location), right.type); + + try_convert_typed_expression_to_function_call(ref left); + try_convert_typed_expression_to_function_call(ref right); + + if (left is null_const_node && right.type.is_value_type) + { + if (right.type is compiled_type_node) + { + var rt = right.type as compiled_type_node; + if (!rt.compiled_type.IsGenericType || rt.compiled_type.GetGenericTypeDefinition() != typeof(System.Nullable<>)) + { + right = convert_strong(ToNullable(node.right)); + } + } + } + else + if (right is null_const_node && left.type.is_value_type) + { + if (left.type is compiled_type_node) + { + var lt = left.type as compiled_type_node; + if (!lt.compiled_type.IsGenericType || lt.compiled_type.GetGenericTypeDefinition() != typeof(System.Nullable<>)) + { + left = convert_strong(ToNullable(node.left)); + } + } + } + + /*var typeComparisonResult = type_table.compare_types(left.type, right.type); + if (typeComparisonResult == type_compare.greater_type) + right = convertion_data_and_alghoritms.convert_type(right, left.type); + else left = convertion_data_and_alghoritms.convert_type(left, right.type);*/ + if (left is null_const_node) + { + left = convertion_data_and_alghoritms.convert_type(left, right.type); + } + else + { + delegated_methods del_left = left.type as delegated_methods; + delegated_methods del_right = right.type as delegated_methods; + if (del_left != null && del_right != null && del_left.empty_param_method == null && del_right.empty_param_method == null) + { + base_function_call bfc = del_left.proper_methods[0]; + common_type_node del = + convertion_data_and_alghoritms.type_constructor.create_delegate(context.get_delegate_type_name(), bfc.simple_function_node.return_value_type, bfc.simple_function_node.parameters, context.converted_namespace, null); + context.converted_namespace.types.AddElement(del); + right = convertion_data_and_alghoritms.explicit_convert_type(right, del); + left = convertion_data_and_alghoritms.explicit_convert_type(left, del); + } + else + { + var rtl = type_table.get_convertions(right.type, left.type); + var ltr = type_table.get_convertions(left.type, right.type); + + if (ltr.first != null && rtl.first == null) + { + left = convertion_data_and_alghoritms.convert_type(left, right.type); + } + else if (ltr.first == null && rtl.first != null) + { + right = convertion_data_and_alghoritms.convert_type(right, left.type); + } + else + { + // если оба типа - целые + if (convertion_data_and_alghoritms.is_value_int_type(left.type) && convertion_data_and_alghoritms.is_value_int_type(right.type)) + { + var lub = convertion_data_and_alghoritms.least_upper_bound_value_int_type(left.type, right.type); + if (lub == left.type) + right = convertion_data_and_alghoritms.convert_type(right, left.type); + else if (lub == right.type) + left = convertion_data_and_alghoritms.convert_type(left, right.type); + else + { + right = convertion_data_and_alghoritms.convert_type(right, lub); + left = convertion_data_and_alghoritms.convert_type(right, lub); + } + } + else if (left.type == SystemLibrary.SystemLibrary.float_type && right.type == SystemLibrary.SystemLibrary.double_type) + left = convertion_data_and_alghoritms.convert_type(left, right.type); + else if (right.type == SystemLibrary.SystemLibrary.float_type && left.type == SystemLibrary.SystemLibrary.double_type) + right = convertion_data_and_alghoritms.convert_type(right, left.type); + else if (left.type == right.type) + { } + else // Это было - для совместимости. Что-то может не учтено + { + right = convertion_data_and_alghoritms.convert_type(right, left.type); + } + + } + + } + + } + + + //right = convertion_data_and_alghoritms.convert_type(right, left.type); + return_value(new double_question_colon_expression(condition, right, get_location(node))); + } + public override void visit(SyntaxTree.question_colon_expression node) { expression_node condition = convert_strong(node.condition); diff --git a/TreeConverter/TreeRealization/Expressions.cs b/TreeConverter/TreeRealization/Expressions.cs index a7d45e63f..a93022c53 100644 --- a/TreeConverter/TreeRealization/Expressions.cs +++ b/TreeConverter/TreeRealization/Expressions.cs @@ -340,7 +340,67 @@ namespace PascalABCCompiler.TreeRealization visitor.visit(this); } } - + + public class double_question_colon_expression : expression_node, SemanticTree.IDoubleQuestionColonExpressionNode + { + private expression_node _condition; + private expression_node _ret_if_null; + + public double_question_colon_expression(expression_node condition, expression_node ret_if_null, + location loc) + : base(condition is null_const_node ? ret_if_null.type : condition.type, loc) + { + this._condition = condition; + this._ret_if_null = ret_if_null; + } + + public expression_node internal_condition + { + get + { + return _condition; + } + } + + + public expression_node internal_ret_if_null + { + get + { + return _ret_if_null; + } + } + + public SemanticTree.IExpressionNode condition + { + get + { + return _condition; + } + } + + public SemanticTree.IExpressionNode ret_if_null + { + get + { + return _ret_if_null; + } + } + + public override semantic_node_type semantic_node_type + { + get + { + return semantic_node_type.double_question_colon_expression; + } + } + + public override void visit(SemanticTree.ISemanticVisitor visitor) + { + visitor.visit(this); + } + } + public class array_initializer : expression_node, SemanticTree.IArrayInitializer { private List _element_values; diff --git a/TreeConverter/TreeRealization/base_nodes.cs b/TreeConverter/TreeRealization/base_nodes.cs index f0b61822f..de6892ebf 100644 --- a/TreeConverter/TreeRealization/base_nodes.cs +++ b/TreeConverter/TreeRealization/base_nodes.cs @@ -38,7 +38,7 @@ namespace PascalABCCompiler.TreeRealization common_constructor_call_as_constant, array_initializer, record_initializer, default_operator, attribute_node, pinvoke_node, basic_function_call_node_as_constant, compiled_static_field_reference_as_constant, common_namespace_event, indefinite_definition_node, indefinite_type, indefinite_function_call, indefinite_reference, - wrapped_statement, wrapped_expression, default_operator_node_as_constant + wrapped_statement, wrapped_expression, default_operator_node_as_constant, double_question_colon_expression }; /// diff --git a/VisualPlugins/LanguageConverter/Source/Visitor.cs b/VisualPlugins/LanguageConverter/Source/Visitor.cs index 3afd97790..e69a5d5de 100644 --- a/VisualPlugins/LanguageConverter/Source/Visitor.cs +++ b/VisualPlugins/LanguageConverter/Source/Visitor.cs @@ -1554,5 +1554,10 @@ namespace VisualPascalABCPlugins { throw new System.NotImplementedException(); } + + public void visit(IDoubleQuestionColonExpressionNode value) + { + throw new System.NotImplementedException(); + } } } diff --git a/VisualPlugins/SemanticTreeVisualisator/Source/Visitor.cs b/VisualPlugins/SemanticTreeVisualisator/Source/Visitor.cs index a63227f4d..47070b483 100644 --- a/VisualPlugins/SemanticTreeVisualisator/Source/Visitor.cs +++ b/VisualPlugins/SemanticTreeVisualisator/Source/Visitor.cs @@ -2560,5 +2560,10 @@ namespace VisualPascalABCPlugins { throw new System.NotImplementedException(); } + + public void visit(IDoubleQuestionColonExpressionNode value) + { + throw new System.NotImplementedException(); + } } }