-cpat s | trace ("J-2: "++show s) $ False  = undefined
  cpat s
   | null s''   = error "\ncompilePat: type constraint must precede a pattern node"
   | isW        = case c of
      '.' -> (Right $ Node (WI as) [], cs)
      '!' -> (Right $ Node (WS as) [], cs)
      '*' -> case parseInt cs [] of
               (Nothing, cs'') -> (Right $ Node (WW   as    ) [], cs'')
               (Just is, cs'') -> (Right $ Node (WN $ asn is) [], cs'')
#if USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS
      '{' ->
#else
      '(' ->
#endif
             if isNothing mmsg_subpats
             then (Right $ Node (WR as) subpats, cs_subpats)
             else (Left $ fromJust mmsg_subpats, cs_subpats)
#if USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS
      '}' ->
#else
      ')' ->
#endif
             (Left "", cs)
      c -> error $ "\ncompilePat: unexpected character '" ++ [c] ++ "'"
   | otherwise  = case c of
      '.' -> (Right $ Node (TI as) [], cs)
--    '!' -> (Right $ Node (TS as) [], cs)
      '*' -> case parseInt cs [] of
               (Nothing, cs'') -> (Right $ Node (TW   as    ) [], cs'')
               (Just is, cs'') -> (Right $ Node (TN $ asn is) [], cs'')
#if USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS
      '{' ->
#else
      '(' ->
#endif
             if isNothing mmsg_subpats
             then (Right $ Node (TR as) subpats, cs_subpats)
             else (Left $ fromJust mmsg_subpats, cs_subpats)
#if USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS
      '}' ->
#else
      ')' ->
#endif
             (Left "", cs)
      c -> error $ "\ncompilePat: unexpected character '" ++ [c] ++ "'"
   where
    s' = dropWhile isSpace s
    (c:cs) = s''
    (as_mods, mmsg_mods, s'') = cmods s'  -- collect any prefix modifiers
    as = case mmsg_mods of
           Nothing -> as_mods
           Just msg -> error $ "\ncompilePat: " ++ msg
    asn is = as { depth = read is :: Int }
    isW = not $ doConstrainType as
    (subpats, mmsg_subpats, cs_subpats) = compilePats cs []

  -- Accumulate any prefix modifiers into an empty PatNodeAttrs structure.

cpat s
   | null s''   = error "\ncompilePat: type constraint must precede a pattern node"
   | isW        = case c of
      '.' -> (Right $ Node (WI as) [], cs)
      '!' -> (Right $ Node (WS as) [], cs)
      '*' -> case parseInt cs [] of
               (Nothing, cs'') -> (Right $ Node (WW   as    ) [], cs'')
               (Just is, cs'') -> (Right $ Node (WN $ asn is) [], cs'')
#if USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS
      '{' ->
#else
      '(' ->
#endif
             if isNothing mmsg_subpats
             then (Right $ Node (WR as) subpats, cs_subpats)
             else (Left $ fromJust mmsg_subpats, cs_subpats)
#if USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS
      '}' ->
#else
      ')' ->
#endif
             (Left "", cs)
      c -> error $ "\ncompilePat: unexpected character '" ++ [c] ++ "'"
   | otherwise  = case c of
      '.' -> (Right $ Node (TI as) [], cs)
--    '!' -> (Right $ Node (TS as) [], cs)
      '*' -> case parseInt cs [] of
               (Nothing, cs'') -> (Right $ Node (TW   as    ) [], cs'')
               (Just is, cs'') -> (Right $ Node (TN $ asn is) [], cs'')
#if USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS
      '{' ->
#else
      '(' ->
#endif
             if isNothing mmsg_subpats
             then (Right $ Node (TR as) subpats, cs_subpats)
             else (Left $ fromJust mmsg_subpats, cs_subpats)
#if USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS
      '}' ->
#else
      ')' ->
#endif
             (Left "", cs)
      c -> error $ "\ncompilePat: unexpected character '" ++ [c] ++ "'"
   where
    s' = dropWhile isSpace s
    (c:cs) = s''
    (as_mods, mmsg_mods, s'') = cmods s'  -- collect any prefix modifiers
    as = case mmsg_mods of
           Nothing -> as_mods
           Just msg -> error $ "\ncompilePat: " ++ msg
    asn is = as { depth = read is :: Int }
    isW = not $ doConstrainType as
    (subpats, mmsg_subpats, cs_subpats) = compilePats cs []

  -- Accumulate any prefix modifiers into an empty PatNodeAttrs structure.
cpat s
   | null s''   = error "\ncompilePat: type constraint must precede a pattern node"
   | isW        = case c of
      '.' -> (Right $ Node (WI as) [], cs)
      '!' -> (Right $ Node (WS as) [], cs)
      '*' -> case parseInt cs [] of
               (Nothing, cs'') -> (Right $ Node (WW   as    ) [], cs'')
               (Just is, cs'') -> (Right $ Node (WN $ asn is) [], cs'')
#if USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS
      '{' ->
#else
      '(' ->
#endif
             if isNothing mmsg_subpats
             then (Right $ Node (WR as) subpats, cs_subpats)
             else (Left $ fromJust mmsg_subpats, cs_subpats)
#if USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS
      '}' ->
#else
      ')' ->
#endif
             (Left "", cs)
      c -> error $ "\ncompilePat: unexpected character '" ++ [c] ++ "'"
   | otherwise  = case c of
      '.' -> (Right $ Node (TI as) [], cs)
--    '!' -> (Right $ Node (TS as) [], cs)
      '*' -> case parseInt cs [] of
               (Nothing, cs'') -> (Right $ Node (TW   as    ) [], cs'')
               (Just is, cs'') -> (Right $ Node (TN $ asn is) [], cs'')
#if USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS
      '{' ->
#else
      '(' ->
#endif
             if isNothing mmsg_subpats
             then (Right $ Node (TR as) subpats, cs_subpats)
             else (Left $ fromJust mmsg_subpats, cs_subpats)
#if USE_CURLY_BRACE_INSTEAD_OF_PAREN_FOR_SUBPATTERNS
      '}' ->
#else
      ')' ->
#endif
             (Left "", cs)
      c -> error $ "\ncompilePat: unexpected character '" ++ [c] ++ "'"
   where
    s' = dropWhile isSpace s
    (c:cs) = s''
    (as_mods, mmsg_mods, s'') = cmods s'  -- collect any prefix modifiers
    as = case mmsg_mods of
           Nothing -> as_mods
           Just msg -> error $ "\ncompilePat: " ++ msg
    asn is = as { depth = read is :: Int }
    isW = not $ doConstrainType as
    (subpats, mmsg_subpats, cs_subpats) = compilePats cs []

  -- Accumulate any prefix modifiers into an empty PatNodeAttrs structure.