$Id: CoreMonadSemantics.lhs,v 1.6 1998/03/19 07:18:13 leavens Exp $

AUTHOR: Gary T. Leavens.

Semantic rules in monadic style for the core language of
David A. Schmidt's "The Structure of Typed Programming Languages"
(MIT Press, 1994).

> module CoreMonadSemantics where
> import CoreLangParser
> import CoreTyping
> import Domains
> import MonadStore

	SEMANTIC FUNCTIONS

The semantic functions are meaningN, meaningL, meaningE, meaningC.
(I don't see how to avoid different names for the
meaning functions, since they aren't parametric.)
We present the semantic functions bottom up, following the book.


For numbers, we really don't convert from syntax to semantics
going from numerals to numbers, because the "syntax"
is already coded as an integer

> meaningN :: ATree Integer -> DInt
> meaningN (( n ::: Node Aint _ )) = n

Booleans are treated similarly

> meaningB :: ATree Boolean -> DBool
> meaningB (( b ::: Node Abool _ )) = b

Locations essentially have themselves as their meaning.

> meaningL :: ATree Location -> DLocation
> meaningL (( (Loc i) ::: Node (Aloc Aint) _ )) = i


        MEANINGS FOR EXPRESSIONS

The ExpressibleValue domain is defined in the module Domains.
This version of the semantics, since it uses the store monad,
would allow side effects in expressions, although in this
particular semantics none are possible.

> meaningE :: ATree Expression
>      -> MStore ExpressibleValue

> meaningE (( Num n ::: Node (Aexp Aint) [atr] )) =
>   return (InInt (meaningN ((n ::: atr)) ) )

> meaningE (( BoolLit b ::: Node (Aexp Abool) [atr] )) =
>   return (InBool (meaningB ((b ::: atr )) ) )

> meaningE (( Deref l ::: Node (Aexp Aint) [atr] )) =
>   do i <- lookupS (meaningL((l ::: atr)) )
>      return (InInt i)

> meaningE (( (e1 `Plus` e2) ::: Node (Aexp Aint) [at1, at2] )) =
>   do (InInt i1) <- (meaningE ((e1 ::: at1)))
>      (InInt i2) <- (meaningE ((e2 ::: at2)))
>      return (InInt (plus (i1,i2)))

> meaningE (( Not e ::: Node (Aexp Abool) [atr] )) =
>   do (InBool b) <- meaningE ((e ::: atr))
>      return (InBool (not b))

> meaningE (( (e1 `Equals` e2) 
>                ::: Node (Aexp Abool)
>                       [at1@(Node (Aexp t1) _),
>                        at2@(Node (Aexp t2) _)] )) =
>   (case (t1, t2) of
>     (Abool, Abool) ->
>       do (InBool b1) <- meaningE((e1 ::: at1))
>          (InBool b2) <- meaningE((e2 ::: at2))
>          return (InBool (equalbool (b1,b2)))
>     (Aint, Aint) ->
>       do (InInt b1) <- meaningE((e1 ::: at1))
>          (InInt b2) <- meaningE((e2 ::: at2))
>          return (InBool (equalint (b1,b2))) )

> meaningE (( (e1 `Lt` e2) ::: Node (Aexp Abool) [at1, at2] )) =
>   do (InInt i1) <- meaningE ((e1 ::: at1))
>      (InInt i2) <- meaningE ((e2 ::: at2))
>      return (InBool (i1 < i2))

> meaningE (( (e1 `Gt` e2) ::: Node (Aexp Abool) [at1, at2] )) =
>   do (InInt i1) <- meaningE ((e1 ::: at1))
>      (InInt i2) <- meaningE ((e2 ::: at2))
>      return (InBool (i1 > i2))

> meaningE (( (e1 `Le` e2) ::: Node (Aexp Abool) [at1, at2] )) =
>   do (InInt i1) <- meaningE ((e1 ::: at1))
>      (InInt i2) <- meaningE ((e2 ::: at2))
>      return (InBool (i1 <= i2))

> meaningE (( (e1 `Ge` e2) ::: Node (Aexp Abool) [at1, at2] )) =
>   do (InInt i1) <- meaningE ((e1 ::: at1))
>      (InInt i2) <- meaningE ((e2 ::: at2))
>      return (InBool (i1 >= i2))

> meaningE (( (e1 `And` e2) ::: Node (Aexp Abool) [at1, at2] )) =
>   do (InBool b1) <- meaningE ((e1 ::: at1))
>      (InBool b2) <- meaningE ((e2 ::: at2))
>      return (InBool (b1 && b2))

> meaningE (( (e1 `Or` e2) ::: Node (Aexp Abool) [at1, at2] )) =
>   do (InBool b1) <- meaningE ((e1 ::: at1))
>      (InBool b2) <- meaningE ((e2 ::: at2))
>      return (InBool (b1 || b2))

          MEANINGS FOR COMMANDS

The meaning of a command is a transformation from one store to another.

> meaningC :: ATree Command -> MStore ()

> meaningC ((Skip ::: Node Acomm _)) =
>   return ()

> meaningC (( (l `Assign` e) ::: Node Acomm [atl, ate] )) =
>   do (InInt i) <- meaningE ((e ::: ate))
>      updateS (meaningL ((l ::: atl))) i

> meaningC (( (c1 `Semi` c2) ::: Node Acomm [at1, at2] )) =
>   do meaningC ((c1 ::: at1))
>      meaningC ((c2 ::: at2))

> meaningC (( (If e c1 c2) ::: Node Acomm [ate, at1, at2] )) =
>   do (InBool b) <- meaningE ((e ::: ate))
>      if b then do meaningC ((c1 ::: at1))
>           else do meaningC ((c2 ::: at2))

> meaningC (( (While e c) ::: Node Acomm [ate, atc] )) =
>   w
>   where w = do (InBool b) <- meaningE ((e:::ate))
>                if b
>                 then do meaningC ((c:::atc))
>                         w
>                 else do meaningC ((Skip ::: Node Acomm []))
