Un
langage de programmation est un langage informatique (Turing-complet)
1, 2, permettant à un être humain d'écrire un programme informatique (le code source) destiné à être exécuté par une machine, généralement un ordinateur.
Le code source subit une transformation ou une évaluation dans une
forme exploitable par la machine, ce qui permet d'obtenir un programme exécutable.
Les langages permettent souvent de faire abstraction des mécanismes de
bas niveau de la machine, de sorte que le code source puisse représenter
une solution telle que comprise ou conçue par un être humain.
L'activité de rédaction du code source d'un programme est nommée programmation
Généralités
Langage
Articles détaillés : Langage formel et Grammaire formelle.
D'un point de vue mathématique, un langage de programmation est un langage formel construit sur un alphabet (ensemble de symboles). Dans cet alphabet, on trouve plusieurs choses :
- des lettres et des chiffres ;
- des mots-clés (combinaisons de lettres et parfois de chiffres) ;
- des caractères :
- correspondant à des opérateurs : par exemple « = », « < », « & » ;
- ou pas, comme « { », « _ », …
L'assemblage de ces symboles forme les « mots » du langage de
programmation. Pour qu'un mot appartienne au langage, il doit vérifier
certaines contraintes exprimées grâce à la théorie des langages dans une grammaire formelle : c'est la « syntaxe » du langage de programmation.
En associant une sémantique
– généralement une opération – à chaque mot, on définit le comportement
de la machine. La mise en relation de mots va donner un programme informatique.
Programmation
Articles détaillés : Compilateur et Langage machine.
Suivant le langage utilisé, un programme doit être interprété ou compilé en passant par un autre langage qui pourra être compris par la machine : l'assembleur ou même en code binaire.
D'un point de vue pratique, un langage de programmation permet
l'écriture de programmes de manière compréhensible par un être humain.
Le programmeur n'a pas besoin de connaître le langage machine,
dit « de bas niveau », pour écrire un programme. Le langage de
programmation fournit une abstraction de niveau supérieur pour utiliser
une machine.
Il existe des milliers de langages de programmation, la plupart
d'entre eux étant réservés à des domaines spécialisés. Ils font l'objet
de recherches constantes dans les universités et dans l'industrie.
Littérature
Étagère remplie de livres traitant de programmation en tout genre
Il existe toute une littérature sur papier ou disponible par internet pour documenter chaque langage de programmation, mais aussi pour expliquer les différentes manières de programmer ;
The Art of Computer Programming de Donald Knuth est une référence sur ce sujet.
Historique
Article détaillé : Chronologie des langages de programmation.
Bien que la notion de programme apparaisse progressivement au cours de la deuxième moitié du
XIXe
siècle, les premiers langages de programmation n'apparaissent qu'autour
de 1950. Chacun pouvant créer son propre langage, il est impossible de
déterminer le nombre total de langages existant à l'heure actuelle.
Particularités
Il existe plusieurs caractéristiques qui permettent de comparer les langages entre-eux :
Typage
Article détaillé : Typage.
Le typage est le fait d'attribuer un type aux éléments du code source (variables, fonctions, etc.). Un type définit une structure de données : nombre entier, tableau, chaîne de caractères. Dans certains langages, il existe des types plus évolués (liste chaînée, sémaphore) et il est parfois possible d'en définir de nouveaux.
Les types que l'on trouve dans un langage de programmation dépendent
de sa sémantique et donc de ses paradigmes. Beaucoup de langages
proposent la notion de variable qui associe un nom à une valeur en mémoire et ce nom ou cette valeur à un type.
Le typage peut être :
- Explicite ou implicite
- On parle de typage explicite quand les types apparaissent
explicitement dans le code source du programme ; un typage implicite est
déterminé par le compilateur ou l'interprète.
- Fort ou faible
- Plus un typage est fort, plus les règles du langage sont strictes et
interdisent dès la compilation les manipulations entre données de types
différents. On trouve souvent dans les langages typés faiblement la
possibilité de faire du transtypage manuel (en anglais cast) pour combler les lacunes du système automatique de typage.
- Statique ou dynamique
- On parle de typage statique quand la vérification des types se fait
dès la phase de compilation, et de typage dynamique lorsque celle-ci est
faite durant l'exécution. De plus un typage dynamique associe les types
aux valeurs, alors qu'un typage statique associe le type à la variable.
Le typage du langage C est explicite,
relativement fort[réf. nécessaire]
(le compilateur peut générer des avertissements de typages, le
transtypage manuel est permis, mais on peut effectuer n'importe quelle
opération entre n'importe quels types sans transtypage), et statique. Le
langage OCaml possède un typage implicite, fort et statique (son typeur est le fruit de nombreux travaux de recherche scientifique
3).
Les langages fournissent parfois des mécanismes pour convertir une
valeur d'un type en une valeur dans un autre type : on peut convertir un
entier en flottant sans aucune perte mais l'inverse n'est pas toujours
possible. Il ne faut pas confondre la conversion avec le transtypage :
le mécanisme de conversion transforme effectivement la donnée, par
contre le transtypage se contente de modifier le type associé. Ce
mécanisme peut être explicite ou implicite.
Syntaxe
Article détaillé : Syntaxe.
Outre les particularités sémantiques des langages, ils utilisent
également des grammaires différentes qui proposent souvent des points
communs.
Les particularités syntaxiques ne sont souvent que des détails qui ne
changent pas les fonctionnalités proposées par les langages de
programmation. Par exemple, dans Objective-C 2, il est possible
d'utiliser les accesseurs avec deux syntaxes différentes pour le même résultat :
object.message
[object message]
Article détaillé : Commentaire (informatique).
Les commentaires sont des parties du programme qui n'apparaissent pas
dans l'application finale. Les commentaires permettent de documenter et
d'expliquer le code source. Presque tous les langages de programmation
permettent d'écrire des commentaires.
Ils sont introduits ou délimités par des caractères spéciaux (
#
en Bash ou Ruby) ou une instruction particulière (
REM
en BASIC).
Dans les langages dont la syntaxe est inspirée de celle du C (C++, C#,
Objective C, D, Java, JavaScript, PHP...), ils sont la plupart du temps
écrits de cette façon :
//pour un commentaire sur une seule ligne
Ou encore comme ceci:
/*pour un commentaire
sur plusieurs lignes*/
Il est possible aussi de préciser que certains commentaires doivent
être pris en compte par des outils de génération automatique de
documentation (Doxygen, Javadoc, Candydoc...) comme ceci:
/// avec un signe "/" en plus pour le commentaire sur une ligne.
OU:
/** en doublant les " * "
pour un commentaire sur plusieurs lignes */
Indentation
Article détaillé : Indentation#Informatique.
L'indentation est l'utilisation d'espaces ou tabulations
en début de ligne. Généralement, elle n'a pas d'incidence sur le
fonctionnement du programme et ne sert qu'à améliorer la lisibilité du
code.
Pour certains langages, l'indentation est significative et
obligatoire : en Python, l'indentation va servir à délimiter une
fonction, une classe ou un test conditionnel – à la différence de
langages comme C où ce sont les accolades
{ }
qui remplissent cette fonction.
Séparation des instructions
Article détaillé : Séparateur (informatique).
Pour distinguer une instruction de la suivante, il existe principalement deux approches :
- soit la fin d'une instruction est marquée par un terminateur (un
;
en C, Java, etc.) ;
- soit il existe un séparateur d'instructions (un
;
en Pascal, une fin de ligne en bash ou Python).
La nuance est importante, car en C, la dernière instruction d'un bloc doit comprendre un
;
(terminateur) alors qu'en Pascal, il est inutile, voire fautif, d'en
mettre un (cela consiste à ajouter une instruction vide en fin de bloc).
De même, le caractère
;
peut être utilisé en C comme instruction vide, ce qui n'aurait pas de sens en Pascal.
Les langages utilisant un terminateur sont réputés engendrer moins de fautes de syntaxe que ceux utilisant un séparateur.
Balisage
Article détaillé : Langage de balisage.
Certains langages utilisent des « balises » délimitant des « environnements ». Une balise est généralement un mot-clé associé à plusieurs caractères :
\
;
< >
; etc.
Les langages permettant de générer du code source ou des documents utilisent souvent des balises. Par exemple, PHP et JSP utilisent des balises pour délimiter les parties de code à interpréter. XML est également un langage à balises, qui permet de définir des langages de programmation comme XSP ou XSLT.
Stratégie d'évaluation
Une stratégie d'évaluation est un ensemble de règles qui décrivent
comment évaluer une expression dans un langage de programmation. La
stratégie d'évaluation définit à quel moment les arguments des fonctions et opérateurs sont évalués ou réduits.
On distingue essentiellement deux stratégies :
- l'évaluation stricte : les arguments des fonctions sont toujours évalués avant que la fonction ne soit appliquée.
- l'évaluation paresseuse
ou évaluation retardée : les arguments ne sont évalués que lorsque leur
valeur est effectivement requise. Ce type d'évaluation est généralement
utilisé dans les langages fonctionnels.
La plupart des langages ont un système d'évaluation stricte, et
utilisent une forme d'évaluation paresseuse pour les expressions
booléennes (évaluation court-circuit). Cependant il est possible de
créer une évaluation paresseuse dans un langage à évaluation stricte.
Par exemple, Scheme fournit la fonction
delay
qui retarde l'évaluation d'une expression et
force
qui oblige l'évaluation.
Gestion de la mémoire
Les langages de programmation offrent plus ou moins de libertés au programmeur en ce qui concerne la gestion de la mémoire :
- Soit elle est entièrement sous le contrôle du développeur qui doit gérer lui-même l'espace mémoire disponible, les allocations et libérations. C'est le cas pour les langages de bas niveau, comme le C.
- Soit tout peut être contrôlé par le compilateur ou par le moteur d'exécution (Java) : même s'il est possible de donner des directives, la machine virtuelle gère elle-même la mémoire à l'aide d'un ramasse-miettes. C'est ainsi que fonctionnent les langages de haut niveau, comme Python.
Certains langages proposent un système intermédiaire. En Objective-C,
il est possible de la gérer directement, d'activer la gestion
automatique de la mémoire ou d'utiliser un système de plus haut niveau.
Réflexivité
Article détaillé : Réflexivité (informatique).
On dit qu'un langage de programmation est « réflexif » s'il permet,
au moment de l'exécution, d'analyser et d'agir sur le fonctionnement
interne du programme lui-même.
Le langage Smalltalk
fut un précurseur dans le domaine de la réflexivité. Il a d'ailleurs
fortement influencé bon nombre de langages réflexifs, tels que Io, Python, Ruby, Java ou Objective-C.
Exceptions
Article détaillé : Système de gestion d'exceptions.
Les exceptions sont des cas limites d'exécution du programme
(division par 0, etc.). Lorsqu'elles sont générées, le déroulement du
programme est interrompu. Au contraire d'une erreur qui interrompt
brutalement le programme, la gestion d'une exception permet
d'interrompre proprement un programme, de corriger l'erreur et d'en
reprendre l'exécution.
La gestion des exceptions peut être différente selon les langages ; soit :
- Il n'y en a pas (C) ;
- Elle signale l'exception sans la traiter (C++, C#, Java) ;
- Elle permet un traitement : par exemple, la modification du
programme par le programme lui-même (comme en Python) pour reprendre une
exécution « normalement ».
Concurrence
Article détaillé : Programmation concurrente.
La programmation concurrente consiste à découper un programme en plusieurs fils d'exécution.
La concurrence permet de simuler l'exécution de différentes tâches de
façon simultanée ou, dans le cadre d'une interface graphique,
d'effectuer des tâches en tâche de fond sans pour autant bloquer le rafraîchissement de l'affichage. La programmation concurrente permet aussi de tirer parti de ressources distribuées (multiples processeurs, cluster de machines, etc.) ou du système d'ordonnancement de processus du système d'exploitation.
Certains langages intègrent directement la concurrence dans leurs primitives (Erlang, Concurrent ML). Généralement, la concurrence est intégrée par l'intermédiaire de bibliothèques spécifiques : le langage C dispose entre autres de la bibliothèque des thread POSIX ; Java dispose d'une classe
Thread dans ses bibliothèques standards.
Principaux paradigmes
Articles détaillés : Paradigme (programmation) et Sémantique des langages de programmation.
Chaque langage de programmation est différent. Une solution exprimée
dans un certain langage peut « ressembler » à une solution exprimée dans
un autre langage ; dans ce cas, on dit que les langages utilisent le
même paradigme
(ou style). Deux programmes fournissant la solution au même problème,
mais écrits avec des paradigmes différents seront fondamentalement très
différents.
De nombreux langages appartiennent simultanément à plusieurs
catégories : ils sont dits « multi-paradigmes ». Par exemple, C++ permet
la programmation impérative, orientée objet et la programmation
générique (à base de classes et de fonctions paramétrées nommées
templates). Common Lisp
est à la fois impératif, fonctionnel, orienté objet ; son caractère
« programmable » (un langage de programmation programmable…) lui permet
d'intégrer d'autres « paradigmes » de programmation en son sein (par
exemple : la programmation logique et la programmation par contraintes).
Langages impératifs et procéduraux
Articles détaillés : Programmation impérative et Programmation procédurale.
On distingue deux types de langages impératifs. D'une part les
langages machines et assembleurs. Ceci explique que les premiers
langages de programmation apparus soient des langages impératifs : une
instruction du langage correspond à un ensemble d'instructions du langage machine. Les structures de données et opérations sont plus complexes qu'au niveau de la machine, mais le paradigme suivi reste le même.
Les langages procéduraux forment la seconde famille de langages impératifs. Une procédure,
appelée également fonction, est une suite d'instructions devant être
effectuée dans un ordre précis. On distingue parfois procédure et
fonction par la caractéristique qu'une procédure ne renvoie pas de
résultat.
Parmi les langages impératifs figurent COBOL, Fortran, Pascal ou encore le C.
Langages déclaratifs
Article détaillé : Programmation déclarative.
Un langage déclaratif ne décrit pas comment est réalisée une
opération, comme dans un langage impératif, mais décrit le problème
lui-même, sans s'intéresser au contexte.
Figurent parmi les langages déclaratifs Oz, Prolog ou encore Clips.
Langages logiques
Article détaillé : Programmation logique.
Un programme logique est composé de faits et de règles qui sont traités par un moteur d'inférence.
Prolog fut le premier langage de ce type à être fonctionnel sur un ordinateur.
Langages fonctionnels
Article détaillé : Programmation fonctionnelle.
Dans ce paradigme, l'opération de base n'est pas l'affectation,
contrairement aux langages impératifs, mais l'évaluation de fonctions.
Ce paradigme est donc principalement efficace pour modéliser des
problèmes qui s'expriment par des valeurs de données, comme en
mathématiques, et non pas des états qui changent au cours de
l'exécution.
Certains langages fonctionnels, dit « purs », interdisent totalement les effets de bord,
tels que la mutation des données où une variable est liée à une valeur
non modifiable. D'autres, intègrent certains traits des langages
impératifs où les variables peuvent changer de valeur au cours de
l'exécution.
Quelques exemples de langages fonctionnels : Objective Caml (langage fonctionnel et impératif), Haskell (langage fonctionnel pur à évaluation paresseuse), Python (propose certaines fonctionnalités du style fonctionnel comme l'utilisation de fonctions lambda ou la compréhension de listes).
Langages à pile
Ces langages ne manipulent que des piles de données où les opérations sont effectuées sur les éléments du sommet d'une ou plusieurs piles.
Des exemples typiques sont les langages Forth, Factor, PostScript, Joy, Cat ou RPL (HP 48).
Langages à objets
Article détaillé : Programmation orientée objet.
Les langages à objets offrent une abstraction à la machine : l'objet est une structure sémantique indépendante qui rassemble des données et des traitements.
En se basant sur une méthode de conception à objet et sur un langage de modélisation à objet, on peut facilement implanter un concept au moyen d'un langage de programmation à objets.
Parmi les langages à objets sont généralement classés Ruby et Smalltalk,
purement objet, c'est-à-dire que tout est objet, depuis les types de
base, jusqu'à l'interprète ou les blocs d'instructions ; le C++, extension de C permettant d'utiliser des objets mais où tout n'est pas objet ; Python, très orienté objet mais qui ne respecte pas tous les principes de la programmation objet comme l'encapsulation.
Utilisations
On peut aussi classer les langages de programmation en fonction de
leur utilisation car beaucoup de langages sont spécialisés à une
application ou à un domaine particulier.
Langages de définition de données
Article détaillé : Langage de définition de données.
Un langage de définition de données ne permet pas d'effectuer de traitement mais de décrire des structure de données (listes, arbres …) et des instances de ces structures.
XML
est par exemple un langage permettant la représentation de données sous
forme de structure arborescente ; la partie DDL de SQL sert à décrire
des données relationnelles. Les langages qui décrivent des documents
peuvent également être considérés comme des langages de définition de
données. Ainsi, LaTeX est un exemple de langage de définition de données qui permet d'écrire un document en centralisant sa mise en forme. LaTeX est compilé vers d'autres langages de description de document, généralement plus « bas niveau » comme PDF ou Postscript.
Ces langages ne sont habituellement pas considérés comme des langages
de programmation. Cependant les codes sources produits avec ces
langages présentent certains traits de codes sources de programmes comme
des structures de contrôle (conditions, boucles...) et des moyens
d'interaction avec le système (variable d'environnement,
formulaires...). Ils sont donc cités ici à titre indicatif, mais sont à
la frontière de la programmation.
Langages de requête
Article détaillé : Langage de requête.
Les langages de requêtes sont destinés à interroger et manipuler les bases de données.
SQL est un langage de requête utilisé par un grand nombre de systèmes de gestion de bases de données tels que Oracle, SQL Server ou MySQL .
Langages pour pages Web dynamiques
Voir la catégorie : Langage pour pages Web dynamiques.
Ce type de langages est utilisé pour une plus grande interaction entre un client et un serveur.
Du côté du serveur Web,
cela permet de produire des pages dont le contenu est généré à chaque
affichage. Ces langages sont par ailleurs souvent couplés avec un
langage pour communiquer avec des bases de données (exemple : PHP).
Côté client (en général le navigateur web), les langages de réagir à certaines actions de l'utilisateur sans avoir à questionner le serveur. Par exemple, le JavaScript d'une page Web peut réagir aux saisies de l'utilisateur dans un formulaire (et vérifier le format des données).
Certains langages permettent de développer à la fois les aspects client et serveur. C'est le cas d'Ocsigen, de Hop ou bien encore du Server-Side JavaScript.
Langages de programmation théorique
Voir la catégorie : Langage de programmation théorique.
On désigne parfois par langages de programmation théoriques les systèmes formels
utilisés pour décrire de façon théorique le fonctionnement des
ordinateurs. Ils ne servent pas à développer des applications mais à
représenter des modèles et démontrer certaines de leurs propriétés.
On peut citer la machine de Turing et le λ-calcul de Church,
qui datent tous les deux des années 1930, et donc antérieurs à
l'invention de l'ordinateur. Le λ-calcul a par la suite servi de base
théorique à la famille des langages de programmation fonctionnelle. Dans les années 1980, Robin Milner a mis au point le π-calcul pour modéliser les systèmes concurrents.
Pour rendre la programmation plus difficile
Article détaillé : Langage de programmation exotique.
Les langages exotiques ont pour but de créer des grammaires complètes
et fonctionnelles mais dans un paradigme éloigné des conventions.
Beaucoup sont d'ailleurs considérés comme des blagues.
Ces langages sont généralement difficiles à mettre en pratique et donc rarement utilisés. Par exemple, le Piet permet de programmer à l'aide d'images matricielles.
On peut également citer le Brainfuck qui est un langage minimaliste et Turing-complet ( 8 instructions seulement ). Il est prévu pour tourner sur une machine de Turing avec un compilateur de seulement 171 octets.
Langages spécialisés
- ABEL, langage pour la programmation électronique des PLD
- CDuce, langage fonctionnel d'ordre supérieur pour la manipulation de documents au format XML.
- Forme de Backus-Naur (BNF), formalisation des langages de programmation
- PROMELA, langage de spécification de systèmes asynchrones
- VRML, description de scènes en trois dimensions
- CUDA, pour la programmation GPU des cartes graphiques nVIDIA, utilisé notamment pour le calcul numérique en mécanique des fluides
Langages synchrones
Langages de programmation synchrones pour les systèmes réactifs : Esterel, Lustre.
Langages à vocation pédagogique
Les pseudo-codes (comme le Langage K) ont généralement un but uniquement pédagogique.
Logo est un langage fonctionnel simple à apprendre.
Dans les années 1990 c'est le langage BASIC
qui était souvent conseillé pour débuter. Il avait cependant la
réputation de favoriser la prise de mauvaises habitudes de
programmation.
Langages pour l'électronique numérique
- Verilog, VHDL :
langages de description matérielle, permettant de synthétiser de
l'électronique numérique (descriptions de portes logiques) et d'en
simuler le fonctionnement
- SystemC, langage de description matérielle de plus haut niveau que les précédents et permettant une simulation plus rapide
Langages pour la statistique
R, SAS et xLispStat sont à la fois un langage de statistiques et un logiciel.
Langages de programmation de Commande Numérique (C.N.)
Article détaillé : Programmation de commande numérique.
Une machine-outil automatisée, ou Commande Numérique (C.N.), a besoin d'un langage de programmation pour réaliser les opérations de tournage, ou de fraisage…
Langages de programmation des automates programmables industriels (API)
- Sequential function chart, langage graphique, dérivé du grafcet (NB : le grafcet définit les spécifications de façon graphique)
- Langage Ladder, langage graphique
Langages de programmation audio
Nyquist est un langage de synthèse et d'analyse sonore. Pure Data est un logiciel de création musicale graphique qui repose sur un langage de programmation procédural.