Langage W description

Le langage W est un langage procédural, à typage faible, mais avec des structures de données souples et puissantes.

Commentaires

Les commentaires sont écrits à la suite du caractère ; Il peut être soit tout seul sur une ligne, soit en fin de ligne après une instruction.
Les lignes vides sont considérées comme des commentaires.

; Premier commentaire
    ; autre commentaire
 
; c'est fini !

Structure d'un programme

Le langage W ne supporte qu'UNE seule instruction par ligne, exception faite du commentaire qui peut apparaître à la fin de la ligne, après l'instruction.
Un programme est constitué de l'instruction de début, du code avec le bloc de traitement et le bloc d'exception, et une instruction de fin.
Dans chaque ligne (= instruction), les différents éléments de l'instruction sont séparés par au moins un blanc (espace, tabulation). Les sauts de lignes acceptés sont ceux au format Unix et Windows, indifféremment.
Les commentaires peuvent être écrits partout comme indiqué ci-dessus.
Chaque programme peut appeler des sous-programmes, appelés sub, ainsi qu'un autre programme qui dans ce cas là s'appelle une library (ou bibliothèque).
La particularité du langage est que sa syntaxe impose un bloc de traitement et un bloc exception dans chaque programme et sous-programme.
Lors de l'exécution, toute exception provoque automatiquement le saut au début du bloc exception du programme ou sous-programme en cours. C'est l'équivalent d'un try/catch systématique.
Reprenons le classique Hello world :

hello.w
; exemple classique...
begin hello   ; instruction de début, marquant le début du bloc principal
   ; bloc de traitement
   echonl "Hello world !"    ; l'instruction echonl permet d'écrire dans la console, avec retour à la ligne
   ; ici, le traitement saute à la fin (end)
except        ; instruction marquant le début du bloc exception
   ; bloc exception
end           ; fin du programme hello

A l'exécution, le traitement démarre à l'instruction de début du bloc principal, puis exécute toutes les instructions jusqu'à l'instruction except. A ce moment là, le traitement passe directement à l'instruction de fin puis il se termine.
La deuxième instruction de début possible est background <nom> : le traitement fonctionne de manière identique à celle avec begin à la seule différence que le traitement s'exécute en tâche de fond, et donc qu'il rend la main immédiatement. Dans ce mode, toutes les écritures et lectures depuis la console sont automatiquement inhibées par l'exécuteur.
La troisième et dernière instruction de début possible est library <nom>(<parametres>). Elle permet au programme d'être appelé depuis n'importe quel autre programme ou library, mais la bibliothèque ne peut pas être le premier programme lancé. Lors de l'appel, le chargement de la bibliothèque se fait à la volée à l'exécution uniquement.

Include et appels externes

L'instruction include permet d'inclure un autre source dans le flux du source courant. La récursion n'est pas autorisée et provoquera une exception.
Le fichier source à inclure doit se trouver dans le répertoire WSRC.

include "calcul.w"

Les appels de bibliothèque et méthode se font avec les instructions do call invoke :

  • appel de bibliothèque, externe au source en cours : call <nom biblio>(param1, param2, …), bibliothèque écrite en W, bloc principal de type library, et disponible dans le répertoire WBIN en compilé ou WSRC en interprété
  • appel de module, type plugins : invoke <module>&<fonction>(parametre), écrits en C et dont le binaire se trouve dans WBIN
  • appel de sub/méthode d'objet : do <var>(param1, param2, …), écrits en W et déclarés dans le même source que le source courant (fichiers include compris)

Tous les passages de paramètres se font par référence : dans les sous-programmes appelées, les accès aux variables agissent sur la variable origine.

Types de données

Les variables se déclarent obligatoirement, mais sans type, et à n'importe quel endroit du code. Elle ne deviennent utilisable qu'à partir de leur déclaration, sous peine de déclencher une exception.

; declaration de 3 variables
declare x, y, tmp

Le typage de chaque variable se fait lors de leur affectation. Il existe 7 types utilisables :

  • Null : variable déclarée mais pas encore utilisée
  • Number : nombre en virgule fixe, 13 chiffres avant la virgule et 5 décimales
  • Dynamic : stockage de chaines de caractères, structurées, ou de tout contenu binaire
  • Hashtable : map de type clé/valeur, chaque valeur étant elle même une autre variable parmi les types de disponible, Hashtable comprise
  • Subroutine : mémorise l'adresse d'une sub
  • Object : identique à Hashtable et permet de stocker/gérer des classes et objets
  • Param : les paramètres passés aux sub étant tous par référence, chaque paramètre est de ce type, pointant sur la vraie variable : chaque action sur le paramètre agira en fait sur la variable passée en paramètre.

