Capucine Example: Course and StudentsA very simple example which shows some of the main features of Capucine. |
This example is work in progress. To compile it, go into the capucine directory and type:
ocamlbuild bench/course-ter.gwhy
logic type set (A) logic function empty(): set (A) logic function cardinal(set (A)): int logic function add(set (A), A): set (A) predicate inset(x: A, s: set(A)) axiom NotInsetEmpty: forall x: A. not inset(x, empty) axiom NotInsetAdd: forall x: A. forall s: set (A). forall y: A. x <> y ==> not inset(x, s) ==> not inset(x, [add(s, y)]) axiom InsetAdd: forall x: A. forall s: set (A). inset(x, [add(s, x)]) axiom InsetAdd: forall x: A. forall y: A. forall s: set (A). inset(x, s) ==> inset(x, [add(s, y)]) class Student = (int * int) end selector (name, mark) class StudentCollection {R} = set (Student [R]) end selector (students, minmark) class Course = own R_s, R_c; (StudentCollection {R_s} [R_c] * int * Student [R_s]) (* HACK to solve a stupid problem, ignore this *) invariant (c) = forall s: Student [R_s]. inset(s, [!(c.students)]) ==> [!s.mark] >= [c.minmark] end val CreateCourse(minmark: int): Course [R] consumes R^e produces R^c ensures [!result.minmark] = minmark = region PLOP in let c = new Course [PLOP] in let students = new StudentCollection {PLOP.R_s} [PLOP.R_c] in students := empty; c := (students, minmark, new Student); c val CreateStudent(c: Course [R], name: int, mark: int): Student [R.R_s] consumes R^c produces R^c ensures [!result.mark] = mark and inset(result, [!(!c.students)]) and forall s: Student [R.R_s]. inset(s, [old(!(!c.students))]) ==> inset(s, [!(!c.students)]) = let s = new Student in s := (name, mark); (focus !c.students) := add(!(!c.students), s); let min = let current = !c.minmark in if mark < current then mark else current in c := (!c.students, min, !c.3); s val SetMark(c: Course [R], s: Student [R.R_s], mark: int): unit consumes R^c produces R^c ensures [!s.mark] = mark and [!c.students] = [old(!c.students)] = let min = let current = !c.minmark in if mark < current then mark else current in c := (!c.students, min, !c.3); (focus s) := (!s.name, mark) val MinMark(c: Course [R]): int consumes R^c produces R^c ensures result = [!c.minmark] = !c.minmark val main(): unit = region ALGEBRA: Course in region TOPOLOGY: Course in let algebra = (CreateCourse(100): Course [ALGEBRA]) in let alice = CreateStudent(algebra, 1, 80) in let bob = CreateStudent(algebra, 2, 30) in SetMark(algebra, alice, 70); SetMark(algebra, bob, 50); let topology = (CreateCourse(100): Course [TOPOLOGY]) in let charlie = CreateStudent(topology, 3, 20) in SetMark(topology, charlie, 90); let m = MinMark(algebra) in assert (m <= [!alice.mark] and (m <= [!bob.mark]))