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
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.
Des nouveaux opérateurs sont disponibles:
+ unaire& (et), | (ou), ^ (xou) et ~ (non)*=, /=, %=, **=, <<=, >>=, &=, |= 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)***, /, %+, ->>, <<&^|==, !=, <=, <, >, >=, <=>and, or, or else, not (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.
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.
null est alors implicitement fourni.fun foo(a: Int, b: nullable Int) do end
foo(2)
foo(2, null) # Équivalent
fun foo(a: nullable Int, b: Int) do end
foo(1)
foo(null, 1) # Équivalent
fun foo(a, b: nullable Int) do end
foo(1)
foo(1, null) # Équivalent
fun foo(a: Int..., b: nullable Int) do end
foo(1) # Erreur: 2 arguments minimum
foo(1, 2) # OK
foo([1]..., 2) # Équivalent
= et, est donc obligatoire)fun foo=(a, b: nullable Int) do ...
foo = 1
foo(null) = 1 # Équivalent
fun foo(a,b: nullable Int) do ...
foo(b=1)
foo(null,1) # Équivalent
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.
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:
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.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 interneLes 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
withDe 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.
with statement 90df56fLe 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.
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.
De grosses améliorations sur la gestion des erreurs et la robustesse.
Un travail systématique a eu lieu pour uniformiser et améliorer les messages d'erreurs.
En particulier, de nouveaux cas d'erreurs sont maintenant signalés
Un des plus vieux bugs qui concerne le typage adaptatif dans le cadre des boucles est enfin résolu!
Amélioration de la robustesse des outils et du code généré (FIXME et TODO)
Étrangement, rien de nouveau niveau bibliothèques de base. Juste du FIXE et TODO.
Beaucoup plus de travail par contre au niveau de la FFI et de app.nit, en particulier le support OS X amélioré.
La ludification du développement de Nit continue avec de nouvelles fonctionnalités: http://nitlanguage.org/rpg/games/privat/nit
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).
Le travail de refactorisation et de modernisation de la nitdoc continue
En parallèle, le plug-in vim offre de nouvelles fonctionnalités de documentation intégrée.
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.
Divers:
nitpretty d6f7877Du 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)
Divers: