[Nitération 11] Nouvelles d'octobre

14 views
Skip to first unread message

Jean Privat

unread,
Nov 1, 2014, 10:35:32 AM11/1/14
to nit...@googlegroups.com

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

Les statistiques combinées pour le mois d'octobre donnent:

$ git diff --shortstat v0.6.9..v0.6.10
 451 files changed, 16531 insertions(+), 3653 deletions(-)
$ git log --first-parent v0.6.9..v0.6.10 | grep 'Pull-Request: #' | wc -l
47

Ont contribué (ou ont eu des patchs intégrés): Jean Privat, Alexis Laferrière, Lucas Bajolet, Jean-Christophe Beaupré.

Encore une barrière psychologique de tombée : plus de 500 PR ont été acceptées dans le dépôt principal.

Des outils Nit pour le monde réel

Scriptage

Nit est syntaxiquement proche du langage de script Ruby, qui est lui-même proche de Perl qui est lui-même proche des outils systèmes shells, sed et awk.

En particulier, le shebang d'indication d'interpréteur fonctionne depuis longtemps et quelques-uns utilisent Nit pour leurs scripts de tous les jours.

#!/usr/bin/env nit
print "Hello World!"

Afin d'améliorer la scriptabilité du langage, l'interpréteur accepte désormais des options habituels des interpréteurs de scripts Unix.0d4de25

L'option -e permet d’interpréter un programme directement passé en argument.

$ nit -e 'print 5+5'
10

L'option -n permet d'itérer sur chaque ligne de l'entrée. Dans le programme, la ligne s’appelle sys.line au lieu de $_ en Perl ou Ruby mais c'est à peu près la seule différence.

$ echo "hello world" | nit -n -e 'print sys.line.capitalized'
Hello World

Là où cela devient intéressant est que l'option -n est implémentée directement dans la bibliothèque (niti_runtime.nit) grâce au raffinement des services de base, et non en dur dans l'interpréteur.

Lignes de produits

L'option --define (ou -D) a également été introduite dans l'interpréteur et le compilateur. Cette option permet de raffiner des méthodes directement dans la ligne de commande. Cela permet de fixer certains paramètres et comportements lors de la compilation sans avoir à créer de bottom-module quasi-vides. ff3bde9

$ nitg foo.nit -D prefix=/opt/nit/

Grace au typage statique, l'existence de la méthode désignée par -D et sa signature sont vérifiées, ce qui rend l'usage de l'option robuste. D'ailleurs, la valeur de l'option est interprétée en fonction du type de retour de la méthode. Actuellement, seul String, Int et Bool sont acceptés mais cela devrait représenter la grande majorité des cas d'utilisations.

module foo
fun str: String do return "test"
fun num: Int do return 1
fun flag: Bool do return false
print str
print num
print flag
$ nitg foo.nit
$ ./foo
test
1
false
$ nitg foo.nit -D str=hello -D num=42 -D flag
$ ./foo
hello
42
true

Distribution de programmes

Comment distribuer des programmes Nit ? Sur de nombreux systèmes, comme Android, distribuer un programme compilé ne pose pas de problème. Dans le monde UNIX, l'hétérogénéité des architectures fait qu'il est souvent plus simple de distribuer le code source.

Or, aussi incroyable que cela puisse sembler, Nit n'est pas disponible sur tous les ordinateurs.

La solution de rechange consiste alors à distribuer le code C qui sert déjà de langage intermédiaire dans notre chaîne de compilation. C'est ce qui est fait dans le répertoire c_src du projet qui contient de quoi bootstrapper les outils mais qui est en réalité issu du code C d'une compilation précédente et nettoyé (cf. le script mkcsrc).

L'idée est de généraliser l'approche pour permettre de produire du code C autonome et distribuable à partir de n'importe quel compilation. Ce qui permet alors de distribuer directement le répertoire de compilation. 98e5400

Avec les bonnes options, un le compilateur Nit peut produire un répertoire de compilation distribuable tel quel.

$ nitg examples/hello_world.nit --semi-global --no-cc --dir hello --compile-dir hello
  • --semi-global pour réduire la taille du code C et optimiser un peu
  • --no-cc pour ne pas lancer la compilation du C
  • --dir hello pour placer le futur binaire dans le répertoire hello
  • --compile-dir hello pour placer les fichiers C également dans hello

Ensuite, le diffuseur distribue le répertoire hello (dans un tarball par exemple). L'utilisateur final n'a alors qu'à décompresser et lancer le make pour avoir son exécutable.

$ cd toto
$ make
[...]
$ ./hello_world
Hello, World!

Nouveautés dans le langage

Varargs

Les fonctions variadiques (varargs) acceptent maintenant qu'on leur donnent un tableau déjà constitué (reverse-vararg). 5121228

Afin d'éviter d'éventuelles ambiguïtés, une syntaxe particulière avec une ellipse est utilisée.

