diff --git a/.gitignore b/.gitignore index 8102f28a3b108b408666fdc397bdeb8ae8617a5d..ffd5a61609c31f949ac82df6ebb251113e23250b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ tests/**/*.cfg3 tests/**/*.e.dump tests/**/*.e.html tests/**/*.exe +tests/**/*.json tests/**/*.lex tests/**/*.linear tests/**/*.linear1 diff --git a/Sujet.pdf b/Sujet.pdf index 6cd99d9db240f72fa9761f1fbbec548db85b35dd..af1239cb519f91d2689a7b3328df0688bcfffcf4 100644 Binary files a/Sujet.pdf and b/Sujet.pdf differ diff --git a/src/elang_run.ml b/src/elang_run.ml index a59fb8be3533492127b99f9cf529cf337d357a16..96c070fac5f5d7e28824f7b56a8eec6ba2f43f6f 100644 --- a/src/elang_run.ml +++ b/src/elang_run.ml @@ -24,36 +24,35 @@ let eval_unop (u: unop) : int -> int = let rec eval_eexpr st (e : expr) : int res = Error "eval_eexpr not implemented yet." -(* [eval_einstr oc st ins] evaluates the instruction [ins] in starting state - [st]. +(* [eval_einstr oc st ins] évalue l'instrution [ins] en partant de l'état [st]. - The parameter [oc], unused for now, is an output channel in which functions - like "print" will write their output, when we add them. + Le paramètre [oc] est un "output channel", dans lequel la fonction "print" + écrit sa sortie, au moyen de l'instruction [Format.fprintf]. - This function returns [(ret, st')] : + Cette fonction renvoie [(ret, st')] : - - [ret] is an [int option]. [Some v] should be returned when a return - instruction is met. [None] means that execution should continue. + - [ret] est de type [int option]. [Some v] doit être renvoyé lorsqu'une + instruction [return] est évaluée. [None] signifie qu'aucun [return] n'a eu + lieu et que l'exécution doit continuer. - - [st'] is the updated state. -*) + - [st'] est l'état mis à jour. *) let rec eval_einstr oc (st: int state) (ins: instr) : (int option * int state) res = Error "eval_einstr not implemented yet." -(* [eval_efun oc st f fname vargs] evaluates function [f] (whose name is - [fname]) starting in state [st], with arguments given in [vargs]. +(* [eval_efun oc st f fname vargs] évalue la fonction [f] (dont le nom est + [fname]) en partant de l'état [st], avec les arguments [vargs]. - This returns a pair (ret, st') with the same meaning as for [eval_einstr]. -*) + Cette fonction renvoie un couple (ret, st') avec la même signification que + pour [eval_einstr]. *) let eval_efun oc (st: int state) ({ funargs; funbody}: efun) (fname: string) (vargs: int list) : (int option * int state) res = - (* A function's environment (mapping from local variables to values) is local - and a function call should not modify the caller's variables. Hence, we - save the caller's environment in [env_save], call the function in a clean - environment with only its arguments set, and restore the caller's - environment. *) + (* L'environnement d'une fonction (mapping des variables locales vers leurs + valeurs) est local et un appel de fonction ne devrait pas modifier les + variables de l'appelant. Donc, on sauvegarde l'environnement de l'appelant + dans [env_save], on appelle la fonction dans un environnement propre (Avec + seulement ses arguments), puis on restore l'environnement de l'appelant. *) let env_save = Hashtbl.copy st.env in let env = Hashtbl.create 17 in match List.iter2 (fun a v -> Hashtbl.replace env a v) funargs vargs with @@ -66,19 +65,22 @@ let eval_efun oc (st: int state) ({ funargs; funbody}: efun) fname (List.length vargs) (List.length funargs) ) -(* [eval_eprog oc ep memsize params] evaluates a complete program [ep], with +(* [eval_eprog oc ep memsize params] évalue un programme complet [ep], avec les arguments [params]. - The [memsize] parameter gives the size of the memory this program will be run - with. This is not useful for now (our programs do not use memory), but it - will when we add memory allocation to our programs. + Le paramètre [memsize] donne la taille de la mémoire dont ce programme va + disposer. Ce n'est pas utile tout de suite (nos programmes n'utilisent pas de + mémoire), mais ça le sera lorsqu'on ajoutera de l'allocation dynamique dans + nos programmes. - Returns: - - [OK (Some v)] when the function evaluation went without problems and - resulted in integer value [v]. - - [OK None] when the function evaluation finished without returning a value. - - [Error msg] when an error has occured. -*) + Renvoie: + + - [OK (Some v)] lorsque l'évaluation de la fonction a lieu sans problèmes et renvoie une valeur [v]. + + - [OK None] lorsque l'évaluation de la fonction termine sans renvoyer de valeur. + + - [Error msg] lorsqu'une erreur survient. + *) let eval_eprog oc (ep: eprog) (memsize: int) (params: int list) : int option res = let st = init_state memsize in diff --git a/src/main.ml b/src/main.ml index 1314160c8637843ce07c128d0a52b09543e9ab3e..b0397bb85b1f4b9d700be7949d075613336db8b3 100644 --- a/src/main.ml +++ b/src/main.ml @@ -85,7 +85,7 @@ let speclist = ("-m32", Arg.Unit (fun _ -> Archi.archi := A32), "32bit mode"); ("-f", Arg.String (fun s -> input_file := Some s), "file to compile"); ("-alloc-order-ts", Arg.Unit (fun _ -> Options.alloc_order_st := false), "Allocate t regs before s regs"); - ("-json", Arg.Set output_json, "Output JSON summary"); + ("-json", Arg.String (fun s -> output_json := s), "Output JSON summary"); ("-nostart", Arg.Set nostart, "Don't output _start code."); ("-nostats", Arg.Set nostats, "Don't output stats."); ("-nomul", Arg.Unit (fun _ -> has_mul := false), "Target architecture without mul instruction."); @@ -358,9 +358,7 @@ let _ = end; - - if !output_json - then begin + let json_output_string = let open Yojson in let jstring_of_ostring o = match o with @@ -380,6 +378,10 @@ let _ = ("data", data) ] ) !results) in - Format.printf "%s\n" (Yojson.pretty_to_string j); - end; + (Yojson.pretty_to_string j) in + + + dump (Some !output_json) (fun oc p -> + Format.fprintf oc "%s\n" p + ) json_output_string (fun _ () -> ()); make_report input report () diff --git a/src/options.ml b/src/options.ml index 63572f6f206a59b6e4c1d4af823c49616789ad03..53c33dfcf99529e7d6ff99ae59174f270a3d2208 100644 --- a/src/options.ml +++ b/src/options.ml @@ -24,7 +24,7 @@ let riscv_run = ref false let show = ref false let params : int list ref = ref [] let input_file : string option ref = ref None -let output_json = ref false +let output_json : string ref = ref "-" let nostart = ref false let nostats = ref false let has_mul = ref true diff --git a/tests/test.py b/tests/test.py index 3ec9d0f27c56dcdd86bf327c513a23ab950bbd26..a77bc49842b5dab72b8cecfc227e7d3c8a52a99d 100755 --- a/tests/test.py +++ b/tests/test.py @@ -56,7 +56,7 @@ if(args.verbose >= 1): # construct the set of commands to be launched, one per file cmds = [] for f in args.file: - cmd = "../main.native -json -f {} {} {} -- {}".format(f, + cmd = "../main.native -json {}.json -f {} {} {} -- {}".format(f, f, " ".join(map(lambda s : "-"+s, args.passes)), " ".join(unknown_args), " ".join(args.args) @@ -142,13 +142,15 @@ class CommandExecutor(Thread): process = self.run_capture_output_interruptible(c) self.stdout = process['stdout'].decode('utf8') self.stderr = process['stderr'].decode('utf8') + json_file_name = self.f + ".json" j = [] - try: - j = json.loads(self.stdout) - except: - j.append({'retval':-1, - 'output': display_verbatim(self.stdout), - 'error': display_verbatim(self.stderr)}) + with open(json_file_name, 'r') as jsonfile: + try: + j = json.load(jsonfile) + except: + j.append({'retval':-1, + 'output': display_verbatim(self.stdout), + 'error': display_verbatim(self.stderr)}) old_ret = None old_out = None old_err = None