This commit is contained in:
parent
0923a10a68
commit
05f94b9dde
|
|
@ -9023,7 +9023,59 @@ namespace PascalABCCompiler.NETGenerator
|
|||
else if (real_parameters[0].type.is_nullable_type && real_parameters[1].type.is_nullable_type)
|
||||
{
|
||||
MethodInfo mi_left = null;
|
||||
MethodInfo mi_right = null;
|
||||
TypeInfo ti_left = helper.GetTypeReference(real_parameters[0].type);
|
||||
TypeInfo ti_right = helper.GetTypeReference(real_parameters[1].type);
|
||||
Label lb_false = il.DefineLabel();
|
||||
Label lb_true = il.DefineLabel();
|
||||
Label lb_end = il.DefineLabel();
|
||||
Label lb_common = il.DefineLabel();
|
||||
if (!(real_parameters[0] is IDefaultOperatorNode) && !(real_parameters[1] is IDefaultOperatorNode))
|
||||
{
|
||||
is_dot_expr = true;
|
||||
real_parameters[0].visit(this);
|
||||
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[] { });
|
||||
il.Emit(OpCodes.Call, mi_left);
|
||||
LocalBuilder tmp_lb = il.DeclareLocal(TypeFactory.BoolType);
|
||||
il.Emit(OpCodes.Stloc, tmp_lb);
|
||||
il.Emit(OpCodes.Ldloc, tmp_lb);
|
||||
is_dot_expr = true;
|
||||
real_parameters[1].visit(this);
|
||||
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[] { });
|
||||
|
||||
il.Emit(OpCodes.Call, mi_right);
|
||||
if (value.basic_function.basic_function_type == basic_function_type.objnoteq)
|
||||
{
|
||||
il.Emit(OpCodes.Ceq);
|
||||
il.Emit(OpCodes.Ldc_I4_0);
|
||||
il.Emit(OpCodes.Ceq);
|
||||
il.Emit(OpCodes.Brtrue, lb_true);
|
||||
il.Emit(OpCodes.Br, lb_common);
|
||||
il.MarkLabel(lb_true);
|
||||
il.Emit(OpCodes.Ldc_I4_1);
|
||||
il.Emit(OpCodes.Br, lb_end);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(OpCodes.Ceq);
|
||||
il.Emit(OpCodes.Brfalse, lb_false);
|
||||
il.Emit(OpCodes.Ldloc, tmp_lb);
|
||||
il.Emit(OpCodes.Brtrue, lb_common);
|
||||
il.Emit(OpCodes.Ldc_I4_1);
|
||||
il.Emit(OpCodes.Br, lb_end);
|
||||
il.MarkLabel(lb_false);
|
||||
il.Emit(OpCodes.Ldc_I4_0);
|
||||
il.Emit(OpCodes.Br, lb_end);
|
||||
}
|
||||
|
||||
}
|
||||
il.MarkLabel(lb_common);
|
||||
if (real_parameters[0] is IDefaultOperatorNode)
|
||||
il.Emit(OpCodes.Ldc_I4_0);
|
||||
else
|
||||
|
|
@ -9045,8 +9097,8 @@ namespace PascalABCCompiler.NETGenerator
|
|||
|
||||
}
|
||||
|
||||
MethodInfo mi_right = null;
|
||||
TypeInfo ti_right = helper.GetTypeReference(real_parameters[1].type);
|
||||
|
||||
|
||||
if (real_parameters[1] is IDefaultOperatorNode)
|
||||
il.Emit(OpCodes.Ldc_I4_0);
|
||||
else
|
||||
|
|
@ -9067,6 +9119,7 @@ namespace PascalABCCompiler.NETGenerator
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
if (!(real_parameters[0] is IDefaultOperatorNode))
|
||||
{
|
||||
is_dot_expr = true;
|
||||
|
|
@ -9079,38 +9132,40 @@ namespace PascalABCCompiler.NETGenerator
|
|||
real_parameters[1].visit(this);
|
||||
il.Emit(OpCodes.Call, mi_right);
|
||||
}
|
||||
EmitOperator(value);
|
||||
if (!(real_parameters[0] is IDefaultOperatorNode) && !(real_parameters[1] is IDefaultOperatorNode))
|
||||
MethodInfo eq_mi = null;
|
||||
if (real_parameters[0].type is IGenericTypeInstance)
|
||||
{
|
||||
is_dot_expr = true;
|
||||
real_parameters[0].visit(this);
|
||||
if (real_parameters[0].type is IGenericTypeInstance)
|
||||
mi_left = TypeBuilder.GetMethod(ti_right.tp, typeof(Nullable<>).GetMethod("get_HasValue", new Type[] { }));
|
||||
else
|
||||
mi_left = ti_left.tp.GetMethod("get_HasValue", new Type[] { });
|
||||
il.Emit(OpCodes.Call, mi_left);
|
||||
is_dot_expr = true;
|
||||
real_parameters[1].visit(this);
|
||||
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[] { });
|
||||
var ctn = (real_parameters[0].type as IGenericTypeInstance).generic_parameters[0] as ICommonTypeNode;
|
||||
|
||||
il.Emit(OpCodes.Call, mi_right);
|
||||
if (value.basic_function.basic_function_type == basic_function_type.objnoteq)
|
||||
if (ctn != null)
|
||||
{
|
||||
il.Emit(OpCodes.Ceq);
|
||||
il.Emit(OpCodes.Ldc_I4_0);
|
||||
il.Emit(OpCodes.Ceq);
|
||||
il.Emit(OpCodes.Or);
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit(OpCodes.Ceq);
|
||||
il.Emit(OpCodes.And);
|
||||
foreach (ICommonMethodNode cmn in ctn.methods)
|
||||
if ((value.basic_function.basic_function_type == basic_function_type.objnoteq? cmn.name == "op_Inequality" || cmn.name == "<>":cmn.name == "op_Equality" || cmn.name == "=") && cmn.parameters.Length == 2 && cmn.parameters[0].type == ctn && cmn.parameters[1].type == ctn)
|
||||
{
|
||||
eq_mi = helper.GetMethod(cmn).mi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else if (real_parameters[0].type is ICompiledTypeNode)
|
||||
{
|
||||
var t = (real_parameters[0].type as ICompiledTypeNode).compiled_type.GetGenericArguments()[0];
|
||||
foreach (MethodInfo mi in t.GetMethods(BindingFlags.Public | BindingFlags.Static))
|
||||
{
|
||||
if ((value.basic_function.basic_function_type == basic_function_type.objnoteq ? mi.Name == "op_Inequality" : mi.Name == "op_Equality") && mi.GetParameters().Length == 2 && mi.GetParameters()[0].ParameterType == t && mi.GetParameters()[1].ParameterType == t)
|
||||
{
|
||||
eq_mi = mi;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (eq_mi != null)
|
||||
il.Emit(OpCodes.Call, eq_mi);
|
||||
else
|
||||
EmitOperator(value);
|
||||
il.MarkLabel(lb_end);
|
||||
|
||||
is_dot_expr = tmp_dot;
|
||||
if (tmp_dot)
|
||||
{
|
||||
|
|
|
|||
19
TestSuite/nullable7.pas
Normal file
19
TestSuite/nullable7.pas
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
var i: integer;
|
||||
type
|
||||
r1 = record
|
||||
static function operator=(a,b: r1): boolean;
|
||||
begin
|
||||
i := 1;
|
||||
Result := false;
|
||||
end;
|
||||
static function operator<>(a,b: r1) := false;
|
||||
end;
|
||||
|
||||
begin
|
||||
var n1, n2: r1?;
|
||||
assert(n1 = n2); // Должно быть true, без вызва r1.operator=
|
||||
n1 := new r1;
|
||||
assert(not (n1 <> n1));
|
||||
assert(not (n1 = n1));
|
||||
assert(i = 1);
|
||||
end.
|
||||
15
TestSuite/nullable8.pas
Normal file
15
TestSuite/nullable8.pas
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
type
|
||||
r1 = record end;
|
||||
|
||||
begin
|
||||
var n1, n2: r1?;
|
||||
assert(n1 = n2);
|
||||
assert(n1 = nil);
|
||||
assert(not (n1<>n2));
|
||||
n1 := new r1;
|
||||
assert(n1 = n1);
|
||||
n2 := new r1;
|
||||
assert(n1 = n2);
|
||||
n2 := nil;
|
||||
assert(n1 <> n2);
|
||||
end.
|
||||
13
TestSuite/nullable9.pas
Normal file
13
TestSuite/nullable9.pas
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
begin
|
||||
var n1, n2: System.TimeSpan?;
|
||||
assert(n1=n2);
|
||||
assert(n1=nil);
|
||||
n1 := System.TimeSpan.Zero;
|
||||
n2 := System.TimeSpan.Zero;
|
||||
assert(n1=n2);
|
||||
assert(not (n1<>n2));
|
||||
n2 := nil;
|
||||
assert(n1<>n2);
|
||||
assert(not (n1=n2));
|
||||
end.
|
||||
Loading…
Reference in a new issue