<commit_before>module CodeGen (
  genModuleBody,
  genExports,
  genImports,
  genTodoItems,
  makeKnownSymbolsMap,
  mungeMethodInfo,
  mungeClassToObject,
  mungeBoxedToObject
  ) where

import Api
import Docs
import FormatDocs
import Marshal
import StringUtils
import ModuleScan
import MarshalFixup (cTypeNameToHSType, maybeNullParameter, maybeNullResult,
                     fixCFunctionName, leafClass, nukeParameterDocumentation)

import Prelude hiding (Enum, lines)
import List   (groupBy, sortBy, isPrefixOf, isSuffixOf, partition, find)
import Maybe  (isNothing, fromMaybe, catMaybes)
import qualified Data.Map as Map

import Debug.Trace (trace)

-------------------------------------------------------------------------------
-- Now lets actually generate some code fragments based on the api info
-------------------------------------------------------------------------------
genFunction :: KnownSymbols -> Bool -> Method -> Maybe FuncDoc -> Maybe MethodInfo -> ShowS
genFunction knownSymbols isConstructor method doc info =
  formattedDoc.
  ss functionName. ss " :: ". functionType. nl.
  ss functionName. sc ' '. formattedParamNames. sc '='.
  indent 1. body

  where functionName = cFuncNameToHsName (method_cname method)
	(classConstraints', paramTypes', paramMarshalers) =
	  unzip3 [ case genMarshalParameter knownSymbols (method_cname method)
                          (changeIllegalNames (cParamNameToHsName (parameter_name p)))
	                  (parameter_type p) of
                     (c, ty, m) -> (c, (ty, parameter_name p), m)
		 | p <- method_parameters method ]
	classConstraints = [ c | Just c <- classConstraints' ]
	inParamTypes = [ (paramType, lookup name paramDocMap)
                     | (InParam paramType, name) <- paramTypes' ]
	inParamNames = [ changeIllegalNames (cParamNameToHsName (parameter_name p))
		     | ((InParam _, _), p) <- zip paramTypes' (method_parameters method) ]
	outParamTypes = [ (paramType, lookup name paramDocMap)
                        | (OutParam paramType, name) <- paramTypes' ]
        formattedParamNames = cat (map (\name -> ss name.sc ' ') inParamNames)
	(returnType', returnMarshaler) =
		genMarshalResult knownSymbols (method_cname method)
                                  isConstructor (method_return_type method)
        returnType | null outParamTypes  = ("IO " ++ returnType', lookup "Returns" paramDocMap)
		   | otherwise = case unzip outParamTypes of
                                   (types', docs') ->
				     let types | returnType' == "()" = types'
				               | otherwise           = returnType' : types'
					 docs = mergeParamDocs (lookup "Returns" paramDocMap) docs'
				      in (case types of
				            [t] -> "IO " ++ t
					    ts  -> "IO (" ++ sepBy ", " types "" ++ ")"
					 ,docs)
	(outParamMarshalersBefore, outParamMarshalersAfter, returnOutParamFragments) =
             unzip3 [ genMarshalOutParameter outParamType (changeIllegalNames (cParamNameToHsName name))
                    | (OutParam outParamType, name) <- paramTypes' ]
        returnOutParams body | null outParamTypes = body
                             | otherwise = body
                                         . indent 1. ss "return (". sepBy' ", " returnOutParamFragments. ss ")"
        functionType = (case classConstraints of
	                  []  -> id
			  [c] -> ss c. ss " => "
			  cs  -> sc '('. sepBy ", " classConstraints. ss ") => ").
                       formatParamTypes (inParamTypes ++ [returnType])
	body = foldl (\body marshaler -> marshaler body)
                     call (paramMarshalers
                       ++ [ (\body -> frag. body) | frag <- reverse outParamMarshalersBefore ]
                       ++ [ (\body -> body. frag) | frag <- outParamMarshalersAfter ]
                       ++ [returnMarshaler,returnOutParams])
	call = ss (genCall (maybe (method_cname method) methodinfo_shortcname info) safety)
        safety = case info of
                  Nothing -> False
                  Just info -> methodinfo_unsafe info
        formattedDoc = haddocFormatDeclaration knownSymbols docNullsAllFixed funcdoc_paragraphs doc
        docNullsAllFixed = maybeNullResult (method_cname method)
                        || or [ maybeNullParameter (method_cname method) (cParamNameToHsName (parameter_name p))
                              | p <- method_parameters method ]
        paramDocMap = case doc of
          Nothing  -> []
          Just doc -> [ (paramdoc_name paramdoc
                        ,(if paramdoc_name paramdoc == "Returns"
                           then [DocText "returns "]
                           else [DocArg (paramdoc_name paramdoc)
                                ,DocText " - "]
                         ) ++ paramdoc_paragraph paramdoc)
                      | paramdoc <- funcdoc_params doc
		      , not $ nukeParameterDocumentation
                                (method_cname method)
                                (cParamNameToHsName (paramdoc_name paramdoc)) ]
        
        formatParamTypes :: [(String, Maybe [DocParaSpan])] -> ShowS
        formatParamTypes paramTypes = format True False paramTypes
                                             -- True to indicate first elem
                                             -- False to mean previous param had no doc<commit_msg>Add deprecated pragmas to deprecated functions<commit_after>module CodeGen (
  genModuleBody,
  genExports,
  genImports,
  genTodoItems,
  makeKnownSymbolsMap,
  mungeMethodInfo,
  mungeClassToObject,
  mungeBoxedToObject
  ) where

import Api
import Docs
import FormatDocs
import Marshal
import StringUtils
import ModuleScan
import MarshalFixup (cTypeNameToHSType, maybeNullParameter, maybeNullResult,
                     fixCFunctionName, leafClass, nukeParameterDocumentation)

import Prelude hiding (Enum, lines)
import List   (groupBy, sortBy, isPrefixOf, isSuffixOf, partition, find)
import Maybe  (isNothing, fromMaybe, catMaybes)
import qualified Data.Map as Map

import Debug.Trace (trace)

-------------------------------------------------------------------------------
-- Now lets actually generate some code fragments based on the api info
-------------------------------------------------------------------------------
genFunction :: KnownSymbols -> Bool -> Method -> Maybe FuncDoc -> Maybe MethodInfo -> ShowS
genFunction knownSymbols isConstructor method doc info =
  formattedDoc.
  dperecatedNote.
  ss functionName. ss " :: ". functionType. nl.
  ss functionName. sc ' '. formattedParamNames. sc '='.
  indent 1. body

  where functionName = cFuncNameToHsName (method_cname method)
	(classConstraints', paramTypes', paramMarshalers) =
	  unzip3 [ case genMarshalParameter knownSymbols (method_cname method)
                          (changeIllegalNames (cParamNameToHsName (parameter_name p)))
	                  (parameter_type p) of
                     (c, ty, m) -> (c, (ty, parameter_name p), m)
		 | p <- method_parameters method ]
	classConstraints = [ c | Just c <- classConstraints' ]
	inParamTypes = [ (paramType, lookup name paramDocMap)
                     | (InParam paramType, name) <- paramTypes' ]
	inParamNames = [ changeIllegalNames (cParamNameToHsName (parameter_name p))
		     | ((InParam _, _), p) <- zip paramTypes' (method_parameters method) ]
	outParamTypes = [ (paramType, lookup name paramDocMap)
                        | (OutParam paramType, name) <- paramTypes' ]
        formattedParamNames = cat (map (\name -> ss name.sc ' ') inParamNames)
	(returnType', returnMarshaler) =
		genMarshalResult knownSymbols (method_cname method)
                                  isConstructor (method_return_type method)
        returnType | null outParamTypes  = ("IO " ++ returnType', lookup "Returns" paramDocMap)
		   | otherwise = case unzip outParamTypes of
                                   (types', docs') ->
				     let types | returnType' == "()" = types'
				               | otherwise           = returnType' : types'
					 docs = mergeParamDocs (lookup "Returns" paramDocMap) docs'
				      in (case types of
				            [t] -> "IO " ++ t
					    ts  -> "IO (" ++ sepBy ", " types "" ++ ")"
					 ,docs)
	(outParamMarshalersBefore, outParamMarshalersAfter, returnOutParamFragments) =
             unzip3 [ genMarshalOutParameter outParamType (changeIllegalNames (cParamNameToHsName name))
                    | (OutParam outParamType, name) <- paramTypes' ]
        returnOutParams body | null outParamTypes = body
                             | otherwise = body
                                         . indent 1. ss "return (". sepBy' ", " returnOutParamFragments. ss ")"
        functionType = (case classConstraints of
	                  []  -> id
			  [c] -> ss c. ss " => "
			  cs  -> sc '('. sepBy ", " classConstraints. ss ") => ").
                       formatParamTypes (inParamTypes ++ [returnType])
	body = foldl (\body marshaler -> marshaler body)
                     call (paramMarshalers
                       ++ [ (\body -> frag. body) | frag <- reverse outParamMarshalersBefore ]
                       ++ [ (\body -> body. frag) | frag <- outParamMarshalersAfter ]
                       ++ [returnMarshaler,returnOutParams])
	call = ss (genCall (maybe (method_cname method) methodinfo_shortcname info) safety)
        safety = case info of
                  Nothing -> False
                  Just info -> methodinfo_unsafe info
        formattedDoc = haddocFormatDeclaration knownSymbols docNullsAllFixed funcdoc_paragraphs doc
        docNullsAllFixed = maybeNullResult (method_cname method)
                        || or [ maybeNullParameter (method_cname method) (cParamNameToHsName (parameter_name p))
                              | p <- method_parameters method ]
        paramDocMap = case doc of
          Nothing  -> []
          Just doc -> [ (paramdoc_name paramdoc
                        ,(if paramdoc_name paramdoc == "Returns"
                           then [DocText "returns "]
                           else [DocArg (paramdoc_name paramdoc)
                                ,DocText " - "]
                         ) ++ paramdoc_paragraph paramdoc)
                      | paramdoc <- funcdoc_params doc
		      , not $ nukeParameterDocumentation
                                (method_cname method)
                                (cParamNameToHsName (paramdoc_name paramdoc)) ]
        dperecatedNote
          | method_deprecated method = ss "{-# DEPRECATED ". ss functionName.
              ss " \"this function should not be used in newly-written code\" #-}". nl
          | otherwise = id
        
        formatParamTypes :: [(String, Maybe [DocParaSpan])] -> ShowS
        formatParamTypes paramTypes = format True False paramTypes
                                             -- True to indicate first elem
                                             -- False to mean previous param had no doc
{'fraction_non_alphanumeric': 0.113578216374269, 'fraction_numerical': 0.0007309941520467836, 'mean_word_length': 1.8502604166666667, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '321609', 'n_tokens_mistral': 2900, 'n_tokens_neox': 2697, 'n_words': 785}