Les nouveautés de Tcl/Tk 8.6

GNU/Linux Magazine n° 165 | novembre 2013 | Gérard Sookahet
Creative Commons
  • Currently 0 out of 5 Stars.
0
Thank you for rating!
You have already rated this page, you can only rate it once!
Your rating has been changed, thanks for rating!
La version 8.6 de Tcl/Tk est sortie fin décembre 2012. Même après deux décennies d'existence, ce langage continue d'évoluer ... à son rythme. Si'l y a deux expressions à retenir parmi les nouveautés les plus visibles, ce sont: programmation orientée objet et stackless. Mais ce n'est pas tout !

1. Introduction

Inventé par John Ousterhout en 1988, Tcl/Tk est un langage de script (Tcl) associé à un toolkit IHM (Tk). Pour comprendre la syntaxe, il suffit de maîtriser 12 règles [DODECA]. Doté d'un compilateur de bytecode et d'un mécanisme de runtime avec un système de fichier virtuel dénommé Starkit [STARKIT], il a été Influencé à l'origine par les langages C, Lisp, Shell, Awk et par Hypercard pour Tk. Cependant il intègre au fur et à mesure les évolutions d'autres langages plus récents. La version 8.6 est le résultat de l'implémentation de 50 TIPs (Tcl Improvement Proposals - documents de projet d'amélioration). Hormis le support natif de la programmation orientée objet dans le noyau de Tcl, on note dans le catalogue des nouveautés une couche d'abstraction de base de données (Tcl Database Connectivity), la gestion des exceptions, le support de zlib dans le noyau, les coroutines et la refonte du mécanisme interne d'exécution (Non-Recursive-Engine) au niveau de la pile du langage C.

2. Installation de Tcl/Tk 8.6

Télécharger les fichiers tcl8.6.0-src.tar.gz et tk8.6.0-src.tar.gz sur : http://www.tcl.tk/software/tcltk/download.html

Et décompresser les deux archives :

tar -zxvf tcl8.6.0-src.tar.gz

tar -zxvf tk8.6.0-src.tar.gz

Ce qui va créer deux répertoires /tcl8.6.0 et /tk8.6.0.

Ensuite passons à la compilation en tenant compte des versions 64 bits:

cd ./tcl8.6.0/unix

./configure --prefix=/usr --mandir=/usr/share/man \

$([ $(uname -m) = x86_64 ] && echo --enable-64bit)

make

Si vous envisagez plus tard de compiler des extensions qui dépendent des sources, un passage par sed vous sera bien utile :

sed -e "s@^\(TCL_SRC_DIR='\).*@\1/usr/include'@" \

-e "/TCL_B/s@='\(-L\)\?.*unix@='\1/usr/lib@" \

-i tclConfig.sh

Et pour bien faire les choses en tant que root :

make install

make install-private-headers

ln -v -sf tclsh8.6 /usr/bin/tclsh

chmod -v 755 /usr/lib/libtcl8.6.so

Faisons de même pour Tk :

cd ../..

cd ./tk8.6.0/unix

./configure --prefix=/usr --mandir=/usr/share/man \

$([ $(uname -m) = x86_64 ] && echo --enable-64bit)

make

Ainsi que :

sed -e "s@^\(TCL_SRC_DIR='\).*@\1/usr/include'@" \

-e "/TCL_B/s@='\(-L\)\?.*unix@='\1/usr/lib@" \

-i tclConfig.sh

Pour parfaire l’installation, en tant que root :

make install

make install-private-headers

ln -v -sf wish8.6 /usr/bin/wish

chmod -v 755 /usr/lib/libtk8.6.so

Finalement faisons un test pour vérifier que la nouvelle version de Tcl /Tk est bien présente.

On lance l’interprète de commande en ligne tclsh :

% tclsh

% info patchlevel

8.6.0

On lance l’interprète de commande en ligne wish :

% wish

% pack [button .b -text [info patchlevel] -command exit]

3. Les nouveautés de Tcl 8.6

3.1 La programmation orientée objet

