// Example of using member theorems to describe desired behaviour of a class. // // Copyright 2001 Escher Technologies Ltd. All rights reserved. // First define the form of word that we wish to spell-check class Word ^= those x:string :- #x ~= 0; // The actual dictionary class class Dictionary ^= abstract var words: set of Word; interface function check(w: Word): bool ^= w in words; schema !add(w: Word) pre ~check(w) post words! = words.append(w) assert self'.check(w); schema !remove(w: Word) pre check(w) post words! = words.remove(w) assert ~self'.check(w); // Constructor for building an empty dictionary build{} post words! = set of Word{} assert forall x: Word :- ~self'.check(x); // Required properties of the dictionary: // Adding a word doesn't affect what other words are in the dictionary property(w1, w2: Word) pre ~check(w1), w1 ~= w2 assert (self after it!add(w1)).check(w2) = check(w2); // Removing a word doesn't affect what other words are in the dictionary property(w1, w2: Word) pre check(w1), w1 ~= w2 assert (self after it!remove(w1)).check(w2) = check(w2); // Adding a word and then removing it leaves the dictionary unchanged property(w: Word) pre ~check(w) assert (self after it!add(w) then it!remove(w)) = self; end;