From 90658e0155dceeb63c05d293c78b916f296ed59a Mon Sep 17 00:00:00 2001 From: Mylloon Date: Sun, 10 Dec 2023 15:45:09 +0100 Subject: [PATCH 01/20] move to correct folder --- jalon-4.pdf => jalons/jalon-4.pdf | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename jalon-4.pdf => jalons/jalon-4.pdf (100%) diff --git a/jalon-4.pdf b/jalons/jalon-4.pdf similarity index 100% rename from jalon-4.pdf rename to jalons/jalon-4.pdf From 63ec3b464e265ceb801602ea721d29696b822064 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Sun, 10 Dec 2023 15:45:36 +0100 Subject: [PATCH 02/20] fmt --- flap/src/fopix/hobixToFopix.ml | 314 +++++++++++++++------------------ 1 file changed, 140 insertions(+), 174 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index 478622a..d49fe01 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -8,152 +8,140 @@ module S = Source.AST module Target = Fopix module T = Target.AST -(** +(** The translation from Hobix to Fopix turns anonymous + lambda-abstractions into toplevel functions and applications into + function calls. In other words, it translates a high-level language + (like OCaml) into a first order language (like C). - The translation from Hobix to Fopix turns anonymous - lambda-abstractions into toplevel functions and applications into - function calls. In other words, it translates a high-level language - (like OCaml) into a first order language (like C). + To do so, we follow the closure conversion technique. - To do so, we follow the closure conversion technique. + The idea is to make explicit the construction of closures, which + represent functions as first-class objects. A closure is a block + that contains a code pointer to a toplevel function [f] followed by all + the values needed to execute the body of [f]. For instance, consider + the following OCaml code: - The idea is to make explicit the construction of closures, which - represent functions as first-class objects. A closure is a block - that contains a code pointer to a toplevel function [f] followed by all - the values needed to execute the body of [f]. For instance, consider - the following OCaml code: + let f = + let x = 6 * 7 in + let z = x + 1 in + fun y -> x + y * z - let f = - let x = 6 * 7 in - let z = x + 1 in - fun y -> x + y * z + The values needed to execute the function "fun y -> x + y * z" are + its free variables "x" and "z". The same program with explicit usage + of closure can be written like this: - The values needed to execute the function "fun y -> x + y * z" are - its free variables "x" and "z". The same program with explicit usage - of closure can be written like this: + let g y env = env[1] + y * env[2] + let f = + let x = 6 * 7 in + let z = x + 1 in + [| g; x; z |] - let g y env = env[1] + y * env[2] - let f = - let x = 6 * 7 in - let z = x + 1 in - [| g; x; z |] + (in an imaginary OCaml in which arrays are untyped.) - (in an imaginary OCaml in which arrays are untyped.) + Once closures are explicited, there are no more anonymous functions! - Once closures are explicited, there are no more anonymous functions! + But, wait, how to we call such a function? Let us see that on an + example: - But, wait, how to we call such a function? Let us see that on an - example: + let f = ... (* As in the previous example *) + let u = f 0 - let f = ... (* As in the previous example *) - let u = f 0 + The application "f 0" must be turned into an expression in which + "f" is a closure and the call to "f" is replaced to a call to "g" + with the proper arguments. The argument "y" of "g" is known from + the application: it is "0". Now, where is "env"? Easy! It is the + closure itself! We get: - The application "f 0" must be turned into an expression in which - "f" is a closure and the call to "f" is replaced to a call to "g" - with the proper arguments. The argument "y" of "g" is known from - the application: it is "0". Now, where is "env"? Easy! It is the - closure itself! We get: + let g y env = env[1] + y * env[2] + let f = + let x = 6 * 7 in + let z = x + 1 in + [| g; x; z |] + let u = f[0] 0 f - let g y env = env[1] + y * env[2] - let f = - let x = 6 * 7 in - let z = x + 1 in - [| g; x; z |] - let u = f[0] 0 f + (Remark: Did you notice that this form of "auto-application" is + very similar to the way "this" is defined in object-oriented + programming languages?) *) - (Remark: Did you notice that this form of "auto-application" is - very similar to the way "this" is defined in object-oriented - programming languages?) +(** Helpers functions. *) -*) - -(** - Helpers functions. -*) - -let error pos msg = - Error.error "compilation" pos msg +let error pos msg = Error.error "compilation" pos msg let make_fresh_variable = let r = ref 0 in - fun () -> incr r; T.Id (Printf.sprintf "_%d" !r) - + fun () -> + incr r; + T.Id (Printf.sprintf "_%d" !r) +;; let make_fresh_function_identifier = let r = ref 0 in - fun () -> incr r; T.FunId (Printf.sprintf "_%d" !r) + fun () -> + incr r; + T.FunId (Printf.sprintf "_%d" !r) +;; let define e f = let x = make_fresh_variable () in T.Define (x, e, f x) +;; let rec defines ds e = match ds with - | [] -> - e - | (x, d) :: ds -> - T.Define (x, d, defines ds e) + | [] -> e + | (x, d) :: ds -> T.Define (x, d, defines ds e) +;; -let seq a b = - define a (fun _ -> b) +let seq a b = define a (fun _ -> b) let rec seqs = function | [] -> assert false - | [x] -> x + | [ x ] -> x | x :: xs -> seq x (seqs xs) +;; -let allocate_block e = - T.(FunCall (FunId "allocate_block", [e])) - -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))) - +let allocate_block e = T.(FunCall (FunId "allocate_block", [ e ])) +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))) (** [free_variables e] returns the list of free variables that - occur in [e].*) + occur in [e].*) let free_variables = let module M = - Set.Make (struct type t = S.identifier let compare = compare end) + Set.Make (struct + type t = S.identifier + + let compare = compare + end) in let rec unions f = function | [] -> M.empty - | [s] -> f s + | [ s ] -> f s | s :: xs -> M.union (f s) (unions f xs) in let rec fvs = function - | S.Literal _ -> - M.empty - | S.Variable x -> - M.singleton x - | S.While (cond, e) -> - failwith "Students! This is your job!" - | S.Define (vd, a) -> - failwith "Students! This is your job!" - | S.ReadBlock (a, b) -> - unions fvs [a; b] - | S.Apply (a, b) -> - unions fvs (a :: b) - | S.WriteBlock (a, b, c) | S.IfThenElse (a, b, c) -> - unions fvs [a; b; c] - | S.AllocateBlock a -> - fvs a - | S.Fun (xs, e) -> - failwith "Students! This is your job!" + | S.Literal _ -> M.empty + | S.Variable x -> M.singleton x + | S.While (cond, e) -> failwith "Students! This is your job!" + | S.Define (vd, a) -> failwith "Students! This is your job!" + | S.ReadBlock (a, b) -> unions fvs [ a; b ] + | S.Apply (a, b) -> unions fvs (a :: b) + | S.WriteBlock (a, b, c) | S.IfThenElse (a, b, c) -> unions fvs [ a; b; c ] + | S.AllocateBlock a -> fvs a + | S.Fun (xs, e) -> failwith "Students! This is your job!" | S.Switch (a, b, c) -> - let c = match c with None -> [] | Some c -> [c] in - unions fvs (a :: ExtStd.Array.present_to_list b @ c) + let c = + match c with + | None -> [] + | Some c -> [ c ] + in + unions fvs ((a :: ExtStd.Array.present_to_list b) @ c) in fun e -> M.elements (fvs e) +;; -(** - - A closure compilation environment relates an identifier to the way +(** A closure compilation environment relates an identifier to the way it is accessed in the compiled version of the function's body. @@ -170,128 +158,106 @@ let free_variables = Indeed, "x" is a local variable that can be accessed directly in the compiled version of this function's body whereas "y" is a free variable whose value must be retrieved from the closure's - environment. + environment. *) +type environment = + { vars : (HobixAST.identifier, FopixAST.expression) Dict.t + ; externals : (HobixAST.identifier, int) Dict.t + } -*) -type environment = { - vars : (HobixAST.identifier, FopixAST.expression) Dict.t; - externals : (HobixAST.identifier, int) Dict.t; -} - -let initial_environment () = - { vars = Dict.empty; externals = Dict.empty } - -let bind_external id n env = - { env with externals = Dict.insert id n env.externals } - -let is_external id env = - Dict.lookup id env.externals <> None - -let reset_vars env = - { env with vars = Dict.empty } +let initial_environment () = { vars = Dict.empty; externals = Dict.empty } +let bind_external id n env = { env with externals = Dict.insert id n env.externals } +let is_external id env = Dict.lookup id env.externals <> None +let reset_vars env = { env with vars = Dict.empty } (** Precondition: [is_external id env = true]. *) let arity_of_external id env = match Dict.lookup id env.externals with - | Some n -> n - | None -> assert false (* By is_external. *) - + | Some n -> n + | None -> assert false (* By is_external. *) +;; (** [translate p env] turns an Hobix program [p] into a Fopix program using [env] to retrieve contextual information. *) let translate (p : S.t) env = let rec program env defs = let env, defs = ExtStd.List.foldmap definition env defs in - (List.flatten defs, env) + List.flatten defs, env and definition env = function | S.DeclareExtern (id, n) -> - let env = bind_external id n env in - (env, [T.ExternalFunction (function_identifier id, n)]) - | S.DefineValue vd -> - (env, value_definition env vd) + let env = bind_external id n env in + env, [ T.ExternalFunction (function_identifier id, n) ] + | S.DefineValue vd -> env, value_definition env vd and value_definition env = function | S.SimpleValue (x, e) -> - let fs, e = expression (reset_vars env) e in - fs @ [T.DefineValue (identifier x, e)] + 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 - fs @ List.map (fun (x, e) -> T.DefineValue (x, e)) defs - - and define_recursive_functions rdefs = - failwith "Students! This is your job!" + let fs, defs = define_recursive_functions fdefs in + fs @ List.map (fun (x, e) -> T.DefineValue (x, e)) defs + and define_recursive_functions rdefs = failwith "Students! This is your job!" and expression env = function - | S.Literal l -> - [], T.Literal (literal l) + | S.Literal l -> [], T.Literal (literal l) | S.While (cond, e) -> - let cfs, cond = expression env cond in - let efs, e = expression env e in - cfs @ efs, T.While (cond, e) + let cfs, cond = expression env cond in + let efs, e = expression env e in + cfs @ efs, T.While (cond, e) | S.Variable x -> let xc = match Dict.lookup x env.vars with - | None -> T.Variable (identifier x) - | Some e -> e + | None -> T.Variable (identifier x) + | Some e -> e in - ([], xc) - | S.Define (vdef, a) -> - failwith "Students! This is your job!" - | S.Apply (a, bs) -> - failwith "Students! This is your job!" + [], xc + | S.Define (vdef, a) -> failwith "Students! This is your job!" + | S.Apply (a, bs) -> failwith "Students! This is your job!" | S.IfThenElse (a, b, c) -> let afs, a = expression env a in let bfs, b = expression env b in let cfs, c = expression env c in afs @ bfs @ cfs, T.IfThenElse (a, b, c) - - | S.Fun (x, e) -> - failwith "Students! This is your job!" + | S.Fun (x, e) -> failwith "Students! This is your job!" | S.AllocateBlock a -> let afs, a = expression env a in - (afs, allocate_block a) + afs, allocate_block a | S.WriteBlock (a, b, c) -> let afs, a = expression env a in let bfs, b = expression env b in let cfs, c = expression env c in - afs @ bfs @ cfs, - T.FunCall (T.FunId "write_block", [a; b; c]) + afs @ bfs @ cfs, T.FunCall (T.FunId "write_block", [ a; b; c ]) | S.ReadBlock (a, b) -> let afs, a = expression env a in let bfs, b = expression env b in - afs @ bfs, - T.FunCall (T.FunId "read_block", [a; b]) + afs @ bfs, T.FunCall (T.FunId "read_block", [ a; b ]) | S.Switch (a, bs, default) -> let afs, a = expression env a in let bsfs, bs = - ExtStd.List.foldmap (fun bs t -> - match ExtStd.Option.map (expression env) t with - | None -> (bs, None) - | Some (bs', t') -> (bs @ bs', Some t') - ) [] (Array.to_list bs) + ExtStd.List.foldmap + (fun bs t -> + match ExtStd.Option.map (expression env) t with + | None -> bs, None + | Some (bs', t') -> bs @ bs', Some t') + [] + (Array.to_list bs) in - let dfs, default = match default with + let dfs, default = + match default with | None -> [], None - | Some e -> let bs, e = expression env e in bs, Some e + | Some e -> + let bs, e = expression env e in + bs, Some e in - afs @ bsfs @ dfs, - T.Switch (a, Array.of_list bs, default) - - + afs @ bsfs @ dfs, T.Switch (a, Array.of_list bs, default) and expressions env = function - | [] -> - [], [] + | [] -> [], [] | e :: es -> - let efs, es = expressions env es in - let fs, e = expression env e in - fs @ efs, e :: es - + let efs, es = expressions env es in + let fs, e = expression env e in + fs @ efs, e :: es and literal = function | S.LInt x -> T.LInt x | S.LString s -> T.LString s | S.LChar c -> T.LChar c - and identifier (S.Id x) = T.Id x - - and function_identifier (S.Id x) = T.FunId x - - in + and function_identifier (S.Id x) = T.FunId x in program env p +;; From 1921101d451e0ae37dd1a15d2ba7660885749e26 Mon Sep 17 00:00:00 2001 From: Nicolas PENELOUX Date: Tue, 12 Dec 2023 16:13:31 +0100 Subject: [PATCH 03/20] =?UTF-8?q?Etape=202=20:=20free=5Fvariables=20(?= =?UTF-8?q?=C3=A0=20tester)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- flap/src/fopix/hobixToFopix.ml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index d49fe01..518ad41 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -120,16 +120,26 @@ let free_variables = | [ s ] -> f s | s :: xs -> M.union (f s) (unions f xs) in + (*Une variable libre est une variable qui peut être substitué*) + + (*TODO : rajouter des explications pour While Define et Fun*) let rec fvs = function | S.Literal _ -> M.empty | S.Variable x -> M.singleton x - | S.While (cond, e) -> failwith "Students! This is your job!" - | S.Define (vd, a) -> failwith "Students! This is your job!" + | 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.RecFunctions (list) -> list + in + let id, expr = List.split liste_def_valeur in + M.diff (unions fvs (a::expr)) (M.of_list id) | S.ReadBlock (a, b) -> unions fvs [ a; b ] | S.Apply (a, b) -> unions fvs (a :: b) | S.WriteBlock (a, b, c) | S.IfThenElse (a, b, c) -> unions fvs [ a; b; c ] | S.AllocateBlock a -> fvs a - | S.Fun (xs, e) -> failwith "Students! This is your job!" + | S.Fun (xs, e) -> M.diff (fvs e) (M.of_list xs) | S.Switch (a, b, c) -> let c = match c with @@ -139,7 +149,7 @@ let free_variables = unions fvs ((a :: ExtStd.Array.present_to_list b) @ c) in fun e -> M.elements (fvs e) -;; + (** A closure compilation environment relates an identifier to the way it is accessed in the compiled version of the function's From edb1219070a00ecc050b165a589bb6cd88c39133 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Fri, 15 Dec 2023 13:13:03 +0100 Subject: [PATCH 04/20] fmt --- flap/src/fopix/hobixToFopix.ml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index 518ad41..765647f 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -121,20 +121,20 @@ let free_variables = | s :: xs -> M.union (f s) (unions f xs) in (*Une variable libre est une variable qui peut être substitué*) - + (*TODO : rajouter des explications pour While Define et Fun*) let rec fvs = function | S.Literal _ -> M.empty | S.Variable x -> M.singleton x - | S.While (cond, e) -> unions fvs [cond;e] + | 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.RecFunctions (list) -> list - in - let id, expr = List.split liste_def_valeur in - M.diff (unions fvs (a::expr)) (M.of_list id) + match vd with + | S.SimpleValue (id, expr) -> [ id, expr ] + | S.RecFunctions list -> list + in + let id, expr = List.split liste_def_valeur in + M.diff (unions fvs (a :: expr)) (M.of_list id) | S.ReadBlock (a, b) -> unions fvs [ a; b ] | S.Apply (a, b) -> unions fvs (a :: b) | S.WriteBlock (a, b, c) | S.IfThenElse (a, b, c) -> unions fvs [ a; b; c ] @@ -149,7 +149,7 @@ let free_variables = unions fvs ((a :: ExtStd.Array.present_to_list b) @ c) in fun e -> M.elements (fvs e) - +;; (** A closure compilation environment relates an identifier to the way it is accessed in the compiled version of the function's From 34cffe16617b0c8951799e06668abf3ec4dcab7f Mon Sep 17 00:00:00 2001 From: Mylloon Date: Fri, 15 Dec 2023 13:41:12 +0100 Subject: [PATCH 05/20] ew :( --- flap/src/fopix/hobixToFopix.ml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index 765647f..7789adc 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -120,9 +120,9 @@ let free_variables = | [ s ] -> f s | s :: xs -> M.union (f s) (unions f xs) in - (*Une variable libre est une variable qui peut être substitué*) + (* Une variable libre est une variable qui peut être substitué *) - (*TODO : rajouter des explications pour While Define et Fun*) + (* TODO : rajouter des explications pour While Define et Fun *) let rec fvs = function | S.Literal _ -> M.empty | S.Variable x -> M.singleton x @@ -204,7 +204,8 @@ let translate (p : S.t) env = | S.RecFunctions fdefs -> let fs, defs = define_recursive_functions fdefs in fs @ List.map (fun (x, e) -> T.DefineValue (x, e)) defs - and define_recursive_functions rdefs = failwith "Students! This is your job!" + and define_recursive_functions rdefs = + failwith "Students! This is your job (define_recursive_functions)!" and expression env = function | S.Literal l -> [], T.Literal (literal l) | S.While (cond, e) -> @@ -218,14 +219,20 @@ let translate (p : S.t) env = | Some e -> e in [], xc - | S.Define (vdef, a) -> failwith "Students! This is your job!" - | S.Apply (a, bs) -> failwith "Students! This is your job!" + | S.Define (vdef, a) -> + let afs, a = expression env a in + (match vdef with + | 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.Apply (a, bs) -> failwith "Students! This is your job (S.Apply)!" | S.IfThenElse (a, b, c) -> let afs, a = expression env a in let bfs, b = expression env b in let cfs, c = expression env c in afs @ bfs @ cfs, T.IfThenElse (a, b, c) - | S.Fun (x, e) -> failwith "Students! This is your job!" + | S.Fun (x, e) -> failwith "Students! This is your job (S.Fun)!" | S.AllocateBlock a -> let afs, a = expression env a in afs, allocate_block a From 22b0811cbece7d3d6d6c7a830fcf6c0a8921a5a0 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Fri, 15 Dec 2023 13:53:55 +0100 Subject: [PATCH 06/20] Apply --- flap/src/fopix/hobixToFopix.ml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index 7789adc..799ef70 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -226,7 +226,10 @@ let translate (p : S.t) env = 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.Apply (a, bs) -> failwith "Students! This is your job (S.Apply)!" + | S.Apply (a, bs) -> + let afs, a = expression env a in + let bsfs, bs = expressions env bs in + afs @ bsfs, T.UnknownFunCall (a, bs) | S.IfThenElse (a, b, c) -> let afs, a = expression env a in let bfs, b = expression env b in From 939d015453d161820dec678627655d23a44c1815 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Fri, 15 Dec 2023 14:06:55 +0100 Subject: [PATCH 07/20] jpige r --- flap/src/fopix/hobixToFopix.ml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index 799ef70..7d39d3b 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -235,7 +235,12 @@ let translate (p : S.t) env = let bfs, b = expression env b in let cfs, c = expression env c in afs @ bfs @ cfs, T.IfThenElse (a, b, c) - | S.Fun (x, e) -> failwith "Students! This is your job (S.Fun)!" + | S.Fun (x, e) -> + let fname = make_fresh_function_identifier () in + let x = List.map identifier x in + let efs, e = expression env e in + failwith "Students! This is your job (S.Fun)!" + (* efs, T.DefineFunction (fname, x, e) *) | S.AllocateBlock a -> let afs, a = expression env a in afs, allocate_block a From ebd95448702acfa86075d5eabc3ef482da967a86 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Fri, 15 Dec 2023 19:15:54 +0100 Subject: [PATCH 08/20] ig? --- flap/src/fopix/hobixToFopix.ml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index 7d39d3b..aaf4a17 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -239,8 +239,7 @@ let translate (p : S.t) env = let fname = make_fresh_function_identifier () in let x = List.map identifier x in let efs, e = expression env e in - failwith "Students! This is your job (S.Fun)!" - (* efs, T.DefineFunction (fname, x, e) *) + T.DefineFunction (fname, x, e) :: efs, e | S.AllocateBlock a -> let afs, a = expression env a in afs, allocate_block a From 814c04c1d019b065ee1c33535ae3c68a86380af6 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Fri, 15 Dec 2023 19:17:29 +0100 Subject: [PATCH 09/20] infinite loop.... --- flap/src/fopix/hobixToFopix.ml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index aaf4a17..59a4426 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -235,11 +235,12 @@ let translate (p : S.t) env = let bfs, b = expression env b in let cfs, c = expression env c in afs @ bfs @ cfs, T.IfThenElse (a, b, c) - | S.Fun (x, e) -> + | S.Fun (x, e) as f -> let fname = make_fresh_function_identifier () in let x = List.map identifier x in let efs, e = expression env e in - T.DefineFunction (fname, x, e) :: efs, e + let ffs, f = expression env f in + (T.DefineFunction (fname, x, e) :: efs) @ ffs, f | S.AllocateBlock a -> let afs, a = expression env a in afs, allocate_block a From 34c2a6c8e354b7bf419115bd7f324e29411b81e7 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Fri, 15 Dec 2023 19:27:03 +0100 Subject: [PATCH 10/20] todos --- flap/src/fopix/hobixToFopix.ml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index 59a4426..0a2ad77 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -122,7 +122,8 @@ let free_variables = in (* Une variable libre est une variable qui peut être substitué *) - (* TODO : rajouter des explications pour While Define et Fun *) + (* 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 @@ -205,6 +206,8 @@ let translate (p : S.t) env = let fs, defs = define_recursive_functions 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 expression env = function | S.Literal l -> [], T.Literal (literal l) @@ -220,6 +223,7 @@ let translate (p : S.t) env = in [], xc | S.Define (vdef, a) -> + (* 1.3 (2) *) let afs, a = expression env a in (match vdef with | S.SimpleValue (id, b) -> @@ -227,8 +231,11 @@ let translate (p : S.t) env = afs @ bfs, T.Define (identifier id, a, b) | S.RecFunctions _ -> failwith "Students! This is your job (S.RecFunctions)!") | S.Apply (a, bs) -> + (* 1.3 (4) *) let afs, a = expression env a in let bsfs, bs = expressions env bs in + (* 1.4 + TODO *) afs @ bsfs, T.UnknownFunCall (a, bs) | S.IfThenElse (a, b, c) -> let afs, a = expression env a in @@ -236,6 +243,8 @@ let translate (p : S.t) env = let cfs, c = expression env c in afs @ bfs @ cfs, T.IfThenElse (a, b, c) | S.Fun (x, e) as f -> + (* 1.3 (3) + TODO: J'ai une boucle infini ici je comprends rien *) let fname = make_fresh_function_identifier () in let x = List.map identifier x in let efs, e = expression env e in From f7567888c9efd3d9c366e7cf1e82fe3f2da43976 Mon Sep 17 00:00:00 2001 From: Nicolas PENELOUX Date: Sun, 17 Dec 2023 21:20:58 +0100 Subject: [PATCH 11/20] Etape S.Fun (ne marche surement pas) --- flap/src/fopix/hobixToFopix.ml | 52 ++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index 0a2ad77..d73ae21 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -179,6 +179,7 @@ let initial_environment () = { vars = Dict.empty; externals = Dict.empty } let bind_external id n env = { env with externals = Dict.insert id n env.externals } let is_external id env = Dict.lookup id env.externals <> None let reset_vars env = { env with vars = Dict.empty } +let bind_var env id expr = {env with vars = Dict.insert id expr env.vars } (** Precondition: [is_external id env = true]. *) let arity_of_external id env = @@ -245,11 +246,21 @@ let translate (p : S.t) env = | S.Fun (x, e) as f -> (* 1.3 (3) TODO: J'ai une boucle infini ici je comprends rien *) + (* let fname = make_fresh_function_identifier () in let x = List.map identifier x in let efs, e = expression env e in let ffs, f = expression env f in - (T.DefineFunction (fname, x, e) :: efs) @ ffs, f + (T.DefineFunction (fname, x, e) :: efs) @ ffs, f*) + (* TODO : debug ce truc *) + + let fname = make_fresh_function_identifier () in + let arguments_x = List.map identifier x in + let cloture, env = creation_cloture env fname (free_variables f) in + let dfs = add_liste_funcdef env fname arguments_x e in + dfs, cloture + + | S.AllocateBlock a -> let afs, a = expression env a in afs, allocate_block a @@ -292,6 +303,43 @@ let translate (p : S.t) env = | S.LString s -> T.LString s | S.LChar c -> T.LChar c and identifier (S.Id x) = T.Id x - and function_identifier (S.Id x) = T.FunId x in + 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 + dfs @ [T.DefineFunction(fid,(T.Id "oldenvironment")::x,expr)] + + and creation_cloture env ?block fname free_vars = + match block with + | None -> + let new_clot = new_cloture 0 free_vars in + let blocks, env = add_to_cloture env fname (T.Variable (T.Id "environment")) free_vars in + T.Define (T.Id "environment",new_clot,blocks), env + + and new_cloture espace list_variable = + allocate_block (lint (espace + List.length list_variable + 1)) + + and add_to_cloture env fname env_var free_vars = + let first_block = write_block env_var (lint 0) (T.Literal (T.LFun fname)) in + let env, vars_free, k = + List.fold_left (fun(env,list,k) id -> + let new_env = bind_var env id (read_block (T.Variable (T.Id "oldenvironment")) (lint k)) in + let new_valeur = + match Dict.lookup id env.vars with + | None -> T.Variable (identifier id) + | Some v -> v in + let new_instr = write_block env_var (lint k) new_valeur in + (new_env, new_instr::list, k+1) + ) + (env,[],1) + + free_vars in + let instrs = List.rev (env_var::first_block::vars_free) in + seqs instrs, env + + in program env p ;; From 37e79d1df6f3834177e2d77dde9e055462592481 Mon Sep 17 00:00:00 2001 From: Nicolas PENELOUX Date: Mon, 18 Dec 2023 13:08:33 +0100 Subject: [PATCH 12/20] =?UTF-8?q?Etape=204=20=3F=20=C3=A0=20tester?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- flap/src/fopix/hobixToFopix.ml | 50 ++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index d73ae21..2c7471a 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -233,11 +233,15 @@ let translate (p : S.t) env = | S.RecFunctions _ -> failwith "Students! This is your job (S.RecFunctions)!") | S.Apply (a, bs) -> (* 1.3 (4) *) + (* let afs, a = expression env a in let bsfs, bs = expressions env bs in (* 1.4 TODO *) + afs @ bsfs, T.UnknownFunCall (a, bs) + *) + apply env a bs | S.IfThenElse (a, b, c) -> let afs, a = expression env a in let bfs, b = expression env b in @@ -311,6 +315,7 @@ let translate (p : S.t) env = and add_liste_funcdef env fid x expr = let dfs, expr = expression env expr in dfs @ [T.DefineFunction(fid,(T.Id "oldenvironment")::x,expr)] + and creation_cloture env ?block fname free_vars = match block with @@ -319,27 +324,68 @@ let translate (p : S.t) env = let blocks, env = add_to_cloture env fname (T.Variable (T.Id "environment")) free_vars in T.Define (T.Id "environment",new_clot,blocks), env + (* fonction qui initialise une cloture de taille espace + 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 = + (*On commence d'abord par écrire dans le premier bloc le nom de la fonction fopix*) let first_block = write_block env_var (lint 0) (T.Literal (T.LFun fname)) in + (*Ensuite, on s'occupe d'écrire dans chaque bloc de notre cloture les variables libres*) let env, vars_free, k = - List.fold_left (fun(env,list,k) id -> + List.fold_left (fun(env,list,k) id -> (*Pour chaque élément de la liste ...*) + (*On commence par lié la variable dans le nouvelle environnement qui se trouve dans l'ancien environnement*) let new_env = bind_var env id (read_block (T.Variable (T.Id "oldenvironment")) (lint k)) in + (*On cherche la valeur de la variable dans le dictionnaire du programme*) let new_valeur = match Dict.lookup id env.vars with | None -> T.Variable (identifier id) | Some v -> v in + (*Enfin, on écrit dans notre cloture la valeur de la variable libre à la position k*) let new_instr = write_block env_var (lint k) new_valeur in - (new_env, new_instr::list, k+1) + (*On rappelle notre fonction avec le nouvelle environnement, en rajoutant notre instruction à la liste d'instruction, et en incrémentant l'index*) + (new_env, new_instr::list, k+1) ) + (*On commence notre fonction avec l'env de base, la liste d'instruction vide et l'indice à 1 (0 étant l'initialisation du début)*) (env,[],1) free_vars in + (*On créé une séquence d'instructions contenant le premier bloc et la suite*) let instrs = List.rev (env_var::first_block::vars_free) in seqs instrs, env + + (* 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 trad_argument argument = expression env argument in + let defs_args, trad_arguments = List.split (List.map trad_argument arguments) in + + (*On créé un FunCall en fonction de f*) + match f with + | S.Variable x when (Dict.lookup x env.externals <> None) -> (*Si f est une externe fonction, on créé directement un FunCall*) + [], T.FunCall (function_identifier x, trad_arguments) + | _ -> (* SInon, ça veut dire que nous l'avons défini au préalable*) + (*On traduit la fonction*) + let defs_func, func = expression env f in + (* On récupère le nom de fonction et son expression*) + let fname, func_expr = + match func with + | T.Variable x -> x, (fun x -> x) + | _ -> + let fname = make_fresh_variable () in + fname, (fun x -> T.Define (fname,func,x)) + in + (*On récupère le pointeur qui pointe vers la première case de la fonction*) + let get_pointer = read_block (T.Variable fname) (lint 0) in + (*On récupère l'appelle de la fonction*) + let defs_call = func_expr (T.UnknownFunCall (get_pointer,(T.Variable fname)::trad_arguments)) in + (*Enfin, on concatène toute les parties de la fonction (la traduction de tout les arguments)*) + let defs = defs_func @ List.concat defs_args in + defs, defs_call (* et on renvoie la def de la fonction ainsi que l'appel*) + in program env p ;; From a6afabb53844acea4a3e896d4aab5257dca46e52 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Mon, 18 Dec 2023 14:06:40 +0100 Subject: [PATCH 13/20] fmt --- flap/src/fopix/hobixToFopix.ml | 173 +++++++++++++++++---------------- 1 file changed, 90 insertions(+), 83 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index 2c7471a..4a8884a 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -179,7 +179,7 @@ let initial_environment () = { vars = Dict.empty; externals = Dict.empty } let bind_external id n env = { env with externals = Dict.insert id n env.externals } let is_external id env = Dict.lookup id env.externals <> None let reset_vars env = { env with vars = Dict.empty } -let bind_var env id expr = {env with vars = Dict.insert id expr env.vars } +let bind_var env id expr = { env with vars = Dict.insert id expr env.vars } (** Precondition: [is_external id env = true]. *) let arity_of_external id env = @@ -232,15 +232,10 @@ let translate (p : S.t) env = afs @ bfs, T.Define (identifier id, a, b) | S.RecFunctions _ -> failwith "Students! This is your job (S.RecFunctions)!") | S.Apply (a, bs) -> - (* 1.3 (4) *) - (* + (* (* 1.3 (4) *) let afs, a = expression env a in let bsfs, bs = expressions env bs in - (* 1.4 - TODO *) - - afs @ bsfs, T.UnknownFunCall (a, bs) - *) + afs @ bsfs, T.UnknownFunCall (a, bs) *) apply env a bs | S.IfThenElse (a, b, c) -> let afs, a = expression env a in @@ -248,23 +243,19 @@ let translate (p : S.t) env = let cfs, c = expression env c in afs @ bfs @ cfs, T.IfThenElse (a, b, c) | S.Fun (x, e) as f -> - (* 1.3 (3) - TODO: J'ai une boucle infini ici je comprends rien *) - (* + (* (* 1.3 (3) *) let fname = make_fresh_function_identifier () in let x = List.map identifier x in let efs, e = expression env e in let ffs, f = expression env f in - (T.DefineFunction (fname, x, e) :: efs) @ ffs, f*) - (* TODO : debug ce truc *) - - let fname = make_fresh_function_identifier () in - let arguments_x = List.map identifier x in - let cloture, env = creation_cloture env fname (free_variables f) in + (T.DefineFunction (fname, x, e) :: efs) @ ffs, f *) + + (* TODO : Debug ce truc *) + let fname = make_fresh_function_identifier () in + let arguments_x = List.map identifier x in + let cloture, env = creation_cloture env fname (free_variables f) in let dfs = add_liste_funcdef env fname arguments_x e in dfs, cloture - - | S.AllocateBlock a -> let afs, a = expression env a in afs, allocate_block a @@ -307,85 +298,101 @@ let translate (p : S.t) env = | S.LString s -> T.LString s | S.LChar c -> T.LChar c and identifier (S.Id x) = T.Id x - 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 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 - dfs @ [T.DefineFunction(fid,(T.Id "oldenvironment")::x,expr)] - - - and creation_cloture env ?block fname free_vars = + dfs @ [ T.DefineFunction (fid, T.Id "oldenvironment" :: x, expr) ] + and creation_cloture env ?block fname free_vars = match block with - | None -> - let new_clot = new_cloture 0 free_vars in - let blocks, env = add_to_cloture env fname (T.Variable (T.Id "environment")) free_vars in - T.Define (T.Id "environment",new_clot,blocks), env - - (* fonction qui initialise une cloture de taille espace + la taille de la liste de variable (le nombre de variable libre)*) + | None -> + let new_clot = new_cloture 0 free_vars in + let blocks, env = + add_to_cloture env fname (T.Variable (T.Id "environment")) free_vars + in + T.Define (T.Id "environment", new_clot, blocks), env + (* Fonction qui initialise une cloture de taille espace + + 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 = - (*On commence d'abord par écrire dans le premier bloc le nom de la fonction fopix*) + (* On commence d'abord par écrire dans le premier bloc le nom de + la fonction fopix *) let first_block = write_block env_var (lint 0) (T.Literal (T.LFun fname)) in - (*Ensuite, on s'occupe d'écrire dans chaque bloc de notre cloture les variables libres*) + (* Ensuite, on s'occupe d'écrire dans chaque bloc de notre cloture + les variables libres *) let env, vars_free, k = - List.fold_left (fun(env,list,k) id -> (*Pour chaque élément de la liste ...*) - (*On commence par lié la variable dans le nouvelle environnement qui se trouve dans l'ancien environnement*) - let new_env = bind_var env id (read_block (T.Variable (T.Id "oldenvironment")) (lint k)) in - (*On cherche la valeur de la variable dans le dictionnaire du programme*) - let new_valeur = - match Dict.lookup id env.vars with - | None -> T.Variable (identifier id) - | Some v -> v in - (*Enfin, on écrit dans notre cloture la valeur de la variable libre à la position k*) - let new_instr = write_block env_var (lint k) new_valeur in - (*On rappelle notre fonction avec le nouvelle environnement, en rajoutant notre instruction à la liste d'instruction, et en incrémentant l'index*) - (new_env, new_instr::list, k+1) - ) - (*On commence notre fonction avec l'env de base, la liste d'instruction vide et l'indice à 1 (0 étant l'initialisation du début)*) - (env,[],1) - - free_vars in - (*On créé une séquence d'instructions contenant le premier bloc et la suite*) - let instrs = List.rev (env_var::first_block::vars_free) in - seqs instrs, env - - - (* Fonction qui s'occupe de S.Apply*) - (* Revoir les explications c'est pas clair*) + List.fold_left + (fun (env, list, k) id -> + (* Pour chaque élément de la liste ... + On commence par lié la variable dans le nouvelle environnement + qui se trouve dans l'ancien environnement *) + let new_env = + bind_var env id (read_block (T.Variable (T.Id "oldenvironment")) (lint k)) + in + (* On cherche la valeur de la variable dans + le dictionnaire du programme *) + let new_valeur = + match Dict.lookup id env.vars with + | None -> T.Variable (identifier id) + | Some v -> v + in + (* Enfin, on écrit dans notre cloture la valeur de la variable libre + à la position k *) + let new_instr = write_block env_var (lint k) new_valeur in + (* On rappelle notre fonction avec le nouvelle environnement, + en rajoutant notre instruction à la liste d'instruction, + et en incrémentant l'index *) + new_env, new_instr :: list, k + 1) + (* On commence notre fonction avec l'env de base, + la liste d'instruction vide et l'indice à 1 + (0 étant l'initialisation du début) *) + (env, [], 1) + free_vars + in + (* On créé une séquence d'instructions contenant + le premier bloc et la suite *) + let instrs = List.rev (env_var :: first_block :: vars_free) 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 *) + (* D'abord, on traduit chaque arguments *) let trad_argument argument = expression env argument in let defs_args, trad_arguments = List.split (List.map trad_argument arguments) in - - (*On créé un FunCall en fonction de f*) + (* On créé un FunCall en fonction de f *) match f with - | S.Variable x when (Dict.lookup x env.externals <> None) -> (*Si f est une externe fonction, on créé directement un FunCall*) + | S.Variable x when Dict.lookup x env.externals <> None -> + (* Si f est une externe fonction, on créé directement un FunCall *) [], T.FunCall (function_identifier x, trad_arguments) - | _ -> (* SInon, ça veut dire que nous l'avons défini au préalable*) - (*On traduit la fonction*) + | _ -> + (* Sinon, ça veut dire que nous l'avons défini au préalable *) + (* On traduit la fonction *) let defs_func, func = expression env f in - (* On récupère le nom de fonction et son expression*) - let fname, func_expr = - match func with - | T.Variable x -> x, (fun x -> x) - | _ -> - let fname = make_fresh_variable () in - fname, (fun x -> T.Define (fname,func,x)) - in - (*On récupère le pointeur qui pointe vers la première case de la fonction*) - let get_pointer = read_block (T.Variable fname) (lint 0) in - (*On récupère l'appelle de la fonction*) - let defs_call = func_expr (T.UnknownFunCall (get_pointer,(T.Variable fname)::trad_arguments)) in - (*Enfin, on concatène toute les parties de la fonction (la traduction de tout les arguments)*) - let defs = defs_func @ List.concat defs_args in - defs, defs_call (* et on renvoie la def de la fonction ainsi que l'appel*) - + (* On récupère le nom de fonction et son expression *) + let fname, func_expr = + match func with + | T.Variable x -> x, fun x -> x + | _ -> + let fname = make_fresh_variable () in + fname, fun x -> T.Define (fname, func, x) + in + (* On récupère le pointeur qui pointe vers la première case + de la fonction *) + let get_pointer = read_block (T.Variable fname) (lint 0) in + (* On récupère l'appelle de la fonction *) + let defs_call = + func_expr (T.UnknownFunCall (get_pointer, T.Variable fname :: trad_arguments)) + in + (* Enfin, on concatène toute les parties de la fonction + (la traduction de tout les arguments) *) + let defs = defs_func @ List.concat defs_args in + (* Et on renvoie la def de la fonction ainsi que l'appel *) + defs, defs_call in program env p ;; From 86e8cead3a23cb7c7227376f8622e644cc24a3f3 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Mon, 18 Dec 2023 14:13:49 +0100 Subject: [PATCH 14/20] Some failwith --- flap/src/fopix/hobixToFopix.ml | 1 + 1 file changed, 1 insertion(+) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index 4a8884a..c6c570f 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -313,6 +313,7 @@ let translate (p : S.t) env = add_to_cloture env fname (T.Variable (T.Id "environment")) free_vars in T.Define (T.Id "environment", new_clot, blocks), env + | Some _ -> failwith "Students! This is your job (creation_cloture)!" (* Fonction qui initialise une cloture de taille espace + la taille de la liste de variable (le nombre de variable libre) *) and new_cloture espace list_variable = From 6078d402150d334a042cf270b143c1005990e6c8 Mon Sep 17 00:00:00 2001 From: Mylloon Date: Mon, 18 Dec 2023 15:46:29 +0100 Subject: [PATCH 15/20] la meme je crois? --- flap/src/fopix/hobixToFopix.ml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index c6c570f..b7d94b6 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -363,8 +363,7 @@ let translate (p : S.t) env = (* Revoir les explications c'est pas clair *) and apply env f arguments = (* D'abord, on traduit chaque arguments *) - let trad_argument argument = expression env argument in - let defs_args, trad_arguments = List.split (List.map trad_argument arguments) in + 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 -> @@ -391,7 +390,7 @@ let translate (p : S.t) env = in (* Enfin, on concatène toute les parties de la fonction (la traduction de tout les arguments) *) - let defs = defs_func @ List.concat defs_args in + let defs = defs_func @ defs_args in (* Et on renvoie la def de la fonction ainsi que l'appel *) defs, defs_call in From 68eec09b05650fd2d4ea25da49bcfd4341d1ee61 Mon Sep 17 00:00:00 2001 From: Nicolas PENELOUX Date: Mon, 18 Dec 2023 17:27:44 +0100 Subject: [PATCH 16/20] =?UTF-8?q?ajout=20def=5Frec=20en=20th=C3=A9orie=20m?= =?UTF-8?q?ais=20=C3=A7a=20ne=20marche=20pas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- flap/src/fopix/hobixToFopix.ml | 100 ++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 19 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index c6c570f..2adda4c 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -209,7 +209,51 @@ let translate (p : S.t) env = and define_recursive_functions rdefs = (* 1.5 TODO *) - failwith "Students! This is your job (define_recursive_functions)!" + (*failwith "Students! This is your job (define_recursive_functions)!"*) + + (*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 =( + let rname = List.map fst rdefs in + let free_vars f = + match f with + | S.Fun(id, expr) -> + let new_id = id @ rname in + let lfree_vars = free_variables (S.Fun(new_id, expr)) in + lfree_vars, id, expr + | _ -> failwith "Error recFunctions : This is not a function" + in + List.map (fun (name, expr) -> name, free_vars expr) rdefs) + in + + match rdefs with + | [name, (free_vars, arguments, expr)] -> + let defs, expre = fonction_anonyme env free_vars arguments expr in + defs, [identifier name, expre] + | _ -> + let rdefs = creation_cloture_rec rdefs in + let fs, rdefs = List.split rdefs in + let trad_rdef = trad_rec_definition rdefs in + let fs', exprs = List.split trad_rdef in + fs @ List.concat fs', exprs + + + (*Fonction qui créé des clotures *) + and creation_cloture_rec rdefs = + let nb = List.length rdefs -1 in + List.map (fun (name, (free_vars, x, e)) -> + let new_name = make_fresh_variable () in + T.DefineValue (new_name, new_cloture nb free_vars), ((name, new_name), (free_vars, x, e))) rdefs + + and trad_rec_definition rdefs = + let rname = List.map fst rdefs in + List.map + (fun ((name,new_name),(fv,x,e)) -> + let names = List.filter (fun (xi,_) -> xi != name) rname in + let defs, expr = fonction_anonyme ~name ~block:(new_name,names) env fv x e in + defs, (identifier name,expr)) + rdefs + and expression env = function | S.Literal l -> [], T.Literal (literal l) | S.While (cond, e) -> @@ -243,19 +287,7 @@ let translate (p : S.t) env = let cfs, c = expression env c in afs @ bfs @ cfs, T.IfThenElse (a, b, c) | S.Fun (x, e) as f -> - (* (* 1.3 (3) *) - let fname = make_fresh_function_identifier () in - let x = List.map identifier x in - let efs, e = expression env e in - let ffs, f = expression env f in - (T.DefineFunction (fname, x, e) :: efs) @ ffs, f *) - - (* TODO : Debug ce truc *) - let fname = make_fresh_function_identifier () in - let arguments_x = List.map identifier x in - let cloture, env = creation_cloture env fname (free_variables f) in - let dfs = add_liste_funcdef env fname arguments_x e in - dfs, cloture + fonction_anonyme env (free_variables f) x e | S.AllocateBlock a -> let afs, a = expression env a in afs, allocate_block a @@ -305,21 +337,38 @@ let translate (p : S.t) env = and add_liste_funcdef env fid x expr = let dfs, expr = expression env expr in dfs @ [ T.DefineFunction (fid, T.Id "oldenvironment" :: x, expr) ] - and creation_cloture env ?block fname free_vars = + + and fonction_anonyme ?name ?block env f x e = + let fname = make_fresh_function_identifier () in + let arguments_x = List.map identifier x in + let cloture, env = creation_cloture env name block fname f in + let dfs = add_liste_funcdef env fname arguments_x e in + dfs, cloture + + and creation_cloture env name block fname free_vars = + let env = + match name with + | None -> env + | Some name -> bind_var env name (T.Variable(T.Id "oldenvironment")) + in match block with | None -> let new_clot = new_cloture 0 free_vars in let blocks, env = - add_to_cloture env fname (T.Variable (T.Id "environment")) free_vars + add_to_cloture env fname (T.Variable (T.Id "environment")) free_vars [] in T.Define (T.Id "environment", new_clot, blocks), env - | Some _ -> failwith "Students! This is your job (creation_cloture)!" + | Some (block, rdefs) -> + add_to_cloture env fname (T.Variable block) free_vars rdefs + + + (* Fonction qui initialise une cloture de taille espace + 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 = + and add_to_cloture env fname env_var free_vars rdefs = (* On commence d'abord par écrire dans le premier bloc le nom de la fonction fopix *) let first_block = write_block env_var (lint 0) (T.Literal (T.LFun fname)) in @@ -354,9 +403,22 @@ let translate (p : S.t) env = (env, [], 1) free_vars in + (*Dans le cas d'une récursion, on rajoute chaque fonction dans l'env et à la liste + d'instruction*) + let env,vars_fun,_ = + List.fold_left (fun (env, list, k) (id, id_var) -> + let new_env = + bind_var env id (read_block (T.Variable (T.Id "oldenvironment")) (lint k)) + in + let new_instr = write_block env_var (lint k) (T.Variable id_var) in + (new_env, new_instr::list,k+1) + ) + (env,[],k) (*On commence avec k car on a mis k variables libres juste avant*) + rdefs + in (* On créé une séquence d'instructions contenant le premier bloc et la suite *) - let instrs = List.rev (env_var :: first_block :: vars_free) in + 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 *) From ec2816ddba78e2e9bdb28e41bc08454700f6e348 Mon Sep 17 00:00:00 2001 From: Nicolas PENELOUX Date: Mon, 18 Dec 2023 18:11:10 +0100 Subject: [PATCH 17/20] =?UTF-8?q?modification=20pour=20Unbound=20Value=20l?= =?UTF-8?q?es=20op=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) | _ -> From e4b7a7bc0cae549b228aaa2deed41122f7093248 Mon Sep 17 00:00:00 2001 From: Nicolas PENELOUX Date: Mon, 18 Dec 2023 19:15:50 +0100 Subject: [PATCH 18/20] ajout de commentaires --- flap/src/fopix/hobixToFopix.ml | 36 +++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index 0fe8702..3fe2c8e 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -221,6 +221,13 @@ let translate (p : S.t) env = | S.RecFunctions fdefs -> let fs, defs = define_recursive_functions env fdefs in fs @ List.map (fun (x, e) -> T.DefineValue (x, e)) defs + + (*Ce qu'il faut faire dans le cadre des fonctions mutuellement récursives : + - On récupère la liste des fonctions + - On créé des clotures pour chaque récursion + - On traduit chaque fonction mutuellement récursive en appel de fonction anonyme + - On finit par combiner chaque liste de définition, celle des la fonction de base, + puis celle des des fonctions traduites. *) and define_recursive_functions env rdefs = (*On récupère d'abord les informations qui nous intéresse : nom, variables libres, @@ -228,6 +235,7 @@ let translate (p : S.t) env = let rdefs =( let rname = List.map fst rdefs in let free_vars f = + match f with | S.Fun(id, expr) -> let new_id = id @ rname in @@ -236,27 +244,32 @@ let translate (p : S.t) env = | _ -> failwith "Error recFunctions : This is not a function" in List.map (fun (name, expr) -> name, free_vars expr) rdefs) + in - + (* On regarde si la fonction recursive est seule, si c'est le cas, on traite + le cas simple d'une fonction anonyme seul.*) match rdefs with | [name, (free_vars, arguments, expr)] -> - let defs, expre = fonction_anonyme env free_vars arguments expr in + let defs, expre = fonction_anonyme env ~name free_vars arguments expr in defs, [identifier name, expre] - | _ -> + | _ -> (*Sinon, on créé des clotures pour chaque fonction de nos fonctions récursives*) let rdefs = creation_cloture_rec rdefs in let fs, rdefs = List.split rdefs in + (* Puis on les traduit toute les fonctions *) let trad_rdef = trad_rec_definition rdefs in let fs', exprs = List.split trad_rdef in fs @ List.concat fs', exprs - (*Fonction qui créé des clotures *) + (*Fonction qui créé des clotures pour chaque récursion *) and creation_cloture_rec rdefs = let nb = List.length rdefs -1 in List.map (fun (name, (free_vars, x, e)) -> let new_name = make_fresh_variable () in T.DefineValue (new_name, new_cloture nb free_vars), ((name, new_name), (free_vars, x, e))) rdefs + (* Fonction qui traduit chaque fonction en appel de fonction anonyme mais également + le nom en identifiant de fonction pour fopix.*) and trad_rec_definition rdefs = let rname = List.map fst rdefs in List.map @@ -280,7 +293,6 @@ let translate (p : S.t) env = in [], xc | S.Define (vdef, a) -> - (* 1.3 (2) *) let afs, a = expression env a in (match vdef with | S.SimpleValue (id, b) -> @@ -330,6 +342,9 @@ let translate (p : S.t) env = bs, Some e in afs @ bsfs @ dfs, T.Switch (a, Array.of_list bs, default) + + + and expressions env = function | [] -> [], [] | e :: es -> @@ -342,6 +357,8 @@ let translate (p : S.t) env = | S.LChar c -> T.LChar c and identifier (S.Id x) = T.Id x and function_identifier (S.Id x) = T.FunId x + + (* Ici, on rajoute notre fonction anonyme dans la liste des définitions de fonctions *) and add_liste_funcdef env fid x expr = @@ -356,10 +373,15 @@ let translate (p : S.t) env = ) in dfs @ [ T.DefineFunction (fid, T.Id "oldenvironment" :: x, expr) ] + (*Traitement des fonctions anonymes*) and fonction_anonyme ?name ?block env f x e = + (*On commence par générer de nouveaux identifiants pour nos fonctions*) let fname = make_fresh_function_identifier () in + (*On traduit l'id de chaque argument*) let arguments_x = List.map identifier x in + (* On créé la cloture pour notre fonction anonyme*) let cloture, env = creation_cloture env name block fname f in + (*On met à jour la liste des définitions de fonctions*) let dfs = add_liste_funcdef env fname arguments_x e in dfs, cloture @@ -370,13 +392,13 @@ let translate (p : S.t) env = | Some name -> bind_var env name (T.Variable(T.Id "oldenvironment")) in match block with - | None -> + | None -> (*Cas où on a une simple fonction anonyme*) let new_clot = new_cloture 0 free_vars in let blocks, env = add_to_cloture env fname (T.Variable (T.Id "environment")) free_vars [] in T.Define (T.Id "environment", new_clot, blocks), env - | Some (block, rdefs) -> + | Some (block, rdefs) -> (*Cas pour les fonctions mutuellements récursive*) add_to_cloture env fname (T.Variable block) free_vars rdefs From 13efd4ad65c2516e7d9961c28dbf7056c0d9cb1d Mon Sep 17 00:00:00 2001 From: Mylloon Date: Mon, 18 Dec 2023 19:24:13 +0100 Subject: [PATCH 19/20] fmt --- flap/src/fopix/hobixToFopix.ml | 243 +++++++++++++++------------------ 1 file changed, 110 insertions(+), 133 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index 3fe2c8e..d3518dc 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -105,22 +105,17 @@ 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" ] +;; - - - -(* 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 +(* 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].*) @@ -146,7 +141,7 @@ let free_variables = | 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 @@ -221,64 +216,62 @@ let translate (p : S.t) env = | S.RecFunctions fdefs -> let fs, defs = define_recursive_functions env fdefs in fs @ List.map (fun (x, e) -> T.DefineValue (x, e)) defs - - (*Ce qu'il faut faire dans le cadre des fonctions mutuellement récursives : - - On récupère la liste des fonctions - - On créé des clotures pour chaque récursion - - On traduit chaque fonction mutuellement récursive en appel de fonction anonyme - - On finit par combiner chaque liste de définition, celle des la fonction de base, - puis celle des des fonctions traduites. *) + (* Ce qu'il faut faire dans le cadre des fonctions mutuellement récursives : + - On récupère la liste des fonctions + - On créé des clotures pour chaque récursion + - On traduit chaque fonction mutuellement récursive en appel + de fonction anonyme + - On finit par combiner chaque liste de définition, + celle des la fonction de base, puis celle des des fonctions traduites. *) 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 =( - let rname = List.map fst rdefs in - let free_vars f = - - match f with - | S.Fun(id, expr) -> - let new_id = id @ rname in - let lfree_vars = free_variables (S.Fun(new_id, expr)) in - lfree_vars, id, expr - | _ -> failwith "Error recFunctions : This is not a function" - in - List.map (fun (name, expr) -> name, free_vars expr) rdefs) - - in - (* On regarde si la fonction recursive est seule, si c'est le cas, on traite - le cas simple d'une fonction anonyme seul.*) - match rdefs with - | [name, (free_vars, arguments, expr)] -> - let defs, expre = fonction_anonyme env ~name free_vars arguments expr in - defs, [identifier name, expre] - | _ -> (*Sinon, on créé des clotures pour chaque fonction de nos fonctions récursives*) - let rdefs = creation_cloture_rec rdefs in - let fs, rdefs = List.split rdefs in - (* Puis on les traduit toute les fonctions *) - let trad_rdef = trad_rec_definition rdefs in - let fs', exprs = List.split trad_rdef in - fs @ List.concat fs', exprs - - - (*Fonction qui créé des clotures pour chaque récursion *) - and creation_cloture_rec rdefs = - let nb = List.length rdefs -1 in - List.map (fun (name, (free_vars, x, e)) -> - let new_name = make_fresh_variable () in - T.DefineValue (new_name, new_cloture nb free_vars), ((name, new_name), (free_vars, x, e))) rdefs - - (* Fonction qui traduit chaque fonction en appel de fonction anonyme mais également - le nom en identifiant de fonction pour fopix.*) - and trad_rec_definition rdefs = - let rname = List.map fst rdefs in + (* 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 = + let rname = List.map fst rdefs in + let free_vars f = + match f with + | S.Fun (id, expr) -> + let new_id = id @ rname in + let lfree_vars = free_variables (S.Fun (new_id, expr)) in + lfree_vars, id, expr + | _ -> failwith "Error recFunctions : This is not a function" + in + List.map (fun (name, expr) -> name, free_vars expr) rdefs + in + (* On regarde si la fonction recursive est seule, si c'est le cas, on traite + le cas simple d'une fonction anonyme seul. *) + match rdefs with + | [ (name, (free_vars, arguments, expr)) ] -> + let defs, expre = fonction_anonyme env ~name free_vars arguments expr in + defs, [ identifier name, expre ] + | _ -> + (* Sinon, on créé des clotures pour chaque fonction de + nos fonctions récursives *) + let rdefs = creation_cloture_rec rdefs in + let fs, rdefs = List.split rdefs in + (* Puis on les traduit toute les fonctions *) + let trad_rdef = trad_rec_definition rdefs in + let fs', exprs = List.split trad_rdef in + fs @ List.concat fs', exprs + (* Fonction qui créé des clotures pour chaque récursion *) + and creation_cloture_rec rdefs = + let nb = List.length rdefs - 1 in List.map - (fun ((name,new_name),(fv,x,e)) -> - let names = List.filter (fun (xi,_) -> xi != name) rname in - let defs, expr = fonction_anonyme ~name ~block:(new_name,names) env fv x e in - defs, (identifier name,expr)) - rdefs - + (fun (name, (free_vars, x, e)) -> + let new_name = make_fresh_variable () in + ( T.DefineValue (new_name, new_cloture nb free_vars) + , ((name, new_name), (free_vars, x, e)) )) + rdefs + (* Fonction qui traduit chaque fonction en appel de fonction anonyme + mais également le nom en identifiant de fonction pour fopix. *) + and trad_rec_definition rdefs = + let rname = List.map fst rdefs in + List.map + (fun ((name, new_name), (fv, x, e)) -> + let names = List.filter (fun (xi, _) -> xi != name) rname in + let defs, expr = fonction_anonyme ~name ~block:(new_name, names) env fv x e in + defs, (identifier name, expr)) + rdefs and expression env = function | S.Literal l -> [], T.Literal (literal l) | S.While (cond, e) -> @@ -299,18 +292,15 @@ let translate (p : S.t) env = let bfs, b = expression env b in afs @ bfs, T.Define (identifier id, a, b) | S.RecFunctions rdefs -> - let fs, defs = define_recursive_functions env rdefs in - afs @ fs, defines defs a - ) - | S.Apply (a, bs) -> - apply env a bs + let fs, defs = define_recursive_functions env rdefs in + afs @ fs, defines defs a) + | S.Apply (a, bs) -> apply env a bs | S.IfThenElse (a, b, c) -> let afs, a = expression env a in let bfs, b = expression env b in let cfs, c = expression env c in afs @ bfs @ cfs, T.IfThenElse (a, b, c) - | S.Fun (x, e) as f -> - fonction_anonyme env (free_variables f) x e + | S.Fun (x, e) as f -> fonction_anonyme env (free_variables f) x e | S.AllocateBlock a -> let afs, a = expression env a in afs, allocate_block a @@ -342,9 +332,6 @@ let translate (p : S.t) env = bs, Some e in afs @ bsfs @ dfs, T.Switch (a, Array.of_list bs, default) - - - and expressions env = function | [] -> [], [] | e :: es -> @@ -357,58 +344,51 @@ let translate (p : S.t) env = | S.LChar c -> T.LChar c and identifier (S.Id x) = T.Id x and function_identifier (S.Id x) = T.FunId x - - (* Ici, on rajoute notre fonction anonyme dans la liste des définitions de fonctions *) and add_liste_funcdef env fid x expr = let dfs, expr = expression env expr in - let dfs, expr = - ( + 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 + | 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) ] - - (*Traitement des fonctions anonymes*) + (* Traitement des fonctions anonymes *) and fonction_anonyme ?name ?block env f x e = - (*On commence par générer de nouveaux identifiants pour nos fonctions*) + (* On commence par générer de nouveaux identifiants pour nos fonctions *) let fname = make_fresh_function_identifier () in - (*On traduit l'id de chaque argument*) - let arguments_x = List.map identifier x in - (* On créé la cloture pour notre fonction anonyme*) - let cloture, env = creation_cloture env name block fname f in - (*On met à jour la liste des définitions de fonctions*) - let dfs = add_liste_funcdef env fname arguments_x e in - dfs, cloture - - and creation_cloture env name block fname free_vars = - let env = - match name with - | None -> env - | Some name -> bind_var env name (T.Variable(T.Id "oldenvironment")) + (* On traduit l'id de chaque argument *) + let arguments_x = List.map identifier x in + (* On créé la cloture pour notre fonction anonyme *) + let cloture, env = creation_cloture env name block fname f in + (* On met à jour la liste des définitions de fonctions *) + let dfs = add_liste_funcdef env fname arguments_x e in + dfs, cloture + and creation_cloture env name block fname free_vars = + let env = + match name with + | None -> env + | Some name -> bind_var env name (T.Variable (T.Id "oldenvironment")) in match block with - | None -> (*Cas où on a une simple fonction anonyme*) + | None -> + (* Cas où on a une simple fonction anonyme *) let new_clot = new_cloture 0 free_vars in let blocks, env = add_to_cloture env fname (T.Variable (T.Id "environment")) free_vars [] in T.Define (T.Id "environment", new_clot, blocks), env - | Some (block, rdefs) -> (*Cas pour les fonctions mutuellements récursive*) + | Some (block, rdefs) -> + (* Cas pour les fonctions mutuellements récursive *) add_to_cloture env fname (T.Variable block) free_vars rdefs - - - (* Fonction qui initialise une cloture de taille espace + 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 @@ -445,35 +425,32 @@ let translate (p : S.t) env = (env, [], 1) free_vars in - (*Dans le cas d'une récursion, on rajoute chaque fonction dans l'env et à la liste - d'instruction*) - let env,vars_fun,_ = - List.fold_left (fun (env, list, k) (id, id_var) -> - let new_env = - bind_var env id (read_block (T.Variable (T.Id "oldenvironment")) (lint k)) - in - let new_instr = write_block env_var (lint k) (T.Variable id_var) in - (new_env, new_instr::list,k+1) - ) - (env,[],k) (*On commence avec k car on a mis k variables libres juste avant*) - rdefs - in + (* Dans le cas d'une récursion, on rajoute chaque fonction dans l'env et + à la liste d'instruction*) + let env, vars_fun, _ = + List.fold_left + (fun (env, list, k) (id, id_var) -> + let new_env = + bind_var env id (read_block (T.Variable (T.Id "oldenvironment")) (lint k)) + in + let new_instr = write_block env_var (lint k) (T.Variable id_var) in + new_env, new_instr :: list, k + 1) + (* On commence avec k car on a mis k variables libres juste avant *) + (env, [], k) + rdefs + in (* On créé une séquence d'instructions contenant 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 - - - - (* 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 || is_a_predefined_function x-> + | 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) | _ -> From 709ad1f43f7aa2d12926e1c5dd9adf598a866eae Mon Sep 17 00:00:00 2001 From: Mylloon Date: Mon, 18 Dec 2023 19:26:12 +0100 Subject: [PATCH 20/20] use fresh variables --- flap/src/fopix/hobixToFopix.ml | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/flap/src/fopix/hobixToFopix.ml b/flap/src/fopix/hobixToFopix.ml index d3518dc..ba84a84 100644 --- a/flap/src/fopix/hobixToFopix.ml +++ b/flap/src/fopix/hobixToFopix.ml @@ -344,6 +344,8 @@ let translate (p : S.t) env = | S.LChar c -> T.LChar c and identifier (S.Id x) = T.Id x and function_identifier (S.Id x) = T.FunId x + and old_env = make_fresh_variable () + and curr_env = make_fresh_variable () (* Ici, on rajoute notre fonction anonyme dans la liste des définitions de fonctions *) and add_liste_funcdef env fid x expr = @@ -356,7 +358,7 @@ let translate (p : S.t) env = in List.fold_right aux dfs ([], expr) in - dfs @ [ T.DefineFunction (fid, T.Id "oldenvironment" :: x, expr) ] + dfs @ [ T.DefineFunction (fid, old_env :: x, expr) ] (* Traitement des fonctions anonymes *) and fonction_anonyme ?name ?block env f x e = (* On commence par générer de nouveaux identifiants pour nos fonctions *) @@ -372,16 +374,14 @@ let translate (p : S.t) env = let env = match name with | None -> env - | Some name -> bind_var env name (T.Variable (T.Id "oldenvironment")) + | Some name -> bind_var env name (T.Variable old_env) in match block with | None -> (* Cas où on a une simple fonction anonyme *) let new_clot = new_cloture 0 free_vars in - let blocks, env = - add_to_cloture env fname (T.Variable (T.Id "environment")) free_vars [] - in - T.Define (T.Id "environment", new_clot, blocks), env + let blocks, env = add_to_cloture env fname (T.Variable curr_env) free_vars [] in + T.Define (curr_env, new_clot, blocks), env | Some (block, rdefs) -> (* Cas pour les fonctions mutuellements récursive *) add_to_cloture env fname (T.Variable block) free_vars rdefs @@ -402,9 +402,7 @@ let translate (p : S.t) env = (* Pour chaque élément de la liste ... On commence par lié la variable dans le nouvelle environnement qui se trouve dans l'ancien environnement *) - let new_env = - bind_var env id (read_block (T.Variable (T.Id "oldenvironment")) (lint k)) - in + let curr_env = bind_var env id (read_block (T.Variable old_env) (lint k)) in (* On cherche la valeur de la variable dans le dictionnaire du programme *) let new_valeur = @@ -418,7 +416,7 @@ let translate (p : S.t) env = (* On rappelle notre fonction avec le nouvelle environnement, en rajoutant notre instruction à la liste d'instruction, et en incrémentant l'index *) - new_env, new_instr :: list, k + 1) + curr_env, new_instr :: list, k + 1) (* On commence notre fonction avec l'env de base, la liste d'instruction vide et l'indice à 1 (0 étant l'initialisation du début) *) @@ -430,11 +428,9 @@ let translate (p : S.t) env = let env, vars_fun, _ = List.fold_left (fun (env, list, k) (id, id_var) -> - let new_env = - bind_var env id (read_block (T.Variable (T.Id "oldenvironment")) (lint k)) - in + let curr_env = bind_var env id (read_block (T.Variable old_env) (lint k)) in let new_instr = write_block env_var (lint k) (T.Variable id_var) in - new_env, new_instr :: list, k + 1) + curr_env, new_instr :: list, k + 1) (* On commence avec k car on a mis k variables libres juste avant *) (env, [], k) rdefs