Le support natif de la programmation orientée objet (POO) avec Tcl/Tk est une très longue histoire. Les premières demandes remontent à 1993 ! Depuis, comme aucun consensus n'avait été trouvé, il a fleuri une dizaine d'extensions OO plus ou moins influencées par CLOS, Smalltalk ou C++ sans compter les implémentations personnelles qui ne servent que dans un seul code. Aujourd'hui avec Tcl/Tk 8.6, la POO est officialisée, standardisée et intégrée au cœur du langage. Il s'agit d'un modèle objet compact reposant sur les classes dont les caractéristiques principales sont :
- l'héritage simple et multiple

- les mixins,

- l'introspection d'objets et de classes.

La syntaxe choisie est la suivante :

Objet Méthode argument1 argument2 ....

C'est celle qui est déjà utilisée avec le toolkit Tk pour décrire les interfaces graphiques.

Voici un exemple simple :

oo::class create DistribuerCartes {

variable compteur

constructor {} {set compteur 0}

method donneCartes {{carte 1}} {

incr compteur

for {set i 0} {$i < $carte} {incr i} {

puts "Voici la carte n° $i pour le joueur $compteur"

}

}

}

set joueur [DistribuerCartes new]

$joueur donneCartes 3

Résultat :

Voici la carte n° 0 pour le joueur 1

Voici la carte n° 1 pour le joueur 1

Voici la carte n° 2 pour le joueur 1

Un exemple formel d’utilisation des mixins :

oo::class create Voiture {

method demarrer {} { .... }

method accelerer {} { .... }

method freiner {} { .... }

}

set voiture_lambda [Voiture new]

$voiture_lambda demarrer

oo::class create ObjetVolant {

method decollage {} { .... }

method prendreAltitude {} { .... }

method aterrissage {} { .... }

}

set voiture_fantomas [Voiture new]

oo::objdefine $voiture_fantomas mixin ObjetVolant

$voiture_fantomas demarrer

$voiture_fantomas decollage

Mots-clefs associés : oo::class, oo::define, oo::objdefine, oo::object, oo::copy, my, self, next.

Les classes, instances et méthodes sont aussi manipulables au niveau de l'API du langage C.

Dans la version antérieure de Tcl 8.5.x, la POO est disponible en tant que package (package require TclOO).

Et pour terminer, la POO est un plus mais pas une obligation. Si vous souhaitez persister dans la programmation procédurale, libre à vous.

3.2 Tcl Database Connectivity

TDBC (Tcl DataBase Connectivity) est une interface unifiée pour accéder aux bases de données SQL comprenant des pilotes pour SQLite, MySQL, PostgreSQL et ODBC.

Connection à une base SQLite3:

package require tdbc::sqlite3

tdbc::sqlite3::connection create db "/path/to/mydatabase.sqlite3"

Connection à une base MySQL:

package require tdbc::mysql tdbc::mysql::connection create db -user hal -passwd hal9000 \

-host 127.0.0.1 -database odyssey

Interrogation de la base:

set mot "Clark"

db foreach res { SELECT prenom FROM auteurs WHERE nom = :mot } {

puts "Résultat \"[dict get $res prenom]\" dans la table des auteurs"

}

A noter que Tcl est distribué avec l’extension SQLite3 prête à l’emploi.

Mots-clefs associés : tdbc::connection , tdbc::mapSqlState, tdbc::result-set, tdbc::statement, tdbc::tokenize, tdbc::mysql, tdbc::odbc, tdbc::postgres, tdbc::sqlite3.

3.3 Non-Recursive-Evaluation-Engine et coroutine

Quand une procédure s'appelle elle-même, la pile du langage C ressemble à un sandwich :

TEBC : TclExecuteByteCode() -> le compilateur de bytecode

TEOV : Tcl_EvalObjv() -> l'évaluateur de commande

TEBC : TclExecuteByteCode() -> le compilateur de bytecode

La récursion est donc très consommatrice pour la pile du langage C.
Dans la version 8.6, le mécanisme interne d'exécution a été complètement repensé afin de minimiser l'utilisation de la pile du langage C. Le fruit du travail de Miguel Sofer ouvre de nouveaux horizons à Tcl/Tk tels qu’une grande profondeur de récursion (limitée par la RAM), la récursion terminale, une meilleure gestion des exceptions, la continuation et un pas vers la programmation concurrente.

Voici une illustration de la récursion terminale (tailcall) avec la très emblématique procédure factorielle :

proc fact {n {k 1}} {

if {$n < 2} {return $k}

tailcall fact [expr {$n - 1}] [expr {$k * $n}]

}

