Nada

L'interpréteur multilangage

1) Introduction

Il est facile de comprendre que le langage de programmation du future si ce n'est déjà le cas aujourd'hui, sera du pseudo code traité par l'IA. Et qu'est ce que le pseudo-code si ce n'est un code écrit dans un langage sur demande.... D'où l'importance de pouvoir choisir son langage de programmation. Ne dit-on pas que la moitier de la résolution d'un problème est résolue par sa formalisation dans un langage sur mesure ?

Les algèbres multi-sortes sont la base des interpréteurs multilangages. Néanmoins les expressions avec nom d'opérateur, parenthèse et virgule peuvent vite devenir illlisibles de par un trop grand nombre de parenthèses emboitées. Pour rendre le langage plus lisible pour un humain, on autorise des syntaxes alternatives, préfixe, infixe, postfixe et délimité, qui nous permettent de définir un véritable langage de programmation mutable. Et on autorise des patrons, des macros, qui permettent de sous-entendre la plus grande partie de l'expression.

Les langages de programmation comme les langages scientifiques et mathématiques possèdent tous la propriété d'être facilement reconnaissable. Cela vient du fait que l'on souhaite condenser dans une formule un ensemble de connaissances à transmettre, et donc dont le but par principe est d'être facile à lire. Or qu'est ce que cela vaut dire "facilement reconnaissable" ? Que l'on repaire immédiatement l'éventuelle erreur de syntaxe.

Partant de ce principe on s'intéresse qu'aux seuls langages dont la syntaxe est résolue par un automate, en une seule lecture de l'expression. Cela va imposer un certain nombre de contraintes sur la conception du langage, et l'on ne pourra pas implémenter toutes les syntaxes altérnatives évoquées précédement en même temps ou sans autre contrainte.

La programmation assistée par l'IA, nous permet de mettre facilement en oeuvre les constructions d'algèbre multi-sorte ainsi que toutes sortes d'algorithmes applicables à ces structures. Cela modifit l'ordre des pertinences dans les constructions (et même des conceptions mathématiques). On s'attardera dans le choix d'une nomenclature de structures et d'une formalisation des opérations sur ces structures. Cela révèlera un nouvel attrait pour le constructivisme par le bas.

On discute avec l'IA sur les langages d'opérateurs et les automates reconnaissant ces langages. Puis on étend progressivement en plusieurs langages imbriqués avec leur automates les reconnaissant. Puis on étend les langages pour pouvoir programmer les automates eux-mêmes, et pour finalement proposer un interpréteur multilangage modifiable à volonté.

Le procédé pouvant prétendre à une certaine universalité, il sera rechercher une terminologie consensuelle (basée sur une norme hispano-latine telle que proposée par la communauté "Désanglisation de la programmation"), des mots-clefs qui donnent envie d'être utilisés.

Comme nous somme soucieux de rendre moins ingrate ces recherches pour ne pas décourager les néophytes, nous proposerons à chaque étape des résultats intermédiaires sous forme d'outils concrets.

La première étape consiste en la conception d'un interpréteur d'algèbre multi-sorte, capable de reconnaitre un terme, capable d'énumérer tous les termes possibles, capable de générer un terme au hasard.

2) L'algèbre libre

La construction ayant quelque prétention à l'universalité, l'ordre des constructions et des concepts à définir revête une grande importance. Le premier prompt est celui définissant une algèbre libre engendrée par des opérateurs internes.

On définit un langage algébrique, et plus précisément un langage associé à une algèbre libre, en présentant ses éléments générateurs et ses opérateurs générateurs entre crochet <...>. Chaque opérateur possède une arité indiquée occasionnellement par le suffixe (.) pour unaire, (.,.) pour binaire, (.,.,.) pour ternaire. Exemple :

       L = <a, b, f(.), g(.,.), h(.,.,.,.)>

Il convient de proposer à l'utilisateur les outils les plus démonstratifs avec les arguments par défaut necéssaires pour cela. Puis il est préférable de regouper ces informations concernant une structure dans la structure elle-même. C'est pourquoi on perfectionne tout de suite la définition du langage avec la possibilité d'ajouter des information concernant chaque symbole, et on commence par des poids associés à chaque générateur. Cela est nécessaire lorsque l'on veut générer au hasard un terme, ou attribuer aux termes une taille pondérée.

On ajoute un poids à chaque générateur. Le suffixe :p fixe le poids, positif, nul autorisé, 1 par défaut. Exemple :

       L = <a:9, b, f(.):3, g(.,.), h(.,.,.,.)>

Notre vision étant par essence récursive, on oriente notre IA dans cette vision d'un traitrement récurcif pour reconnaitre un terme du langage.

On définit un automate récursif qui reconnaît les termes du langage <a, b, f(.), g(.,.), h(.,.,.,.)>. L'automate est représenté par un ensemble de règles de production :

{|--a, |--b, |--f(.), |--g(.,.), |--h(.,.,.,.)}

Chaque élément de cet ensemble est une règle de production possible. Le symbole point désigne un terme quelconque du langage, et constitue un appel récursif de cet automate.

Sans développer davantage la conception du langage, on peut demander à l'IA de programmer une fonction idioma("<a,b,f(.), g(.,.),h(.,.,.)>") qui retourne l'automate capable de reconnaitre un élément du langage. Un petit synopsis à destination de l'utilisateur devra être consultable par la commande.

