[Nitération] Nouvelles d'avril 2015

19 views
Skip to first unread message

Jean Privat

unread,
May 4, 2015, 5:01:22 PM5/4/15
to nit...@googlegroups.com

Nous avons le plaisir de vous présenter le quatrième numéro de l'année de « Nitération », la lettre d’information du projet Nit.

Les statistiques combinées pour le mois de avril 2015 donnent:

$ git diff --shortstat v0.7.3..v0.7.4
1072 files changed, 12428 insertions(+), 6528 deletions(-)
$ git log --first-parent v0.7.3..v0.7.4 | grep 'Pull-Request: #' | wc -l
49

Ont contribué (ou ont eu des patchs intégrés): Jean Privat, Alexandre Terrasa, Alexis Laferrière, Romain Chanoir et Lucas Bajolet

Langage

Ce mois-ci, de nombreuses améliorations au niveau du langage, en particulier au niveau des trous de spécification et autres FIXME et TODO.

Plusieurs de ces améliorations sont à l'essai et pourraient changer (ou être carrément supprimées) en fonction de leur utilité, utilisabilité et utilisation.

Extension des opérateurs

Des nouveaux opérateurs sont disponibles:

  • le + unaire
  • les opérateurs logiques bit-à-bit & (et), | (ou), ^ (xou) et ~ (non)
  • les affectation combinées: *=/=%=**=<<=>>=&=|= et ^=

La priorité des opérateurs et globalement définie mais les classes peuvent décider de les implémenter avec une sémantique spécifique.

Pour récapituler, voici la liste des opérateurs existants qui va du plus prioritaire au moins prioritaire. Pour un même niveau de priorité, l'associativité se fait à gauche (sauf pour ** qui est associatif à droite).

  • . (pas vraiment un opérateur), []
  • + unaire, - unaire, ~ unaire (le ~ binaire existe pas en fait)
  • **
  • */%
  • +-
  • >><<
  • &
  • ^
  • |
  • ==!=<=<>>=<=>
  • andoror elsenot (pas des opérateurs redéfinissables)

Note: pour des raisons de bootstrap, les nouveaux opérateurs ne sont pas encore offerts par standard, mais cela viendra dans une prochaine version.

Arguments par défaut et nommés

Afin de permettre aux bibliothèques d'offrir des API de qualité, un nouvel outil est disponible aux concepteurs de bibliothèques: les arguments par défaut et nommés.

La spécification a été choisie en visant à être la plus simple et la moins surprenante possible tout en permettant un contrôle statique de la validité des appels avec des messages d'erreur informatifs.

  • Un paramètre dont le type type statique est nullable, peut-être ignoré. null est alors implicitement fourni.
fun foo(a: Int, b: nullable Int) do end
foo(2)
foo(2, null) # Équivalent
  • Les paramètres par défaut peuvent être n'importe où (pas forcément à la fin)
fun foo(a: nullable Int, b: Int) do end
foo(1)
foo(null, 1)  # Équivalent
  • Quand plusieurs associations entre les arguments et les paramètres sont possibles, les arguments sont associés en premier aux paramètres les plus à gauche (les premiers). Les types statiques des paramètres ou des arguments ne sont pas considérés pour l'association.
fun foo(a, b: nullable Int) do end
foo(1)
foo(1, null)  # Équivalent
  • En cas de vararg, tous les autres paramètres sont obligatoires (pas de défaut)
fun foo(a: Int..., b: nullable Int) do end
foo(1) # Erreur: 2 arguments minimum
foo(1, 2) # OK
foo([1]..., 2) # Équivalent
  • Le dernier paramètre d'une méthode d'affectation n'est jamais un défaut (vu que l'argument est statiquement distingué en étant l'expression à droite du = et, est donc obligatoire)