Les maniaques de la monoligne peuvent toujours continuer à écrire ceci :

proc fact n {expr {$n < 2 ? 1: $n * [fact [incr n -1]]}}

Le seuil de récursion (limité à 1000 par défaut) est contrôlable avec la commande interp recursionlimit .

L'implémentation des coroutines est gérée par 4 nouvelles commandes: coroutine, yield, yieldto et info coroutine.

proc decompte n {

while {$n > 0} {

yield "Compteur: $n"

incr n -1

}

return "MISE A FEU !"

}

% coroutine fusee decompte 5

Compteur: 5

% fusee

Compteur: 4

% fusee

Compteur: 3

% fusee

Compteur: 2

% fusee

Compteur: 1

% fusee MISE A FEU !

Concernant la commande yieldto, elle peut être utilisée pour transférer le contrôle d’une coroutine à une autre.

3.4 La gestion des exceptions

Tcl disposait déjà d'une commande pour gérer les erreurs avec catch. Pour plus de clarté try/trap/finally vient la compléter. Il s'agit d'une syntaxe plus familière que l'on retrouve dans d’autres langages.

proc division {x y} {

try {

puts "Résultat de la division : $x/$y=[expr {$x/$y}]"

} trap {ARITH DIVZERO} msg {

puts "Division par zéro impossible : $msg"

} trap {ARITH DOMAIN} msg {

puts "En dehors du domaine de validité : $msg"

} on error msg {

puts "Autre erreur : $msg"

}

}

# Test

foreach {x y} {16 4 16 0 16.0 0.0 0 0 0.0 0.0 0 coin} {division $x $y}

qui donne ceci :

Résultat de la division : 16/4=4

Division par zéro impossible : 16/0 -> divide by zero

Résultat de la division : 16.0/0.0=Inf

Division par zéro impossible : 0/0 -> divide by zero

En dehors du domaine de validité : 0.0/0.0 -> domain error: argument not in valid range

Autre erreur : 0/coin -> can't use non-numeric string as operand of "/"

Un autre exemple avec la gestion de l'ouverture d'un fichier :

try {

set f [open /usr/bin/tempo]

} trap {POSIX EISDIR} {} {

puts "Impossible d'ouvrir /usr/bin/tempo: c'est un répertoire"

} trap {POSIX ENOENT} {} {

puts "Impossible d'ouvrir /usr/bin/tempo: il n'existe pas"

} finally {

close $f

}

Le contenu de la clause finally sera exécuté dans tous les cas.

3.5 La compression et l’encodage

3.5.1 La compression zlib dans le noyau

La commande zlib permet la compression/décompression de données et de flux ainsi que le check-summing. Elle est basée sur la bibliothèque Zlib [ZLIB] de Jean-Loup Gailly et Mark Adler.

La compression d’un fichier au format gzip :

set file test.txt

set fi [open $file rb]

set header [dict create filename $file time [file mtime $file] comment "Test gzip"]

set fo [zlib push gzip [open $file.gz wb] -header $header]

fcopy $fi $fo

close $fi

close $fo

Le calcul d’un CRC32 :

% set a [format %x [expr {[zlib crc32 GNULinuxMag 42] & 0xffffffff}]]

% 5258be05

3.5.2 Encodage et décodage de séquences binaires

Les sous-commandes binary encode/decode permettent l’encodage et le décodage des séquences binaires. Les formats supportés sont base64, hex et uuencode.

Encodage en paire hexadécimale d’un chaîne de caractère :

% binary encode hex "GNU Linux Magazine"

% 474e55204c696e7578204d6167617a696e65

Encodage d’un fichier binaire en base 64 avec un formatage 64 caractères par ligne :

set f (open fichier.bin rb]

set data [read $f]

close $f

puts [binary encode base64 -maxlen 64 $data]

3.6 Les listes et chaînes de caractères

3.6.1 Les listes

Dans le tri des listes avec la commande lsort, l'option -stride permet de trier des éléments groupés.

lsort -stride 2 {slackware 10 ubuntu 24 redhat 32 debian 16 suse 28}

Et renverra :

debian 16 redhat 32 suse 28 slackware 10 ubuntu 24

En effet, le tri est effectué par groupe de deux en prenant comme référence par défaut le 1er élément de chaque groupe. Pour faire un tri selon le second élément il suffit de le mentionner avec l'option -index (qui commence à 0) :

