module Env:
  type Ident = string

  datatype Value = INTVAL of int
                 | REALVAL of real
                 | BOOLVAL of bool

  datatype Value2 = INTVAL2 of int*int
                  | REALVAL2 of real*real

  datatype Type = INTTYPE
                | REALTYPE
                | BOOLTYPE

  datatype Bind = BIND of Ident * Type * Value
  type Env = Bind list

  relation initial: () => Env
  relation lookup: (Env,Ident) => Value
  relation lookuptype: (Env,Ident) => Type
  relation update: (Env,Ident,Type,Value) => Env
end

relation initial =
  axiom initial => [BIND("false", BOOLTYPE, BOOLVAL false),
                    BIND("true",  BOOLTYPE, BOOLVAL true)]
end

relation lookup: (Env, Ident) => Value =

  rule  id = idenv
        ----------------------------------
        lookup(BIND(idenv,_,v)::_,id) => v

  rule  not id = idenv & lookup(rest,id) => v
        -------------------------------------
        lookup(BIND(idenv,_,_)::rest,id) => v

end

relation lookuptype: (Env, Ident) => Type =

  rule  id = idenv
        --------------------------------------
        lookuptype(BIND(idenv,t,_)::_,id) => t

  rule  not id = idenv & lookuptype(rest,id) => t
        -----------------------------------------
        lookuptype(BIND(idenv,_,_)::rest,id) => t


end

relation update: (Env,Ident,Type,Value) => Env =

  rule  let newenv = (BIND(id,ty,v)::env)
        -----------------------------
        update(env,id,ty,v) => newenv
end
