SNUSP

SNUSP (sigle signifiant SNUSP's Not Unix, but Structured PATH) est un langage de programmation exotique issu de la transformation du Brainfuck en un langage à deux dimensions, inspiré d'un langage appelé PATH[réf. nécessaire].

Le jeu d'instructions de SNUSP est plus proche du brainfuck que PATH, en conservant la même syntaxe pour les instructions relatives à la mémoire (+, -, > et <) et aux entrées/sorties (. et ,). Les instructions de contrôle de flot du brainfuck (] et [) sont remplacées par quatre instructions SNUSP nécessaires pour gérer le flot bidimensionnel : /, \, ? et !.

Fonctionnalités

Toutes les instructions sont représentées par un caractère non numérique.

L'exécution d'un programme SNUSP commence au caractère $, ou si absent du code source, au caractère le plus en haut et à gauche du programme, autrement dit le premier caractère du fichier. L'exécution commence vers la droite en ligne droite, un caractère à la fois, jusqu'à ce qu'une instruction de changement de direction modifie le flot d'exécution.

Les deux instructions de base du contrôle de flot, ruld (\) et lurd (/), provoquent un changement de direction de l'exécution par un virage à 90°. Ils peuvent être vus comme des miroirs. Comme en brainfuck, tous les caractères alphanumériques sont ignorés et peuvent être utilisés comme commentaires. En fait, les commentaires peuvent même contenir des instructions valides, du moment que le flot d'exécution n'y passe pas. L'ajout d'instructions valides dans les zones où le flot d'exécution ne passe pas permet d'écrire du code impénétrable. Dans l'exemple suivant, l'exécution commence au $ et suit le chemin tracé autour du commentaire.

De ce fait, le programme n'affichera rien, malgré la présence d'une instruction de sortie (.). Les caractères = et | sont ignorés lors de l'exécution et permettent au programmeur et à d'éventuels lecteurs de mieux suivre le flot d'exécution.

   /============#
   | Ceci est un
$==/ commentaire.

En plus des instructions de changement de direction du flot d'exécution, il existe une instruction de saut inconditionnel (!) qui permet d'ignorer le caractère suivant, et une instruction de saut conditionnel (?) qui ignore le caractère suivant si et seulement si la cellule de mémoire courante contient zéro.

Il est possible de créer des fonctions par les instructions enter (@) et leave (#):

$===avant====@\===après===#
              |
              \===la=fonction===#

L'instruction enter 'empile' (mémorise) sa position et la direction du flot d'exécution dans la pile d'appel. Cette information est utilisée par l'instruction leave, qui 'dépile' (reprend les dernières informations) la pile d'appel et revient à l'endroit enregistré. Pour éviter de faire une boucle infinie, le caractère suivant le @ est ignoré . Si la pile est vide, l'instruction leave provoque l'arrêt du programme.

Spécification

Le langage est compartimenté en 3 langages de puissance croissante, chacun contenant le précédent :

Core SNUSP
Équivalent du Brainfuck en puissance avec une sémantique quasi-équivalente.
Modular SNUSP
Ajoute les fonctions en introduisant une pile d'appel et les instructions enter (@) et leave (#).
Bloated SNUSP
Ajoute la simultanéité et le non-déterminisme.

Cependant, voici l'adresse d'un entretien pour évoluer en un langage SRFI-style extension model plus scalable[1].

Exemple

Ce code SNUSP calcule le quotient et le reste obtenus par la division euclidienne de deux nombres décimaux à un chiffre issus de l'entrée standard :

   /==!/============atoi=@@@@=@@=--#
   |   |   /==!/====itoa=@@@@=@@=++#
   |   |   |   |
$,@/>,@/@\@/.<@/.#
         |           /-\  
         \===div=?\<!\?/#!===+<<<\      /-\
                  \<==@\>@\>>!/?!/=<?\>!\?/<<#
                          |  |  #\->->+</
                          \=!\=?!/->>+<<?\#
                                #\?<<+>>-/

Dans le programme ci-dessus, la conversion de chiffres ASCII en nombre entier est faite par les fonctions atoi et itoa, tandis que le calcul réel est exécuté par la fonction div. Finalement, le résultat est affiché par la sortie standard.

Un autre exemple implantant la fonction d'Ackermann :

   /==!/==atoi=@@@@=@@=--#
   |   |
   |   | [j]{i} -> {A(i,j)}, où A est la fonction d'Ackermann
   |   |       /=========\!==\!====\   ** recursive **
$,@/>,@/==ack=!\?\<+#    |   |     |   A(0,j) -> j+1
 j   i           \<?\+>-@/#  |     |   A(i,0) -> A(i-1,1)
                    \@\>@\->@/@\<-@/#  A(i,j) -> A(i-1,A(i,j-1))
 {a}[ ][0]  #      #  |  |     |
 {0}[ ][a]  /-<<+>>\!=/  \=====|==@\>>>@\<<#  {a}[ ][0]
  (a > 0)   ?      ?           |   |    |     [a]{ }[a]
 [0][ ]{a}  \>>+<<-/!==========/   |    |
 [a][ ]{0}  #      #               |    |
                     {a}[ ][0][0]  |    |  [0][ ][ ]{a}
                     {0}[ ][a][a]  |    |  [a][ ][ ]{0}
                    #/?========\!==/    \==!/=======?\#
                     \->>+>+<<</            \>>>+<<<-/

Comme dans l'exemple précédent, ce programme lit deux chiffres ASCII décimaux, les convertit en nombres entiers, et les utilise comme paramètres de la fonction ack.
Cependant, dans ce cas-ci, le résultat de la fonction n'est jamais affiché par la sortie standard; il ne peut être extrait que par l'utilisation d'un débogueur. À cause de l'extrême taux de croissance fonction d'Ackermann, le résultat de la majorité des entrées ne tiendrait pas dans un seul nombre décimal à un seul chiffre; ainsi, un simple appel à la fonction itoa ne suffirait pas ici.

Les commentaires ressemblant à {a}[ ][0] commentent l'etat de la pile pour chaque fonction. La disposition de la pile antérieure à l'exécution de la fonction est écrite en premier, tandis que la disposition résultante est écrite au-dessous ou à droite. Chaque cellule est encadrée, et les accolades entourent la cellule courante.

Le programme qui utilise la fonction d'Ackermann démontre une propriété remarquable des langages dérivés de Befunge : le code peut être exécuté dans deux directions. Ceci est utilisé par la boucle qui déplace une valeur de deux cellules vers le haut, tout en pouvant déplacer une valeur de deux cellules vers le bas simplement en s'exécutant dans la direction opposée!

Pour compléter le programme, la fonction suivante peut être utilisée pour afficher le résultat dans un nombre ASCII décimal à plusieurs chiffres :

           /recursive\  #/?\ zero
==print10=!\@\>?!\@/<@\.!\-/
             |   \=/  \==itoa=@@@+@+++++#
             !     /+ !/+ !/+ !/+   \  mod10
             /<+> -\!?-\!?-\!?-\!?-\!
             \?!\-?!\-?!\-?!\-?!\-?/\  div10
                #  +/! +/! +/! +/! +/

Notes et références

  1. « Snusp Language ».

Voir aussi

Liens externes