Un 8ème type, Buffer, sert uniquement en interne à l'exécuteur W (gestion de la pile d'expression et d'appel).

Portée

Les variables déclarées dans le bloc principal (begin/background) du programme ont une portée globale.
Les variables déclarées dans les bibliothèques (library) et sous-programmes (sub) ont une portée locale au sous-programme.
Les sub, classes et objets ont une portée globale, même si ils apparaissent dans un sous-programme (A Préciser quand créés depuis une librabry).
Les variables appartenant à une hashtable ne sont accessible que via la hashtable, sauf les classes et objets stockées globalement.

Utilisation

Les variables s'affectent avec l'instruction let. Il est possible de dés-affecter une variable avec l'instruction delet. Dans ce cas, la variable est supprimée et n'est plus déclarée. L'ajout de variables dans une Hashtable n'a pas besoin de déclaration, mais elles s'affectent et se dés-affectent comme les autres. La syntaxe à utiliser est <varht>.<membre>

declare h, n, d
let h = {}       ; h est une Hashtable
let n = -12.34   ; n est un Number
let d = "coucou" ; d est un Dynamic
 
; h va contenir 2 variables de type Number, x et y, qui ne se déclarent pas avec "declare"
let h.x = 10
let h.y = 20

Exceptions

Chaque programme et sous-programme contient obligatoirement une instruction except. Lorsque qu'une exception survient, l'exécuteur saute automatiquement au bloc exception, c'est à dire à la première instruction qui suit la ligne except.
Dans le bloc de traitement, il est possible de forcer la levée d'une exception avec l'instruction throw.
Dans le bloc exception, par défaut si rien n'est codé, l'exception se propage au programme appelant, et remonte ainsi jusqu'au programme principal. Dans ce cas, l'exception remonte un code exit au shell correspondant au code exception (en gérant le code retour sur 8 bits).
Toujours dans le bloc exception, il est possible d'annuler l'exception en cours par l'instruction catch : le programme sort immédiatement du bloc sans exception. Il est également possible de lever une autre exception avec l'instruction throw : le programme sort aussi immédiatement du bloc, avec le code exception indiqué dans throw.
Enfin, la variable système @except contient l'exception en cours et @exceptline donne le numéro de ligne du source qui a provoqué l'exception.
A tout moment, l'instruction return permet de sortir du bloc en cours, soit le bloc de traitement soit le bloc exception, sans changer les conditions de sortie (exception). Lorsque le bloc courant est le bloc principal, return provoque la fin du programme et le retour à l'appelant (le shell, etc.) avec comme retour le code exception courant (sur 8 bits), 0 si pas d'exception.
Exemple

begin test
   declare x
   let x = 10
   let y = 20             ; => déclenche une exception EX_NOVAR (variable "y" non déclarée)
   echonl "Non affiche"   ; cette ligne n'apparaîtra pas dans la console
except
   catch                  ; => sort du programme sans erreur
   echonl "Exception"     ; cette ligne n'apparaîtra pas dans la console
end

Liste des instructions

Par ordre alphabétique

Fonctionnement interne

Le code source W est compilé sous forme de p-code.
Ce p-code est une série d'instructions élémentaires spécifique au langage W.
C'est le même programme qui analyse le code source W et le découpe en instructions p-code :

  • en mode interprété, les instructions sont alors directement exécutées
  • en mode compilé, les instructions sont écrites dans le fichier assembleur de sortie. A la fin, ce fichier assembleur est converti en binaire, traduction numérique des instructions du p-code

L'exécuteur de p-code peut également être appelé depuis un autre traitement, le p-code servant de langage/bibliothèque de type plugins. Un module FastCGI fourni facilite l'utilisation du W comme langage serveur de sites Internet.
Le format binaire du p-code est en big-endian, ce qui permet à un même fichier binaire W d'être utilisé sur tout type d'OS et d'architecture.
Les expressions ne concernent que les variables de type Dynamic et Number, et sont gérées dans une pile en notation polonaise Inverse.

Liste des instructions du p-code W.

Règles de transformation du source W en p-code (assembleur W).


Outils pour utilisateurs