lsort -stride 2 -index 1 {slackware 10 ubuntu 24 redhat 32 debian 16 suse 28}

Qui renvoit cette fois-ci :

slackware 10 debian 16 ubuntu 24 suse 28 redhat 32

Pour la recherche dans une liste déjà triée avec la commande lsearch, l’option -bisect permet de trouver le point d’insertion d’un nouvel élément. Cette situation se présente lors d’une interpolation ou une approximation dans une table de données.

Dans l’exemple ci-dessous, le point d’insertion de 6 se trouve après le 3ième élément (la numérotation des listes commence à zéro) :

% lsearch -sorted -bisect {1 3 5 7 9 11} 6

% 2

La commande lmap permet de parcourir tous les éléments d'une liste ou plusieurs listes en y effectuant des modifications. Elle remplace avantageusement une boucle foreach sur les éléments de la liste.

set l [list 1 2 3 4 5 6 7 8 9]

set lc [lmap x $l {expr {$x**2}}]

lmap s'utilise aussi avec plusieurs listes :

set lx [list 1 2 3 4 5 6 7 8 9]

set ly [list 9 8 7 6 5 4]

set lc [lmap x $lx y $ly {expr {$x**2}} {expr {$y**3}}]

Remarquons que si les listes ne sont pas de la même longueur, des éléments vides seront créés pour la compléter la plus courte.

Une astuce pour trouver les éléments non-communs à deux listes (différence symétrique) :

set l [lmap x $lx {if {$x in $ly} continue}]

3.6.2 Les dictionnaires

Il y a deux nouveautés à ajouter aux dictionnaires. Ce sont dict map et dict filter.

A l’instar de lmap, la sous-commande dict map réalise le même type d’opérations pour les dictionnaires :

set d [dict create a 1 b 2 c 3 d 4 e AAA]

set r [dict map {key value} $d {

try {

expr {$value**2}

} on error {} {

continue

}

}]

Dans l’exemple ci-dessus, on évite les valeurs non-numériques en gérant les exceptions.

Quant à la sous-commande dict filter, elle retourne un sous-ensemble d’un dictionnaire selon une règle de filtrage des données. Le filtrage peut porter sur la clef, la valeur ou les deux.

# Création d’un dictionnaire avec des types de fichier

set type [dict create .jpg "image" .jpeg "image" .html "texte" .txt "texte" mp3 "son" .gif "image" .mp4 "video"]

Filtre sur la valeur :

set flt1 [dict filter $type value {ima*}]

Filtre sur la clef :

set flt2 [dict filter $type key {.jp*}]

Filtre sur la clef ou sur la valeur :

set flt3 [dict filter $type script {key value} {expr {$key eq "mp4" || $value eq "video"}}]

3.7 Les canaux

3.7.1 Fermeture des canaux bidirectionnels

La commande close permet de fermer un canal correspondant à l’ouverture d’un fichier ou d’un socket. Dans le cas où le canal est bidirectionnel, on peut le fermer en écriture ( w ) ou en lecture ( r ).

La syntaxe est la suivante :

close canal r | w

Sans les options r | w le canal est fermé totalement.

3.7.2 Les canaux virtuels

La commande chan push permet d’attacher une transformation particulière à un canal.

La syntaxe est la suivante :

chan push canal [transformation]

transformation est une procédure à écrire prenant en charge la transformation du flux de données qui transitera par le canal.

A titre d’exemple on pourrait crypter la sortie standard en faisant :

chan push stdout [cryptage]

Et pour revenir à l’état précédent :

chan pop stdout

On peut empiler plusieurs transformations avec chan push (stacked channel). La commande chan pop dépilera alors la dernière transformation. C’est à dire celle qui se trouve au sommet de la pile. Si aucune transformation n’est présente, cela revient à fermer le canal.

Avant la version 8.6, ces fonctionnalités n’étaient disponibles qu’avec l’API du langage C (Tcl_StackChannel, Tcl_UnstackChannel, Tcl_GetStackedChannel, Tcl_GetTopChannel).

3.8 Autres nouveautés de Tcl 8.6

- Des commandes acceptent zéro arguments sans broncher : file delete, file mkdir, glob, global, lassign,linsert, lrepeat, namespace upvar, tcl::tm::path add, tcl::tm::path remove et variable