fun foo=(a, b: nullable Int) do ...
foo = 1
foo(null) = 1 # Équivalent
  • Un paramètre par défaut peut-être passé par nom (et c'est seulement possible pour les paramètres par défaut)
fun foo(a,b: nullable Int) do ...
foo(b=1)
foo(null,1) # Équivalent
  • Les arguments nommés peuvent apparaître n'importe où (pas seulement à la fin)
fun foo(a: Int, b: nulable Int)
foo(b=1,2)
foo(2,1) # Équivalent
  • L'ordre d'évaluation des arguments est celui des arguments, et non celui des paramètres.

  • Les noms des paramètres à utiliser sont ceux de la définition statiquement la plus précise (et non les noms de l'introduction)

Note: cette spécification est pour l'instant à l'essai et pourrait changer, en particulier les règles pour les arguments nommés.

Méthode top-level

Le statut des méthodes top-level (celles définies directement dans un module en dehors des classe) restait en suspens.

Jusqu'à maintenant, ces méthodes étaient considérées comme définies dans Object donc accessibles n'importe où; ainsiprint("hello") était en réalité self.print("hello") (astuce aussi utilisée par Eiffel). Toutefois, des règles additionnelles de visibilité permettaient d'éviter des écritures bizarres telles que l'utilisation explicite de self dans ces méthodes ou des choses du genre 50.print("Hello").

Une solution pour donner un statut plus sain à ces méthodes est enfin disponible: les méthodes top-level sont maintenant implicitement définies dans Sys, la classe du singleton sys qui est l'objet principal du programme.

Ainsi, print("hello") est en réalité sys.print("hello").

Pour le programmeur, le changement est principalement invisible, toutefois cette modification a plusieurs avantages:

  • les méthodes top-levels ont enfin un receveur sémantique: le système courant;
  • plus besoin des règles spécifiques pour les méthodes top-levels: ça simplifie la spécification;
  • self est utilisable dans les méthodes top-level: pas forcément utile en soit car c'est sys, mais en cas de super-classe à Sys,self garde son sens.
  • plus de conflit de noms systématique entre méthodes top-level et méthodes normales.
  • permet d'intégrer les méthodes top-level dans un modèle objet traditionnel où différentes sortes de sys offriraient des services ou des implémentations spécifiques.

  • Merge: Sys is top 2ef74df

new primitif interne

Les fabriques new sont une astuce syntaxique pour exposer une fabrique via la syntaxe traditionnelle new Foo.bar. Introduites initialement par la FFI, elles ont été généralisées aux classes normales (et aux interfaces!).

Le seul problème était que lorsque l'on définissait une fabrique anonyme, le constructeur par défaut était masqué:

class A
   new do
      var res = new A # Récursivité infinie
      res.trucs
      return res
   end
end

Pour résoudre ce problème, l'allocateur primitif (celui qui alloue l'objet et initialise les attributs par défaut, mais n'invoque pas init) possède un nom est s'appelle intern, ce qui permet de l'utiliser dans les fabriques.

var res = new A.intern

Instruction with

De façon analogue au with de Python ou au using de C#, Nit propose une instruction with dont l'intérêt est l'invocation automatique de services de gestion, ce qui permet de déporter dans la bibliothèque ces mécanismes et donc simplifie le code client.

Ainsi, le code

with a = foo do
   a.bar
end

est en fait plus ou moins équivalent au code suivant:

var a = foo
a.start
a.bar
a.finish

On peut voir le with comme une construction intermédiaire au var et au for car comme dans ces deux constructions il y'a déclaration automatique de variable locale, et comme dans le for la méthode finish et automatiquement invoquée à la fin du traitement.

Note: la proposition actuelle, sa syntaxe et sa sémantique ne font pas l'unanimité et est donc intégrée en tant qu'essai pour voir si des utilisations intéressantes émergent et si des bibliothèques en profitent. On pourrait s'attendre à voir cette construction utilisée pour de la gestion automatique de ressources, de transactions, de section critiques, ou autre.

  • Merge: new with statement 90df56f

Type non null

Le système de type de Nit exprime explicitement le fait qu'une valeur puisse être null ou pas, via le mot clé nullable. Ainsi, lorsque nullable est absent, on a généralement la garantie que le type en question ne peut contenir null. Généralement, car ce n'est pas vrai dans le cadre des types formels (types virtuels ou types génériques paramétriques) qui peuvent être ancrés sur un type nullable sans être nullables eux-même.

class G[E: nullable Object]
   fun foo(e: E)
   do
      foo e # Erreur: `e: E` peut contenir `null`
   end
end

En soi, cela n'est pas un problème car le comportement est correctement spécifié et raisonnablement naturel. Là où cela devient gênant c'est lorsque l'on veut manipuler une expression typée par un tel type formel tout en excluant null, par exemple via un caste.as(not null).

C'est pourquoi le langage possède un nouveau modificateur du type not null réservé aux types formels pour résoudre ce problème.

Note: pour l'instant le modificateur est utilisé seulement à l'interne et n'est pas encore accessible au niveau de la grammaire.

Preuve de concept: Parallélisme

Dans le cadre du cours de compilation INF7641, une annotation de méthode is threaded a été proposé pour l'invocation asynchrone de méthodes (c'est-à-dire que la méthode est invoquée dans son propre thread).

fun foo is threaded do
   print "thread"
end

var t = foo
print "main"
t.join

Toutefois, l'utilisation de l'annotation, comme tout lib/pthread, est expérimentale car un audit des situations de compétition (race conditions) dans la bibliothèque et dans le code généré par le compilateur reste à faire.

  • Merge: Parallelization phase introduction 5da14ad
  • Merge: Improved parallelization phase 7cd8b6e
  • Merge: Parallelization phase improvement aa7db72

Compilateur

De grosses améliorations sur la gestion des erreurs et la robustesse.

Messages d'erreurs

Un travail systématique a eu lieu pour uniformiser et améliorer les messages d'erreurs.

  • Merge: Review errors messages e64156c

En particulier, de nouveaux cas d'erreurs sont maintenant signalés

  • Merge: Improve checking of virtual types 5934106
  • Merge: Hint vararg ad0a769

Typage adaptatif

Un des plus vieux bugs qui concerne le typage adaptatif dans le cadre des boucles est enfin résolu!

  • Merge: Fix type adaptation when there is loops 57d544c

Robustesse

Amélioration de la robustesse des outils et du code généré (FIXME et TODO)

Bibliothèques

Étrangement, rien de nouveau niveau bibliothèques de base. Juste du FIXE et TODO.

  • Merge: lib/standard/string: Added faster to_cstring method on FlatText. 3bf5fbe
  • Merge: Robust IO 3bb4fee
  • Merge: miniclean quadtrees 008dbe7

FFI, plate-formes et app.nit

Beaucoup plus de travail par contre au niveau de la FFI et de app.nit, en particulier le support OS X amélioré.

  • Merge: Test compilation of OS X and iOS programs, on OS X a268d1b
  • Merge: Unite app.nit metadata annotations common to Android and iOS bb2212e
  • Merge: Make the generated iOS project compilable in the XCode GUI 3079df7
  • Merge: Inkscape tool revamp and gamnit support 7e29399
  • Merge: Small clean up and improvements to MNit from WBTW ce31837

Nitrpg

La ludification du développement de Nit continue avec de nouvelles fonctionnalités: http://nitlanguage.org/rpg/games/privat/nit

  • Merge: nitrpg: minor enhancements 0dbaa61
  • Merge: Nitrpg work 9b51849
  • Merge: nitrpg: periodize stats a0a920e

D'ailleurs, le système devrait être moins fréquemment indisponible vu que maintenant il est relancé automatiquement lorsque le serveur doit redémarrer (en cas de mise a jour du noyau par exemple).

Nitdoc et autre outils

Le travail de refactorisation et de modernisation de la nitdoc continue

  • Merge: nitdoc: introduce Bootstrap components 59e1e40
  • Merge: Nitdoc: more cleaning and uniformize method names a77ea29
  • Merge: nitdoc: prepare the migration of nitdoc component to new phases 43df577

En parallèle, le plug-in vim offre de nouvelles fonctionnalités de documentation intégrée.

  • Merge: Vim plugin fixes and make Nitdoc a command with search capabilities 5fca479

Le loader sait gérer correctement les répertoires contenant des bibliothèques ou des projets, ce qui permet d'écrire de choses comme:

$ nitpick ../lib ../contrib

Afin de simplifier le déboguage du parseur (et déterminer plus facilement si un bug vient de nit, du parseur nit généré, de sablecc3altgen ou de la grammaire), un parseur basique en Java fabriqué à partir de la même grammaire est disponible.

  • Merge: parser: add a basic sabblecc3 parser in Java f9c4a71

Divers:

  • Merge: Snake phase names cea8021
  • Merge: share/man: Update man for nitpretty d6f7877
  • Merge: Model: add mclassdef2node 95fdb9d
  • Merge: Some metrics improvement and cleaning 34685ab

Tests et benches

Du nettoyage et de la consolidation des tests et des benches.

En particulier, l'option --autosav de tests.sh pour mettre automatiquement à jour les fichier .sav qui ont été modifiés (et ainsi éviter les copie manuelles et fastidieuses de fichiers)

  • Merge: tests: add --autosav to automatically update the sav directory. d78b0c5

Divers:

  • Merge: Bench markdown --semi-global 7926613
  • Merge: benches/markdown: add pandoc engine. 3fb4c23
  • Merge: Updated bench scripts for strings 3926f1a
  • Merge: Clean benches 58d8043
  • Merge: Check contrib fb53880
  • Merge: Microbenches for niti 394613d
Reply all
Reply to author
Forward
0 new messages