Programme en python une fonction idioma("<a,b,f(.), g(.,.),h(.,.,.,.)>") qui retourne cet automate capable de reconnaître un terme du langage.

Et fait une synopsis à destination de l'utilisateur qui devra être accessible par la commande synop(idioma).

3) Terminologie hispano-latine

L'algèbre comprend un ensemble de règles de production, un ensemble d'éléments générateurs, un ensemble d'opérateurs générateurs, une liste de symboles générateurs (regroupant opérateurs générateur et éléments générateurs mais énuméré dans un ordre), et une méthode pour reconnaitre un terme.

A = idioma("<a:9,b,f(.):3, g(.,.)>")   
Construit l'automate `A`
Attributs :    
A.regles  =  {'|--g(.,.)', '|--b', '|--a', '|--f(.)'}
Régles de production
A.generateurs  =  {'a':9, 'b':1}
Eléments générateurs
A.operateurs  =  {'f':(1,3), 'g':(2,1)}
Opérateurs générateurs
A.symboles  =  [('a', 0, 9), ('b', 0, 1), ('f', 1, 3), ('g', 2, 1)]    
Symboles générateurs
Méthodes :    
A.reconnait("g(f(a),b)")  =  vero
Teste si le terme appartient au langage.
A.reconnait("g(f(b))")  =  falso

On peut penser que ces 4 attributs et cette méthode sont des identifiants suffisament généraux pour devoir leur attribuer des noms commun de programmation (mot-clef).

Voyons ce que ChatGPT peut nous proposer concernant le nom de méthode "reconnait" :

On définie un langage algébrique, et plus précisément un langage associé à une algèbre libre, par la liste de ses éléments générateurs et opérateurs générateurs entre crochets "<a,b,f(.),g(.,.)>". La fonction "idioma" appliqué à la chaine "<a,b,f(.),g(.,.)>" retourne l'automate capable de reconnaitre un terme du langage algébrique en question.

Le nom "idioma" obéit bien à la norme hispano-latine.
L'automate possède une méthode, "reconnait", qui appliqué à une chaine retourne vrai si c'est un terme du langage et faux sinon. Quel mot-clef de norme hispano-latine pourrait remplacer le nom de méthode "reconnait" ?
Dans ce cas précis, je choisirais acepta.

La distinction conceptuelle est utile :

  • un automate reconnaît un langage ;
  • un automate accepte ou rejette une chaîne particulière.

Ainsi :

</> Python

L = idioma("<a,b,f(.),g(.,.)>")

L.acepta("a")           # vero
L.acepta("f(a)")       # vero
L.acepta("g(a,b)")   # vero
L.acepta("g(a)")      # falso

acepta présente plusieurs avantages : c'est espagnol, très court, issu du latin acceptare, et son sens correspond exactement à l'usage classique en théorie des automates.

reconoce serait néanmoins également très bon, et c'est la traduction hispanique directe de reconnait :
L.reconoce("f(a)")

Mais je réserverais idéalement reconoce à une relation plus générale avec le langage :
« El autómata reconoce el idioma L. »
« El autómata acepta el término t. »

Une troisième possibilité serait pertenece, qui exprime directement l'appartenance :
L.pertenece("f(a)")

Cela se lit comme :
f(a) pertenece a L.

Mais grammaticalement, c'est plutôt le terme qui appartient au langage, et non le langage qui « pertenece » au terme. En notation objet, L.pertenece(t) est donc légèrement moins naturel.

Je proposerais donc la norme suivante :

Opération Mot-clef recommandé
Construire le langage / automate idioma(...)
Tester si une chaîne est un terme accepté acepta(...)
Dire qu'un automate reconnaît un langage reconoce(...)
Valeurs retournées vero / falso
Donc, pour votre bibliothèque, idioma(...).acepta(terme) me paraît être la formulation la plus précise et la plus élégante.

4) L'implémentation

On considère que le langage va piloter un système (un système qui est extérieur au langage).

D'un point de vue informatique, un élément générateur désigne une valeur au sens générale, mais c'est un peu plus que cela, il représente une procédure sans argument qui retourne une valeur, une valeur qui dépend donc de l'état du système piloté contenant cette procédure.

Et, un opérateur générateur représente une procédure prenant en argument une ou plusieurs valeurs pour retourner une valeur.

Ces procédures représentent l'implémentation du langage dans le système piloté. L'implémentation va donc associer à chaque symbole une procédure de même arité. L'évaluation d'un terme va exécuter la procédure associée au symbole racine du terme et lui transmettre comme argument le résultat de l'évaluation des termes arguments du symbole racine, puis va retourner le résultat.

Exemple : L'instruction I = implemanta({'a':A, 'b':B, 'f':F, 'g':G}) va créer une implémentation dans laquelle le symbole 'a' est associé à la procédure nullaire A, le symbole 'b' est associé à la procédure nullaire B, le symbole 'f' est associé à la procédure unaire F, et le symbole 'g' est associé à la procédure binaire G. L'implémentation I comprend une méthode d'évaluation ejec. Exemple : I.ejec("g(f(a),b)") exécutera l'instruction `G(F(A()),B())` et retournera son résultat. Cette méthode ejec constitue l'interpréteur. C'est l'opération de base d'un interpréteur appelée « traduction directe ».

 

Répondre sur Communauté Reddit

---- 1 septembre 2026 ----

 

Nada


Dominique Mabboux-Stromberg
(Septembre 2026)