Work:
PROC [la, lb:
LORA, namePrefixA, namePrefixB:
ROPE]
RETURNS [differenceReport:
ROPE] = {
nameStepA: ROPE = ToName[la.first];
nameStepB: ROPE = ToName[lb.first];
nameA: ROPE = namePrefixA.Cat[".", nameStepA];
nameB: ROPE = namePrefixB.Cat[".", nameStepB];
strA: LORA = NARROW[la.rest.first];
strB: LORA = NARROW[lb.rest.first];
propsA: LORA ← NARROW[la.rest.rest.first];
propsB: LORA ← NARROW[lb.rest.rest.first];
IF la.rest.rest.rest # NIL OR lb.rest.rest.rest # NIL THEN ERROR;
IF
NOT nameStepA.Equal[nameStepB]
THEN
RETURN [
IO.PutFR[
"name disagreement at %g ~ %g",
[rope[nameA]],
[rope[nameB]]
]];
IF strA.first # strB.first
THEN
RETURN [
IO.PutFR[
"structural disagreement (%g vs %g) at %g ~ %g",
[atom[NARROW[strA.first]]],
[atom[NARROW[strB.first]]],
[rope[nameA]],
[rope[nameB]]
]];
SELECT strA.first
FROM
$atom => NULL;
$sequence => IF (differenceReport ← Work[NARROW[strA.rest.first], NARROW[strB.rest.first], nameA, nameB]) # NIL THEN RETURN;
$record => {
subsA: LORA ← strA.rest;
subsB: LORA ← strB.rest;
WHILE subsA #
NIL
AND subsB #
NIL
DO
IF (differenceReport ← Work[NARROW[subsA.first], NARROW[subsB.first], nameA, nameB]) # NIL THEN RETURN;
subsA ← subsA.rest;
subsB ← subsB.rest;
ENDLOOP;
IF subsA #
NIL
OR subsB #
NIL
THEN
RETURN [
IO.PutFR[
"different number of children at %g ~ %g",
[rope[nameA]],
[rope[nameB]]
]];
};
ENDCASE => ERROR;
WHILE propsA #
NIL
AND propsB #
NIL
DO
pairA: LORA = NARROW[propsA.first];
pairB: LORA = NARROW[propsB.first];
keyA: ATOM = NARROW[pairA.first];
keyB: ATOM = NARROW[pairB.first];
valA: REF ANY = pairA.rest.first;
valB: REF ANY = pairB.rest.first;
valEq: BOOL ← valA = valB;
IF pairA.rest.rest # NIL OR pairB.rest.rest # NIL THEN ERROR;
IF keyA # keyB
THEN
RETURN [
IO.PutFR[
"property list difference (%g vs %g) at %g ~ %g",
[atom[keyA]],
[atom[keyB]],
[rope[nameA]],
[rope[nameB]]
]];
WITH valA
SELECT
FROM
rba:
REF
BOOL =>
WITH valB
SELECT
FROM
rbb: REF BOOL => valEq ← rba^ = rbb^;
ENDCASE;
ENDCASE;
IF
NOT valEq
THEN
RETURN [
IO.PutFR[
"property %g value difference (%g vs %g) at %g ~ %g",
[atom[keyA]],
[refAny[valA]],
[refAny[valB]],
[rope[nameA]],
[rope[nameB]]
]];
propsA ← propsA.rest;
propsB ← propsB.rest;
ENDLOOP;
IF propsA #
NIL
OR propsB #
NIL
THEN
RETURN [
IO.PutFR[
"different number of properties, at %g ~ %g",
[rope[nameA]],
[rope[nameB]]
]];
RETURN [NIL];
};