modification pour Unbound Value les op binaires et les fonctions prédéfini

This commit is contained in:
Nicolas PENELOUX 2023-12-18 18:11:10 +01:00
parent f13440c6f2
commit ec2816ddba

View file

@ -105,6 +105,23 @@ let write_block e i v = T.(FunCall (FunId "write_block", [ e; i; v ]))
let read_block e i = T.(FunCall (FunId "read_block", [ e; i ])) let read_block e i = T.(FunCall (FunId "read_block", [ e; i ]))
let lint i = T.(Literal (LInt (Int64.of_int i))) let lint i = T.(Literal (LInt (Int64.of_int i)))
(* Liste de fonction prédéfini par le code, que l'on retrouve dans les tests*)
let fonction_predef =
["print_string";
"equal_string";
"equal_char";
"observe_int";
"print_int"]
(* On regarde si la fonction est prédéfini : soit par des noms, soit par des opérations binaires*)
let is_a_predefined_function (S.Id op) =
FopixInterpreter.is_binary_primitive op ||
List.mem op fonction_predef
(** [free_variables e] returns the list of free variables that (** [free_variables e] returns the list of free variables that
occur in [e].*) occur in [e].*)
let free_variables = let free_variables =
@ -121,17 +138,15 @@ let free_variables =
| s :: xs -> M.union (f s) (unions f xs) | s :: xs -> M.union (f s) (unions f xs)
in in
(* Une variable libre est une variable qui peut être substitué *) (* Une variable libre est une variable qui peut être substitué *)
(* 1.2
TODO : rajouter des explications pour While Define et Fun *)
let rec fvs = function let rec fvs = function
| S.Literal _ -> M.empty | S.Literal _ -> M.empty
| S.Variable x -> M.singleton x (* Si la fonction est prédéfini, alors ce n'est pas une variable libre. *)
| S.Variable x -> if is_a_predefined_function x then M.empty else M.singleton x
| S.While (cond, e) -> unions fvs [ cond; e ] | S.While (cond, e) -> unions fvs [ cond; e ]
| S.Define (vd, a) -> | S.Define (vd, a) ->
let liste_def_valeur = let liste_def_valeur =
match vd with match vd with
| S.SimpleValue (id, expr) -> [ id, expr ] | S.SimpleValue (id, expr) -> [(id, expr)]
| S.RecFunctions list -> list | S.RecFunctions list -> list
in in
let id, expr = List.split liste_def_valeur in let id, expr = List.split liste_def_valeur in
@ -204,13 +219,10 @@ let translate (p : S.t) env =
let fs, e = expression (reset_vars env) e in let fs, e = expression (reset_vars env) e in
fs @ [ T.DefineValue (identifier x, e) ] fs @ [ T.DefineValue (identifier x, e) ]
| S.RecFunctions fdefs -> | S.RecFunctions fdefs ->
let fs, defs = define_recursive_functions fdefs in let fs, defs = define_recursive_functions env fdefs in
fs @ List.map (fun (x, e) -> T.DefineValue (x, e)) defs fs @ List.map (fun (x, e) -> T.DefineValue (x, e)) defs
and define_recursive_functions rdefs = and define_recursive_functions env rdefs =
(* 1.5
TODO *)
(*failwith "Students! This is your job (define_recursive_functions)!"*)
(*On récupère d'abord les informations qui nous intéresse : nom, variables libres, (*On récupère d'abord les informations qui nous intéresse : nom, variables libres,
arguments, et le corps de la fonction récursive *) arguments, et le corps de la fonction récursive *)
let rdefs =( let rdefs =(
@ -274,12 +286,11 @@ let translate (p : S.t) env =
| S.SimpleValue (id, b) -> | S.SimpleValue (id, b) ->
let bfs, b = expression env b in let bfs, b = expression env b in
afs @ bfs, T.Define (identifier id, a, b) afs @ bfs, T.Define (identifier id, a, b)
| S.RecFunctions _ -> failwith "Students! This is your job (S.RecFunctions)!") | S.RecFunctions rdefs ->
let fs, defs = define_recursive_functions env rdefs in
afs @ fs, defines defs a
)
| S.Apply (a, bs) -> | S.Apply (a, bs) ->
(* (* 1.3 (4) *)
let afs, a = expression env a in
let bsfs, bs = expressions env bs in
afs @ bsfs, T.UnknownFunCall (a, bs) *)
apply env a bs apply env a bs
| S.IfThenElse (a, b, c) -> | S.IfThenElse (a, b, c) ->
let afs, a = expression env a in let afs, a = expression env a in
@ -333,9 +344,16 @@ let translate (p : S.t) env =
and function_identifier (S.Id x) = T.FunId x and function_identifier (S.Id x) = T.FunId x
(* Ici, on rajoute notre fonction anonyme dans la liste des (* Ici, on rajoute notre fonction anonyme dans la liste des
définitions de fonctions *) définitions de fonctions *)
(* Pas sûr pour les T.Id, pareil dans les autres fonctions d'ailleurs *)
and add_liste_funcdef env fid x expr = and add_liste_funcdef env fid x expr =
let dfs, expr = expression env expr in let dfs, expr = expression env expr in
let dfs, expr =
(
let aux x (xs, acc) =
match x with
| T.DefineValue (id, exp) -> xs, T.Define (id,exp,acc)
| x -> x::xs, acc in
List.fold_right aux dfs ([], expr)
) in
dfs @ [ T.DefineFunction (fid, T.Id "oldenvironment" :: x, expr) ] dfs @ [ T.DefineFunction (fid, T.Id "oldenvironment" :: x, expr) ]
and fonction_anonyme ?name ?block env f x e = and fonction_anonyme ?name ?block env f x e =
@ -367,6 +385,8 @@ let translate (p : S.t) env =
+ la taille de la liste de variable (le nombre de variable libre) *) + la taille de la liste de variable (le nombre de variable libre) *)
and new_cloture espace list_variable = and new_cloture espace list_variable =
allocate_block (lint (espace + List.length list_variable + 1)) allocate_block (lint (espace + List.length list_variable + 1))
(* Fonction qui rajoute à la cloture l'ensemble de variable libres *) (* Fonction qui rajoute à la cloture l'ensemble de variable libres *)
and add_to_cloture env fname env_var free_vars rdefs = and add_to_cloture env fname env_var free_vars rdefs =
(* On commence d'abord par écrire dans le premier bloc le nom de (* On commence d'abord par écrire dans le premier bloc le nom de
@ -420,15 +440,18 @@ let translate (p : S.t) env =
le premier bloc et la suite *) le premier bloc et la suite *)
let instrs = List.rev (env_var :: first_block :: vars_free @ vars_fun) in let instrs = List.rev (env_var :: first_block :: vars_free @ vars_fun) in
seqs instrs, env seqs instrs, env
(* 1.4
TODO : Fonction qui s'occupe de S.Apply *)
(* Revoir les explications c'est pas clair *) (* Revoir les explications c'est pas clair *)
and apply env f arguments = and apply env f arguments =
(* D'abord, on traduit chaque arguments *) (* D'abord, on traduit chaque arguments *)
let defs_args, trad_arguments = expressions env arguments in let defs_args, trad_arguments = expressions env arguments in
(* On créé un FunCall en fonction de f *) (* On créé un FunCall en fonction de f *)
match f with match f with
| S.Variable x when Dict.lookup x env.externals <> None -> | S.Variable x when Dict.lookup x env.externals <> None || is_a_predefined_function x->
(* Si f est une externe fonction, on créé directement un FunCall *) (* Si f est une externe fonction, on créé directement un FunCall *)
[], T.FunCall (function_identifier x, trad_arguments) [], T.FunCall (function_identifier x, trad_arguments)
| _ -> | _ ->