(* Qu'est ce qu'une variable ? Un enregistrement *) (* un nom : string *) (* une valeur mutable de type int *) type variable = {nom: string; mutable valeur: int};; (* Qu'est ce que l'état ? *) (* Une liste de variables au départ la liste vide [] *) (* lorsqu'on veut manipuler une variable non déclarée ... *) exception VariableNonDeclaree;; (* Pour lire la valeur d'une variable. *) let rec valeur nom etat = match etat with | [] -> raise VariableNonDeclaree | x::xs when x.nom = nom -> x.valeur | x::xs -> valeur nom xs;; (* exemples *) valeur "x" [{nom = "x"; valeur = 34}];; valeur "x" [{nom = "y"; valeur = 34}];; valeur "retour de pause" [{nom = "retour de pause"; valeur = -1}];; valeur "x" [{nom = "y"; valeur = 34}; {nom = "x"; valeur = 10}; {nom = "z"; valeur = 34}; {nom = "t"; valeur = 34}; {nom = "x"; valeur = 22}];; (* représenter la déclaration *) let declaration nom etat = {nom=nom; valeur = 0}::etat;; (* exemples *) let etat = declaration "x" [] in declaration "x" etat;; (* représenter l'affectation *) let rec affectation nom valeur etat = match etat with | [] -> raise VariableNonDeclaree | x::xs when x.nom = nom -> x.valeur <- valeur | x::xs -> affectation nom valeur xs;; (* Exemples d'affectation *) let etat = [{nom= "x"; valeur = 9}] in affectation "x" 100 etat; etat;; (*"retourne" [{nom: "x", valeur: 100}] *) let etat = [{nom= "y"; valeur= 9};{nom= "z"; valeur= 3}] in affectation "x" 100 etat; etat;; (*provoque une erreur VariableNonDeclaree *) (*------ cas d'usage (pas du caml) --------*) (* declarer une variable *) etats = [x = 1] "Block [" "Declaration i;" etats = [x = 1; i = 0 ] "Affectation i := 4 + 5" etats = [x = 1; i = 9 ] "]" etats = [x = 1] (* effet de portée *) (* autre situation à traiter: redéclarer une variable *) etats = [i = 1] "Block [" "Declaration i;" etats = [i = 0] (* masquer une variable *) "Affectation i := 4 + 5" etats = [i = 9] "]" etats = [i = 1] (* cas d'erreur *) etats = [ x = 1; y = 2; z = 3; i = 9 ];; "Affectation j := 4";; raise VariableNonDeclaree;; " Declaration x; Declaration y; Affectation x 3; While (y < 1) { Declaration x; Affectation x 5; Affectation y (Valeur x); } " ;; type expression = Ent of int | Plus of expression * expression | Mult of expression * expression | Div of expression * expression | Moins of expression * expression | Opp of expression | Egal of expression * expression | Sup of expression * expression | Inf of expression * expression | Var of string ;; let rec eval e etat = match e with | Ent n -> n | Plus (e1, e2) -> (eval e1 etat) + (eval e2 etat) | Mult (e1, e2) -> (eval e1 etat) * (eval e2 etat) | Div (e1, e2) -> (eval e1 etat) / (eval e2 etat) | Moins (e1, e2) -> (eval e1 etat) - (eval e2 etat) | Opp e1 -> (-1) * (eval e1 etat) | Egal (e1, e2) -> (match (eval e1 etat) = (eval e2 etat) with true -> 1 | false -> 0) | Sup (e1, e2) -> (match (eval e1 etat) > (eval e2 etat) with true -> 1 | false -> 0) | Inf (e1, e2) -> (match (eval e1 etat) < (eval e2 etat) with true -> 1 | false -> 0) | Var nom -> valeur nom etat ;; (* exemples *) (* dans l'environnement x <- 2 on évalue 4 + x *) let etat = [{nom="x"; valeur = 2}] in let e = Plus (Ent 4, Var "x") in eval e etat;; (* dans l'environnement x <- 2 on évalue 4 + y *) let etat = [{nom="x"; valeur = 2}] in let e = Plus (Ent 4, Var "y") in eval e etat;; type instruction = Printstr of string | Print of expression | Block of instruction list | Declaration of string | Affectation of string * expression | While of expression * instruction | Haut | Bas | Droite | Gauche | If of expression * instruction ;; let rec exec prog etat = match prog with | Printstr s -> print_string s; etat | Print e -> print_int (eval e etat); etat | Block [] -> etat | Block (x::xs) -> let nouveletat = exec x etat in exec (Block xs) nouveletat | Declaration nom -> declaration nom etat | Affectation (nom, exp) -> let v = eval exp etat in affectation nom v etat; etat | While (exp, instruction1) as w -> (match (eval exp etat) with | 0 -> etat | _ -> let nouveletat = exec instruction1 etat in exec w nouveletat) | Haut | Bas | Droite | Gauche -> print_string "a implementer"; etat | If (exp, instr) -> (match (eval exp etat) with | 0 -> etat | _ -> exec instr etat) ;; (* un petit exemple *) " int x; x = 10; while (x < 40) { print x; if (x < 30) { printstr ,; } x = x + 10; }";; let p = Block [ Declaration "x"; Affectation ("x", Ent 10); While ( Inf (Var "x", Ent 400), Block [ Print (Var "x"); If (Inf (Var "x", Ent 390), Printstr ", "); Affectation ("x", Plus ((Var "x"), Ent 10)) ]); Printstr "\n" ];; exec p [];;