wlp (postConds, progParams, _) (FnCallAssign target progName params) q =
  let
    targetExp = case target of
      VarTarget name -> EName name
      ArrTarget arrName expr -> ArrAccess arrName expr
    progPostcond = postConds Map.! progName
    paramNames = map (\(Variable _ name _) -> name)$ progParams Map.! progName
    paramPairs = zip paramNames params
    postCondWithParams = foldr
                         (\(pname, pexp) pcond  -> subExpForName [pname] pexp pcond)
                         progPostcond paramPairs
    postCondWithRet = subExpForName [ToName "return"] targetExp postCondWithParams

  in (BinOp postCondWithRet Implies q, [])
wlp (postConds, progParams, _) (FnCallAssign target progName params) q =
  let
    targetExp = case target of
      VarTarget name -> EName name
      ArrTarget arrName expr -> ArrAccess arrName expr
    progPostcond = postConds Map.! progName
    paramNames = map (\(Variable _ name _) -> name)$ progParams Map.! progName
    paramPairs = zip paramNames params
    postCondWithParams = foldr
                         (\(pname, pexp) pcond  -> subExpForName [pname] pexp pcond)
                         progPostcond paramPairs
    postCondWithRet = subExpForName [ToName "return"] targetExp postCondWithParams

  in (BinOp postCondWithRet Implies q, [])
wlp (postConds, progParams, _) (FnCallAssign target progName params) q =
  let
    targetExp = case target of
      VarTarget name -> EName name
      ArrTarget arrName expr -> ArrAccess arrName expr
    progPostcond = postConds Map.! progName
    paramNames = map (\(Variable _ name _) -> name)$ progParams Map.! progName
    paramPairs = zip paramNames params
    postCondWithParams = foldr
                         (\(pname, pexp) pcond  -> subExpForName [pname] pexp pcond)
                         progPostcond paramPairs
    postCondWithRet = subExpForName [ToName "return"] targetExp postCondWithParams

  in (BinOp postCondWithRet Implies q, [])