- A partir de Tcl 8.6, la version avec thread devient la version par défaut. Plus besoin de la compiler spécialement.

Le support du protocol IPV6 pour être à la page :

- La gestion des fichiers temporaires avec file tempfile,

- Un contrôle plus fin du chargement des bibliothèques avec la commande load -global et -lazy,

- Une nouvelle variable intéressante si vous faites de la programmation multiplate-forme : tcl_platform(pathSeparator) détermine le caractère qui sert de séparateur dans le PATH.

(La liste de toutes les variables s’obtient en faisant parray tcl_platform).

Notons aussi une dizaine de nouveautés concernant l’API C qui n’ont pas été abordées dans cet article.

4. Les nouveautés de Tk 8.6

Les nouveautés sont plus modestes pour le toolkit Tk sachant que la majeure partie du travail de cette version 8.6 s’est concentrée sur Tcl.

4.1 Les nouvelles options du widget canvas

4.1.1 Le texte en oblique

Le widget canvas (conteneur d’objets graphiques) autorise l’affichage de texte en oblique selon un angle en degré :

pack [canvas .c -bg white]

foreach theta {10 20 30 40 50 60 70 80} {

.c create text 140 140 -text "GNU Linux Magazine" -font {Arial 14} -angle $theta

}

4.1.2 Le déplacement d’objets graphiques

Le déplacement absolu d'objets dans le widget canvas se fait avec la commande canvas moveto.

Les objets du canvas sont déplacés par rapport à l’origine du repère orthonormal (coin en haut à gauche) et non pas par rapport aux dernières coordonnées de l’objet (ce que fait canvas move).

Déplacement en diagonal d’un carré orange de 60x60 pixels :

pack [canvas .c]

set carre [.c create rect 20 20 80 80 -fill orange]

for {set i 20} {$i <= 120} {incr i 2} {.c moveto $carre $i $i}

Le déplacement de noeuds avec canvas imove (espérons que le terme imove n’ait pas été déposé par la firme à la pomme !).

Dans cet exemple avec canvas imove, on déplace le 2nd nœud d’un quadrilatère orange qui passe des coordonnées (60,180) à (60,120). La numérotation des nœuds va de 0 à n-1.

pack [canvas .c]

set poly [.c create polygon 60 60 60 180 120 240 240 120 -fill orange]

.c imove $poly 1 60 120

4.1.3 La substitution de texte ou de noeuds

La sous-commande canvas rchars permet de substituer du texte pour un objet text ou de substituer des coordonnées pour un objet graphique possédant des nœuds (line, polygon ).

Dans ce premier exemple, on substitue les trois lettres du mot GNU au mot NEW. L’indice des lettres variant de 0 à n-1.

pack [canvas .c]

set text [.c create text 140 140 -text "GNU Linux Magazine" -font {Arial 14}]

.c rchars $text 0 2 NEW

Dans ce second exemple, on modifie les coordonnées du troisième nœud (180,120) dans une courbe de Bézier :

pack [canvas .c]

set bz [.c create line 60 180 120 60 180 120 240 60 300 180 -smooth 1]

.c rchars $bz 4 5 {180 180}

Une courbe de Bézier s’obtient à partir d’un objet line ou polygon auquel on applique l’option -smooth.

4.2 Tk busy pour geler une fenêtre

La commande tk busy permet de suspendre l'interactivité d'une fenêtre si besoin durant un traitement. Ce qui signifie que le clavier, les boutons et le curseur de la souris sont inactifs sur la fenêtre en question. Le curseur peut être remplacé par un sablier ou une montre.

Pour neutraliser tous les widgets d’une fenêtre, il suffit d’appliquer tk busy au widget le plus haut dans la hiérarchie :

frame .top

entry .top.e1

button .top.b1 -text Run -command Run

button .top.b2 -text Exit

pack .top.e1 .top.b1 .top.b2

pack .top

proc Run {} {

tk busy hold .top ;# Suspension de l’interactivité

update

tk busy configure .top -cursor "watch"

...

# Phase de traitement

...

tk busy forget .top ;# On redonne la main

}

4.3 Le format d'image PNG et les couleurs du Web

Tk supporte nativement le format PNG en lecture/écriture avec le contrôle de la transparence (canal alpha).

Pour afficher une image au format PNG avec une transparence de 0.6 :

