MIC : Langage mini-Caml

abstraction concrète

Le langage mini-Caml (version réo maohi)

Bien que le langage mini-Caml soit défini à partir d'un sous-ensemble du langage fonctionnel Caml, il n'en conserve pas moins son caractère en implémentant la synthèse des types, la pleine fonctionnalité et le polymorphisme.

La pleine fonctionnalité considère les fonctions comme des valeurs fonctionnelles rendues par les expressions qui définissent ces fonctions. Les valeurs fonctionnelles peuvent être passées en arguments à d'autres fonctions ou retournées comme valeur de résultat d'autres fonctions.

Une fonction polymorphe est une fonction qui peut être appliquée à tous les types.

Les phrases

Les phrases acceptées par l'interprète sont des définitions ou des expressions du langage mini-Caml terminées par un double point-virgule ";;".

De plus, l'interprète reconnaît une unique commande "ha'amata_fa'ahou();;" qui produit le même effet que le bouton

L'évaluation des expressions et l'environnement

L'interprète type et évalue les expressions mini-Caml en effectuant les opérations indiquées sur les valeurs qu'elles contiennent. Lorsqu'un identificateur figure dans une expression, l'interprète tente de le remplacer par la valeur qui lui est associée dans l'environnement courant.

Les identificateurs

Ils commencent obligatoirement par une lettre soit seule soit suivie d'une séquence de caractères dont chacun d'entre-eux peut être :

- une lettre,
- un chiffre,
- le caractère "tiret_bas" ou "underscore" : `_`
- ou le caractère "apostrophe" ou "quote" : `'`.

Les lettres comprennent les lettres accentuées.

Les majuscules sont distinguées des minuscules.

