CurryInfo: currydoc-5.0.0 / CurryDoc.Info.AbstractCurry

classes: Info
 
documentation: Info
 
name: Info
 CurryDoc.Info.AbstractCurry
operations: Info
 addAbstractCurryProg
sourcecode: Info
 
{- |
     Author  : Kai-Oliver Prott
     Version : March 2025

     Operations to add information from AbstactCurry to the
     commented declarations.
-}
module CurryDoc.Info.AbstractCurry ( addAbstractCurryProg ) where

import AbstractCurry.Types
import AbstractCurry.Select

import CurryDoc.Data.AnaInfo
import CurryDoc.Data.CurryDoc
import CurryDoc.Info.Comments
import CurryDoc.Info.Goodies

import Data.List  ( last )
import Data.Maybe ( listToMaybe )

-- | Remove unexported entities and
--   add exported entities that did not have any comments.
--   All entities get a lot more information about thei type or ...
--   Also translates into CurryDoc representations and sets a flag for
--   ExternalDataDecls
addAbstractCurryProg :: CurryProg -> [CommentedDecl] -> [CurryDocDecl]
addAbstractCurryProg (CurryProg _ _ _ cls inst typ func _) ds =
  let withins  = addAbstractCurryInstInfo inst ds ++
                 concatMap generateDerivingInstances typ
      withcls  = addAbstractCurryClassesInfo cls ds
      withtyp  = addAbstractCurryDataInfo typ ds withins
      withfun  = addAbstractCurryFunInfo func ds
  in withcls ++ withtyp ++ withfun

-- All addXInfo function are mostly the same:
--   look for the CommentedDecl that matches the AbstractCurry decl
--   When it exists, then add some additional information to the decl
--   Otherwise create one with those infos
-- All this is only done, when the AbstractCurry decl is public (exported)

-- Currently ignores comments and declarations and just adds context and type
addAbstractCurryInstInfo :: [CInstanceDecl] -> [CommentedDecl]
                         -> [CurryDocInstanceDecl]
