// RUN: %dafny /compile:0 /print:"%t.print" /dprint:"%t.dprint" "%s" > "%t" // RUN: %diff "%s.expect" "%t" function fact6(n: nat): nat { fact(n+6) } function fact(n: nat): nat { if (n==0) then 1 else n*fact(n-1) } ghost method compute_fact6() ensures fact(6)==720; { } ghost method compute_fact6_plus() ensures fact6(0)==720; { } datatype intlist = IntNil | IntCons(head: int, tail: intlist) function intsize(l: intlist): nat { if (l.IntNil?) then 0 else 1+intsize(l.tail) } function intapp(a: intlist, b: intlist): intlist { if (a.IntNil?) then b else IntCons(a.head, intapp(a.tail, b)) } ghost method compute_intappsize() ensures intsize(intapp(IntCons(1, IntCons(2, IntNil)), IntCons(3, IntCons(4, IntNil))))==4; { } ghost method compute_intsize4() ensures intsize(IntCons(1, IntCons(2, IntCons(3, IntCons(4, IntNil))))) == 4; { } function cintsize(l: intlist): nat { match l case IntNil => 0 case IntCons(hd, tl) => 1+cintsize(tl) } function cintapp(a: intlist, b: intlist): intlist { match a case IntNil => b case IntCons(hd, tl) => IntCons(hd, cintapp(tl, b)) } ghost method compute_cintappsize() ensures cintsize(cintapp(IntCons(1, IntCons(2, IntNil)), IntCons(3, IntCons(4, IntNil))))==4; { } ghost method compute_cintsize4() ensures cintsize(IntCons(1, IntCons(2, IntCons(3, IntCons(4, IntNil))))) == 4; { } datatype list = Nil | Cons(head: A, tail: list) function size(l: list): nat { if (l.Nil?) then 0 else 1+size(l.tail) } function app(a: list, b: list): list { if (a.Nil?) then b else Cons(a.head, app(a.tail, b)) } ghost method compute_size4() ensures size(Cons(1, Cons(2, Cons(3, Cons(4, Nil))))) == 4; { } ghost method compute_size4_cons() ensures size(Cons(IntNil, Cons(IntNil, Cons(IntNil, Cons(IntNil, Nil))))) == 4; { } ghost method compute_appsize() ensures size(app(Cons(1, Cons(2, Nil)), Cons(3, Cons(4, Nil))))==4; { } datatype exp = Plus(e1: exp, e2: exp) | Num(n: int) | Var(x: int) function interp(env: map, e: exp): int decreases e; { if (e.Plus?) then interp(env, e.e1)+interp(env, e.e2) else if (e.Num?) then e.n else if (e.Var? && e.x in env) then env[e.x] else 0 } ghost method compute_interp1() ensures interp(map[], Plus(Plus(Num(1), Num(2)), Plus(Num(3), Num(4))))==10; { } ghost method compute_interp2(env: map) requires 0 in env && env[0]==10; ensures interp(env, Plus(Plus(Var(0), Num(1)), Num(0)))==11; { } ghost method compute_interp3(env: map) requires 0 in env && env[0]==10 && 1 !in env; ensures interp(env, Plus(Var(0), Plus(Var(1), Var(0))))==20; { } function cinterp(env: map, e: exp): int decreases e; { match e case Plus(e1, e2) => cinterp(env, e1)+cinterp(env, e2) case Num(n) => n case Var(x) => if x in env then env[x] else 0 } ghost method compute_cinterp1() ensures cinterp(map[], Plus(Plus(Num(1), Num(2)), Plus(Num(3), Num(4))))==10; { } ghost method compute_cinterp2(env: map) requires 0 in env && env[0]==10; ensures cinterp(env, Plus(Plus(Var(0), Num(1)), Num(0)))==11; { } ghost method compute_cinterp3(env: map) requires 0 in env && env[0]==10 && 1 !in env; ensures cinterp(env, Plus(Var(0), Plus(Var(1), Var(0))))==20; { } function opt(e: exp): exp { match e case Num(n) => e case Var(x) => e case Plus(e1, e2) => var o1 := opt(e1); if (o1.Num? && o1.n==0) then e2 else Plus(o1, e2) } ghost method opt_test() ensures opt(Plus(Plus(Plus(Num(0), Num(0)), Num(0)), Num(1)))==Num(1); { } function copt(e: exp): exp { match e case Num(n) => e case Var(x) => e case Plus(e1, e2) => match e1 case Num(n) => if n==0 then e2 else e case Var(x) => e case Plus(e11, e12) => var o1 := copt(e1); if (o1.Num? && o1.n==0) then e2 else Plus(o1, e2) } ghost method copt_test() ensures copt(Plus(Plus(Plus(Num(0), Num(0)), Num(0)), Num(1)))==Num(1); { } function power(b: int, n: nat): int { if (n==0) then 1 else b*power(b, n-1) } ghost method test_power() ensures power(power(2, 3), 1+power(2, 2))==32768; { } function fib(n: nat): nat { if (n<2) then n else fib(n-1)+fib(n-2) } ghost method test_fib() ensures fib(12)==144; { } ghost method test_fib1(k: nat) ensures k==12 ==> fib(k)==144; { } ghost method test_fib2(k: nat) ensures 12<=k && k<=12 ==> fib(k)==144; { } ghost method test_fib3(k: nat, m: nat) { var y := 12; assert y <= k && k < y + m && m == 1 ==> fib(k)==144; } module NeedsAllLiteralsAxiom { // The following test shows that there exist an example that // benefits from the all-literals axiom. (It's not clear how // important such an example is, nor is it clear what the cost // of including the all-literals axiom is.) function trick(n: nat, m: nat): nat decreases n; // note that m is not included { if n < m || m==0 then n else trick(n-m, m) + m } lemma lemma_trick(n: nat, m: nat) ensures trick(n, m) == n; { } lemma calc_trick(n: nat, m: nat) ensures trick(100, 10) == 100; { } }