Les expressions

  • Les expressions simples
  • L'expression conditionnelle
  • L'expression conditionnelle par cas
  • L'expression fonctionnelle
  • L'application

    Les expressions simples

    Il s'agit d'expression constituée soit d'une valeur, soit d'un identificateur. Elles rendent la valeur correspondante.

    Session en cours avec a = 7 dans l'environnement courant et b est inconnu.
    # 99;;
    - : numera ta'ato'a = 99
    # mau;;
    - : parau 'ite = mau
    # a;;
    - : numera ta'ato'a = 7
    # b;;
    Erreur : b est inconnu
    

    L'expression conditionnelle

    L'expression
    'ia condition mai_te_mea_e expr_alors mai_te_mea_aita expr_sinon
    évalue l'expression booléenne condition, et si elle vaut mau elle retourne la valeur de expr_alors, sinon elle retourne la valeur de expr_sinon.

    Session en cours avec u = 101 et huru = 212 dans l'environnement courant.
    # 'ia huru = 2*u mai_te_mea_e 1 mai_te_mea_aita 0 ;;
    - : numera ta'ato'a = 0
    # 'ia huru = 2*u+10 mai_te_mea_e 1 mai_te_mea_aita 0 ;;
    - : numera ta'ato'a = 1
    

    L'expression conditionnelle par cas

    L'expression
    fa'afaito expression mai_te
        motif_1 -> expr_1
       ...
      | motif_i -> expr_i
       ...
      | motif_n -> expr_n
    compare successivement la valeur de l'expression à filtrer expression avec les motifs motif_1 à motif_n.
    Si l'un des motifs est égal à la valeur de expression le résultat obtenu donné par la valeur de l'expression à droite de la flèche correspondant au motif sélectionné. expr_sinon.
    Si plusieurs motifs ont la même valeur que l'expression à filtrer, c'est le premier d'entre-eux qui est choisi.
    Si aucun motif ne peut correspondre à la valeur à filtrer, une erreur d'échec du filtrage est déclenchée.

    Un motif est une valeur, un identificateur, ou une construction formée par la combinaison de valeurs et/ou d'identificateurs avec le constructeur de paires "," et/ou le constructeur de listes "::".

    >MIC : nouvelle session (just for <fun> !)
    
    # fa'afaito (5*5-1) mai_te 16 -> 1 | 20 -> 2 | 24 -> 3 | 30 -> 4 ;; - : numera ta'ato'a = 3 # fa'afaito (5*5-1) mai_te 16 -> 1 | 20 -> 2 | 30 -> 3 ;; Erreur : Echec filtrage

    Si un identificateur apparaît dans un motif, il représente alors toute la gamme des valeurs du type qui lui est associé, et s'il est sélectionné, il est lié à la valeur filtrée.

    Session en cours avec mahana = 4 dans l'environnement courant.
    # fa'afaito mahana mai_te 1 -> 0 | n -> n * 3 ;;
    - : numera ta'ato'a = 12
    

    L'expression fonctionnelle

    Une expression fonctionnelle
    mai_te_au_i
        motif_1 -> expr_1
       ...
      | motif_i -> expr_i
       ...
      | motif_n -> expr_n
    est une construction destinée à accepter un argument et à y faire correspondre un résultat par comparaison de la valeur de l'argument à la suite des associations (motif -> expression) en procédant à un filtrage comme pour l'expression conditionnelle par cas.

    >MIC : nouvelle session (just for <fun> !)
    
    # mai_te_au_i mau -> 0 | hape -> 1 ;; - : (parau 'ite -> numera ta'ato'a) = <fun> # mai_te_au_i x -> x*x ;; - : (numera ta'ato'a -> numera ta'ato'a) = <fun>

    L'application

    Une application est une expression formée par la juxtaposition de deux expressions dont la première est une expression fonctionnelle et la seconde son argument.
    L'application expr_fonction expr_arg rend la valeur prise par l'expression fonctionnelle expr_fonction pour la valeur de l'argument expr_arg.

    >MIC : nouvelle session (just for <fun> !)
    
    # (mai_te_au_i x -> x*x) 8 ;; - : numera ta'ato'a = 64 # (mai_te_au_i mau -> 0 | hape -> 1) mau ;; - : numera ta'ato'a = 0 # (mai_te_au_i mau -> 0 | hape -> 1) hape ;; - : numera ta'ato'a = 1

    Les définitions

  • Les définitions simples
  • Les définitions imbriquées
  • Les définitions récursives

    Les définitions simples :

    Les définitions de la forme te_vai ident = expr installent, dans l'environnement courant, des associations (ident,valeur_expr) où valeur_expr est la valeur de l'expression expr.

    >MIC : nouvelle session (just for <fun> !)
    
    # te_vai x = 3 ;; x : numera ta'ato'a = 3 # te_vai h = mai_te_au_i u -> x*u + x ;; h : (numera ta'ato'a -> numera ta'ato'a) = # h 4 ;; - : numera ta'ato'a = 15

    Les définitions imbriquées :

    Dans les expressions de la forme te_vai ident = expr 'i_roto expression la définition à gauche du mot-clé dans ajoute l'association (ident,valeur_expr) à l'environnement courant pour former un environnement temporaire dans lequel expression est évaluée.

    >MIC : nouvelle session (just for <fun> !)
    
    # te_vai y = -8 'i_roto 9 + y*y ;; - : numera ta'ato'a = 73 # te_vai g = mai_te_au_i x -> 5*x*x - 44*x + 1 'i_roto (g 7);; - : numera ta'ato'a = -62 # te_vai a = te_vai s = mai_te_au_i x -> (x+4,x-4) 'i_roto s 3 ;; a : (numera ta'ato'a * numera ta'ato'a) = ( 7, -1)

    Les définitions récursives :

    L'interprète accepte les constructions récursives pour la définition d'expressions fonctionnelles.

    1er exemple : la fonction factorielle.

    >MIC : nouvelle session (just for <fun> !)
    
    # te_vai rec fact = mai_te_au_i 0 -> 1 | n -> 'ia(n<0) mai_te_mea_e 1/0 mai_te_mea_aita n*fact(n-1) ;; fact : (numera ta'ato'a -> numera ta'ato'a) = <fun> # fact 0;; - : numera ta'ato'a = 1 # fact 6;; - : numera ta'ato'a = 720 # fact -2;; Erreur : division par 0

    Noter que dans le cas où un entier négatif est passé en argument, le calcul de l'expression n*fact(n-1) forme une boucle infinie. On utilise, ici, une division par zéro, pour déclencher une erreur qui provoque la sortie du programme.

    La gestion des exceptions ne fait pas partie de la définition de ce sous-ensemble du langage Caml.

    2eme exemple : la fonction mem.

    L'application (mem objet liste_explorée) vérifie si objet est membre de la liste liste_explorée.

    >MIC : nouvelle session (just for <fun> !)
    
    # te_vai rec mem = mai_te_au_i x -> (mai_te_au_i [] -> hape | a::r -> 'ia x=a mai_te_mea_e mau mai_te_mea_aita mem x r) ;; mem : ('a -> ('a list -> parau 'ite)) = <fun> # mem 4 (0::1::3::[]) ;; - : parau 'ite = hape # mem 4 (0::1::3::4::[]) ;; - : parau 'ite = mau

    Les valeurs et les types

  • Entiers
  • Booléens
  • Paires
  • Listes

    Les nombres entiers :

    Les nombres entiers sont représentés par le type numera ta'ato'a,
    avec les quatre opérateurs arithmétiques (+, -, *, /)
    et les opérateurs de comparaison (<, <=, >, >=, =, <>)

    >MIC : nouvelle session (just for <fun> !)
    
    # te_vai x=5 ;; x : numera ta'ato'a = 5 # te_vai y = -3 dans y*x - x*x + y*y ;; - : numera ta'ato'a = -31 # 19/x ;; - : numera ta'ato'a = 3

    Les booléens :

    Les booléens mau et hape sont représentés par le type parau 'ite,
    ils sont utilisés avec les opérateurs de comparaison (<, <=, >, >=, =, <>)

    >MIC : nouvelle session (just for <fun> !)
    
    # te_vai a = (0 = 1-1) ;; a : parau 'ite = mau # te_vai equiv = mai_te_au_i mau -> (mai_te_au_i mau -> mau | hape -> hape) | hape -> (mai_te_au_i mau -> hape | hape -> mau) ;; equiv : (parau 'ite -> (parau 'ite -> parau 'ite)) = <fun> # equiv mau mau ;; - : parau 'ite = mau # equiv hape mau ;; - : parau 'ite = hape # equiv mau hape ;; - : parau 'ite = hape # equiv hape hape ;; - : parau 'ite = mau

    Les paires :

    Une paire est constituée par un couple de valeurs de types 'a et 'b quelconques, et est representée par le type ('a * 'b).

    Si u est une valeur de type 'a et v une valeur de type 'b, en associant ces deux valeurs avec le constructeur de paires "," on obtient la valeur (u,v) qui est une paire du type ('a * 'b).

    >MIC : nouvelle session (just for <fun> !)
    
    # te_vai fst = mai_te_au_i(a,b) -> a ;; fst : (('a * 'b) -> 'a) = <fun> # fst(4,3);; - : numera ta'ato'a = 4 # te_vai snd = mai_te_au_i(a,b) -> b ;; snd : (('a * 'b) -> 'b) = <fun> # snd(4,3) ;; - : numera ta'ato'a = 3

    Les listes :

    Une liste du type 'a tapura est :
  • soit une liste vide,
  • soit formée d'une tête de liste et d'un reste de liste :
    • la tête de liste est une valeur de type 'a
    • le reste de liste est une liste du type 'a tapura.

    La liste vide a pour valeur []. La valeur x::r exprime une liste non vide dans laquelle x est la tête de la liste, "::" est le constructeur de listes et r est le reste de liste.

    Ce qui précède constitue la seule représentation des listes reconnue par l'interprète. En revanche l'interprète affiche les listes en énumérant tous leurs éléments entre crochets et séparés par des points-virgules.

    1. Exemple de liste reconnue par l'interprète : 1::2::3::[]
    2. Exemple de liste affichée par l'interprète : [ 1; 2; 3]
    Attention : l'interprète affiche mais ne reconnaît pas les listes sous la deuxième forme.

    >MIC : nouvelle session (just for <fun> !)
    
    # te_vai hd = mai_te_au_i x::r -> x ;; hd : ('a tapura -> 'a) = <fun> # hd (5::3::[]) ;; - : numera ta'ato'a = 5 # hd ([]) ;; Erreur : Echec filtrage # te_vai tl = mai_te_au_i x::r -> r ;; tl : ('a tapura -> 'a tapura) = <fun> # tl(2::0::5::[]) ;; - : numera ta'ato'a tapura = [ 0; 5] # tl [] ;; Erreur : Echec filtrage

    On remarque que dans la définition des fonctions hd et tl le cas de la liste vide n'est pas filtré, ce qui provoque un échec du filtrage lors de l'application de l'une de ces fonctions à la liste vide [].

    Le polymorphisme :

    Certaines fonctions sont polymorphes, c'est à dire qu'elles peuvent être appliquées à des types variés.

    Un exemple est donné, ici, avec la fonction qui construit une paire à partir de ses arguments.

    >MIC : nouvelle session (just for <fun> !)

    # te_vai f = mai_te_au_i x -> mai_te_au_i y -> (x,y) ;;
    f : ('a -> ('b -> ('a * 'b))) = <fun>
    # f 8 5 ;;
    - : (numera ta'ato'a * numera ta'ato'a) = (8, 5)
    # f mau [] ;;
    - : (parau 'ite * 'a list) = ( mau, [])
    # f mau hape ;;
    - : (parau 'ite * parau 'ite) = ( mau, hape)

    Quelques cas d'erreurs

    >MIC : nouvelle session (just for <fun> !)
    
    # g 4 Erreur : syntaxe incorrecte ou phrase incomplète
    Il manque le double point-virgule pour terminer la phrase.
    # te_vai _a = 9 ;;
    Erreur : erreur lexicale
    
    le mot "_a" n'est pas reconnu comme étant un identificateur valide.
    # te_vai alpha' = 5 ;;
    alpha' : numera ta'ato'a = 5
    # te_vai beta_1 = 3 ;;
    beta_1 : numera ta'ato'a = 3
    # te_vai gamma = alpha + beta ;;
    Erreur : alpha est inconnu
    # te_vai gamma = alpha' + beta ;;
    Erreur : beta est inconnu
    # te_vai gamma = alpha' + beta_1 ;;
    gamma : numera ta'ato'a = 8
    
    Les identificateurs alpha et beta n'ont pas été déclarés.
    # te_vai g = mai_te_au_i x -> x * x * 3 - 94 * x - 1 ;;
    g : (numera ta'ato'a -> numera ta'ato'a) = <fun>
    # g 7 ;;
    - : numera ta'ato'a = -512
    # g mau ;;
    Conflit de types : 
    incompatibilté numera ta'ato'a avec parau 'ite
    
    La fonction g reçoit un argument du type numera ta'ato'a et ne peut donc pas être appliquée à une valeur parau 'itene.
    # te_vai rec a = 9 ;;
    Erreur : te_vai rec non fonctionnel
    
    La construction récursive "te_vai rec" ne peut être utilisée qu'avec une valeur fonctionnelle.

    Contacter l'auteur :
    <Jacques.Rouable@wanadoo.fr>

    dernière modification : 05/04/97