6 votes

Comment lire la sortie du simplificateur ?

Considérons une fonction simple de la question récente :

myButLast :: [a] -> a
myButLast [x, y] = x
myButLast (x : xs) = myButLast xs
myButLast _ = error "List too short"

Nous pouvons demander à GHC de nous donner la sortie du simplifieur avec ghc -ddump-simpl . (Éventuellement avec un peu de drapeaux supplémentaires comme -dsuppress-module-prefixes -dsuppress-uniques .) Si je comprends bien, c'est c'est la dernière étape de la compilation où le résultat ressemble encore au code original de haut niveau. d'origine. Voici donc ce qui est écrit :

-- RHS size: {terms: 21, types: 22, coercions: 0, joins: 0/0}
myButLast :: forall a. [a] -> a
[GblId,
 Arity=1,
 Str=<S,1*U>,
 Unf=Unf{Src=<vanilla>, TopLvl=True, Value=True, ConLike=True,
         WorkFree=True, Expandable=True, Guidance=IF_ARGS [30] 100 0}]
myButLast
  = \ (@ a) (ds :: [a]) ->
      case ds of {
        [] -> myButLast1 @ a;
        : x ds1 ->
          case ds1 of {
            [] -> myButLast1 @ a;
            : y ds2 ->
              case ds2 of {
                [] -> x;
                : ipv ipv1 -> myButLast_$smyButLast1 @ a y ipv ipv1
              }
          }
      }

Qu'est-ce qui se passe ici ? Voyons voir.

  1. À la signature de type, maintenant avec un quantificateur explicite, des sortes d'annotations sont attachées. Je peux deviner qu'elles disent "identifiant global, unaire, de premier niveau". ce qui est tout à fait vrai pour cette fonction. Les autres annotations, comme WorkFree=True , Str=<S,1*U> sont pour moi énigmatiques.

  2. El "valeur" est maintenant un lambda qui accepte, en plus d'une liste, une variable de type en argument, et procède à l'étude de la liste par analyse de cas. [] -> myButLast1 @ a est un glorifié glorifié, alors ignorons-le pour l'instant. La partie intéressante est l'appel à myButLast_$smyButLast1 (Quel genre de nom est-ce ? J'ai pensé $ ne pouvait pas faire partie d'un identifiant). qui s'avère être une fonction récursive de queue qui parcourt réellement la liste.

  3. Et le voici, un seul membre de ce que nous reconnaissons comme un bloc mutuellement récursif :

    Rec {
    -- RHS size: {terms: 13, types: 12, coercions: 0, joins: 0/0}
    myButLast_$smyButLast1 [Occ=LoopBreaker]
      :: forall a. a -> a -> [a] -> a
    [GblId,
     Arity=3,
     Caf=NoCafRefs,
     Str=<L,1*U><L,1*U><S,1*U>,
     Unf=OtherCon []]
    myButLast_$smyButLast1
      = \ (@ a) (sc :: a) (sc1 :: a) (sc2 :: [a]) ->
          case sc2 of {
            [] -> sc;
            : ipv ipv1 -> myButLast_$smyButLast1 @ a sc1 ipv ipv1
          }
    end Rec }

    Il est assez lucide, mais il comporte quelques fonctionnalités nouvelles pour nous, comme le bloc récursif délimiteur Rec ... end Rec et une remarque énigmatique [Occ=LoopBreaker] . Les annotations sont également différentes : les Unf est vide, et un Caf apparaît à la place. Je peux seulement en déduire que le site Unf le champ intéressant est une qualité de noms définie par le programmeur, alors que myButLast_$smyButLast1 est créé par le compilateur.

Ainsi, je peux comprendre environ la moitié de ce que le simplificateur me donne, par nombre de lignes, mais de certaines parties, je ne peux même pas commencer à deviner le sens.

  • La prémisse est-elle que la sortie simplifiée est généralement l'intermédiaire le plus utile ? la plus utile, est-elle correcte ?

  • Ma lecture est-elle correcte jusqu'à présent ?

  • Y a-t-il un manuel pour toutes ces remarques cryptiques ? Que signifient-elles ?

2voto

K. A. Buhr Points 14622

À ma connaissance, il n'existe pas de manuel ou de documentation autonome sur Core qui entre dans le genre de détails que vous recherchez. Il y a bien sûr page sur Core du Wiki, mais il ne fait qu'expliquer le langage Core à un haut niveau et le fait principalement en termes de structures de données du compilateur utilisées pour représenter un arbre syntaxique abstrait Core, plutôt que la syntaxe concrète "pretty print".

La seule façon d'obtenir les détails que vous souhaitez est de télécharger une copie du code source de GHC et de commencer à parcourir le code dans la section ghc/compiler/coreSyn/ .

GHC est grand et compliqué, mais la plus grande partie est écrite en Haskell, et donc une grande partie du code est de très haut niveau et assez lisible, et le code source est fortement commenté avec d'excellentes explications et notes parsemées partout.

Si vous voulez savoir ce que WorkFree=True signifie, par exemple, que vous :

  1. Trouvez le code dans PprCore.hs qui génère l'annotation, pour déterminer qu'il s'agit de la uf_is_work_free domaine de CoreUnfolding .

  2. Vérifiez la définition de CoreUnfolding sur CoreSyn.hs et les commentaires qui s'y rattachent, où l'on peut voir qu'une Unfolding est une représentation d'un identifiant qui peut être substitué lors de l'inlining, et l'élément uf_is_work_free est une copie en cache de exprIsWorkFree qui indique en quelque sorte que l'alignement du déroulement ne constitue pas un "gaspillage de travail".

  3. Regardez les commentaires dans CoreSyn.hs , CoreUnfold.hs y CoreUtils.hs pour trouver une explication supplémentaire de exprIsWorkFree et ce que cela signifie :

    exprIsWorkFree est utilisé pour décider si l'on doit mettre quelque chose en ligne. Nous ne le mettons pas en ligne si cela risque de dupliquer le travail, en retirant une ligne copie complète de l'expression.

    Un exemple est donné :

    let x = a #+ b in x +# x  -- I think `#+` is a typo and should be `+#`

    où il est indiqué que x n'est pas "sans travail", car s'il était inlined sur le RHS, cela provoquerait l'apparition de l'élément a +# b l'opération doit être évaluée deux fois

Dans votre cas, la version de myButLast dans votre sortie Core est sans travail parce qu'elle n'évalue aucune expression indépendamment des arguments qui pourraient être réutilisés à chaque fois que la fonction myButLast est appliquée.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X