#include "/sys/lpctypes.h"
/*
* deep equality: make a best effort to check whether arg1 and arg2
* represent the same value.
*/
int deep_eq(mixed arg1, mixed arg2)
{
for (;;) {
if (typeof(arg1) != typeof(arg2))
return 0;
switch (typeof(arg1)) {
case T_INVALID:
raise_error("Don't know how to compare T_INVALID.\n");
case T_LVALUE:
raise_error("Don't know how to compare T_LVALUE.\n");
case T_NUMBER:
case T_FLOAT:
case T_STRING:
case T_OBJECT:
return arg1 == arg2;
case T_POINTER:
if (sizeof(arg1) != sizeof(arg2))
return 0;
for (int i = 0; i < sizeof(arg1); i++)
if (!deep_eq(arg1[i], arg2[i]))
return 0;
return 1;
case T_MAPPING:
if (widthof(arg1) != widthof(arg2) ||
sizeof(arg1) != sizeof(arg2))
return 0;
foreach (mixed k: arg1) {
mixed row1 = m_entry(arg1, k);
mixed row2 = m_entry(arg2, k);
if (!row2)
return 0;
for (int i = 0; i < sizeof(row1); i++)
if (!deep_eq(row1[i], row2[i]))
return 0;
}
return 1;
case T_CLOSURE:
if (get_type_info(arg1, 1) != get_type_info(arg2, 1) ||
get_type_info(arg1, 2) != get_type_info(arg2, 2))
return 0;
int t = get_type_info(arg1, 1);
if (CLOSURE_IS_LFUN(t))
return to_int(arg1) == to_int(arg2);
if (CLOSURE_IS_IDENTIFIER(t))
return to_int(arg1) == to_int(arg2);
if (CLOSURE_IS_BOUND_LAMBDA(t) ||
CLOSURE_IS_LAMBDA(t) ||
CLOSURE_IS_UNBOUND_LAMBDA(t))
raise_error("Don't know how to compare lambda closures.\n");
if (CLOSURE_IS_SIMUL_EFUN(t))
return 1;
if (CLOSURE_IS_EFUN(t))
return 1;
if (CLOSURE_IS_OPERATOR(t))
return 1;
raise_error("Unknown closure type " + t + ".\n");
case T_SYMBOL:
case T_QUOTED_ARRAY:
arg1 = unquote(arg1);
arg2 = unquote(arg2);
break;
default:
raise_error("Unknown type " + typeof(arg1) + ".\n");
}
}
return 0; /* not reached */
}