From f04a1c2161b9b9c4408531e856c9798de59a4743 Mon Sep 17 00:00:00 2001 From: Ivan Bondarev Date: Sun, 29 Aug 2021 10:37:11 +0200 Subject: [PATCH] #2504 --- NETGenerator/NETGenerator.cs | 115 ++++++++++++++++++++++++++--------- TestSuite/nullable4.pas | 9 +++ 2 files changed, 94 insertions(+), 30 deletions(-) create mode 100644 TestSuite/nullable4.pas diff --git a/NETGenerator/NETGenerator.cs b/NETGenerator/NETGenerator.cs index fda394f05..e593d9149 100644 --- a/NETGenerator/NETGenerator.cs +++ b/NETGenerator/NETGenerator.cs @@ -8951,16 +8951,25 @@ namespace PascalABCCompiler.NETGenerator if (real_parameters[0].type.is_nullable_type && real_parameters[1] is INullConstantNode) { bool tmp = is_dot_expr; - is_dot_expr = true; - TypeInfo ti = helper.GetTypeReference(real_parameters[0].type); - real_parameters[0].visit(this); - is_dot_expr = tmp; - MethodInfo mi = null; - if (real_parameters[0].type is IGenericTypeInstance) - mi = TypeBuilder.GetMethod(ti.tp, typeof(Nullable<>).GetMethod("get_HasValue")); + if (real_parameters[0] is IDefaultOperatorNode) + { + il.Emit(OpCodes.Ldc_I4_0); + } else - mi = ti.tp.GetMethod("get_HasValue"); - il.Emit(OpCodes.Call, mi); + { + is_dot_expr = true; + TypeInfo ti = helper.GetTypeReference(real_parameters[0].type); + + real_parameters[0].visit(this); + is_dot_expr = tmp; + MethodInfo mi = null; + if (real_parameters[0].type is IGenericTypeInstance) + mi = TypeBuilder.GetMethod(ti.tp, typeof(Nullable<>).GetMethod("get_HasValue")); + else + mi = ti.tp.GetMethod("get_HasValue"); + il.Emit(OpCodes.Call, mi); + } + if (ft == basic_function_type.objeq) { il.Emit(OpCodes.Ldc_I4_0); @@ -8972,16 +8981,23 @@ namespace PascalABCCompiler.NETGenerator else if (real_parameters[1].type.is_nullable_type && real_parameters[0] is INullConstantNode) { bool tmp = is_dot_expr; - is_dot_expr = true; - TypeInfo ti = helper.GetTypeReference(real_parameters[1].type); - real_parameters[1].visit(this); - is_dot_expr = tmp; - MethodInfo mi = null; - if (real_parameters[1].type is IGenericTypeInstance) - mi = TypeBuilder.GetMethod(ti.tp, typeof(Nullable<>).GetMethod("get_HasValue")); + if (real_parameters[1] is IDefaultOperatorNode) + { + il.Emit(OpCodes.Ldc_I4_0); + } else - mi = ti.tp.GetMethod("get_HasValue"); - il.Emit(OpCodes.Call, mi); + { + is_dot_expr = true; + TypeInfo ti = helper.GetTypeReference(real_parameters[1].type); + real_parameters[1].visit(this); + is_dot_expr = tmp; + MethodInfo mi = null; + if (real_parameters[1].type is IGenericTypeInstance) + mi = TypeBuilder.GetMethod(ti.tp, typeof(Nullable<>).GetMethod("get_HasValue")); + else + mi = ti.tp.GetMethod("get_HasValue"); + il.Emit(OpCodes.Call, mi); + } if (ft == basic_function_type.objeq) { il.Emit(OpCodes.Ldc_I4_0); @@ -8993,22 +9009,61 @@ namespace PascalABCCompiler.NETGenerator { MethodInfo mi_left = null; TypeInfo ti_left = helper.GetTypeReference(real_parameters[0].type); - if (real_parameters[0].type is IGenericTypeInstance) - mi_left = TypeBuilder.GetMethod(ti_left.tp, typeof(Nullable<>).GetMethod("GetValueOrDefault", new Type[] { })); + if (real_parameters[0] is IDefaultOperatorNode) + il.Emit(OpCodes.Ldc_I4_0); else - mi_left = ti_left.tp.GetMethod("GetValueOrDefault", new Type[] { }); + { + if (real_parameters[1] is IDefaultOperatorNode) + { + if (real_parameters[0].type is IGenericTypeInstance) + mi_left = TypeBuilder.GetMethod(ti_left.tp, typeof(Nullable<>).GetMethod("get_HasValue", new Type[] { })); + else + mi_left = ti_left.tp.GetMethod("get_HasValue", new Type[] { }); + } + else + { + if (real_parameters[0].type is IGenericTypeInstance) + mi_left = TypeBuilder.GetMethod(ti_left.tp, typeof(Nullable<>).GetMethod("GetValueOrDefault", new Type[] { })); + else + mi_left = ti_left.tp.GetMethod("GetValueOrDefault", new Type[] { }); + } + + } + MethodInfo mi_right = null; TypeInfo ti_right = helper.GetTypeReference(real_parameters[1].type); - if (real_parameters[1].type is IGenericTypeInstance) - mi_right = TypeBuilder.GetMethod(ti_right.tp, typeof(Nullable<>).GetMethod("GetValueOrDefault", new Type[] { })); + if (real_parameters[1] is IDefaultOperatorNode) + il.Emit(OpCodes.Ldc_I4_0); else - mi_right = ti_right.tp.GetMethod("GetValueOrDefault", new Type[] { }); - is_dot_expr = true; - real_parameters[0].visit(this); - il.Emit(OpCodes.Call, mi_left); - is_dot_expr = true; - real_parameters[1].visit(this); - il.Emit(OpCodes.Call, mi_right); + { + if (real_parameters[0] is IDefaultOperatorNode) + { + if (real_parameters[1].type is IGenericTypeInstance) + mi_right = TypeBuilder.GetMethod(ti_right.tp, typeof(Nullable<>).GetMethod("get_HasValue", new Type[] { })); + else + mi_right = ti_right.tp.GetMethod("get_HasValue", new Type[] { }); + } + else + { + if (real_parameters[1].type is IGenericTypeInstance) + mi_right = TypeBuilder.GetMethod(ti_right.tp, typeof(Nullable<>).GetMethod("GetValueOrDefault", new Type[] { })); + else + mi_right = ti_right.tp.GetMethod("GetValueOrDefault", new Type[] { }); + } + + } + if (!(real_parameters[0] is IDefaultOperatorNode)) + { + is_dot_expr = true; + real_parameters[0].visit(this); + il.Emit(OpCodes.Call, mi_left); + } + if (!(real_parameters[1] is IDefaultOperatorNode)) + { + is_dot_expr = true; + real_parameters[1].visit(this); + il.Emit(OpCodes.Call, mi_right); + } EmitOperator(value); is_dot_expr = tmp_dot; if (tmp_dot) diff --git a/TestSuite/nullable4.pas b/TestSuite/nullable4.pas new file mode 100644 index 000000000..3c661b9d5 --- /dev/null +++ b/TestSuite/nullable4.pas @@ -0,0 +1,9 @@ +var b: boolean := default(System.Nullable) = byte(0); +begin + assert(default(System.Nullable) = default(System.Nullable)); + assert(default(System.Nullable) <> byte(0)); + assert(default(System.Nullable) = nil); + assert(nil = default(System.Nullable)); + assert(byte(0) <> default(System.Nullable)); + assert(not b); +end. \ No newline at end of file