TP-programmation-fonctionnelle/BE/listmem.ml

116 lines
3.4 KiB
OCaml
Raw Normal View History

2023-06-21 18:13:54 +00:00
open Mem
open Util
(* generate: int -> 'a -> 'a list
* Créer une liste de taille fixe qui contient un élément particulier.
* Paramètres :
* n : int, taille de la liste
* x : 'a, élément dont la est remplie
* Retour :
* liste de taille n et qui contient des x
*)
let rec generate n x =
if n <= 0 then []
else x::(generate (n - 1) x)
let%test "generate-0" = generate 0 5 = []
let%test "generate-1" = generate 5 'a' = ['a';'a';'a';'a';'a']
let%test "generate-2" = generate 3 1 = [1;1;1]
(* get: 'a list -> int -> 'a
* Récupère l'élément en n-ième position d'une liste
* Paramètres :
* l : 'a list, liste à parcourir
* n : int, position de l'élément à récupérer
* Retour :
* élément à la position n de l
* Exception :
* OutOfBound si la position souhaitée n'est pas dans la liste
*)
let rec get l n =
match l,n with
| t::_, 0 -> t
| _::q, n -> get q (n - 1)
| [], _ -> raise OutOfBound
(* Autre version avec List :
* let get l n =
* if n >= List.length l then
* raise OutOfBound
* else
* List.nth l n
*)
let%test "get-1" = get [5;7;9] 2 = 9
let%test "get-2" = get ['o';'c';'a';'m';'l'] 3 = 'm'
let%test "get-3" =
try let _ = get [1;2;3] 5 in false with OutOfBound -> true
(* set: 'a list -> int -> 'a -> 'a list
* Modifie l'élement en n-ième position d'une liste
* Paramètres :
* l : 'a list, liste à modifier
* n : int, position de l'élément à changer
* x : 'a, nouvelle valeur de l'élément
* Retour l
* liste modifiée (telle que l[n] = x)
* Exception l
* OutOfBound si la position souhaitée n'est pas dans la liste
*)
let rec set l n x =
match l,n with
| _::q, 0 -> x::q
| t::q, n -> t::(set q (n - 1) x)
| [], _ -> raise OutOfBound
let%test "set-1" = set [5;7;9] 2 3 = [5;7;3]
let%test "set-2" = set ['o';'c';'a';'m';'l'] 3 'b' = ['o';'c';'a';'b';'l']
let%test "set-3" =
try let _ = set [1;2;3] 5 0 in false with OutOfBound -> true
(* Implémentation simpliste et peu efficace d'une mémoire à base de listes.
*
* En OCaml, on pourrait utiliser des vecteurs (non vu en cours), mais les
* listes sont bien pour mettre en évidence les problèmes de complexité
* temporelle et surtout spatiale !
*)
module ListMemory : Memory =
struct
(* Le type "support" est une liste *)
type mem_type = char list
(* Un type qui contient la mémoire + la taille de son bus d'adressage *)
type mem = int * mem_type
let name = "list"
(* Obtenir la taille du bus d'adressage *)
let bussize (bs, _) = bs
(* Obtenir la taille de la mémoire *)
let size (bs, _) = pow2 bs
(* Obtenir la taille effective de la mémoire.
* On a alloué une liste de 2^bs éléments...
*)
let allocsize (_, l) = List.length l
(* Obtenir le nombre de valeurs stockées en mémoire. *)
let busyness (_, l) =
List.fold_left (fun acc t -> if t = _0 then acc else acc + 1) 0 l
(* List.length (List.filter (fun i -> i <> _0) l) *)
(* Lire une valeur *)
(* Obtenir une mémoire vide avec adressage sur n bits *)
(* À essayer : clear 20 => stack overflow ! *)
let clear bs = (bs, generate (pow2 bs) _0)
(* Complexité : O(2^bs) *)
let read (_, l) addr = get l addr
(* Écrire une valeur. *)
(* Complexité : O(2^bs) *)
let write (bs, l) addr value =
(bs, set l addr value)
end