set photo [image create photo -file monimage.png -format "png -alpha 0.6"]

pack [label .l -image $photo]

Les noms des couleurs dans Tk ont été redéfinis pour suivre les standards du Web (html,CSS) au lieu de ceux de X11. Ainsi les couleurs gray/grey, green, maroon et purple auront un rendu plus sombre [CLR].

De même, les couleurs aqua, crimson, fuchsia, indigo, lime, olive, silver et teal ont été ajoutées à la liste des noms de couleurs reconnus.

4.4 Autres nouveautés de Tk

- Un nouveau sélecteur de fonte tk fontchooser qui fournit une interface portable au sélecteur de fonte de la plate-forme, qu'il soit modal ou non.

- La modernisation des menus déroulants en cascade sous X11.

- Un changement de la gestion de l'événement qui est actif dès que la souris est sur une fenêtre.

5. Nouveautés plus générales

5.1 Tcllib et Tklib les deux bibliothèques standards

Les deux bibliothèques standards, Tcllib [TCLLIB] et Tklib [TKLIB], continuent de s'étoffer fortes respectivement de 400 packages répartis dans 110 modules et de 75 packages répartis dans 27 modules. Entrer dans le détail nécessiterait un autre article mais sachez que ces packages couvrent la cryptographie, les mathématiques, différents protocoles de communication, des utilitaires de texte ou de fichiers, des structures de données complexes, la représentation graphique de données, de diagrammes et de tableaux.

Par exemple :

Une fonction de hashage.

% package require sha256

% sha2::sha256 "GNU Linux Magazine"

% 2dbfbd7d9588ce0bf0035b7414f879921b0c282bb390352e69e213531ee5072c

L’algorithme phonétique d’indexation soundex.

% package require soundex

% foreach s {concert cancer conforté confronté} {puts [::soundex::knuth $s]}

C526

C526

C516

C516

Le tracé d’un graphique 2D.

package require Plotchart

pack [canvas .c -bg white -width 400 -height 320]

set pi 3.1415926

set p [::Plotchart::createXYPlot .c {0 12 2} {-1 1 0.25}]

$p background gradient green top-down

$p dataconfig voltage -filled up -fillcolour white -color green

$p ytext "(V)"

$p xconfig -ticklength 20 -format %.3f

$p yconfig -ticklength 20 -minorticks 4 -labeloffset 10

for {set i 0} {$i < 100} {incr i} {

set phase [expr {2.0*$pi*$i/50.0}]

$p plot voltage $phase [expr {0.9*cos($phase)*sin(2*$phase)}]

}

5.2 Les commandes dissimulées du namespace tcl::unsupported

Le namespace tcl::unsupported contient des commandes expérimentales susceptibles d'être intégrées dans une prochaine version de Tcl.

tcl::unsupported::assemble :
Comme pour la plupart des langages dynamiques, Tcl compile les programmes dans un code intermédiaire (bytecode) qui est ensuite exécuté par l’interpréteur. Il est donc envisageable d’écrire du code Tcl directement dans l’assembleur du bytecode qui gère une pile de donnée.

Un exemple avec ce code classique qui calcule les nombres de Fibonacci :

proc tcl::mathfunc::fib n {expr {$n < 2 ? $n : fib($n-1) + fib($n-2)}}

Ce qui nous donne dans l’assembleur du bytecode :

proc fib n {

::tcl::unsupported::assemble {

load n ;# n

dup ;# n n

push 1 ;# n n 1

gt ;# n n>1

jumpFalse done ;# n

push 1 ;# n 1

sub ;# n-1

push fib ;# n-1 fib

dup ;# n-1 fib fib

over 2 ;# n-1 fib fib n-1

invokeStk 2 ;# n-1 fib fib(n-1)

reverse 3 ;# fib(n-1) fib n-1

push 1 ;# fib(n-1) fib n-1 1

sub ;# fib(n-1) fib n-2

invokeStk 2 ;# fib(n-1) fib(n-2)

add ;# fib(n)

label done ;# result

}

}

L’état de la pile est décrite après le symbole # en commentaire. Certaines mnémoniques rappellent les instructions du langage Forth ou Postscript.

