CSC 530 Lecture Notes Week 10
Algebraic Semantics
obj STACK is sort Stack . protecting NAT . op push : Stack Nat -> Stack . op pop : Stack -> Stack . op top : Stack -> Nat . op emptyStack : -> Stack . op emptyElem : -> Nat . var S : Stack . var E E' : Nat . eq pop(emptyStack) = emptyStack . eq pop(push(S, E)) = S . eq top(emptyStack) = emptyElem . eq top(push(S, E)) = E . endo
in Stack *** *** obj MAIN is comparable to a class or module declaration. obj MAIN is *** The protecting clause in OBJ is like importing. protecting STACK . protecting INT . *** An OBJ op primarily declares functions, such as main here. op main : -> Stack . *** An OBJ parameterlesss op decl can also be used to declare a single- *** assignment variable of a particular type op s1 : -> Stack . op s2 : -> Stack . op i : -> Int . *** OBJ equations declare what the program does. Typically, they're used *** as in object STACK to define behavior of ADT operations. They can also *** be used as below to simulate a form of single assignment programming. *** E.g., the immediately following four equations simulate the following *** ML-style let block: *** eq s1 = pop(push(push(push(emptyStack, 1), 2), 3)) . eq i = top(push(push(push(emptyStack, 1), 2), 3)) + 1 . eq s2 = push(push(s1, i), 5) . eq main = pop(s2) . endo *** The following executes program main reduce main . *** The result of execution is the stack push(push(push(emptyStack,1),2),4).
obj LIST is sort List . protecting INT . op car : List -> Int . op cdr : List -> List . op cons : Int List -> List . op append : List List -> List . op emptyList : -> List . var e : Int . var l l1 l2 : List . eq car(cons(e,l)) = e . eq cdr(cons(e,l)) = l . eq car(append(l1,l2)) = car(l1) . eq cdr(append(l1,l2)) = append(cdr(l1),l2) . eq append(emptyList,l) = l . eq append(l,emptyList) = l . endo
th ELEM is sort Elem . endth view ELEM-TO-NAT from ELEM to NAT is sort Elem to Nat . endv obj SET[EL :: ELEM] is sort Set . op insert : Set Elem -> Set . op delete : Set Elem -> Set . op find : Set Elem -> Bool . op emptyset : -> Set . op equal : Set Set -> Bool . var S S' : Set . var E E' : Elem . eq find(emptyset, E) = false . eq find(insert(S, E), E') = if E == E' then true else find(S, E') fi . eq delete(emptyset, E) = emptyset . eq delete(insert(S, E), E') = if E == E' then delete(S, E') else insert(delete(S, E'), E) fi . eq equal(emptyset, emptyset) = true . eq equal(emptyset, insert(S, E)) = false . eq equal(insert(S, E), emptyset) = false . eq equal(S, insert(S', E)) = if find(S, E) then equal(delete(S, E), delete(S', E)) else false fi . endo
in List-Int obj BinSearchTree is sort BST . protecting LIST + INT . op makeTree : Int BST BST -> BST . op root : BST -> Int . op find : BST Int -> BST . op del : BST Int -> BST . op reinsert : BST BST -> BST . op enum : BST -> List . op emptyTree : -> BST . op legalBST : BST -> Bool . *** Optional (see below) op insert : BST Int -> BST . *** Optional (ibid.) var b b1 b2 : BST . var e e1 e2 : Int . eq root(makeTree(e, b1, b2)) = e . eq find(emptyTree,e) = emptyTree . eq find(makeTree(e1,b1,b2),e2) = if legalBST(makeTree(e1,b1,b2)) then if e1 == e2 then makeTree(e1,b1,b2) else if e2 < e1 then find(b1,e2) else find(b2,e2) fi fi else emptyTree fi . eq del(emptyTree,e) = emptyTree . eq del(makeTree(e1,b1,b2),e2) = if e1 == e2 then reinsert(b1,b2) else if e2 < e1 then makeTree(e1,del(b1,e2),b2) else makeTree(e1,b1,del(b2,e2)) fi fi . eq reinsert(b,makeTree(e,b1,b2)) = if b1 == emptyTree then makeTree(e,b,b2) else makeTree(e,reinsert(b,b1),b2) fi . eq reinsert(b,emptyTree) = b . eq reinsert(emptyTree,b) = b . eq enum(makeTree(e,b1,b2)) = append(enum(b1), cons(e, enum(b2))) . eq enum(emptyTree) = emptyList . *** ALTERNATIVES FOR OPTIONAL WELL-FORMEDNESS CHECKING *** Eqns for legalBST could be expanded to check search tree well-formedness. eq legalBST(makeTree(e,b1,b2)) = true . *** Alternatively, eqns for an insert op could enforce well-formedness: eq insert(emptyTree,e) = makeTree(e,emptyTree,emptyTree) . eq insert(makeTree(e1,b1,b2),e2) = if e1 == e2 then makeTree(e1,b1,b2) else if e2 < e1 then makeTree(e1,insert(b1,e2),b2) else makeTree(e1,b1,insert(b2,e2)) fi fi . endo *** Instantiate a BinSearchTree object make BST-INT is BinSearchTree endm *** Do some sample reductions reduce del( makeTree(5, makeTree(2, makeTree(1,emptyTree,emptyTree), makeTree(3,emptyTree,emptyTree)), makeTree(10, makeTree(6,emptyTree,emptyTree), makeTree(12,emptyTree,emptyTree))), 5) . *** Result is: *** makeTree(10, *** makeTree(6, *** makeTree(2, *** makeTree(1,emptyTree,emptyTree), *** makeTree(3,emptyTree,emptyTree)), *** emptyTree), *** makeTree(12,emptyTree,emptyTree)) reduce enum( makeTree(5, makeTree(2, makeTree(1,emptyTree,emptyTree), makeTree(3,emptyTree,emptyTree)), makeTree(10, makeTree(6,emptyTree,emptyTree), makeTree(12,emptyTree,emptyTree))) ) . *** Result is: *** append(append(cons(1,emptyList),cons(2,cons(3,emptyList))), *** cons(5,append(cons(6,emptyList),cons(10,cons(12,emptyList))))) reduce car(cdr(cdr( enum( makeTree(5, makeTree(2, makeTree(1,emptyTree,emptyTree), makeTree(3,emptyTree,emptyTree)), makeTree(10, makeTree(6,emptyTree,emptyTree), makeTree(12,emptyTree,emptyTree))) )))) . *** Result is: 3
th ELEM is sort Elem . endth view ELEM-TO-NAT from ELEM to NAT is sort Elem to Nat . endv obj LIST[E :: ELEM] is sort List . op car : List -> Elem . op cdr : List -> List . op cons : Elem List -> List . op append : List List -> List . op emptyList : -> List . var e : Elem . var l l1 l2 : List . eq car(cons(e,l)) = e . eq cdr(cons(e,l)) = l . eq car(append(l1,l2)) = car(l1) . eq cdr(append(l1,l2)) = append(cdr(l1),l2) . endo make LIST-NAT is LIST[ELEM-TO-NAT] endm make LIST-INT is LIST[ELEM-TO-NAT] endm
in list2 th POSET is sort Elt . op _<_ : Elt Elt -> Bool . vars E1 E2 E3 : Elt . eq E1 < E1 = false . cq E1 < E3 = true if E1 < E2 and E2 < E3 . endth th TOSET is using POSET . vars E1 E2 E3 : Elt . cq E1 < E2 or E2 < E1 = true if E1 =/= E2 . endth obj BUBBLES[X :: TOSET] is protecting LIST[X] . op sorting_ : List -> List . op sorted_ : List -> Bool . vars L L' L'' : List . vars E E' : Elt . cq sorting L = L if sorted L . cq sorting L E E' L'' = sorting L E' E L'' if E' < E . eq sorted nil = true . eq sorted E = true . cq sorted E E' L = sorted E' L if E < E' or E == E' . endo in bubbles view NATD from POSET to NAT is vars L1 L2 : Elt . op L1 < L2 to L1 divides L2 and L1 =/= L2 . endv reduce in A is BUBBLES[NAT] : sorting(18 5 6 3) . ***> should be: 3 5 6 18 reduce sorting(8 5 4 2) . ***> should be: 2 4 5 8 reduce in B is BUBBLES[NATD] : sorting(18 5 6 3) . ***> mightnt contain: 3 6 18 reduce sorting(8 5 4 2) . ***> mightnt contain: 2 4 8
in lib/list in lib/array *** the expressions of Fun obj EXP is dfn Env is ARRAY[QID,INT] . sorts IntExp BoolExp . subsorts Int Id < IntExp . subsorts Bool < BoolExp . ops (_and_)(_or_) : BoolExp BoolExp -> BoolExp . op not_ : BoolExp -> BoolExp . op _<_ : IntExp IntExp -> BoolExp . op _=_ : IntExp IntExp -> BoolExp . op if_then_else_fi : BoolExp IntExp IntExp -> IntExp . ops (_+_)(_-_)(_*_) : IntExp IntExp -> IntExp . op [[_]]_ : IntExp Env -> Int . op [[_]]_ : BoolExp Env -> Bool . var N : Int . var T : Bool . vars E E' : IntExp . vars B B' : BoolExp . var I : Id . var V : Env . eq [[ N ]] V = N . eq [[ I ]] V = V [ I ] . eq [[ E + E' ]] V = ([[ E ]] V) + ([[ E' ]] V) . eq [[ E - E' ]] V = ([[ E ]] V) - ([[ E' ]] V) . eq [[ E * E' ]] V = ([[ E ]] V) * ([[ E' ]] V) . eq [[ T ]] V = T . eq [[ E < E' ]] V = ([[ E ]] V) < ([[ E' ]] V) . eq [[(E = E')]] V = ([[ E ]] V) == ([[ E' ]] V) . eq [[ B and B' ]] V = ([[ B ]] V) and ([[ B' ]] V) . eq [[ B or B' ]] V = ([[ B ]] V) or ([[ B' ]] V) . eq [[ not B ]] V = not([[ B ]] V) . eq [[ if B then E else E' fi ]] V = if [[ B ]] V then [[ E ]] V else [[ E' ]] V fi . endo *** the statements of Fun obj STMT is sort Stmt . protecting EXP . op _;_ : Stmt Stmt -> Stmt [assoc] . op _:=_ : Id IntExp -> Stmt . op while_do_od : BoolExp Stmt -> Stmt . op [[_]]_ : Stmt Env -> Env . vars S S' : Stmt . var V : Env . var E : IntExp . var B : BoolExp . var I : Id . eq [[ I := E ]] V = put(I,[[ E ]] V, V) . eq [[ S ; S' ]] V = [[ S' ]] [[ S ]] V . eq [[ while B do S od ]] V = if [[ B ]] V then [[ while B do S od ]] [[ S ]] V else V fi . endo *** evaluation of Fun programs obj FUN is sorts Fun Init . protecting STMT . dfn IdList is LIST[QID] . dfn IntList is LIST[INT] . dfn InitList is (LIST *(op nil to nil-init, op (__) to (_;_)))[Init] . op _initially_ : Id IntExp -> Init [prec 1]. op fun _ _ is vars _ body: _ : Id IdList InitList Stmt -> Fun . op [[_:=_]]_ : IdList IntList Env -> Env . op [[_]]_ : InitList Env -> Env . op [[_]][_]_ : Fun Env IntList -> Env . op [[_]]_ : Fun IntList -> Int . op wrong#args : -> Env . *** err-op vars I F : Id . var Is : IdList . var N : Int . var Ns : IntList . var E : IntExp . var INs : InitList . var S : Stmt . var V : Env . eq [[ nil-init ]] V = V . eq [[(I initially E); INs ]] V = [[ INs ]] [[ I := E ]] V . eq [[ I Is := N Ns ]] V = ([[ I := N ]] ([[ Is := Ns ]] V)).STMT . eq [[(nil).IdList := (nil).IntList ]] V = V . eq [[ fun F(Is) is vars nil-init body: S ]][ V ](Ns) = [[ S ]] V . eq [[ fun F(Is) is vars INs body: S ]][ V ](Ns) = [[ S ]] [[ INs ]] [[ Is := Ns ]] V . eq [[ fun F(Is) is vars INs body: S ]](Ns) = [[ fun F(Is) is vars INs body: S ]][ nilArr ](Ns) [ F ] . cq [[ Is := Ns ]] V = wrong#args if | Is | =/= | Ns | . *** err-qn endo *** pow(n m) finds the nth power of m for positive n or 0 reduce [[ fun 'pow('n 'm) is vars 'pow initially 1 body: while 0 < 'n do ('pow := 'pow * 'm);('n := 'n - 1) od ]](4 2) . ***> should be: 16 *** factorial of n reduce [[ fun 'fac('n) is vars ('fac initially 1);('i initially 0) body: while 'i < 'n do ('i := 'i + 1); ('fac := 'i * 'fac) od ]](5) . ***> should be: 120 *** max finds the maximum of a list of three numbers reduce [[ fun 'max('a 'b 'c) is vars 'n initially 2 body: ('max := 'a); while 0 < 'n do ('n := 'n - 1); ('x := 'b); ('b := 'c); ('max := if 'x < 'max then 'max else 'x fi) od ]](3 123 32) . ***> should be: 123
obj NAT is sort Nat . op 0 : -> Nat . op s_ : Nat -> Nat [prec 1] . op _+_ : Nat Nat -> Nat [assoc comm prec 3] . vars M N : Nat . eq M + 0 = M . eq M + s N = s(M + N). op _*_ : Nat Nat -> Nat [prec 2] . eq M * 0 = 0 . eq M * s N = M * N + M . endo obj VARS is protecting NAT . ops m n : -> Nat . endo ***> first show two lemmas, 0*n=0 and sm*n=m*n+n ***> base for first lemma reduce 0 * 0 == 0 . ***> induction step for first lemma obj HYP1 is using VARS . eq 0 * n = 0 . endo reduce 0 * s n == 0 . *** thus we can assert obj LEMMA1 is protecting NAT . vars N : Nat . eq 0 * N = 0 . endo ***> base for second lemma reduce in VARS + LEMMA1 : s n * 0 == n * 0 + 0 . ***> induction step for second lemma obj HYP2 is using VARS . eq s m * n = m * n + n . endo reduce s m * s n == (m * s n)+ s n . *** so we can assert obj LEMMA2 is protecting NAT . vars M N : Nat . eq s M * N = M * N + N . endo obj SUM is protecting NAT . op sum : Nat -> Nat . var N : Nat . eq sum(0) = 0 . eq sum(s N) = s N + sum(N) . endo ***> show sum(n)+sum(n)=n*sn ***> base case reduce in SUM + LEMMA1 : sum(0) + sum(0) == 0 * s 0 . ***> induction step obj HYP is using SUM + VARS . eq sum(n) + sum(n) = n * s n . endo reduce in HYP + LEMMA2 : sum(s n) + sum(s n) == s n * s s n .
in list th FN is sort S . op f : S -> S . endth obj MAP[F :: FN] is protecting LIST[F] . op map : List -> List . var X : S . var L : List . eq map(nil) = nil . eq map(X L) = f(X) map(L) . endo in map obj FNS is protecting INT . ops (sq_)(dbl_)(_*3) : Int -> Int . var N : Int . eq sq N = N * N . eq dbl N = N + N . eq N *3 = N * 3 . endo reduce in MAP[(sq_).FNS] : map(0 nil 1 -2 3) . ***> should be: 0 1 4 9 reduce in MAP[(dbl_).FNS] : map(0 1 -2 3) . ***> should be: 0 2 -4 6 reduce in MAP[(_*3).FNS] : map(0 1 -2 nil 3) . ***> should be: 0 3 -6 9