fun foo(a: Int...) do print a.join(":")
foo(1,2,3) # => "1:2:3"
var a = [4,5,6]
foo(a...)  # => "4:5:6"

La PR en profite également pour nettoyer et simplifier la façon dont les varargs sont gérées par les moteurs.

Attributs initialisés avec un bloc

Les attributs acceptent une syntaxe additionnelle, proche de celle de méthodes, pour leur valeur initiale. 070e1b0

class A
   var toto: String do
      var res = "hello"
      res += ", world!"
      return res
   end
end

Cela est surtout utile dans le cas des attributs lazy dont la valeur est calculée seulement au premier accès (et non lors de l’instanciation).

class B
   var toto: String = ""
   var tata: String is lazy do
      var t = toto
      if t == "" then return "Hello!"
      return "Hello, {t}!"
   end
end
var b = new B
print b.tata # => "Hello!"
var b2 = new B
b2.toto = "World"
print b2.tata # => "Hello, World!"

Attributs autoinit

Pour rappel, l'annotation autoinit permet d'indiquer que certaines méthodes doivent être invoquées automatiquement pendant la phase des initialiseurs lors de la construction.

L'annotation a été étendue aux attributs pour indiquer que la valeur initiale doit être également évaluée pendant la phase des initialiseurs, et non au début de l’instanciation comme cela est fait par défaut. afceecb

L’intérêt de retarder l'évaluation de la valeur initiale apparaît lorsque la valeur dépend d'autres initialiseurs.

class A
   var toto: String
   var tata: String = toto + ", World!" is autoinit
end
var a = new A("Hello")
print a.tata # => "Hello, World!"

Sans le autoinit, le new A aurait échoué car au moment de l'initialisation de tatatoto aurait été non-initialisé.

Alternativement, le programmeur aurait pu choisir l'annotation lazy, voire noinit et effectuer l'affectation lui-même (dans le initpar exemple).

Au final, l’intérêt de l'annotation reste douteux mais l'implémentation fut triviale et un bon prétexte pour nettoyer le code. On verra si les gens l'utilisent...

new-factory

Les fabriques new, introduites pour la FFI puis utilisées pour certaines classes internes, ont été généralisées. e71e1df

Les méthodes introduites par le mot clé new (à la place de fun ou init) sont définies dans des classes mais se comportent comme des méthodes top-level (statiques). Elle servent à retournent des instances construites à la main.

L’intérêt est de pouvoir court-circuiter le mécanisme d’instanciation normal via une sorte de sucre syntaxique.

Cela permet aussi de fournir des pseudo-constructeurs aux interfaces et classes abstraites qui peuvent choisir parmi leurs sous-classes laquelle est la plus intéressante à instancier réellement.

Cela permet au final d'encapsuler davantage de détails, à la grande joie des concepteurs d'API.

abstract class Personne
   new(age: Int) do
      if age >= 18 then
         return new Adulte(age)
      else
         return new Enfant(age)
      end
   end
end

Toujours dans les constructeurs, la page de la manuel qui les concerne a commencé à être réécrite.

Retours multiples

Rien n'est codé encore, mais une excellente discussion sur la bonne syntaxe à utiliser s'est déroulé sur github.

Le problème semble ne pas avoir de solution parfaite. Il faut donc réussir à trouver la meilleure solution imparfaite.

Nouveautés dans les bibliothèques

Threads

Nouvelle bibliothèque pthreads de manipulation des threads POSIX en Nit. 35d9538

Elle permet de créer de façon simple des threads, des mutex et des barrières. Le programmeur est toutefois responsable de la validité et de la cohérence de ses programmes car les bibliothèques de Nit ne sont pas thread safe.

Pour limiter le problème, deux façons de gérer des collections synchronisées sont offertes : une par spécialisation (proxy) et une par raffinement.

Toutefois, l'absence volontaire de variable globale dans le langage limite généralement les problèmes de synchronisation aux objets que le programmeur partage volontairement entre plusieurs threads.

Saxophonit

Afin de s'inter-connecter avec les technologies des années 2000, Nit acquiert enfin un parseur XML. Et pas des moindres vu qu'il s'agit d'un parseur SAX, subtilement nommé saxophonitcdd10a3

Comparator

La classe Comparator et ses sous-classes laissent tomber leurs paramètres formels au profit d'un type virtuel. 6a72930

Cela permet de résoudre les problèmes de contravariance et rend au final le code plus lisible et plus robuste qu'il ne l'était avant.

Finish

Un nouveau service finish a été introduit dans les itérateurs. b2e361b

