AssertingImpl:
CEDAR
PROGRAM
IMPORTS Rope
EXPORTS Asserting =
{OPEN Asserting;
Error: PUBLIC ERROR [a: Assertion] = CODE;
Warning: PUBLIC SIGNAL [a: Assertion] = CODE;
ROPE: TYPE = Rope.ROPE;
Bool: TYPE = REF BOOL;
Int: TYPE = REF INT;
Reel: TYPE = REF REAL;
Assert:
PUBLIC
PROC [reln: Term, args: Composite, inAdditionTo: Assertions]
RETURNS [allTogetherNow: Assertions] =
{allTogetherNow ← CONS[CONS[reln, args], inAdditionTo]};
AssertionsAbout:
PUBLIC
PROC [reln: Term, from: Assertions]
RETURNS [filtered: Assertions] = {
filtered ← NIL;
FOR from ← from, from.rest
WHILE from #
NIL
DO
IF Equal[from.first.first, reln] THEN filtered ← CONS[from.first, filtered];
ENDLOOP;
filtered ← filtered --so we can break at exit--};
EnumerateAssertionsAbout:
PUBLIC
PROC [reln: Term, from: Assertions, to: AssertionConsumer] = {
FOR from ← from, from.rest
WHILE from #
NIL
DO
IF Equal[from.first.first, reln] THEN to[from.first];
ENDLOOP;
};
AssertFn:
PUBLIC
PROC [fn: Term, args: Composite, inAdditionTo: Assertions]
RETURNS [allTogetherNow: Assertions] = {
FOR al: Assertions ← inAdditionTo, al.rest
WHILE al #
NIL
DO
IF Equal[al.first.first, fn]
THEN
{al.first.rest ← args; RETURN [inAdditionTo]};
ENDLOOP;
allTogetherNow ← CONS[CONS[fn, args], inAdditionTo]};
AssertFn1:
PUBLIC
PROC [fn, arg: Term, inAdditionTo: Assertions]
RETURNS [allTogetherNow: Assertions] = {
FOR al: Assertions ← inAdditionTo, al.rest
WHILE al #
NIL
DO
IF Equal[al.first.first, fn]
THEN
{al.first.rest ← LIST[arg]; RETURN [inAdditionTo]};
ENDLOOP;
allTogetherNow ← CONS[LIST[fn, arg], inAdditionTo]};
FnVals:
PUBLIC
PROC [fn: Term, from: Assertions]
RETURNS [vals: Composite] = {
FOR from ← from, from.rest
WHILE from #
NIL
DO
IF Equal[from.first.first, fn] THEN RETURN [from.first.rest];
ENDLOOP;
vals ← NIL};
FnVal:
PUBLIC
PROC [fn: Term, from: Assertions]
RETURNS [val: Term] = {
FOR from ← from, from.rest
WHILE from #
NIL
DO
IF Equal[from.first.first, fn]
THEN {
IF from.first.rest.rest # NIL THEN ERROR Error[LIST[$MultipleValued, from.first]];
RETURN [from.first.rest.first]};
ENDLOOP;
val ← NIL};
CheckFn:
PUBLIC
PROC [fn: Term, in: Assertions] = {
found: INT ← 0;
FOR al: Assertions ← in, al.rest
WHILE al #
NIL
DO
IF Equal[al.first.first, fn] THEN found ← found + 1;
ENDLOOP;
IF found # 1 THEN ERROR Error[LIST[$NotFunctional, fn, in, NEW [INT ← found]]]};
Union:
PUBLIC
PROC [a, b: Assertions]
RETURNS [c: Assertions] = {
c ← b;
WHILE a #
NIL
DO
c ← CONS[a.first, c];
a ← a.rest;
ENDLOOP;
c ← c};
Equal:
PUBLIC
PROC [a, b: Term]
RETURNS [
BOOL] = {
IF (a = NIL) # (b = NIL) THEN RETURN [FALSE];
IF a = NIL THEN RETURN [TRUE];
WITH a
SELECT
FROM
aa: ATOM => RETURN [a = b];
ra: ROPE => RETURN [ISTYPE[b, ROPE] AND ra.Equal[NARROW[b]]];
ba: Bool => RETURN [ISTYPE[b, Bool] AND ba^ = NARROW[b, Bool]^];
ia: Int => RETURN [ISTYPE[b, Int] AND ia^ = NARROW[b, Int]^];
ra: Reel => RETURN [ISTYPE[b, Reel] AND ra^ = NARROW[b, Reel]^];
ca: Composite =>
IF
ISTYPE[b, Composite]
THEN {
cb: Composite ← NARROW[b];
WHILE (ca #
NIL)
AND (cb #
NIL)
DO
IF NOT Equal[ca.first, cb.first] THEN RETURN [FALSE];
ca ← ca.rest;
cb ← cb.rest;
ENDLOOP;
RETURN [(ca = NIL) = (cb = NIL)];
} ELSE RETURN [FALSE];
ENDCASE => RETURN [a = b];
};
}.