From ec2816ddba78e2e9bdb28e41bc08454700f6e348 Mon Sep 17 00:00:00 2001 From: Nicolas PENELOUX Date: Mon, 18 Dec 2023 18:11:10 +0100 Subject: [PATCH] =?UTF-8?q?modification=20pour=20Unbound=20Value=20les=20o?= =?UTF-8?q?p=20binaires=20et=20les=20fonctions=20pr=C3=A9d=C3=A9fini?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- flap/src/fopix/hobixToFopix.ml | 63 +++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 20 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index 5c7b208..0fe8702 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -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 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 occur in [e].*) let free_variables = @@ -121,17 +138,15 @@ let free_variables = | s :: xs -> M.union (f s) (unions f xs) in (* 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 | 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.Define (vd, a) -> let liste_def_valeur = match vd with - | S.SimpleValue (id, expr) -> [ id, expr ] + | S.SimpleValue (id, expr) -> [(id, expr)] | S.RecFunctions list -> list 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 fs @ [ T.DefineValue (identifier x, e) ] | 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 - and define_recursive_functions rdefs = - (* 1.5 - TODO *) - (*failwith "Students! This is your job (define_recursive_functions)!"*) - + and define_recursive_functions env rdefs = + (*On récupère d'abord les informations qui nous intéresse : nom, variables libres, arguments, et le corps de la fonction récursive *) let rdefs =( @@ -274,12 +286,11 @@ let translate (p : S.t) env = | S.SimpleValue (id, b) -> let bfs, b = expression env b in 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) -> - (* (* 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 | S.IfThenElse (a, b, c) -> 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 (* Ici, on rajoute notre fonction anonyme dans la liste des 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 = 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) ] 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) *) and new_cloture espace list_variable = allocate_block (lint (espace + List.length list_variable + 1)) + + (* Fonction qui rajoute à la cloture l'ensemble de variable libres *) and add_to_cloture env fname env_var free_vars rdefs = (* 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 *) let instrs = List.rev (env_var :: first_block :: vars_free @ vars_fun) in seqs instrs, env - (* 1.4 - TODO : Fonction qui s'occupe de S.Apply *) + + + + (* Revoir les explications c'est pas clair *) and apply env f arguments = (* D'abord, on traduit chaque arguments *) + let defs_args, trad_arguments = expressions env arguments in (* On créé un FunCall en fonction de f *) 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 *) [], T.FunCall (function_identifier x, trad_arguments) | _ ->