3 points par GN⁺ 2023-07-19 | 1 commentaires | Partager sur WhatsApp
  • Hylo vise une programmation système et générique sûre, fondée sur la sémantique de valeur ; son compilateur et sa bibliothèque standard en sont encore à un stade précoce, mais il est possible d’exécuter des exemples dans Compiler Explorer
  • Les recherches sur le langage se concentrent sur des sujets comme l’extension des subscripts de Swift avec des projections inout, les method bundles, la concurrence structurée et les listes doublement chaînées fondées sur la sémantique de valeur
  • Le compilateur utilise LLVM et traite aussi la compilation générique avec cohérence, la mise en cache et la sérialisation de l’état du programme, ainsi que les recherches sur l’interopérabilité avec C
  • L’environnement de développement propose une extension VSCode, un compilateur de documentation et un prototype de Language Server ; il prend en charge SPM/CMake, Ninja/Xcode, Windows/Linux/macOS et des images Docker de toolchain de développement
  • Les exemples font apparaître au niveau du code les règles de propriété et de libération au moyen de projections sûres et de sink methods, et montrent comment un langage système peut imposer la sûreté

Périmètre et état actuel de Hylo

  • Le compilateur et la bibliothèque standard de Hylo en sont encore à un stade précoce
  • Des exemples de code Hylo avancé peuvent être exécutés dans Compiler Explorer
  • La page d’accueil fournit également un lien pour essayer Hylo dans Compiler Explorer

Sémantique de valeur et recherches sur le langage

Compilateur et bibliothèque standard

  • Les travaux sur le compilateur couvrent la compilation fondée sur LLVM, les génériques, la persistance de l’état et l’interopérabilité avec C
    • Compilation avec LLVM
    • Une nouvelle technique pour la compilation générique avec cohérence
    • Mise en cache et sérialisation de l’état du programme dans le compilateur
    • Recherche sur C interop
  • Côté bibliothèque standard, la documentation de l’implémentation actuelle et des travaux liés aux algorithmes de collections sont publiés

Expérience développeur et environnement de build

  • Des outils sont fournis pour l’éditeur, la documentation et le serveur de langage
  • L’environnement de build et de développement prend en charge plusieurs systèmes d’exploitation ainsi que des flux basés sur des conteneurs
    • Prise en charge de Development Containers afin de réduire les étapes de démarrage
    • Prise en charge de SPM/CMake, Ninja/Xcode et Windows/Linux/macOS
    • Plugin de compilateur pour la génération de tests
    • Images Docker précompilées de la Hylo development toolchain
    • Le compilateur est écrit en Swift 6.2

Recherches et présentations liées à Hylo

Exemple de code : projection sûre et libération explicite

  • L’exemple Subscripts - A Safe Projection Mechanism montre une structure où le type Angle stocke une valeur radians et expose la propriété degrees au moyen de blocs let et inout
    • Le let de degrees convertit radians en degrés et renvoie le résultat
    • inout expose la valeur temporaire en degrés d avec yield &d, puis reconvertit la valeur modifiée en radians pour la refléter dans self.radians
    • main obtient une projection avec inout d = &a.degrees, remplace d par 0.0, puis vérifie que a.radians == 0.0
  • L’exemple Sink Methods - Capability for Deinitializing montre une structure où le type Computer fournit shutdown() comme sink method
    • shutdown() affiche le contenu de la mémoire, puis traite self.ram comme un sink
    • test1 crée un Computer sans appeler shutdown, ce qui provoque Cannot deinit computer
    • test2 n’appelle shutdown qu’à l’intérieur de if random_bool() ; le chemin qui n’entre pas dans le if provoque donc Cannot deinit computer
    • Dans test3, appeler shutdown dans un while entraîne après la première itération un problème d’utilisation d’un objet consommé, et le chemin qui n’entre pas dans le while conserve l’impossibilité de deinit
  • D’autres exemples sont disponibles dans la compiler test suite