addAbstractCurryInstInfo []                          _   = []
addAbstractCurryInstInfo (CInstance n cx ts ds : is) cds =
  maybe (CurryDocInstanceDecl n cx ts (addAbstractCurryFunInfo ds []) [])
    (\(CommentedInstanceDecl _ _ cs ds') -> CurryDocInstanceDecl n cx ts
        (addAbstractCurryFunInfo ds ds') cs) (lookupInstance n ts cds)
    : addAbstractCurryInstInfo is cds

-- | Adds superclass and type variable.
addAbstractCurryClassesInfo :: [CClassDecl] -> [CommentedDecl] -> [CurryDocDecl]
addAbstractCurryClassesInfo []                               _   = []
addAbstractCurryClassesInfo (CClass n Public  cx vn fdeps ds:cs) cds =
  maybe (CurryDocClassDecl n cx vn cdfdeps (addAbstractCurryFunInfo ds []) [])
    (\(CommentedClassDecl _ cs' ds') -> CurryDocClassDecl n cx vn cdfdeps
        (addAbstractCurryFunInfo ds ds') cs') (lookupClass n cds)
    : addAbstractCurryClassesInfo cs cds
 where cdfdeps = map CurryDocFunDep fdeps

addAbstractCurryClassesInfo (CClass _ Private _ _ _ _:cs) cds =
  addAbstractCurryClassesInfo cs cds

-- | Adds empty Analysis, qualified type and typesig (if it exists).
addAbstractCurryFunInfo :: [CFuncDecl] -> [CommentedDecl] -> [CurryDocDecl]
addAbstractCurryFunInfo []                             _   = []
addAbstractCurryFunInfo (CFunc n _ Public  qty _ : ds) cds =
  maybe (CurryDocFunctionDecl n qty typesig NoAnalysisInfo [])
    (\(CommentedFunctionDecl _ cs) -> CurryDocFunctionDecl n qty typesig
        NoAnalysisInfo cs)
    (lookupFunc n cds)
    : addAbstractCurryFunInfo ds cds
  where typesig = transformTypesig qty (lookupTypeSig [n] cds)
addAbstractCurryFunInfo (CFunc _ _ Private _   _ : ds) cds =
  addAbstractCurryFunInfo ds cds
addAbstractCurryFunInfo (CmtFunc _ a b c d e : ds) cds =
  addAbstractCurryFunInfo (CFunc a b c d e : ds) cds

-- | Transforms the content of a typesig to CurryDocTypeSig.
transformTypesig :: CQualTypeExpr -> Maybe CommentedDecl
                 -> Maybe CurryDocTypeSig
transformTypesig (CQualType cx _) d = case d of
  Just (CommentedTypeSig [n] cs ps) -> Just (CurryDocTypeSig n cx ps cs)
  _                                 -> Nothing

-- | For data: Adds external info, typevars, instances,
--             and modifies constructors (see below).
--   For new: Adds typevars, instances and modifies constructor.
--   For syn: Adds type and typevars.
addAbstractCurryDataInfo :: [CTypeDecl] -> [CommentedDecl]
                         -> [CurryDocInstanceDecl] -> [CurryDocDecl]
addAbstractCurryDataInfo []                                _   _   = []
addAbstractCurryDataInfo (CTypeSyn n Public vs ty    : ds) cds ins =
  maybe (CurryDocTypeDecl n vs ty [])
    (\(CommentedTypeDecl _ cs) -> CurryDocTypeDecl n vs ty cs)
    (lookupTypeDecl n cds)
    : addAbstractCurryDataInfo ds cds ins
addAbstractCurryDataInfo (CNewType n Public vs con _ : ds) cds ins =
  maybe (CurryDocNewtypeDecl n vs (getInstances n ins)
          (listToMaybe (addAbstractCurryConsInfo [con] [])) [])
    (\(CommentedNewtypeDecl _ cs cn) -> CurryDocNewtypeDecl n vs
        (getInstances n ins)
        (listToMaybe (addAbstractCurryConsInfo [con] [cn])) cs)
    (lookupNewDecl n cds)
    : addAbstractCurryDataInfo ds cds ins
addAbstractCurryDataInfo (CType n Public vs cons _   : ds) cds ins =
  maybe (CurryDocDataDecl n vs (getInstances n ins)
          (null cons) (addAbstractCurryConsInfo cons []) [])
    (\(CommentedDataDecl _ cs cns) -> CurryDocDataDecl n vs (getInstances n ins)
          (null cons) (addAbstractCurryConsInfo cons cns) cs)
    (lookupDataDecl n cds)
    : addAbstractCurryDataInfo ds cds ins
addAbstractCurryDataInfo (CTypeSyn _ Private _ _     : ds) cds ins =
  addAbstractCurryDataInfo ds cds ins
addAbstractCurryDataInfo (CNewType _ Private _ _ _   : ds) cds ins =
  addAbstractCurryDataInfo ds cds ins
addAbstractCurryDataInfo (CType _ Private _ _ _      : ds) cds ins =
  addAbstractCurryDataInfo ds cds ins

-- | Adds type and analysis info and modifies fields for recordss (see below).
addAbstractCurryConsInfo :: [CConsDecl] -> [CommentedConstr] -> [CurryDocCons]
addAbstractCurryConsInfo []                              _   = []
addAbstractCurryConsInfo (CCons   n Public  tys : cs) cds =
  maybe (createConsInfo n tys) (transformConstructor n tys)
    (lookupCons n cds)
    : addAbstractCurryConsInfo cs cds
addAbstractCurryConsInfo (CRecord n Public  fs  : cs) cds =
  maybe (createRecordInfo n fs) (transformRecord n fs)
    (lookupRecord n cds)
    : addAbstractCurryConsInfo cs cds
addAbstractCurryConsInfo (CCons   _ Private _   : cs) cds =
  addAbstractCurryConsInfo cs cds
addAbstractCurryConsInfo (CRecord _ Private _   : cs) cds =
  addAbstractCurryConsInfo cs cds

-- | Creates constructor info.
createConsInfo :: QName -> [CTypeExpr] -> CurryDocCons
createConsInfo n tys
  | isOperator && length tys == 2 =
            let [ty1, ty2] = tys
            in  CurryDocConsOp n ty1 ty2 NoAnalysisInfo []
  | otherwise = CurryDocConstr n tys     NoAnalysisInfo []
  where isOperator = all (`elem` "~!@#$%^&*+-=<>:?./|\\") (snd n)

-- | Creates constructor info for records.
createRecordInfo :: QName -> [CFieldDecl] -> CurryDocCons
createRecordInfo n fs =
  CurryDocRecord n (map cFieldType fs) (addAbstractCurryField fs [])
                 NoAnalysisInfo []

-- | Adds type to constructor.
transformConstructor :: QName -> [CTypeExpr] -> CommentedConstr -> CurryDocCons
transformConstructor n tys c = case c of
  CommentedConstr _ cs
    -> CurryDocConstr n tys                   NoAnalysisInfo cs
  CommentedConsOp _ cs
    -> CurryDocConsOp n (head tys) (last tys) NoAnalysisInfo cs
  _ -> error "CurryDoc.Info.AbstractCurry. transformConstructor"

-- | Adds type to record constructor and modifies fields (see below).
transformRecord :: QName -> [CFieldDecl] -> CommentedConstr -> CurryDocCons
transformRecord n fs c = case c of
  CommentedRecord _ cs fs'
    -> CurryDocRecord n (map cFieldType fs) (addAbstractCurryField fs fs')
                      NoAnalysisInfo cs
  _ -> error "CurryDoc.Info.AbstractCurry. transformRecord"

-- | Adds empty `AnalysisInfo` and type to record fields.
addAbstractCurryField :: [CFieldDecl] -> [CommentedField] -> [CurryDocField]
addAbstractCurryField []                         _   =  []
addAbstractCurryField (CField n Public  ty : fs) cfs =
  maybe (CurryDocField n ty NoAnalysisInfo [])
    (\(_,cs) -> CurryDocField n ty NoAnalysisInfo cs) (lookupField n cfs)
    : addAbstractCurryField fs cfs
addAbstractCurryField (CField _ Private _  : fs) cfs =
  addAbstractCurryField fs cfs

-------------------------------------------------------------------------------
-- Collecting instance informations

-- | Generates all `CurryDocInstanceDecl` for a given type declaration
--   with its deriving clauses.
generateDerivingInstances :: CTypeDecl -> [CurryDocInstanceDecl]
generateDerivingInstances (CType    n Public vs _ der) =
  map (generateDerivingInstanceFor n vs) der
generateDerivingInstances (CNewType n Public vs _ der) =
  map (generateDerivingInstanceFor n vs) der
generateDerivingInstances (CTypeSyn _ _       _ _  ) = []
generateDerivingInstances (CNewType _ Private _ _ _) = []
generateDerivingInstances (CType    _ Private _ _ _) = []

-- | Generates a `CurryDocInstanceDecl` for a given type and deriving clause.
generateDerivingInstanceFor :: QName -> [CTVarIName] -> QName
                            -> CurryDocInstanceDecl
generateDerivingInstanceFor t vs d =
  CurryDocInstanceDecl d (CContext (map (generateConstraintFor d) vs))
    [generateType t vs] [] []

-- | Generates a unary constraint.
generateConstraintFor :: QName -> CTVarIName -> CConstraint
generateConstraintFor n v = (n, [CTVar v])

-- | Generates a type expression for a given type name and type variables.
generateType :: QName -> [CTVarIName] -> CTypeExpr
generateType n = foldl (\t v -> CTApply t (CTVar v)) (CTCons n)

-- | Returns all known instances associated with a given type.
--
-- That is, for a given type name, this function returns all instances
-- that have the given type name in their list of types.
getInstances :: QName -> [CurryDocInstanceDecl] -> [CurryDocInstanceDecl]
getInstances n = filter (any (=~= n) . instTypeNames)
types: Info
 
unsafe: Info
 unsafe due to modules CASS.Registry Analysis.NondetOps System.IO.Unsafe Analysis.UnsafeModule