Le gain en vitesse est de l’ordre de 30 % à 40 %. Mais c’est encore très expérimental ! Ce qui signifie que l’on n'est pas à l’abri d’un plantage de la machine virtuelle !
tcl::unsupported::disassemble :Il désassemble le bytecode des commandes, des expressions lambda, des scripts, des méthodes ou des objets :

proc add {a b} {

return [expr {$a + $b}]

}

% tcl::unsupported::disassemble proc add

ByteCode 0x011CA980, refCt 1, epoch 5, interp 0x00835EA0 (epoch 5)

Source "\n return [expr {$a + $b}]\n"

Cmds 2, src 26, inst 7, litObjs 0, aux 0, stkDepth 2, code/src 0.00

Proc 0x011CE4C0, refCt 1, args 2, compiled locals 2

slot 0, scalar, arg, "a"

slot 1, scalar, arg, "b" Commands 2:

1: pc 0-5, src 2-24 2: pc 0-4, src 10-23

Command 1: "return [expr {$a + $b}]"

Command 2: "expr {$a + $b}"

[0] loadScalar1 %v0 # var "a"

[2] loadScalar1 %v1 # var "b"

[4] add

[5] done

[6] done

Le code désassemblé ne correspond pas pour le moment au code de l’assembleur !
tcl::unsupported::representation : Il décrit la représentation interne d’une donnée :

% tcl::unsupported::representation 7

value is a pure string with a refcount of 3, object pointer at 011FB620, string representation "7".

% set a "Linux"

% tcl::unsupported::representation $a

value is a pure string with a refcount of 4, object pointer at 011F7A40, string representation "Linux".

% tcl::unsupported::representation [list 2 4 8 16]

value is a list with a refcount of 1, object pointer at 0104E588, internal representation 01205350:00000000, no string representation.

tcl::unsupported::inject : Cette commande permet d’injecter un code dans une coroutine pendant qu’elle est suspendue à des fins de débogage par exemple.

5.3 Migration de l’infrastructure de développement

Le développement de Tcl/Tk migre de CVS vers Fossil [FOSSIL], un logiciel de gestion de version développé par D. Richard Hipp (le créateur de SQLite).

Par exemple, pour cloner le code source de Tcl-Tk :

% fossil clone http://core.tcl.tk/tcl/ tcl.fossil

% fossil clone http://core.tcl.tk/tk/ tk.fossil

6. Tcl/Tk 9 pour la suite ?

Eh bien la suite sera Tcl/Tk 9 dont le développement a déjà commencé depuis le début de l'année. A l'instar de Perl 6 ou Python 3, il faut s'attendre à une rupture de la rétro-compatibilité. Surtout au niveau de l'API du langage C. Cependant elle ne sera pas radicale car cela reste un facteur important pour les développeurs. Mais ce ne sera plus le facteur le plus important.

Il faut s'attendre également à une sérieuse amélioration du rendu de Tk dont l'aspect ne correspond plus tellement aux canons esthétiques actuels. Tk tiendra d'autant plus compte du côté tactile des récentes interfaces graphiques.

Conclusion

Tcl/Tk continu d'évoluer à son rythme et s'apprête à fêter dignement ses 25 ans en 2013. On peut s’étonner du rythme très espacé des versions. Mais après un quart de siècle (ce qui est un temps très long en informatique!), on aspire à plus de stabilité.

Le principal intérêt pour migrer vers Tcl/Tk 8.6 est l’officialisation de la POO. Mais au-delà, les coroutines nous font envisager d’autres niveaux de programmation.

Ce langage stable bénéficie toujours d'une base d'utilisateurs et de contributeurs fidèles tant auprès des développeurs professionnels que des amateurs.

Pour en savoir plus dans le détail sur toutes ces nouveautés, n’oubliez pas de lire le manuel [MAN].

Références

[CLR] http://en.wikipedia.org/wiki/X11_color_names#Color_name_clashes

[DODECA] http://www.tcl.tk/man/tcl/TclCmd/Tcl.htm

[FOSSIL] http://www.fossil-scm.org/

[MAN] http://www.tcl.tk/man/tcl8.6/

[STARKIT] Découvrez Tclkit, les starkits et les starpacks, GNU Linux Magazine France n°60, Avril 2004, pp66-69.

[TCLLIB] http://core.tcl.tk/tcllib/home

[TKLIB] http://core.tcl.tk/tklib/home

[ZLIB] http://www.zlib.net/