diff --git a/README.md b/README.md index 057f53c866f0a80decdb110579007babe6aa9b91..df455d1b19c2e1998dd08cc68cfdd8cf43205bfc 100644 --- a/README.md +++ b/README.md @@ -6,28 +6,28 @@ - [Rappels git et gitlab](gitlab.md) - [Questions sur le cours](https://forge.univ-lyon1.fr/programmation-fonctionnelle/lifpf/-/issues/?sort=updated_desc&state=all&label_name%5B%5D=Question) -| jour | heure | type | supports / remarques | -| ----- | ------------- | ------------- | ----------------------------------------------------------------------------------------- | -| 16/01 | 8h | CM | [Diapositives](cm/lifpf-cm1.pdf) | -| | 9h45 | TD | [Sujet](td/lifpf-td1-enonce.pdf), [corrigé](td/lifpf-td1-correction.pdf) | -| 23/01 | 8h | CM | [Diapositives](cm/lifpf-cm2.pdf), [Script démos](cm/cm2-demo.md) | -| | 9h45 ou 11h30 | TP | [Sujet](tp/tp1.md), [corrigé](tp/tp1.ml) <br> Groupe de TP, horaire et salle sur [tomuss] | -| 30/01 | 8h | TD + QCM | [Sujet](td/lifpf-td2-enonce.pdf), [corrigé](td/lifpf-td2-correction.pdf) | -| | 9h45 ou 11h30 | TP | [Sujet](tp/tp2.md), [corrigé](tp/tp2.ml) <br> Groupe de TP, horaire et salle sur [tomuss] | -| 20/02 | 8h | CM | [Diapositives](cm/lifpf-cm3.pdf) | -| | 9h45 ou 11h30 | TP | [Sujet](tp/tp3.md), [corrigé](tp/tp3.ml) | -| 27/02 | 8h | TD + QCM | [Sujet](td/lifpf-td3-enonce.pdf), [corrigé](td/lifpf-td3-correction.pdf) | -| | 9h45 ou 11h30 | TP | [Sujet](tp/tp4.md), [corrigé](tp/tp4.ml) | -| 06/03 | 8h | CM | [Diapositives](cm/lifpf-cm4.pdf) | -| | 9h45 | TD + QCM | [Sujet](td/lifpf-td4-enonce.pdf), [corrigé](td/lifpf-td4-correction.pdf) | -| 13/03 | 8h | CM | [Diapositives](cm/lifpf-cm5.pdf) | -| | 9h45 ou 11h30 | TP | [Sujet](tp/tp5.md), [corrigé de l'exercice 1](tp/tp5.ml) | -| 20/03 | 8h | TD + QCM | [Sujet](td/lifpf-td5-enonce.pdf), [corrigé](td/lifpf-td5-correction.pdf) | -| | 9h45 ou 11h30 | TP | [Sujet](tp/tp6.md), corrigés dans les TD/TPs référencés dans le sujet | -| 27/03 | 9h45 ou 11h15 | TP | [Sujet](tp/tp7.md), [corrigé](tp/tp7.zip) | -| 03/04 | 8h | CM | [Diapositives](cm/lifpf-cm6.pdf), [code](cm/cm6-code.ml) | -| | 9h45 | TD + Contrôle | [Sujet](td/lifpf-td6-enonce.pdf) | -| 24/04 | 9h45 ou 11h15 | TP | [Sujet](tp/tp8.md) <br> Horaires et groupes sur [tomuss] | +| jour | heure | type | supports / remarques | +| ----- | ------------- | ------------- | -------------------------------------------------------------------------------------------------------------- | +| 16/01 | 8h | CM | [Diapositives](cm/lifpf-cm1.pdf) | +| | 9h45 | TD | [Sujet](td/lifpf-td1-enonce.pdf), [corrigé](td/lifpf-td1-correction.pdf) | +| 23/01 | 8h | CM | [Diapositives](cm/lifpf-cm2.pdf), [Script démos](cm/cm2-demo.md) | +| | 9h45 ou 11h30 | TP | [Sujet](tp/tp1.md), [corrigé](tp/tp1.ml) | +| 30/01 | 8h | TD + QCM | [Sujet](td/lifpf-td2-enonce.pdf), [corrigé](td/lifpf-td2-correction.pdf) | +| | 9h45 ou 11h30 | TP | [Sujet](tp/tp2.md), [corrigé](tp/tp2.ml) | +| 20/02 | 8h | CM | [Diapositives](cm/lifpf-cm3.pdf) | +| | 9h45 ou 11h30 | TP | [Sujet](tp/tp3.md), [corrigé](tp/tp3.ml) | +| 27/02 | 8h | TD + QCM | [Sujet](td/lifpf-td3-enonce.pdf), [corrigé](td/lifpf-td3-correction.pdf) | +| | 9h45 ou 11h30 | TP | [Sujet](tp/tp4.md), [corrigé](tp/tp4.ml) | +| 06/03 | 8h | CM | [Diapositives](cm/lifpf-cm4.pdf) | +| | 9h45 | TD + QCM | [Sujet](td/lifpf-td4-enonce.pdf), [corrigé](td/lifpf-td4-correction.pdf) | +| 13/03 | 8h | CM | [Diapositives](cm/lifpf-cm5.pdf) | +| | 9h45 ou 11h30 | TP | [Sujet](tp/tp5.md), [corrigé de l'exercice 1](tp/tp5.ml) | +| 20/03 | 8h | TD + QCM | [Sujet](td/lifpf-td5-enonce.pdf), [corrigé](td/lifpf-td5-correction.pdf) | +| | 9h45 ou 11h30 | TP | [Sujet](tp/tp6.md), corrigés dans les TD/TPs référencés dans le sujet | +| 27/03 | 9h45 ou 11h15 | TP | [Sujet](tp/tp7.md), [corrigé](tp/tp7.zip) | +| 03/04 | 8h | CM | [Diapositives](cm/lifpf-cm6.pdf), [code](cm/cm6-code.ml) | +| | 9h45 | TD + Contrôle | [Sujet](td/lifpf-td6-enonce.pdf) | +| 24/04 | 9h45 ou 11h15 | TP | [Sujet](tp/tp8.md), corrigé calculette programmable: [sans](tp/tp8.ml) ou [avec](tp/tp8b.ml) fonctions natives | ### Évaluation diff --git a/tp/tp8.ml b/tp/tp8.ml new file mode 100644 index 0000000000000000000000000000000000000000..6a155a73f2f37a08a44af993cfb7376d03af2d13 --- /dev/null +++ b/tp/tp8.ml @@ -0,0 +1,126 @@ +(**********************************************************************) +(* Calculatrice programmable *) +(**********************************************************************) + +(** +Type représentant les opérateurs binaires. +*) +type binop = Plus | Moins | Mult | Div + +(** +Expressions arithmétiques + let + fun + app +*) +type expr = + | Cst of int + | Binop of binop * expr * expr + | Var of string + | Let of string * expr * expr + | Fun of string * expr + | App of expr * expr + +(** affichage **) +let rec string_of_expr (e : expr) : string = + let string_of_binop (b : binop) = + match b with + | Plus -> " + " + | Moins -> " - " + | Mult -> " * " + | Div -> " / " + in + + match e with + | Cst n -> string_of_int n + | Binop (op, l, r) -> + "(" ^ string_of_expr l ^ string_of_binop op + ^ string_of_expr r ^ ")" + | Var x -> x + | Let (v, e1, e2) -> + "(let " ^ v ^ " = " ^ string_of_expr e1 ^ " in " + ^ string_of_expr e2 ^ ")" + | Fun (x, e) -> "(fun " ^ x ^ " -> " ^ string_of_expr e ^ ")" + | App (e1, e2) -> + "(" ^ string_of_expr e1 ^ " " ^ string_of_expr e2 ^ ")" + +(** Erreurs *) +type eval_err = DivZero | VarNonDef | PasUneFonction | PasUnInt + +(** Résultats: int ou erreur ou fermeture*) +type resultat = + | Int of int + | Err of eval_err + | Fermeture of string * expr * (string * resultat) list + +(** +Évalue une expression dans un environnement +*) +let rec eval_expr (e : expr) (env : (string * resultat) list) : + resultat = + match e with + | Cst n -> Int n + | Binop (op, e1, e2) -> ( + match (eval_expr e1 env, eval_expr e2 env) with + | Int v1, Int v2 -> ( + match op with + | Plus -> Int (v1 + v2) + | Moins -> Int (v1 - v2) + | Mult -> Int (v1 * v2) + | Div -> if v2 = 0 then Err DivZero else Int (v1 / v2)) + | Fermeture _, _ -> Err PasUnInt + | _, Fermeture _ -> Err PasUnInt + | Err e, _ -> Err e + | _, Err e -> Err e) + | Var x -> ( + match List.assoc_opt x env with + | None -> Err VarNonDef + | Some r -> r) + | Let (x, e1, e2) -> ( + match eval_expr e1 env with + | Err e -> Err e + | v1 -> eval_expr e2 ((x, v1) :: env)) + | Fun (x, e) -> Fermeture (x, e, env) + | App (f, a) -> ( + match eval_expr f env with + | Err e -> Err e + | Int _ -> Err PasUneFonction + | Fermeture (x, e, env_f) -> ( + match eval_expr a env with + | Err e -> Err e + | v -> eval_expr e ((x, v) :: env_f))) + +let e1 = Cst 3 +let e2 = Binop (Plus, Cst 3, Cst 5) +let e3 = Binop (Div, Cst 3, Cst 0) +let e4 = Let ("a", Cst 3, Binop (Moins, Var "a", Cst 3)) +let e5 = Let ("a", Cst 3, Var "b") + +let e6 = + Let + ( "f1", + Fun ("x", Binop (Plus, Var "x", Cst 3)), + Let + ( "f2", + Fun ("y", Binop (Mult, App (Var "f1", Var "y"), Cst 5)), + App (Var "f2", Cst 2) ) ) + +let e7 = + Let + ( "f", + Fun + ( "x", + Fun + ( "y", + Binop (Mult, Var "x", Binop (Plus, Var "y", Cst 3)) + ) ), + App (App (Var "f", Cst 5), Cst 3) ) +;; + +assert (eval_expr e1 [] = Int 3);; +assert (eval_expr e2 [] = Int 8);; +assert (eval_expr e3 [] = Err DivZero);; +assert (eval_expr e4 [] = Int 0);; +assert (eval_expr e5 [] = Err VarNonDef);; +assert (eval_expr e5 [ ("b", Int 11) ] = Int 11);; +assert (eval_expr e6 [] = Int 25);; +assert (eval_expr e7 [] = Int 30) + +(**********************************************************************) diff --git a/tp/tp8b.ml b/tp/tp8b.ml new file mode 100644 index 0000000000000000000000000000000000000000..571433baa06f64927deb3642313191b58bbdae2a --- /dev/null +++ b/tp/tp8b.ml @@ -0,0 +1,127 @@ +(**********************************************************************) +(* Calculatrice programmable, pour aller plus loin *) +(**********************************************************************) + +(** +Expressions arithmétiques + let + fun + app +*) +type expr = + | Cst of int + | Var of string + | Let of string * expr * expr + | Fun of string * expr + | App of expr * expr + +(** affichage **) +let rec string_of_expr (e : expr) : string = + match e with + | Cst n -> string_of_int n + | Var x -> x + | Let (v, e1, e2) -> + "(let " ^ v ^ " = " ^ string_of_expr e1 ^ " in " + ^ string_of_expr e2 ^ ")" + | Fun (x, e) -> "(fun " ^ x ^ " -> " ^ string_of_expr e ^ ")" + | App (e1, e2) -> + "(" ^ string_of_expr e1 ^ " " ^ string_of_expr e2 ^ ")" + +(** Erreurs *) +type eval_err = DivZero | VarNonDef | PasUneFonction | PasUnInt + +(** Résultats: int ou erreur ou fermeture*) +type resultat = + | Int of int + | Err of eval_err + | Fermeture of string * expr * (string * resultat) list + | Native of (resultat -> resultat) + +(** +Évalue une expression dans un environnement +*) +let rec eval_expr (e : expr) (env : (string * resultat) list) : + resultat = + match e with + | Cst n -> Int n + | Var x -> ( + match List.assoc_opt x env with + | None -> Err VarNonDef + | Some r -> r) + | Let (x, e1, e2) -> ( + match eval_expr e1 env with + | Err e -> Err e + | v1 -> eval_expr e2 ((x, v1) :: env)) + | Fun (x, e) -> Fermeture (x, e, env) + | App (f, a) -> ( + match eval_expr f env with + | Err e -> Err e + | Int _ -> Err PasUneFonction + | Fermeture (x, e, env_f) -> ( + match eval_expr a env with + | Err e -> Err e + | v -> eval_expr e ((x, v) :: env_f)) + | Native f -> f (eval_expr a env)) + +let native_binop_res (f : int -> int -> resultat) : resultat = + Native + (fun (a : resultat) -> + Native + (fun (b : resultat) -> + match (a, b) with + | Err e, _ -> Err e + | _, Err e -> Err e + | Int va, Int vb -> f va vb + | _, _ -> Err PasUnInt)) + +let native_binop (f : int -> int -> int) : resultat = + native_binop_res (fun a b -> Int (f a b)) + +let builtins = + [ + ("+", native_binop ( + )); + ("-", native_binop ( - )); + ("*", native_binop ( * )); + ( "/", + native_binop_res (fun x y -> + if y = 0 then Err DivZero else Int (x / y)) ); + ] + +let e1 = Cst 3 +let e2 = App (App (Var "+", Cst 3), Cst 5) +let e3 = App (App (Var "/", Cst 3), Cst 0) +let e4 = Let ("a", Cst 3, App (App (Var "-", Var "a"), Cst 3)) +let e5 = Let ("a", Cst 3, Var "b") + +let e6 = + Let + ( "f1", + Fun ("x", App (App (Var "+", Var "x"), Cst 3)), + Let + ( "f2", + Fun + ( "y", + App (App (Var "*", App (Var "f1", Var "y")), Cst 5) + ), + App (Var "f2", Cst 2) ) ) + +let e7 = + Let + ( "f", + Fun + ( "x", + Fun + ( "y", + App + ( App (Var "*", Var "x"), + App (App (Var "+", Var "y"), Cst 3) ) ) ), + App (App (Var "f", Cst 5), Cst 3) ) +;; + +assert (eval_expr e1 builtins = Int 3);; +assert (eval_expr e2 builtins = Int 8);; +assert (eval_expr e3 builtins = Err DivZero);; +assert (eval_expr e4 builtins = Int 0);; +assert (eval_expr e5 builtins = Err VarNonDef);; +assert (eval_expr e5 (("b", Int 11) :: builtins) = Int 11);; +assert (eval_expr e6 builtins = Int 25);; +assert (eval_expr e7 builtins = Int 30) + +(**********************************************************************)