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 programmé en python.
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.
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 une 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).
L'argument de idioma est une chaine de caractères écrites dans un méta-langage.
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 productionA.generateurs = `{'a'":"9, 'b'":"1}` Eléments générateursA.operateurs = `{'f'":"(1,3), 'g'":"(2,1)}` Opérateurs générateursA.symboles = `"["('a', 0, 9), ('b', 0, 1), ('f', 1, 3), ('g', 2, 1)"]"` Symboles générateursMéthodes : A.reconnait("`g(f(a),b)`") = vero Teste si le terme appartient au langage.A.reconnait("`g(f(b))`") = falso
Remarquez que l'argument de la méthode reconnait est une chaine de caractères pouvant représenter un terme du langage. En effet, un interpréteur analyse par principe une chaine de caractère. Les autres syntaxes concernant les attributs sont celles de python.
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)") # falsoacepta 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 :
Donc, pour votre bibliothèque, idioma(...).acepta(terme) me paraît être la formulation la plus précise et la plus élégante.
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
Une fois posé le langage, il existe un cheminement de conceptualisations quasi-canonique définissant l'implémentation, l'implémentation par défaut, puis toute une liste de méta-opérations.
On part d'un langage L que l'on définit par l'instruction L = idioma("`"<"a, b, f("."), g(".,.")">"`"). C'est le langage d'une algèbre libre. Ce langage doit piloter un système. Cela se fait en associant à chaque opérateur, une procédure de même arité qui prend en argument des valeurs produites par le système piloté, et qui retourne une valeur produite par le système piloté. Cet ensemble de procédures associées constitue ce qu'on appelle l'implémentation du langage dans le système piloté. Notez que le système piloté peut alors être considéré comme le produit de cette seule implémentation.
On procède à l'implémentation en associant à chaque élément générateur, une valeur. Et en associant à chaque opérateur générateur du langage, une procédure de même arité.
Pour le raisonnement, improvisons quelques notations que nous redéfinirons plutard. L'instruction L.implemanta([A,B,F,G]) va modifier l'implémentation du langage comme suit : le symbole `a` sera associé à la valeur A, le symbole `b` sera associé à la valeur B, le symbole `f` sera associé à la procédure unaire F, et le symbole `g` sera associé à la procédure binaire G. On peut aussi prendre une notation plus fine telle que :
L.i("a") = A
L.i("b") = B
L.i("f") = F
L.i("g") = G
L'évaluation d'un terme par exemple `g(f(a),b)` s'obtient en utilisant la méthode ejec du langage. La commande L.ejec("`g(f(a),b)`") exécutera 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 mot-à-mot » appliqué ici à une simple algèbre libre.
Comme nous programmons cet interpréteur en python, les valeurs peuvent être de n'importe quel type python.
---- 8 novembre 2026 ---
Si les valeurs des constantes et valeurs résultats des procédures sont des chaines de caractères représentant des termes d'un langage, on dira que l'implémentation est homocentrée, et si ce langage est inclus dans le langage de départ, on dira que l'implémentation est autocentré.
Ces deux types d'implémentation intéressent plus particulièrement les mathématiciens. L'évaluation d'un terme du langage, son interprétation, s'apparente alors à un morphisme de structure entre deux algèbres. Un terme du langage est un élément de la structure de départ. Le résultat de l'interprétation est un élément de la structure d'arrivé.
Dans le cas d'implémentation morphique, il existe une implémentation par défaut assez facile à décrire qui correspond à une extension du langage de départ.
---- 8 novembre 2026 ---
où les valeurs produites, si elles sont utilisées comme élément, doivent donc être convertie en chaines de caractères, ce qui oblige à utiliser un interface d'échange entre les types python utilisés et des chaines de caractères représentant des éléments d'un langage.
Nous greffons l'interpréteur sur du Python, ce qui nécessite un interface pour convertir les données pythons en chaine de caractère désignant un élément du langage et inversement.
Prenons par exemple l'implémentation suivante qui traduit en faite une absence d'implémentation :
A non défini
B non défini
F non défini
G non défini
L'évalution de "a" se fait en lançant l'instruction L.ejec("a"). Celle-ci tentera d'exécuter la procédure associée A(). Comme celle-ci n'est pas définie, elle retournera l'élément à évaluer tel quel, "a".
L'évalution de "f(a)" se fait en lançant l'instruction L.ejec("f(a)"). Elle commencera par évaluer l'argument "a" et le remplacera par le résultat, ce qui ne change rien ici. Puis elle tentera d'exécuter la procédure associée à f avec l'argument évalué "a". Comme celle-ci n'est pas définie, elle retournera l'opérateur f avec ces arguments évalués, c'est à dire "f(a)".
L'évalution de "g(a,f(b))" se fait en lançant l'instruction L.ejec("g(b,f(a))"). Elle commencera par évaluer les arguments "b" et "f(a)", ce qui ne change rien ici. Puis elle tentera d'exécuter la procédure associée à g avec les arguments évalués "b" et "f(a)". Comme celle-ci n'est pas définie, elle retournera l'opérateur g avec ces arguments évalués, c'est à dire "g(a,f(b))".
Prenons par exemple l'implémentation suivante :
A = {27}
B = non défini
F = non défini
G = non défini
L'évalution de "a" se fait en lançant l'instruction L.ejec("a"). Celle-ci exécutera A() et retournera 27.
L'évalution de "f(a)" se fait en lançant l'instruction L.ejec("f(a)"). Elle commencera par évaluer l'argument "a" par 27. Puis elle tentera d'exécuter la procédure associée à f c'est à dire qu'elle tentera d'exécuter F(27). Comme cette procédure n'est pas définie, elle retournera l'opérateur f avec ces arguments évalués que l'on doit convertir en chaine de caractères, c'est à dire "f(27)".
Et cela a pour conséquence d'ajouter l'élément "27" au langage.
---- 8 novembre 2026 ---
Il y a une différence entre l'élément "a" et l'élément "27". L'évaluation de "a" exécutera A() et retournera la valeur 27. Tandis que l'évaluation de "27" retrounera "27" sans exécuter A(). Tout se pase comme si l'implémentation de "27" est absente. Néanmoins cette description est trop limité. L'évaluation de l'élément "a" peut produire dans les faits tun élément d'arrivé possédant également une implémentation spécifique c'est à dire une procédure d'évaluation déterminée. Et d'une manière générale, l'évaluation de "a" peut modifier toute l'implémentation (la procédure A peut modifier l'implémentation). Au départ, cette implémentation est posée par défaut, et donc telle que décrite ici.
Prenons par exemple l'implémentation suivante :
A = {27}
B = non défini
F = non défini
G = {x,y | x+y}
L'évalution de "g(a,a)" se fait en lançant l'instruction L.ejec("g(a,a)"). Elle commencera par évaluer "a" en 27 une première fois pour le premier argument, et une seconde fois pour le second argument, sans les transformer en chaine de caractère (puisque ce ne sont pas encore des résultats de tout calcul), puis exécutera "G(27,27)" pour produire 54 qui sera transformé en un nouveau élément "54".
L'évaluation de "g(27,27)" va exécuter la procédure G sur des éléments convertis qu'il faut donc préalablement déconvertir. G(27,27) produit 54 qui est converti en l'élément "54". Il faut donc que l'interpréteur sache si un élément est convertie ou pas, c'est à dire s'il possède une valeur. On ajoute donc un attribut L.v["a"] à l'élément "a" qui est null par défaut ou égale à sa valeur s'il est converti. On peut alors, au lieu de définir la procédure d'évaluation A={27} seulement modifier l'attribut L.v["a"]=27
L'évaluation de "g(27,a)" va exécuter la procédure G sur un élément convertis qu'il faut donc préalablement déconvertir, et sur un élément "a" qu'il faut évaluer, G(27,27) produit 54 qui est converti en l'élément "54". Il faut donc que l'interpréteur sache si un élément est convertie ou pas, c'est à dire s'il possède une valeur. On ajoute donc un attribut L.v["a"] à l'élément "a" qui est null par défaut ou égale à sa valeur s'il est converti. On peut alors, au lieu de définir la procédure d'évaluation A={27} seulement modifier l'attribut L.v["a"]=27.
L'évaluation de "g(g(a,27),b)" commence par évaluer "a" en 27, et par évaluer "27" en "27" (car il n'y a pas d'implémentation de l'élément "27") puis en sa valeur 27. Puis calcul G(27,27) pour produire 54. Puis évalue "b" en "b" puis en sa valeur null. L'argumentation étant incomplète on produit l'appel "g(54,b)".
Prenons par exemple l'implémentation suivante :
A = {27}
B = non défini
F = non défini
G = non défini
L'évalution de "a" se fait en lançant l'instruction L.ejec("a"). Celle-ci exécutera A() et retournera 27. Comme ce résultat n'est pas réutilisé par une procédure, il est converti par l'interface en une chaine de caractères désignant un nouvel élément "27". L'évaluation de "a" produit. "ɨ27".
Il y a alors une différence entre l'élément "a" et l'élément "27". L'évaluation de "a" exécutera A() et retournera "27". Tandis que l'évaluation de "27" retrounera "27" sans exécuter A(). Tout se pase comme si l'implémentation de "27" est absente. Néanmoins cette description est trop limité. L'évaluation de l'élément "a" peut produire dans les faits tun élément d'arrivé possédant également une implémentation spécifique c'est à dire une procédure d'évaluation déterminée. Et d'une manière générale, l'évaluation de "a" peut modifier toute l'implémentation (la procédure A peut modifier l'implémentation). Au départ, cette implémentation est posée par défaut, et donc telle que décrite ici.
L'évalution de "f(a)" se fait en lançant l'instruction L.ejec("f(a)"). Elle commencera par évaluer l'argument "a" par 27. Puis elle tentera d'exécuter la procédure associée à f c'est à dire qu'elle tentera d'exécuter F(27). Comme cette procédure n'est pas définie, elle retournera l'opérateur f avec ces arguments évalués converti, c'est à dire "f(27)".
Prenons par exemple l'implémentation suivante :
A = {27}
B = non défini
F = non défini
G = {x,y | x+y}
L'évalution de "g(a,a)" se fait en lançant l'instruction L.ejec("g(a,a)"). Elle commencera par évaluer "a" en 27 une première fois pour le premier argument, et une seconde fois pour le second argument, sans les transformer en chaine de caractère (puisque ce ne sont pas encore des résultats de tout calcul), puis exécutera "G(27,27)" pour produire 54 qui sera transformé en un nouveau élément "54".
L'évaluation de "g(27,27)" va exécuter la procédure G sur des éléments convertis qu'il faut donc préalablement déconvertir. G(27,27) produit 54 qui est converti en l'élément "54". Il faut donc que l'interpréteur sache si un élément est convertie ou pas, c'est à dire s'il possède une valeur. On ajoute donc un attribut L.v["a"] à l'élément "a" qui est null par défaut ou égale à sa valeur s'il est converti. On peut alors, au lieu de définir la procédure d'évaluation A={27} seulement modifier l'attribut L.v["a"]=27
L'évaluation de "g(27,a)" va exécuter la procédure G sur un élément convertis qu'il faut donc préalablement déconvertir, et sur un élément "a" qu'il faut évaluer, G(27,27) produit 54 qui est converti en l'élément "54". Il faut donc que l'interpréteur sache si un élément est convertie ou pas, c'est à dire s'il possède une valeur. On ajoute donc un attribut L.v["a"] à l'élément "a" qui est null par défaut ou égale à sa valeur s'il est converti. On peut alors, au lieu de définir la procédure d'évaluation A={27} seulement modifier l'attribut L.v["a"]=27.
L'évaluation de "g(g(a,27),b)" commence par évaluer "a" en 27, et par évaluer "27" en "27" (car il n'y a pas d'implémentation de l'élément "27") puis en sa valeur 27. Puis calcul G(27,27) pour produire 54. Puis évalue "b" en "b" puis en sa valeur null. L'argumentation étant incomplète on produit l'appel "g(54,b)".
Les langages évolués sont encore des langages algébriques, et donc obéïssent aux règles précédentes. Et il est tout à fait pertinent, utile, et politiquement important, à un moment où il est justement important de prendre position, de vouloir établir une norme sur les principes généraux de programmation, sur une base linguistique hispano-latine, sachant que les anciens langages ne seront peut ou plus utilisés dans la phase de conception des programmes.
---- 8 novembre 2026 ----
Répondre sur le Groupe Facebook
Répondre sur Communauté Reddit