isBuiltInOcc_maybe :: OccName -> Maybe Name
-- Built in syntax isn't "in scope" so these OccNames
-- map to wired-in Names with BuiltInSyntax
isBuiltInOcc_maybe occ
  = case occNameString occ of
        "[]"             -> choose_ns listTyCon nilDataCon
        ":"              -> Just consDataConName
        "[::]"           -> Just parrTyConName
        "(##)"           -> choose_ns unboxedUnitTyCon unboxedUnitDataCon
        "()"             -> choose_ns unitTyCon        unitDataCon
        '(':'#':',':rest -> parse_tuple UnboxedTuple 2 rest
        '(':',':rest     -> parse_tuple BoxedTuple   2 rest
        _other           -> Nothing
  where
    ns = occNameSpace occ

    parse_tuple sort n rest
      | (',' : rest2) <- rest   = parse_tuple sort (n+1) rest2
      | tail_matches sort rest  = choose_ns (tupleTyCon sort n)
                                            (tupleCon   sort n)
      | otherwise               = Nothing

    tail_matches BoxedTuple   ")"  = True
    tail_matches UnboxedTuple "#)" = True
    tail_matches _            _    = False

    choose_ns tc dc
      | isTcClsNameSpace ns   = Just (getName tc)
      | isDataConNameSpace ns = Just (getName dc)
      | otherwise             = Just (getName (dataConWorkId dc))
isBuiltInOcc_maybe :: OccName -> Maybe Name
isBuiltInOcc_maybe occ
  = case occNameString occ of
        "[]"             -> choose_ns listTyCon nilDataCon
        ":"              -> Just consDataConName
        "[::]"           -> Just parrTyConName
        "(##)"           -> choose_ns unboxedUnitTyCon unboxedUnitDataCon
        "()"             -> choose_ns unitTyCon        unitDataCon
        '(':'#':',':rest -> parse_tuple UnboxedTuple 2 rest
        '(':',':rest     -> parse_tuple BoxedTuple   2 rest
        _other           -> Nothing
  where
    ns = occNameSpace occ

    parse_tuple sort n rest
      | (',' : rest2) <- rest   = parse_tuple sort (n+1) rest2
      | tail_matches sort rest  = choose_ns (tupleTyCon sort n)
                                            (tupleCon   sort n)
      | otherwise               = Nothing

    tail_matches BoxedTuple   ")"  = True
    tail_matches UnboxedTuple "#)" = True
    tail_matches _            _    = False

    choose_ns tc dc
      | isTcClsNameSpace ns   = Just (getName tc)
      | isDataConNameSpace ns = Just (getName dc)
      | otherwise             = Just (getName (dataConWorkId dc))
isBuiltInOcc_maybe occ
  = case occNameString occ of
        "[]"             -> choose_ns listTyCon nilDataCon
        ":"              -> Just consDataConName
        "[::]"           -> Just parrTyConName
        "(##)"           -> choose_ns unboxedUnitTyCon unboxedUnitDataCon
        "()"             -> choose_ns unitTyCon        unitDataCon
        '(':'#':',':rest -> parse_tuple UnboxedTuple 2 rest
        '(':',':rest     -> parse_tuple BoxedTuple   2 rest
        _other           -> Nothing
  where
    ns = occNameSpace occ

    parse_tuple sort n rest
      | (',' : rest2) <- rest   = parse_tuple sort (n+1) rest2
      | tail_matches sort rest  = choose_ns (tupleTyCon sort n)
                                            (tupleCon   sort n)
      | otherwise               = Nothing

    tail_matches BoxedTuple   ")"  = True
    tail_matches UnboxedTuple "#)" = True
    tail_matches _            _    = False

    choose_ns tc dc
      | isTcClsNameSpace ns   = Just (getName tc)
      | isDataConNameSpace ns = Just (getName dc)
      | otherwise             = Just (getName (dataConWorkId dc))