1 commentaires

 
GN⁺ 2023-07-19
Commentaires sur Hacker News
  • Comme successeur de C++, Val semble peut-être plus prometteur que l’excellent CppFront de Herb Sutter. Je n’ai vu que les deux présentations ci-dessous, mais les points clés paraissent être la compilation statique, le typage statique, l’interopérabilité avec C++, la sûreté mémoire, la sûreté des types et l’absence de data races
    Quand je l’explique, je dis ceci : « Si l’on démarrait un nouveau projet C++ sans trop se soucier des performances, et qu’on passait tout par valeur et qu’on retournait tout par valeur, sans pointeurs ni références, ne serait-ce pas agréable de ne pas avoir à se soucier des effets de bord ni des data races ? » Ce qui est intéressant avec Val, c’est que même si le langage supprime les pointeurs et les références, le compilateur applique en interne le passage par référence const et l’optimisation des valeurs de retour afin de préserver à la fois la sémantique souhaitée et les performances
    Val: A Safe Language to Interoperate with C++ - Dimitri Racordon - CppCon 2022 https://www.youtube.com/watch?v=ws-Z8xKbP4w
    https://cppcast.com/val-and-mutable-value-semantics/

    • Cela vaut aussi le coup d’écouter les deux épisodes récents de ADSP Podcast dans lesquels Sean Parent parle de Val. Adobe Research Labs soutient le développement de façon assez sérieuse
      https://adspthepodcast.com/
    • L’idée d’« interopérer avec C++ » me paraît douteuse. J’ai du mal à croire qu’un autre langage puisse vraiment bien interopérer avec C++, alors que même les compilateurs C++ cassent parfois la compatibilité binaire, y compris entre versions d’un même compilateur
    • Cela donne l’impression d’une architecture qui fait trop confiance au compilateur. Je crains qu’un petit changement ne casse une optimisation dans un morceau de code très éloigné et ne détruise les performances
    • Si l’on « passe par valeur et retourne par valeur toute la journée », il devient difficile de modifier ou de stocker efficacement des références à l’intérieur des structures. Si un programme a besoin de structures de données un tant soit peu atypiques ou complexes, cela semble être une contrainte fatale. Cela dit, vu la difficulté de bien implémenter ce genre de structures, c’est peut-être au contraire un avantage
    • J’écris en pratique des programmes PHP de cette manière depuis des années, en passant constamment des tableaux sans m’en préoccuper
      Je suppose que l’interpréteur PHP est suffisamment intelligent pour utiliser le copy-on-write, mais je ne l’ai jamais profilé moi-même. Malgré cela, même en faisant à chaque chargement de page du traitement de données assez complexe, du parsing caractère par caractère d’une DSL, de la génération dynamique de SQL et du remaniement des résultats dans des structures arbitraires, je n’ai jamais constaté de problème de performances perceptible
      À l’époque de PHP 4, les objets se comportaient aussi comme des valeurs stockées dans des variables, et je trouve que le passage ultérieur des variables objet à une sémantique de référence a été une occasion manquée, car ils n’ont pas fait de « valeur, référence de variable, pointeur vers une valeur » des propriétés de variable orthogonales au type de stockage
      $a = $b; // copie la valeur de $b dans $a
      $a = &$b; // $a et $b sont désormais la même variable
      $a = *$b; // $a pointe vers le même objet que $b, mais contrairement à $a = &$b, les variables elles-mêmes ne sont pas liées
  • C’est bien, d’un côté, de voir apparaître autant de langages à abstraction à coût nul, mais j’aimerais aussi que les programmeurs système finissent par en choisir un gagnant. J’aimerais éviter que la petite communauté des programmeurs système ne se fragmente encore davantage entre Rust, Zig, Val, etc., et j’aimerais que la guerre des langages système se termine vite

    • Peut-être qu’on en a choisi un trop tôt et que, du coup, l’innovation dans ce domaine a trop longtemps manqué. La guerre est la bienvenue
    • À ce stade, Rust me paraît être le gagnant. Il a déjà franchi l’énorme barrière consistant à entrer réellement dans les noyaux Linux et Windows. De ce point de vue, il ne semble plus vraiment rester de place pour un nouveau langage système
    • Je ne pense pas que cela arrivera. C’est précisément pour cela qu’il faut encore davantage étendre partout la prise en charge de wasm + wasi
  • Voici le cheminement de mes sentiments en découvrant Val aujourd’hui pour la première fois. « Oh, encore un nouveau langage système. Ce n’est peut-être rien de spécial, mais allons voir. La documentation est correcte. Les idées autour de la propriété sont plutôt réfléchies, et la syntaxe tient la route. Mais est-ce assez différent pour avoir une raison d’être propre ? Qui est derrière ? »
    Puis j’ai vu que Dave Abrahams travaillait dessus, et mon intérêt a grandi. Je l’avais croisé chez Apple, et je me souvenais aussi de sa présentation Crusty sur Swift[1]. J’aimais ses positions tranchées, mais Apple a ensuite retiré cette vidéo en expliquant qu’elle contenait des conseils devenus anciens. Maintenant qu’il est chez Adobe, on se demande si c’est en quelque sorte un langage Adobe
    En conclusion, cela mérite d’être surveillé, et je suis plutôt du côté « attendons de voir » après avoir regardé la présentation liée
    [1] J’ai retrouvé la présentation Crusty : "I don't do Object Oriented!" https://www.youtube.com/watch?v=p3zo4ptMBiQ

    • David Abrahams était déjà un contributeur très important de Boost avant son passage chez Apple, ainsi qu’un membre du comité C++ et un fervent défenseur de la programmation générique à la Stepanov. Sa participation au projet Val n’a rien de surprenant
  • En tant que développeur de compilateurs, j’ai été choqué en voyant les problèmes ci-dessous
    https://github.com/val-lang/val/issues/758
    https://github.com/val-lang/val/issues/711
    Ça sent une implémentation dans un mauvais état. Il faudrait faire du self-hosting dès que possible, et cela permettrait de trouver davantage de bugs aussi élémentaires. Malgré tout, il y a déjà plus de 500 étoiles

    • Vu depuis la perspective d’un autre développeur de compilateurs, il y a peu d’erreurs aussi néfastes qu’un self-hosting trop précoce. Même si le langage apporte déjà un bénéfice net sur des programmes petits ou moyens, il faut bien plus de temps avant qu’il convienne à de gros projets comme un compilateur et qu’il dispose de l’outillage nécessaire. Heureusement qu’ils ne se précipitent pas
    • Si ce genre de bugs existait dans un compilateur en production, ce serait inquiétant, mais pour le compilateur d’un langage encore en cours de définition, ce n’est pas si grave. Il suffit de comparer Rust 1.0 et 1.71 pour voir l’ampleur de l’écart entre une « première version stable » et le compilateur d’un langage stable largement utilisé en conditions réelles
      Le self-hosting n’est pas tout non plus. C’est avant tout un jalon symbolique ; quand on l’atteint, c’est à célébrer, mais je ne pense pas que son absence doive être considérée comme une faiblesse du langage avant une phase bien plus avancée du cycle de développement
    • Swift lui-même n’est toujours pas self-hosted, alors même que la sortie de la version 6 approche. Je ne suis pas développeur de compilateurs, mais la conclusion des discussions autour de ce sujet dans la communauté Swift semblait être que cela n’en valait toujours pas la peine
  • Je repoussais depuis longtemps le moment de « jouer avec Val », et je m’y suis enfin mis aujourd’hui, mais même avec plus de 4 000 commits, on est encore loin d’un état réellement utilisable. La plupart des exemples du tour d’horizon du langage ne compilent pas, et même des exemples apparemment simples échouent
    Carbon n’a encore rien vraiment livré, et Sean Baxter fait beaucoup de progrès avec le compilateur Circle tout en implémentant plusieurs des bonnes idées de Carbon. Tant que cela ressemble à peine à un langage, c’est difficile d’en faire un successeur

  • Maintenant on a V, Val, Vala et Vale. Est-ce qu’il y a d’autres langages que j’oublie ?

    • Il y a aussi VAL. C’est un langage des années 80 qui a influencé Haskell via SISAL. Cela dit, en dehors de la communauté des langages parallèles, il n’y a sans doute pas grand monde qui connaisse ce VAL-là
    • Des noms similaires peuvent au contraire jouer en leur faveur. Les personnes qui apprennent ce genre de langages cherchent probablement « le nouveau truc à la mode » ; elles peuvent donc tomber aussi sur d’autres langages au nom proche et aller les voir. JavaScript a connu ça aussi, et le résultat n’a pas été mauvais
    • J’ai vraiment cru que c’était Vale. C’est dommage qu’il y ait un tel conflit de nom
    • Pour couronner le tout, V est aussi appelé Vlang, et Vale aussi s’appelait autrefois Vlang
  • C’est un point qui revient à chaque fois, mais la seule chose qui me déplaît vraiment chez Val, c’est que Vale et V sont aussi de nouveaux langages système. À cause des noms, il est beaucoup trop facile de confondre les trois

    • Il y a aussi Vala. Ce n’est pas tout à fait le même créneau, mais ça fait encore un langage au nom proche
    • J’ai dû cliquer sur le lien juste pour vérifier s’il s’agissait d’un langage à projection ou d’un langage à régions
    • Il y a aussi VAL: Variable Assembly Language https://en.m.wikipedia.org/wiki/Variable_Assembly_Language
  • Il y a déjà un article lié. Il y en a d’autres ?
    Val, a new programing language inspired by Swift and Rust - https://news.ycombinator.com/item?id=31788527 - juin 2022, 19 commentaires

  • J’ai parcouru l’article sur les “mutable value semantics” et je me demande si je comprends bien la proposition des auteurs : remplacer les références et les pointeurs par a) une certaine indirection et des vérifications à l’exécution via des structures imbriquées et Any, et b) des indices de tableau
    Le passage « il est légitime de demander comment des structures de données auto-référentielles comme des listes doublement chaînées ou des graphes orientés peuvent être représentées avec des types valeur mutables. En réalité, un graphe arbitraire peut être représenté comme une liste d’adjacence… » m’a marqué. Je vois mal comment implémenter de façon raisonnable une liste doublement chaînée sans recréer dans l’implémentation un tas mémoire et une sorte de ramasse-miettes
    J’ai aussi trouvé une discussion ici : https://github.com/orgs/val-lang/discussions/736 ; il semble qu’une porte de sortie à la Rust avec unsafe finira par exister. Dans ce cas, tous les problèmes trouvent une solution, mais la question de savoir si « le sous-ensemble sûr de Val suffit à lui seul pour construire des applications pratiques » restera probablement débattue encore longtemps

    • En utilisant des tableaux et des indices de tableau à la place des pointeurs, on peut en pratique recréer de la mémoire
      Ce n’est pas une approche aussi absurde qu’il n’y paraît, parce que ces indices sont liés à une structure de données donnée, par exemple une liste doublement chaînée ou un graphe, et qu’il n’est donc pas facile de les manipuler pour accéder à d’autres parties du programme. Cela vaut aussi si le compilateur vérifie cela, y compris face à des tentatives délibérées de casser le programme
  • Je ne sais pas comment lire l’explication de l’exemple sur le site. Il est écrit : « Aucune allocation inutile n’a lieu. Le résultat de longer_of est une projection de l’argument le plus long, donc si emphasize modifie z, la valeur de y est modifiée directement. La valeur n’est ni copiée ni déplacée, mais elle n’est pas non plus passée par référence à emphasize »
    On est dans une situation où un argument de type chaîne est passé à une fonction et où des caractères sont ajoutés ; la chaîne existante devait pourtant avoir une longueur initiale ainsi qu’une position et une taille précises sur la pile, donc je ne comprends pas comment cela peut fonctionner sans nouvelle copie de y. Est-ce qu’ils laissent un padding supplémentaire à la fin de la chaîne au cas où quelqu’un ajouterait quelque chose ? Si oui, quelle quantité de padding, et pourquoi cela ne serait-il pas globalement moins efficace ?

    • Le préfixe de quatre espaces ne sert pas aux citations, mais aux blocs de code / à chasse fixe. Sur HN, on utilise généralement la convention > pour citer, et ça fonctionne bien même sans traitement spécial du parseur
    • Qu’une valeur soit immuable ne signifie pas forcément qu’elle doit se trouver sur la pile
      Cela dit, j’ai une question similaire. Que se passe-t-il si on modifie une chaîne de 1 Go ? Est-ce une copie à l’écriture ?
      Dans 99 % des cas, cela peut sans doute être éliminé par optimisation, mais j’ai l’impression que dans le 1 % restant, on risque d’avoir une dégradation de performances très difficile à repérer
    • Pour essayer d’y répondre moi-même quelques jours plus tard, cela semble possible si la variable modifiée shadowe discrètement sur la pile l’ancien nom de variable avec une nouvelle valeur plus longue. C’est peut-être ce que signifie « projection ». Dans ce cas, la pile est déjà allouée, donc il n’y a pas de nouvelle allocation. Je ne suis ni spécialiste du langage ni du compilateur, donc il est possible que ce terme soit bien connu dans ce domaine
    • Il y a plus d’explications plus bas. longer_of n’est pas une fonction mais un subscript, et un subscript ne renvoie pas une valeur ; il projette une valeur et donne à l’appelant un droit d’accès temporaire en lecture/écriture
      Je ne vois pas bien en quoi cela ne correspond pas à un déplacement. Dans le cas des chaînes, elles peuvent aussi être placées sur le tas pour autoriser une taille variable, comme en Rust