3

En arrière-plan: J'écris un compilateur générique de haut niveau à bas niveau. Au niveau supérieur, il comprend les classes, les méthodes, les champs, les appels de méthodes virtuelles, etc. Il comprend les fonctions, les structures, les tableaux, etc. Les frontaux traduisent des formes compilées de langages comme Java (l'objectif principal) et C# dans mon IR. Une étape intermédiaire abaisse les classes, les méthodes, les champs et les appels virtuels, etc. en appels et structures de fonction. L'extrémité arrière crache C, LLVM IR (l'objectif principal), ou potentiellement d'autres.Traduction de structure complexe avec évaluation paresseuse

Actuellement, les types (comme les entiers, les flottants, les structures, les classes, etc.) sont (pour la plupart) immuables. Les classes vous permettent d'ajouter des champs et des méthodes car ceux-ci ne modifient pas le type (c'est-à-dire le pointeur de classe). Il y a seulement un type donné par unité de traduction ("Module") - structures, pointeurs, tableaux et autres types "dérivés". En d'autres termes, les types ont une équivalence de structure, comme LLVM - au lieu de l'équivalence de nom, comme C++. Le problème que je rencontre est la traduction des instances de ClassType que le frontal Java crache dans les instances de StructType (avec un pointeur vtable et tous les champs de la classe) que le backend LLVM comprend, de telle sorte que le système conserve un état cohérent tout au long du processus. L'une des difficultés est de maintenir l'équivalence de structure - deux classes différentes peuvent être abaissées à la même structure, et cela doit soit être détecté au début du processus d'abaissement, soit corrigé après le processus d'abaissement.

Cette longue explication m'amène à ma question: les langages d'évaluation paresseux comme Haskell peuvent-ils être une solution pratique? Si oui, comment cela peut-il être traduit en Java, peut-être en utilisant le modèle "Promise"?

Répondre

1

Je ne sais pas si vous êtes à la recherche d'une réponse générale ou quelque chose de plus spécifique, mais il semble quelque chose comme,

lower :: Eq b => a -> b 
lower = undefined 

generate :: Eq b => [a] -> [b] 
generate xs = go $ map lower xs 
    where go [] = [] 
      go (y:ys) = y : go (filter (not . (==y)) ys) 

qui produit des éléments uniques progressivement. L'aspect incrémental est juste dû à des paresseux, sauf si vous pouvez également rendre votre instance Eq paresseuse (par exemple en comparant uniquement sur un type de code de hachage structurel qui pourrait vous laisser passer une étape de génération de code plus coûteuse).

+0

J'ai oublié comment, dans les langages de fonction, il n'y a pas vraiment de distinction entre égalité de référence (==) et égalité réelle (.equals()). Ce simple fait rend la solution dans le cas fonctionnel beaucoup plus facile, et d'autant moins applicable en Java. Pour ce qui est de voir comment quelqu'un pourrait faire ça chez Haskell, c'est parfait. –

Questions connexes