Il permet aux boucles for d'informer l'itérateur que le travail est terminé (par exemple parce-qu'il a été interrompu par un break) ce qui permet à l'itérateur de libérer d'éventuelles ressources.

Divers

Nouveau module push-back reader qui propose des flots en lecture avec remise. C'est toujours utile. 04f4deb

Ajout de la fonction Int::bin_not dans lib/math. 4b62a1a

Le module console gagne une nouvelle API plus robuste pour les couleurs. 0146538

Nettoyage du répertoire examples. De nombreux fichiers sont déplacés dans un sous-répertoire de leur bibliothèques respective. Cela donne le sentiment que les choses sont mieux rangées. d65a790

Programmes, Produits, Outils, Exemples

Opportunity

Un nouveau programme, opportunity, propose une alternative aux doodle et framadate de ce monde. 323e292c591913 et8894e31.

Du travail reste à faire mais c'est une nouvelle preuve de concept de programme complet en Nit. Les technologies Nit utilisées sont les bibliothèques nitcorn (serveur web), sqlite3 (base de données) et template (patrons de pages).

Le service est publiquement accessible (quand il n'est pas en maintenance).

Tests de régression massivement parallèles.

Les tests de régression de Nit ne sont pas des blagues : plus de 4h sur notre serveur jenkins qui teste des milliers de programmes les uns à la suite des autres.

D'où l'idée de tester les programmes en parallèle pour gagner du temps.

Le nouveau programme nitester utilise la bibliothèque Nit openmpi pour distribuer les tests sur les noeuds d'un cluster.

Pour le cluster turing de l'UQAM, quelques 9000 tests se déroulent en moins de 3 minutes si l'on répartit les taches sur les 120 processeurs disponibles. C'est impressionnant vu que plus de 2h sont nécessaires si un seul processeur est utilisé.

Il reste encore un peu de travail de finition pour profiter de cette nouvelle infrastructure directement dans les jobs du serveur d'intégration.

Brainfuck

Quoi de mieux qu'un interpréteur brainfuck pour valider l'expressivité d'un langage? 4d482e6

Plein de choses en fait...

Outils Nit

Un nouveau warning détecte les comparaisons inutiles à null894c39e

Les outils gagnent des pages de manuel. Pour l'instant il n'y a pas grand chose d’intéressant mais cela devrait s'améliorer avec un peu d'effort. d7a953d

Le débogueur devient plus robuste et amical. Peut-être un jour il sera même rapide... 8ab2093

Un bug dans nitlight a été identifié et contourné. Le service http://nitlanguage.org/code/ est maintenant rétabli. dcf6b2f

Rosetta Code

Le projet Rosetta Code propose de répertorier, pour plus de 700 taches, les meilleurs implémentations naturelles dans plus de500 langages de programmation.

Pour le langage Nit, tenter de résoudre ces tâches est un bon exercice de mesure de l'expressivité du langage.

C'est aussi de la programmation facile à donner à réaliser à un débutant en Nit, ou à un expert désœuvré.

Enfin, c'est un bon moyen de documentation du langage par l'exemple.

Une première brique a été posé par la réalisation de 12 premières taches. a97e7e7

Sous le capot

Du nettoyage de code (c'est toujours bien). e43a2bf et 2e2b3f3

De l’extension de grammaire pour préparer les fabrique new, les retours multiples et les attributs initialisés avec un bloc. (voir au dessus.) e1e9193

transform sait enfin transformer les boucles complexes (while et for) en des boucles plus simples (loop). Cela permettra de simplifier les moteurs voire d'ajouter un jour des phases d'optimisation de haut niveau. 380d220

Le compilateur primitif c_src a été regénéré. La dernière génération datait de fin juillet. Cela permettra à la bibliothèque standard et aux outils de profiter des nouveautés du langage de ces trois derniers mois, en particulier les nouveaux constructeurs. 84a38b0

Correction de bogues divers

  • Merge: nitunit: accept an absolute path for --dir.. e527858
  • Merge: Can refine inits. 89060e2
  • Merge: Fix test of for abuse. 97b5433
  • Merge: tests: detect and use portable time and date command. 25cb999
  • Merge: console: use snake case.. c446ed4
  • Merge: file: Fix join_path to handle paths ending with a slash.. db10c01
  • Merge: Small compiler things. 93e91cb
  • Merge: neo: correct the documentation of neo.nit according to PR #781.. 63a6c01
  • Merge: Fix the old bug where (-0.1).to_s == "0.-1". 817b1ed
  • Merge: neo: Add MAttributeDef.static_type in the graph.. 50e4753
  • Merge: model: better implementation of the two intro methods. db8e46c
  • Merge: neo: Fix definition lists. dcf916f
  • Merge: grammar: allow '`' inside foreign code blocks. 6c2cbe3
  • Merge: lib: fix semantic on has_substring on extreme cases. 4569405
  • Merge: neo4j: Implement missing methods in JsonArray54be77b
  • Merge: neo4j: Print an error message when the server is down. 0ada949
  • Merge: lib/android: hack to fix new_global_ref. 6310a16
Reply all
Reply to author
Forward
0 new messages