diff --git a/.gitignore b/.gitignore index 42765851f67e460d370e8baed8a80bb4998717c3..bd07ec66bb53e2b7ab6cb82b7f3316eecb33c041 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,8 @@ grammar.html src/generated_parser.ml src/config.ml **/*.native +ecomp skeleton src/.vscode/ .vscode/ -Makefile.config \ No newline at end of file +Makefile.config diff --git a/Makefile b/Makefile index 241c2f6c24ef0e5303ebfb827ef7b988e787aaf9..47838aaa427e07b026212bc5925c802c5f333d09 100644 --- a/Makefile +++ b/Makefile @@ -1,28 +1,33 @@ -all: main.native +all: ecomp include opts.mk -.PHONY: main.native +.PHONY: ecomp src/config.ml: configure opts.mk ./configure ${CONF_OPTS} -main.native: src/config.ml +.PHONY: alpaga +alpaga/alpaga: make -C alpaga + +src/generated_parser.ml: expr_grammar_action.g alpaga/alpaga ./alpaga/alpaga \ -g expr_grammar_action.g \ -pml src/generated_parser.ml \ -t grammar.html + +ecomp: src/generated_parser.ml src/config.ml make -C src - ln -sf src/main.native main.native + ln -sf src/_build/default/main.exe ecomp clean: make -C alpaga clean rm -f src/generated_parser.ml rm -f grammar.html make -C src clean - rm -f main.native + rm -f ecomp make -C tests clean -test: main.native +test: ecomp make -C tests diff --git a/Sujet.pdf b/Sujet.pdf index 6e3b066a2f625d74939dbafa9972222d03003dbf..d9bafe17d7526dbda73abd2d6d39e7afb75aec14 100644 Binary files a/Sujet.pdf and b/Sujet.pdf differ diff --git a/alpaga/.merlin b/alpaga/.merlin deleted file mode 100644 index 882e9c09fe4d45ededf8a498ac3a85fcbf8c26ec..0000000000000000000000000000000000000000 --- a/alpaga/.merlin +++ /dev/null @@ -1,3 +0,0 @@ -S . -B _build -PKG batteries \ No newline at end of file diff --git a/alpaga/Makefile b/alpaga/Makefile index ae5b04de755159e85e076276feefcd327da4ec18..caabc9f71a78cf343e81be2a7e14f7a30581e452 100644 --- a/alpaga/Makefile +++ b/alpaga/Makefile @@ -1,4 +1,4 @@ -OCB=ocamlbuild -use-ocamlfind -cflag -g +#OCB=ocamlbuild -use-ocamlfind -cflag -g SRC=ml_parser_generator.ml \ grammar_parser.ml \ @@ -12,11 +12,9 @@ TG = alpaga all: $(TG) -$(TG): ml_parser_generator.native - cp ml_parser_generator.native $(TG) - -ml_parser_generator.native: $(SRC) - $(OCB) ml_parser_generator.native +$(TG): $(SRC) + dune build ml_parser_generator.exe + ln -sf _build/default/ml_parser_generator.exe alpaga clean: rm -f ml_parser_generator.native $(TG) diff --git a/alpaga/_tags b/alpaga/_tags deleted file mode 100644 index 6fea563c5d06918d4cc2d7a963acd8754c9d756b..0000000000000000000000000000000000000000 --- a/alpaga/_tags +++ /dev/null @@ -1,3 +0,0 @@ -<.>: include -true: package(str, batteries) -true: use_menhir diff --git a/alpaga/dune b/alpaga/dune new file mode 100644 index 0000000000000000000000000000000000000000..c1980e29d4a2ce8f8c69cbec0da8baf77ccee6de --- /dev/null +++ b/alpaga/dune @@ -0,0 +1,14 @@ +(menhir + (modules grammar_parser_yacc) +) +(ocamllex grammar_lexer) + +(executable + (name ml_parser_generator) + (libraries + batteries + menhirLib + ) + (flags (:standard -warn-error -A -w -27 -w -33 -w -9 -w -39)) + +) diff --git a/alpaga/dune-project b/alpaga/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..192d77fdc7853a217a9338cf6209a8cdf00597c5 --- /dev/null +++ b/alpaga/dune-project @@ -0,0 +1,2 @@ +(lang dune 2.9) +(using menhir 2.1) diff --git a/alpaga/grammar.ml b/alpaga/grammar.ml index 0032c4d794fcabda226393710b3cecfae08f9c0a..d3a95dd5c5e2e22287287207577dd2645abe50c8 100644 --- a/alpaga/grammar.ml +++ b/alpaga/grammar.ml @@ -24,5 +24,6 @@ let dump_grammar oc (toks, nts, rules) = Printf.fprintf oc "\nnon-terminals "; List.iter (fun n -> Printf.fprintf oc " %s" n) nts; Printf.fprintf oc "\nrules\n"; - List.iter (fun (n,lt,a) -> Printf.fprintf oc "%s ->%s\n" n (print_seq (fun x -> x) lt)) rules + List.iter (fun (n,lt,_) -> + Printf.fprintf oc "%s ->%s\n" n (print_seq (fun x -> x) lt)) rules diff --git a/src/.merlin b/src/.merlin deleted file mode 100644 index 5aca64dac0daf41b44358cea1613e02df7820526..0000000000000000000000000000000000000000 --- a/src/.merlin +++ /dev/null @@ -1,11 +0,0 @@ -S . -B _build -PKG lwt -PKG lwt.unix -PKG logs -PKG logs.lwt -PKG batteries -PKG yojson -PKG websocket -PKG websocket-lwt-unix -PKG menhirLib \ No newline at end of file diff --git a/src/Makefile b/src/Makefile index ea616e9fd16eec28c0af0a909a3e910833e202d5..3c9a73582238f649621436e7687a8a1a838727f1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,18 +9,18 @@ ltl_gen.ml ltl_run.ml ltl_debug.ml main.ml options.ml parser.ml prog.ml \ regalloc.ml report.ml riscv.ml rtl.ml rtl_print.ml rtl_gen.ml rtl_run.ml \ symbols.ml tokenize.ml utils.ml -TG = main.native +TG = main.exe PROF:=$(if $(PROF),-ocamlopt ocamloptp,) all: $(TG) $(TG): $(SRC) - ocamlbuild $(PROF) -cflags -warn-error,"+a-26" -cflags -w,"-26" -menhir "menhir --unused-tokens" -use-ocamlfind $(TG) + dune build $(TG) + # ocamlbuild $(PROF) -cflags -warn-error,"+a-26" -cflags -w,"-26" -menhir "menhir --unused-tokens" -use-ocamlfind $(TG) test_lexer: archi.ml config.ml e_regexp.ml lexer_generator.ml symbols.ml test_lexer.ml utils.ml - ocamlbuild -use-ocamlfind test_lexer.native - ./test_lexer.native + dune exec test_lexer.exe dot -Tsvg /tmp/dfa.dot -o /tmp/dfa.svg dot -Tsvg /tmp/nfa.dot -o /tmp/nfa.svg @@ -28,5 +28,5 @@ config.ml: ../configure ../opts.mk cd .. && ./configure ${CONF_OPTS} clean: - rm -rf _build - rm -f config.ml main.native test_lexer.native + dune clean + rm -f config.ml diff --git a/src/_tags b/src/_tags deleted file mode 100644 index 85863b57f6f3a210cf25acdd94cceeb1b6d447d4..0000000000000000000000000000000000000000 --- a/src/_tags +++ /dev/null @@ -1,7 +0,0 @@ -true: debug -true: bin_annot -<runtime>: -traverse -<*>: package(lwt lwt.unix logs logs.lwt batteries yojson websocket websocket-lwt-unix menhirLib) -true: thread -true: use_menhir, explain, table -<tykernel>: -traverse diff --git a/src/archi.ml b/src/archi.ml index 988790064fc6218be79355941aaed39e8ed720ab..cfaa1b381f91cdf88d6b055240323e8447c393a8 100644 --- a/src/archi.ml +++ b/src/archi.ml @@ -1,4 +1,3 @@ -open Config type archi = A64 | A32 diff --git a/src/ast.ml b/src/ast.ml index 64d50fb94d64f2e7c126921282d64695ab58c8ff..bfd93a8a25c70dd90d9f6504fa19e221ed3bb193 100644 --- a/src/ast.ml +++ b/src/ast.ml @@ -1,5 +1,4 @@ open Batteries -open BatPrintf (* Les AST sont des arbres, du type [tree], étiquetés par des [tag]. @@ -31,7 +30,7 @@ type tag = Tassign | Tif | Twhile | Tblock | Treturn | Tprint | Tlistglobdef | Tfundef | Tfunname | Tfunargs | Tfunbody | Tassignvar - | Targ + | Targ type tree = | Node of tag * tree list | StringLeaf of string diff --git a/src/cfg.ml b/src/cfg.ml index 3df451950df479a00cda85835f38178410c72b4b..7c4cb023ce56fa2c68501c5b9369ec311c7996cc 100644 --- a/src/cfg.ml +++ b/src/cfg.ml @@ -1,6 +1,5 @@ open Elang open Prog -open Utils open Batteries open BatList @@ -51,10 +50,10 @@ let preds cfgfunbody n = ) cfgfunbody Set.empty -let size_binop b e1 e2 = +let size_binop _ e1 e2 = 1 + e1 + e2 -let size_unop u e = +let size_unop _ e = 1 + e let rec size_expr (e: expr) : int = @@ -62,16 +61,16 @@ let rec size_expr (e: expr) : int = | Ebinop (b, e1, e2) -> size_binop b (size_expr e1) (size_expr e2) | Eunop (u, e) -> size_unop u (size_expr e) | Eint _ -> 1 - | Evar v -> 1 + | Evar _ -> 1 -let rec size_instr (i: cfg_node) : int = +let size_instr (i: cfg_node) : int = match (i : cfg_node) with - | Cassign (v, e, s) -> 1 + size_expr e + | Cassign (_, e, _) -> 1 + size_expr e | Creturn e -> 1 + (size_expr e) - | Cprint (e, s) -> 1 + (size_expr e) - | Ccmp (e, s1, s2) -> 1 + size_expr e - | Cnop s -> 1 + | Cprint (e, _) -> 1 + (size_expr e) + | Ccmp (e, _, _) -> 1 + size_expr e + | Cnop _ -> 1 let size_fun f = - Hashtbl.fold (fun k v acc -> acc + size_instr v) f 0 + Hashtbl.fold (fun _ v acc -> acc + size_instr v) f 0 diff --git a/src/cfg_constprop.ml b/src/cfg_constprop.ml index 10ffa8a04e3dbfc7d1c3fc96c22fea114b305563..7309a1a170c5fe60a043427be4d9ffc6ab651cb9 100644 --- a/src/cfg_constprop.ml +++ b/src/cfg_constprop.ml @@ -37,8 +37,8 @@ let rec const_prop_expr (e: expr) = let constant_propagation_instr (i: cfg_node) : cfg_node = i -let constant_propagation_fun ({ cfgfunargs; cfgfunbody; cfgentry } as f: cfg_fun) = - let ht = Hashtbl.map (fun n m -> +let constant_propagation_fun ({ cfgfunbody; _ } as f: cfg_fun) = + let ht = Hashtbl.map (fun _ m -> constant_propagation_instr m ) cfgfunbody in { f with cfgfunbody = ht} diff --git a/src/cfg_dead_assign.ml b/src/cfg_dead_assign.ml index 8130533fdab83225fe79e4c2dd028ae284f9028d..e35fc4762eb958bb4ec5ad1be98fbbb409a6e39e 100644 --- a/src/cfg_dead_assign.ml +++ b/src/cfg_dead_assign.ml @@ -13,7 +13,7 @@ open Options function [f]. Cette fonction renvoie un couple [(f',c)] oú [f'] est la nouvelle fonction, et [c] est un booléen qui indique si du progrès a été fait. *) -let dead_assign_elimination_fun ({ cfgfunargs; cfgfunbody; cfgentry } as f: cfg_fun) = +let dead_assign_elimination_fun ({ cfgfunbody; _ } as f: cfg_fun) = let changed = ref false in let cfgfunbody = Hashtbl.map (fun (n: int) (m: cfg_node) -> diff --git a/src/cfg_gen.ml b/src/cfg_gen.ml index b20b93392d02bcde3a7e0a8f599991289fd51f54..18509ef62dd1711bdfe41db26dfd56fe3e5676f5 100644 --- a/src/cfg_gen.ml +++ b/src/cfg_gen.ml @@ -106,7 +106,7 @@ let cfg_gdef_of_edef gd = Gfun f -> cfg_fun_of_efun f >>= fun f -> OK (Gfun f) let cfg_prog_of_eprog (ep: eprog) : cfg_fun prog res = - assoc_map_res (fun fname -> cfg_gdef_of_edef) ep + assoc_map_res (fun _ -> cfg_gdef_of_edef) ep let pass_cfg_gen ep = match cfg_prog_of_eprog ep with diff --git a/src/cfg_liveness.ml b/src/cfg_liveness.ml index 1fee07ab1b5a52f6a7156862265b25746f3041ce..1671af63478814178261144435ad31d5b85e53d1 100644 --- a/src/cfg_liveness.ml +++ b/src/cfg_liveness.ml @@ -1,7 +1,5 @@ open Batteries open Cfg -open Prog -open Utils (* Analyse de vivacité *) diff --git a/src/cfg_print.ml b/src/cfg_print.ml index 135c810aa53b0a4a040d2d808f7220416f800936..6ec810a6254e741900bea58fd5954da1e5f8062a 100644 --- a/src/cfg_print.ml +++ b/src/cfg_print.ml @@ -2,7 +2,6 @@ open Batteries open Cfg open Elang_print open Prog -open Utils let rec dump_cfgexpr : expr -> string = function | Ebinop(b, e1, e2) -> Format.sprintf "(%s %s %s)" (dump_cfgexpr e1) (dump_binop b) (dump_cfgexpr e2) @@ -44,7 +43,7 @@ let dump_liveness_state oc ht state = flush_all () ) ht -let dump_cfg_fun oc cfgfunname ({ cfgfunargs; cfgfunbody; cfgentry; }: cfg_fun) = +let dump_cfg_fun oc cfgfunname ({ cfgfunbody; cfgentry; _ }: cfg_fun) = Format.fprintf oc "subgraph cluster_%s {\n label=\"%s\";\n" cfgfunname cfgfunname; Hashtbl.iter (fun n node -> Format.fprintf oc "n_%s_%d [label=\"%a\" xlabel=\"%d\" shape=%s];\n" cfgfunname n dump_cfg_node node n (if n = cfgentry then "rectangle peripheries=2" else "rectangle"); diff --git a/src/dune b/src/dune new file mode 100644 index 0000000000000000000000000000000000000000..18d7936f4fe6fb1a2ef48f0f1eedc7c6922c26e1 --- /dev/null +++ b/src/dune @@ -0,0 +1,19 @@ +(menhir + (modules yaccparser) + (flags (--unused-tokens)) + ; unused-tokens +) +(ocamllex lexer) + +(executable + (name main) + (libraries + batteries + yojson + lwt + websocket + websocket-lwt-unix + menhirLib + ) + (flags (:standard -warn-error -A -w -27 -w -33 -w -9 -w -39)) +) diff --git a/src/dune-project b/src/dune-project new file mode 100644 index 0000000000000000000000000000000000000000..192d77fdc7853a217a9338cf6209a8cdf00597c5 --- /dev/null +++ b/src/dune-project @@ -0,0 +1,2 @@ +(lang dune 2.9) +(using menhir 2.1) diff --git a/src/e_regexp.ml b/src/e_regexp.ml index 4f6c43f4e9007f42ef117097e9581eb78cb17b1d..bbc5b204ba11e4fcba87a032c342ff699b2719e6 100644 --- a/src/e_regexp.ml +++ b/src/e_regexp.ml @@ -66,43 +66,43 @@ let keyword_regexp s = str_regexp (char_list_of_string s) (* La liste des expressions régulières permettant d'identifier les tokens du langage E *) let list_regexp : (regexp * (string -> token option)) list = [ - (keyword_regexp "while", fun s -> Some (SYM_WHILE)); - (keyword_regexp "int", fun s -> Some (SYM_INT)); + (keyword_regexp "while", fun _ -> Some (SYM_WHILE)); + (keyword_regexp "int", fun _ -> Some (SYM_INT)); (* begin TODO *) - (Eps, fun s -> Some (SYM_VOID)); - (Eps, fun s -> Some (SYM_CHAR)); - (Eps, fun s -> Some (SYM_IF)); - (Eps, fun s -> Some (SYM_ELSE)); - (Eps, fun s -> Some (SYM_RETURN)); - (Eps, fun s -> Some (SYM_PRINT)); - (Eps, fun s -> Some (SYM_STRUCT)); - (Eps, fun s -> Some (SYM_POINT)); - (Eps, fun s -> Some (SYM_PLUS)); - (Eps, fun s -> Some (SYM_MINUS)); - (Eps, fun s -> Some (SYM_ASTERISK)); - (Eps, fun s -> Some (SYM_DIV)); - (Eps, fun s -> Some (SYM_MOD)); - (Eps, fun s -> Some (SYM_LBRACE)); - (Eps, fun s -> Some (SYM_RBRACE)); - (Eps, fun s -> Some (SYM_LBRACKET)); - (Eps, fun s -> Some (SYM_RBRACKET)); - (Eps, fun s -> Some (SYM_LPARENTHESIS)); - (Eps, fun s -> Some (SYM_RPARENTHESIS)); - (Eps, fun s -> Some (SYM_SEMICOLON)); - (Eps, fun s -> Some (SYM_COMMA)); - (Eps, fun s -> Some (SYM_ASSIGN)); - (Eps, fun s -> Some (SYM_EQUALITY)); - (Eps, fun s -> Some (SYM_NOTEQ)); - (Eps, fun s -> Some (SYM_LT)); - (Eps, fun s -> Some (SYM_GT)); - (Eps, fun s -> Some (SYM_LEQ)); - (Eps, fun s -> Some (SYM_GEQ)); + (Eps, fun _ -> Some (SYM_VOID)); + (Eps, fun _ -> Some (SYM_CHAR)); + (Eps, fun _ -> Some (SYM_IF)); + (Eps, fun _ -> Some (SYM_ELSE)); + (Eps, fun _ -> Some (SYM_RETURN)); + (Eps, fun _ -> Some (SYM_PRINT)); + (Eps, fun _ -> Some (SYM_STRUCT)); + (Eps, fun _ -> Some (SYM_POINT)); + (Eps, fun _ -> Some (SYM_PLUS)); + (Eps, fun _ -> Some (SYM_MINUS)); + (Eps, fun _ -> Some (SYM_ASTERISK)); + (Eps, fun _ -> Some (SYM_DIV)); + (Eps, fun _ -> Some (SYM_MOD)); + (Eps, fun _ -> Some (SYM_LBRACE)); + (Eps, fun _ -> Some (SYM_RBRACE)); + (Eps, fun _ -> Some (SYM_LBRACKET)); + (Eps, fun _ -> Some (SYM_RBRACKET)); + (Eps, fun _ -> Some (SYM_LPARENTHESIS)); + (Eps, fun _ -> Some (SYM_RPARENTHESIS)); + (Eps, fun _ -> Some (SYM_SEMICOLON)); + (Eps, fun _ -> Some (SYM_COMMA)); + (Eps, fun _ -> Some (SYM_ASSIGN)); + (Eps, fun _ -> Some (SYM_EQUALITY)); + (Eps, fun _ -> Some (SYM_NOTEQ)); + (Eps, fun _ -> Some (SYM_LT)); + (Eps, fun _ -> Some (SYM_GT)); + (Eps, fun _ -> Some (SYM_LEQ)); + (Eps, fun _ -> Some (SYM_GEQ)); (Eps, fun s -> Some (SYM_IDENTIFIER s)); (* end TODO *) (Cat(keyword_regexp "//", Cat(Star (char_range (List.filter (fun c -> c <> '\n') alphabet)), Alt (char_regexp '\n', Eps))), - fun s -> None); + fun _ -> None); (Cat(keyword_regexp "/*", Cat( Cat (Star (Alt ( @@ -111,7 +111,7 @@ let list_regexp : (regexp * (string -> token option)) list = plus(char_range (List.filter (fun c -> c <> '/' && c <> '*') alphabet))) )), Star (char_range ['*'])), keyword_regexp "*/")), - fun s -> None); + fun _ -> None); (Cat (char_regexp '\'', Cat (char_range (List.filter (fun c -> c <> '\'' && c <> '\\') alphabet), char_regexp '\'')), @@ -141,8 +141,8 @@ let list_regexp : (regexp * (string -> token option)) list = ), char_regexp '"')), fun s -> Some (SYM_STRING (Stdlib.Scanf.unescaped (String.slice ~first:1 ~last:(-1) s)))); - (char_range (char_list_of_string " \t\n"), fun s -> None); + (char_range (char_list_of_string " \t\n"), fun _ -> None); (plus digit_regexp, fun s -> Some (SYM_INTEGER (int_of_string s))); - (Eps, fun s -> Some (SYM_EOF)) + (Eps, fun _ -> Some (SYM_EOF)) ] diff --git a/src/elang.ml b/src/elang.ml index 76c786546e12f93c3c61e3b1239c2a199b830682..72b8e18b5c4a94b0226063a502ed274af1822d59 100644 --- a/src/elang.ml +++ b/src/elang.ml @@ -1,7 +1,4 @@ -open Ast -open Batteries open Prog -open Utils type binop = Eadd | Emul | Emod | Exor | Ediv | Esub (* binary operations *) | Eclt | Ecle | Ecgt | Ecge | Eceq | Ecne (* comparisons *) diff --git a/src/elang_run.ml b/src/elang_run.ml index f955cd1f2913dc47d20389d585da570bc124145f..494b2c6ac0da84d327a4e1016b7da8f57b3ae57e 100644 --- a/src/elang_run.ml +++ b/src/elang_run.ml @@ -1,10 +1,7 @@ open Elang open Batteries -open BatList open Prog open Utils -open Builtins -open Utils let binop_bool_to_int f x y = if f x y then 1 else 0 @@ -88,5 +85,5 @@ let eval_eprog oc (ep: eprog) (memsize: int) (params: int list) (* ne garde que le nombre nécessaire de paramètres pour la fonction "main". *) let n = List.length f.funargs in let params = take n params in - eval_efun oc st f "main" params >>= fun (v, st) -> + eval_efun oc st f "main" params >>= fun (v, _) -> OK v diff --git a/src/ltl_debug.ml b/src/ltl_debug.ml index b3d870aa9f3446f21bb59a5411bf4b53bff0d6f5..6e2d7753b21d0161f75ad66b400dad93b9a118b3 100644 --- a/src/ltl_debug.ml +++ b/src/ltl_debug.ml @@ -214,11 +214,11 @@ let debug_ltl_prog progname lp memsize params : unit= let st = ref (init_state memsize lp params) in let state = ref (None) in let breaks = ref [] in - let ctx = Conduit_lwt_unix.default_ctx in + let ctx = Lazy.force Conduit_lwt_unix.default_ctx in let uri = "http://localhost:8080" in let (pstop, rstop) = Lwt.task () in let server () = - Resolver_lwt.resolve_uri (Uri.of_string uri) Resolver_lwt_unix.system >>= fun endp -> + Resolver_lwt.resolve_uri ~uri:(Uri.of_string uri) Resolver_lwt_unix.system >>= fun endp -> Conduit_lwt_unix.endp_to_server ~ctx endp >>= fun server -> Websocket_lwt_unix.establish_server ~ctx ~mode:server diff --git a/src/ltl_gen.ml b/src/ltl_gen.ml index 609470626ef64f1258b4e29bae8775798135e8a3..aa6a9fa16cc866bdcb76848577ada490f3b5ae22 100644 --- a/src/ltl_gen.ml +++ b/src/ltl_gen.ml @@ -325,7 +325,7 @@ let ltl_instrs_of_linear_instr fname live_out allocation | Rlabel l -> OK [LLabel (Format.sprintf "%s_%d" fname l)] in res >>= fun l -> - OK (LComment (Format.asprintf "#<span style=\"background: pink;\"><b>Linear instr</b>: %a #</span>" (Rtl_print.dump_rtl_instr fname (None, None)) ins)::l) + OK (LComment (Format.asprintf "#<span style=\"background: pink;\"><b>Linear instr</b>: %a #</span>" (Rtl_print.dump_rtl_instr fname (None, None) ~endl:"") ins)::l) (** Retrieves the location of the n-th argument (in the callee). The first 8 are passed in a0-a7, the next are passed on the stack. *) diff --git a/src/main.ml b/src/main.ml index 7df1d41e4df078f4dcbc5e53782f7e805b497dbc..92b967f912e7519179fbca97c174b70313980d05 100644 --- a/src/main.ml +++ b/src/main.ml @@ -165,7 +165,7 @@ let _ = | Some input -> add_to_report "Source" "Source" (Code (file_contents input)); - match Filename.chop_suffix_opt ".e" input with + match Filename.chop_suffix_opt ~suffix:".e" input with None -> failwith (Format.sprintf "File (%s) should end in .e" input) | Some basename -> diff --git a/src/report.ml b/src/report.ml index ba312d99e4715967ff4e4c237b5494ee28f6df3f..82fddb4da1531c5e29b7007a980d5cf00b188de7 100644 --- a/src/report.ml +++ b/src/report.ml @@ -25,18 +25,59 @@ let add_to_report id title content = let make_report filename report () = let html = open_out (filename ^ ".html") in - Printf.fprintf html "<ul id=\"top\">"; + Printf.fprintf html "\ +<html>\n\ + <head>\n\ + <link rel=\"stylesheet\" href=\"https://www.w3schools.com/w3css/4/w3.css\">\n\ + <script src=\"https://kit.fontawesome.com/1f5d81749b.js\" crossorigin=\"anonymous\"></script>\n\ + <style type=\"text/css\">\n\ + a.anchor {\n\ + display: block; \ + position: relative; \ + left: -250px; \ + visibility: hidden;\ + }\n\ + </style>\n\ + </head>\n\ + <body>\n\ +"; + Printf.fprintf html "<div \ + class=\"w3-container w3-cell\" \ + style=\"position: fixed; z-index: 1; top: 0; bottom: 0; width: 250px; overflow-y: scroll;\"\ + >\n <ul class=\"w3-ul\">\n"; + let t = Unix.time () in + let tm = Unix.localtime t in + let open Unix in + Printf.fprintf html "<li>%02d/%02d/%04d - %02dh%02d</li>" + tm.tm_mday + (tm.tm_mon + 1) + (tm.tm_year + 1900) + tm.tm_hour + tm.tm_min + ; + Printf.fprintf html " <li><a href=\"../results.html\"><i class=\"fa fa-home\"></i> Results</a></li>\n"; List.iter - (fun { sect_id; sect_title } -> - Printf.fprintf html "<li><a href=\"#%s\">%s</a></li>\n" sect_id sect_title + (fun { sect_id; sect_title; _ } -> + Printf.fprintf html " <li><a href=\"#%s\">%s</a></li>\n" sect_id sect_title ) !report; - Printf.fprintf html "</ul>"; + Printf.fprintf html "</ul></div><div \ + class=\"w3-container w3-cell-row\" \ + style=\"margin-left: 250px;\"\ + ><a class=\"anchor\" id=\"top\"></a>"; List.iter (fun { sect_id; sect_title; sect_content } -> - Printf.fprintf html "<fieldset><h3 id=\"%s\"><a href=\"#top\">↑</a> %s</h3>%a</fieldset>\n" sect_id sect_title print_html sect_content + Printf.fprintf html "<fieldset>\n\ + <a class=\"anchor\" id=\"%s\"></a>\n\ + <h3><a href=\"#top\">↑</a> %s</h3>\n\ + %a\n\ + </fieldset>\n" sect_id sect_title print_html sect_content ) !report; + Printf.fprintf html "\ +</div>\n\ +</body>\n\ +</html>"; close_out html; () @@ -109,7 +150,7 @@ let timeout (f: 'a -> 'b res) (arg: 'a) (time: float) : ('b * string) res = Marshal.to_channel oc (Error (Printf.sprintf "Timeout after %f seconds." time)) []; close_out oc; exit 0 - | pid1 -> let ic = Unix.in_channel_of_descr pipe_r in + | _ -> let ic = Unix.in_channel_of_descr pipe_r in let result = Marshal.from_channel ic in result )) @@ -146,7 +187,6 @@ let run step flag eval p = let json_output_string () = - let open Yojson in let jstring_of_ostring o = match o with | None -> `Null diff --git a/src/rtl.ml b/src/rtl.ml index 3ce33fdec0214095ec8ced78b74b5e8e5c76b275..ab703a052a576fcb000cc3eb1ed68a08653d225b 100644 --- a/src/rtl.ml +++ b/src/rtl.ml @@ -1,9 +1,6 @@ open Batteries -open BatList open Elang open Cfg -open Utils -open Prog type reg = int diff --git a/src/rtl_print.ml b/src/rtl_print.ml index c8ed813944d2722f5266a043b1af819e2d321860..f0b473438d9927b2ae15de2daf7975c48bb44a20 100644 --- a/src/rtl_print.ml +++ b/src/rtl_print.ml @@ -17,7 +17,7 @@ let print_cmpop (r: rtl_cmp) = | Rceq -> "==" | Rcne -> "!=") -let dump_rtl_instr name (live_in, live_out) oc (i: rtl_instr) = +let dump_rtl_instr name (live_in, live_out) ?(endl="\n") oc (i: rtl_instr) = let print_node s = Format.sprintf "%s_%d" name s in let dump_liveness live where = @@ -42,7 +42,7 @@ let dump_rtl_instr name (live_in, live_out) oc (i: rtl_instr) = | Rprint r -> Format.fprintf oc "print %s" (print_reg r) | Rlabel n -> Format.fprintf oc "%s_%d:" name n end; - Format.fprintf oc "\n"; + Format.fprintf oc "%s" endl; dump_liveness live_out "after" let dump_rtl_node name lives = @@ -52,6 +52,7 @@ let dump_rtl_node name lives = None -> (None, None) | Some (lin, lout) -> Hashtbl.find_option lin i, Hashtbl.find_option lout i) + ~endl:"\n" ) "" "" "" let dump_rtl_fun oc rtlfunname ({ rtlfunargs; rtlfunbody; rtlfunentry }: rtl_fun) = diff --git a/src/symbols.ml b/src/symbols.ml index 8659b7511b8b4b9b7c2e2817685332e523cab7e7..71760ef8380d4e4fefc2f934565fab43c68fe9b4 100644 --- a/src/symbols.ml +++ b/src/symbols.ml @@ -1,6 +1,4 @@ -open BatPrintf open Batteries -open Utils let string_of_position pos = let open Lexing in diff --git a/src/utils.ml b/src/utils.ml index 48ad33f9c0eef6eccb7c40fa7f7d3a42e4d5da32..35479bfb29f2ae40c4c2c6aba8a764010feaa3f9 100644 --- a/src/utils.ml +++ b/src/utils.ml @@ -1,5 +1,4 @@ open Batteries -open BatPrintf open BatBuffer open BatList @@ -131,18 +130,18 @@ module Mem : sig val write_log : t -> unit -> (int * int) list end = struct type t = int array * int list ref * (int * int) list ref - let write_bytes (m,rl,wl) addr bytes = + let write_bytes (m,_,wl) addr bytes = write_mem_bytes m addr bytes >>= fun w -> wl := w @ !wl; OK () - let write_char (m,rl,wl) addr c = + let write_char (m,_,wl) addr c = write_mem_char m addr c >>= fun w -> wl := w @ !wl; OK () - let read_bytes (m,rl,wl) addr len = + let read_bytes (m,rl,_) addr len = read_mem_bytes m addr len >>= fun (vl,addrl) -> rl := addrl @ !rl ; OK vl - let read_bytes_as_int (m,rl,wl) addr len = + let read_bytes_as_int (m,rl,_) addr len = read_mem_bytes_as_int m addr len >>= fun (v,addrl) -> rl := addrl @ !rl; OK v - let read_char (m,rl,wl) addr = + let read_char (m,rl,_) addr = read_mem_char m addr >>= fun (v,addrl) -> rl := addrl @ !rl; OK v let init n = Array.init n (fun _ -> 0), ref [], ref [] @@ -154,7 +153,7 @@ let assoc_opti k l = let rec aux l n = match l with | [] -> None - | (a,v)::l when a = k -> Some (n, v) + | (a,v)::_ when a = k -> Some (n, v) | _::l -> aux l (n+1) in aux l 0 @@ -169,7 +168,7 @@ let assoc_map_res f l = OK (acc@[(k,v)]) ) (OK []) l -let rec assoc_split fl fr l = +let assoc_split fl fr l = let rec aux l (accl, accr) = match l with | [] -> (accl, accr) @@ -339,7 +338,7 @@ let file_contents file = try let line = input_line ic in (* read line from in_channel and discard \n *) aux (s ^ line ^ "\n") () (* close the input channel *) - with e -> (* some unexpected exception occurs *) + with _ -> (* some unexpected exception occurs *) close_in_noerr ic; (* emergency closing *) s in aux "" () diff --git a/tests/Makefile b/tests/Makefile index 78c3657f7a434bd91dd0b8d0d4c4a55edfd59f09..7f5a992327ddebee63e223a3f3eda7070950bfbf 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -6,13 +6,13 @@ FILES := $(if $(DIR),$(DIR),basic/*.e) OPTS := $(if $(OPTS), $(OPTS),) .PHONY: all -all: ../main.native +all: ../ecomp ./test.py -f $(FILES) $(OPTS) -expect: ../main.native +expect: ../ecomp OCAMLRUNPARAM=b ./test.py --make-expect -f $(FILES) $(OPTS) --args 1 2 3 OCAMLRUNPARAM=b ./test.py --make-expect -f $(FILES) $(OPTS) --args 14 12 3 8 12 - for f in $(FILES); do ../main.native -f $$f -show-tokens $$f.expect_lexer; done + for f in $(FILES); do ../ecomp -f $$f -show-tokens $$f.expect_lexer; done clean: diff --git a/tests/basic/whileret.e b/tests/basic/whileret.e deleted file mode 100644 index 921facb0703457a4ac60fde806d771d080b13175..0000000000000000000000000000000000000000 --- a/tests/basic/whileret.e +++ /dev/null @@ -1,9 +0,0 @@ -main(x){ - while(x > 0){ - if (x == 3){ - return 12; - } - x = x - 1; - } - return -3; -} diff --git a/tests/basic/whileret.e.expect_14_12_3_8_12 b/tests/basic/whileret.e.expect_14_12_3_8_12 deleted file mode 100644 index bcf7b802b7bc81daf4f5967753206a451b8eac6e..0000000000000000000000000000000000000000 --- a/tests/basic/whileret.e.expect_14_12_3_8_12 +++ /dev/null @@ -1 +0,0 @@ -{"output": "", "error": null, "retval": 12} \ No newline at end of file diff --git a/tests/basic/whileret.e.expect_1_2_3 b/tests/basic/whileret.e.expect_1_2_3 deleted file mode 100644 index e50078bef0dc9408205eb44eb97394dfaff5447d..0000000000000000000000000000000000000000 --- a/tests/basic/whileret.e.expect_1_2_3 +++ /dev/null @@ -1 +0,0 @@ -{"output": "", "error": null, "retval": -3} \ No newline at end of file diff --git a/tests/basic/whileret.e.expect_lexer b/tests/basic/whileret.e.expect_lexer deleted file mode 100644 index 8f900ffcd7084813acfd539f3115ca7a34433e04..0000000000000000000000000000000000000000 --- a/tests/basic/whileret.e.expect_lexer +++ /dev/null @@ -1,36 +0,0 @@ -SYM_IDENTIFIER(main) -SYM_LPARENTHESIS -SYM_IDENTIFIER(x) -SYM_RPARENTHESIS -SYM_LBRACE -SYM_WHILE -SYM_LPARENTHESIS -SYM_IDENTIFIER(x) -SYM_GT -SYM_INTEGER(0) -SYM_RPARENTHESIS -SYM_LBRACE -SYM_IF -SYM_LPARENTHESIS -SYM_IDENTIFIER(x) -SYM_EQUALITY -SYM_INTEGER(3) -SYM_RPARENTHESIS -SYM_LBRACE -SYM_RETURN -SYM_INTEGER(12) -SYM_SEMICOLON -SYM_RBRACE -SYM_IDENTIFIER(x) -SYM_ASSIGN -SYM_IDENTIFIER(x) -SYM_MINUS -SYM_INTEGER(1) -SYM_SEMICOLON -SYM_RBRACE -SYM_RETURN -SYM_MINUS -SYM_INTEGER(3) -SYM_SEMICOLON -SYM_RBRACE -SYM_EOF diff --git a/tests/test.py b/tests/test.py index 06f26656aafd5a4a2910fb651593d6fa6bf913e9..91bf090cca70a4e8209ab6691bd7356f71552d46 100755 --- a/tests/test.py +++ b/tests/test.py @@ -1,100 +1,57 @@ #!/usr/bin/python3 -import argparse, glob +"""Test orchestration for ecomp""" +import argparse +import glob from threading import Thread -import subprocess import json -from subprocess import * +from subprocess import Popen, PIPE import signal import sys import time import textwrap import difflib - -parser = argparse.ArgumentParser() -parser.add_argument("-f", "--file", - help="files to compile", - default=glob.glob("*.e"), - nargs='+') -parser.add_argument("-p", "--passes", - help="passes to execute", - nargs='+', - default=["e-run", - "cfg-run", - "cfg-run-after-cp", - "cfg-run-after-dae", - "cfg-run-after-ne", - "rtl-run", - "linear-run", - "linear-run-after-dse", - "ltl-run", - "riscv-run"]) -parser.add_argument("--args", - help="args for programs", - nargs='+', - default=["14","12","3","8","12"]) -parser.add_argument("--html", help="Output HTML file", - default="results.html") -parser.add_argument("-d", "--dry-run", help="Dry-run. Don't actually compile anything", - action="store_true") -parser.add_argument("-v", "--verbose", help="Verbosity level", - action="count", default=0) -parser.add_argument("--make-expect", help="Make .expect files for each test", - action="store_true") -args,unknown_args = parser.parse_known_args() - -# show options -if(args.verbose >= 1): - print("args.file=" + str(args.file)) - print("args.passes=" + str(args.passes)) - print("args.args=" + str(args.args)) - print("args.html=" + str(args.html)) - print("args.dry_run=" + str(args.dry_run)) - print("args.verbose=" + str(args.verbose)) - -# construct the set of commands to be launched, one per file -cmds = [] -for f in args.file: - cmd = "../main.native -json {}.json -f {} {} {} -- {}".format(f, f, - " ".join(map(lambda s : "-"+s, args.passes)), - " ".join(unknown_args), - " ".join(args.args) - ) - cmds.append((f,cmd)) - -# dyr_run : simply show the commands but don't execute them -if args.dry_run: - for (f,cmd) in cmds: - print(cmd) - exit() - -# The list of threads that will be launched -threads = [] +from typing import List +import datetime # The displayer thread shows what commands are still running class Displayer(Thread): - def __init__(self): + """A Displayer thread""" + + def __init__(self, threads): Thread.__init__(self) + self.threads = threads def run(self): width = 120 - l = [x for x in threads if x.running] - while len(l): - s = "{} threads running ".format(len(l)) - thrs = str(list(map(lambda x: x.f, l)))[:(width-len(s))] - print("\r{}({}).{}".format(s, thrs, " "*(width-len(thrs) - len(s))), end="") + l_running = [x for x in self.threads if x.running] + while len(l_running) > 0: + s_running = "{} threads running ".format(len(l_running)) + thrs = str(list(map(lambda x: x.filename, + l_running)))[:(width - len(s_running))] + print("\r{}({}).{}".format( + s_running, thrs, " " * (width - len(thrs) - len(s_running))), + end="") time.sleep(1) - l = [x for x in threads if x.running] + l_running = [x for x in self.threads if x.running] print() -# The number of columns in the HTML table -numcols = len(args.passes) + 1 # 1 colonne pour le lexer + + def display_verbatim(body): - return '\n'.join(['\n'.join(textwrap.wrap(line, 90, - break_long_words=False, replace_whitespace=False)) - for line in body.splitlines() if line.strip() != '']) + "Show verbatim contents" + return '\n'.join([ + '\n'.join( + textwrap.wrap(line, + 90, + break_long_words=False, + replace_whitespace=False)) + for line in body.splitlines() if line.strip() != '' + ]) + def make_td(td): + "Create a TD HTML tag" if isinstance(td, list): text = td[0] opts = " ".join(td[1:]) @@ -102,16 +59,18 @@ def make_td(td): text = str(td) opts = "" - return "<td {}>{}</td>".format(opts,text) + return "<td {}>{}</td>".format(opts, text) -def make_table_row(tds): - return "<tr>\n" + "".join(map(make_td,tds)) + "</tr>\n" +icon_ok = "<i class='fa fa-check' style='color: green;'></i>" +icon_warn = "<i class='fa fa-exclamation-circle' style='color: orange;'></i>" +icon_ko = "<i class='fa fa-times-circle' style='color:red;'></i>" # CommandExecutor run a command [cmd] and operates on file [f] class CommandExecutor(Thread): - def __init__(self, f, cmd): + """Command Executor""" + def __init__(self, filename, cmd, args, make_expect, numcols): Thread.__init__(self) - self.f = f + self.filename = filename self.cmd = cmd self.s = "" self.running = True @@ -119,210 +78,358 @@ class CommandExecutor(Thread): self.stderr = "" self.lastcorrectstep = -1 self.proc = None + self.args = args + self.make_expect = make_expect + self.numcols = numcols # run cmd and get stdout and stderr in dict - def run_capture_output_interruptible(self,cmd): - process = Popen(cmd, stdout=PIPE, stderr=PIPE) - self.proc = process + def run_capture_output_interruptible(self, cmd): + self.proc = Popen(cmd, stdout=PIPE, stderr=PIPE) try: - stdout, stderr = process.communicate() - retcode = process.poll() - return {'stdout' : stdout, 'stderr': stderr} + self.stdout, self.stderr = self.proc.communicate() + self.proc.poll() + self.stdout = self.stdout.decode('utf8') + self.stderr = self.stderr.decode('utf8') except: - return {'stdout' : b"[]", 'stderr': ""} + self.stdout = (b"[]").decode('utf8') + self.stderr = "".decode('utf8') def stop(self): + """Stop the thread""" if self.proc: self.proc.kill() - def run(self): - c = self.cmd.split(" ") - 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 = [] + def get_test_results(self, json_file_name): + "Get test results, handle errors" try: with open(json_file_name, 'r') as jsonfile: try: - j = json.load(jsonfile) + return json.load(jsonfile) except: - j.append({'retval':-1, - 'output': display_verbatim(self.stdout), - 'error': display_verbatim(self.stderr)}) + return [{ + 'retval': -1, + 'output': display_verbatim(self.stdout), + 'error': display_verbatim(self.stderr) + }] except: - j.append({'retval':-1, - 'output': display_verbatim(self.stdout), - 'error': "No file {} generated...".format(json_file_name)}) - old_ret = None - old_out = None - old_err = None + return [{ + 'retval': -1, + 'output': display_verbatim(self.stdout), + 'error': "No file {} generated...".format(json_file_name) + }] + + @staticmethod + def register_expect(expect_file_name, out, err, ret): + "Creates a .expect file" + with open(expect_file_name, 'w') as expectfile: + json.dump( + { + 'output': out, + 'error': err, + 'retval': ret + }, expectfile) + + @staticmethod + def check_expect(expect_file_name, out, err, ret): + "Checks a result wrt an expect file" + try: + with open(expect_file_name, 'r') as expectfile: + j = json.load(expectfile) + return j['retval'] == ret and \ + j['output'] == out and \ + j['error'] == err + except: + return None + + + def run(self): + """Actually run the test""" + self.run_capture_output_interruptible(self.cmd.split(" ")) + json_file_name = self.filename + ".json" + j = self.get_test_results(json_file_name) self.s = "" curcol = 0 - numrunstep = 0 - for i, r in enumerate(j, start=0): + first_runstep = True + for _, r in enumerate(j, start=0): if "runstep" in r: - expect_file_name = self.f + ".expect_" + "_".join(args.args) - if numrunstep == 0: - if args.make_expect: - with open(expect_file_name, 'w') as expectfile: - json.dump({ 'output' : r['output'], - 'error' : r['error'], - 'retval': r['retval']}, expectfile) - numrunstep = numrunstep + 1 - if old_ret == None: - old_ret = r['retval'] - if old_out == None: old_out = r['output'] - if old_err == None: old_err = r['error'] + expect_file_name = self.filename + ".expect_" + "_".join(self.args) + if first_runstep and self.make_expect: + self.register_expect(expect_file_name, r['output'], r['error'], r['retval']) + first_runstep = False cls = "good" - try: - with open(expect_file_name, 'r') as expectfile: - j = json.load(expectfile) - if j['retval'] == r['retval'] and j['output'] == r['output'] and j['error'] == r['error']: - cls = "good" - else: - cls = "bad" - except: + test_ok = self.check_expect(expect_file_name, r['output'], r['error'], r['retval']) + if test_ok is None: cls = "" + else: + cls = "good" if test_ok else "bad" if cls == "good": self.lastcorrectstep = curcol - self.s += make_td(["Ret = {}.<br>Output = <pre>'{}'</pre>{}<br>Time: {:.2f} seconds.<br>". - format(r['retval'], r['output'], - "Error: <pre>"+r['error']+"</pre>" if r['error'] != None else "", - r['time']), - "class=\"{}\"".format(cls)]) - curcol+=1 + err_str = "Error: <pre>" + r['error'] + "</pre>" if r['error'] is not None else "" + self.s += make_td([ + "{}<div name='{}' style='display:none;'>Ret = {}.<br>Output = <pre>'{}'</pre>{}<br>Time: {:.2f} seconds.</div>" + .format( + icon_ok if cls == 'good' else icon_ko, + self.filename, + r['retval'], + r['output'], + err_str, + r['time']), + "class=\"{}\"".format(cls) + ]) + "\n" + curcol += 1 elif "compstep" in r: compstep_td = "" err = r['error'] - if err != None: - compstep_td=""" - <td class="bad" style="text-align: left;" colspan="{}">{} error:<br><pre>{}</pre></td> - """.format( numcols - curcol, r['compstep'],err) - self.s += compstep_td - break + if err is not None: + compstep_td = """ + <td class="bad" style="text-align: left;" colspan="{}">{}<div name='{}' style='display:none'>{} error:<br><pre>{}</pre></div></td> + """.format(self.numcols - curcol, + icon_ko, + self.filename, + r['compstep'], err) elif r["compstep"] == "Lexing": - expect_lex_file_name = self.f + ".expect_lexer" - out_lex_file_name = self.f[:-2] + ".lex" + expect_lex_file_name = self.filename + ".expect_lexer" + out_lex_file_name = self.filename[:-2] + ".lex" try: - with open(expect_lex_file_name, "r") as expect_lex_file, open(out_lex_file_name, "r") as out_lex_file: + with open(expect_lex_file_name, "r") as expect_lex_file, \ + open(out_lex_file_name, "r") as out_lex_file: expected_tokens = expect_lex_file.readlines() out_tokens = out_lex_file.readlines() - diff = difflib.unified_diff(expected_tokens, out_tokens, - fromfile=expect_lex_file_name, - tofile=out_lex_file_name) + diff = difflib.unified_diff( + expected_tokens, + out_tokens, + fromfile=expect_lex_file_name, + tofile=out_lex_file_name) diff = list(diff) if diff == []: - compstep_td = "<td class=\"good\">OK</td>" + compstep_td = "<td class=\"good\">{}</td>".format(icon_ok) else: - compstep_td = "<td class=\"warn\" style=\"text-align: left;\" >{} not-what-expected:<br><pre>".format(r['compstep']) - for line in diff: - compstep_td += line - compstep_td += "{}</pre></td>" + compstep_td = "<td class=\"warn\" style=\"text-align: left;\" >{}<div name='{}'>Lexing not-what-expected:<br><pre>{}</pre></div></td>".format(icon_warn, self.filename, "".join(diff)) except: compstep_td = "<td>No .expect_lexer file</td>" - - self.s += compstep_td + self.s += compstep_td + "\n" else: err = r['error'] - if err != None: - self.s +=""" + if err is not None: + self.s += """ <td class="bad" style="text-align: left;" colspan="{}">error:<br><pre>{}</pre></td> - """.format( numcols - curcol, err) + """.format(self.numcols - curcol, err) + "\n" else: - self.s +=""" + self.s += """ <td class="bad" colspan="{}">error:<br><pre>{}</pre></td> - """.format( numcols - curcol, r) - - self.s = """<tr><td class="rowname"><a href="{}.html">{}</a></td>{}</tr>""".format(self.f,self.f,self.s) - self.running = False - + """.format(self.numcols - curcol, r) + "\n" -def interrupt_handler(sig, frame): - print('You pressed Ctrl+C!') - for t in threads: - t.stop() - -signal.signal(signal.SIGINT, interrupt_handler) - - -for (f,cmd) in cmds: - t = CommandExecutor(f, cmd) - threads.append(t) - t.start() - - -d = Displayer() -d.start() - - -for t in threads: - t.join() - -d.join() -print ("All threads terminated!") - -res_html = open(args.html, "w") -res_html.write(""" -<style type="text/css"> - -table , table th, table td , table tr{ - border: 1px solid black; - border-collapse: collapse; - text-align: center; -} -.rowname, th { - background-color: #ccc; -} -td { - padding: 0.4em; -} -.bad{ - background-color: #f9d7dc; -} -.good{ - background-color: #c7f0d2; -} -.warn{ - background-color: orange; -} -fieldset { - display: inline; - margin: 1em; - padding: 1em; -} -</style> -<table> + self.s = """ <tr> -<th>File</th><th>Lexer</th>""") -for p in args.passes: - res_html.write("<th>{}</th>\n".format(p)) -res_html.write(""" -</tr> -""") + <td class="rowname"> + <a href="{}.html">{}</a> + <input class="w3-btn" id='toggle{}' type="button" onclick="toggle('{}')" value="+"/> + </td> + {} +</tr>""".format(self.filename, self.filename, + self.filename, self.filename, self.s) + "\n" -def k(t): - return (t.lastcorrectstep,t.f) - -threads = sorted(threads, key=k, reverse=False) - -for t in threads: - res_html.write(t.s) -res_html.close() - -numtotal = len(threads) -ok = [t for t in threads if t.lastcorrectstep == numcols-2] -ko = [t for t in threads if t.lastcorrectstep != numcols-2] - -print("{}/{} OK.".format(len(ok), numtotal)) -print("{}/{} KO : {}".format(len(ko), numtotal,list(map((lambda t: (t.f, t.lastcorrectstep)), ko)))) + self.running = False -if args.verbose >= 1: - for t in ko + (ok if args.verbose >= 2 else []): - print(t.f) - print("STDOUT: \n{}".format(t.stdout)) - print("STDERR: \n{}".format(t.stderr)) +def interrupt_handler(threads): + "Interrupt handler" + def int_handler(_sig, _frame): + "Interrupt handler" + print('You pressed Ctrl+C!') + for thr in threads: + thr.stop() + return int_handler + +def get_args(): + "Get arguments" + parser = argparse.ArgumentParser() + parser.add_argument("-f", + "--file", + help="files to compile", + default=glob.glob("*.e"), + nargs='+') + parser.add_argument("-p", + "--passes", + help="passes to execute", + nargs='+', + default=[ + "e-run", "cfg-run", "cfg-run-after-cp", + "cfg-run-after-dae", "cfg-run-after-ne", "rtl-run", + "linear-run", "linear-run-after-dse", "ltl-run", + "riscv-run" + ]) + parser.add_argument("--args", + help="args for programs", + nargs='+', + default=["14", "12", "3", "8", "12"]) + parser.add_argument("--html", help="Output HTML file", default="results.html") + parser.add_argument("-d", + "--dry-run", + help="Dry-run. Don't actually compile anything", + action="store_true") + parser.add_argument("-v", + "--verbose", + help="Verbosity level", + action="count", + default=0) + parser.add_argument("--make-expect", + help="Make .expect files for each test", + action="store_true") + args, unknown_args = parser.parse_known_args() + return args, unknown_args + +def main(): + "Main function" + args, unknown_args = get_args() + # show options + if args.verbose >= 1: + print("args.file=" + str(args.file)) + print("args.passes=" + str(args.passes)) + print("args.args=" + str(args.args)) + print("args.html=" + str(args.html)) + print("args.dry_run=" + str(args.dry_run)) + print("args.verbose=" + str(args.verbose)) + + # construct the set of commands to be launched, one per file + cmds = [] + for fname in args.file: + cmd = "../ecomp -json {f}.json -f {f} {passes} {uargs} -- {args}" + cmd = cmd.format(passes=" ".join(map(lambda s: "-" + s, args.passes)), + uargs=" ".join(unknown_args), + args=" ".join(args.args), + f=fname) + cmds.append((fname, cmd)) + + # dyr_run : simply show the commands but don't execute them + if args.dry_run: + for (_, cmd) in cmds: + print(cmd) + sys.exit() + + # The list of threads that will be launched + threads: List[Thread] = [] + + + + signal.signal(signal.SIGINT, interrupt_handler(threads)) + + for (fname, cmd) in cmds: + exec_thread = CommandExecutor(fname, cmd, + args.args, args.make_expect, + # 1 colonne pour le lexer + len(args.passes) + 1) + threads.append(exec_thread) + exec_thread.start() + + print("Before launching displayer: {} threads".format(len(threads))) + + disp_thread = Displayer(list(threads)) + disp_thread.start() + + for thr in threads: + thr.join() + + disp_thread.join() + print("After displayer: {} threads".format(len(threads))) + print("All threads terminated!") + + res_html = open(args.html, "w") + res_html.write(""" + <html> + <head> + <link rel="stylesheet" href="w3.css"> + <script src="https://kit.fontawesome.com/1f5d81749b.js" crossorigin="anonymous"></script> + <style type="text/css"> + /* + table , table th, table td , table tr{ + border: 1px solid black; + border-collapse: collapse; + text-align: center; + } + .rowname, th { + background-color: #ccc; + } + td { + padding: 0.4em; + } + .bad{ + background-color: #f9d7dc; + } + .good{ + background-color: #c7f0d2; + } + .warn{ + background-color: orange; + } + + fieldset { + display: inline; + margin: 1em; + padding: 1em; + }*/ + </style> + <script type="text/javascript"> + function toggleVisibility(elt){ + if (elt.style.display == 'none') + elt.style.display = 'block'; + else + elt.style.display = 'none'; + } + + function toggle(name){ + var elts = document.getElementsByName(name); + console.log(elts); + for (var k = 0; k < elts.length; k++){ + toggleVisibility(elts[k]); + } + var x = document.getElementById('toggle'+name); + if (x.value == '+') x.value = '-'; + else x.value = '+'; + } + </script> + </head> + <body>""") + + now = datetime.datetime.now() + res_html.write ("{}".format(now)) + + res_html.write(""" + <table class="w3-table w3-striped w3-responsive"> + <tr><th>File</th>""") + for pass_name in ["Lexer"] + args.passes: + res_html.write("<th style='transform: rotate(180deg); writing-mode: vertical-rl;'>{}</th>\n".format(pass_name)) + res_html.write(""" + </tr> + """) + + print("Before sorting: {} threads".format(len(threads))) + threads = sorted(threads, key=lambda t: (t.lastcorrectstep, t.filename), reverse=False) + print("After sorting: {} threads".format(len(threads))) + for thr in threads: + res_html.write(thr.s) + res_html.write("\n") + res_html.write("</table>\n") + res_html.write("</body>\n") + res_html.write("</html>\n") + res_html.close() + + numtotal = len(threads) + thr_ok = [t for t in threads if t.lastcorrectstep == len(args.passes) - 1] + thr_ko = [t for t in threads if t.lastcorrectstep != len(args.passes) - 1] + + print("{}/{} OK.".format(len(thr_ok), numtotal)) + print("{}/{} KO : {}".format( + len(thr_ko), numtotal, list(map((lambda t: (t.filename, t.lastcorrectstep)), thr_ko)))) + + if args.verbose >= 1: + for thr in thr_ko + (thr_ok if args.verbose >= 2 else []): + print(thr.filename) + print("STDOUT: \n{}".format(thr.stdout)) + print("STDERR: \n{}".format(thr.stderr)) + +if __name__ == "__main__": + main() diff --git a/tests/w3.css b/tests/w3.css new file mode 100644 index 0000000000000000000000000000000000000000..08cad907ac3643704fdd4369b5545b4b821e3760 --- /dev/null +++ b/tests/w3.css @@ -0,0 +1,235 @@ +/* W3.CSS 4.15 December 2020 by Jan Egil and Borge Refsnes */ +html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit} +/* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */ +html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0} +article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item} +audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline} +audio:not([controls]){display:none;height:0}[hidden],template{display:none} +a{background-color:transparent}a:active,a:hover{outline-width:0} +abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted} +b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000} +small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} +sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none} +code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible} +button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold} +button,input{overflow:visible}button,select{text-transform:none} +button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button} +button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0} +button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText} +fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em} +legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto} +[type=checkbox],[type=radio]{padding:0} +[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto} +[type=search]{-webkit-appearance:textfield;outline-offset:-2px} +[type=search]::-webkit-search-decoration{-webkit-appearance:none} +::-webkit-file-upload-button{-webkit-appearance:button;font:inherit} +/* End extract */ +html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden} +h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px} +.w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace} +h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px} +hr{border:0;border-top:1px solid #eee;margin:20px 0} +.w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit} +.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc} +.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1} +.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1} +.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center} +.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top} +.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px} +.w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap} +.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)} +.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} +.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none} +.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none} +.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%} +.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none} +.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block} +.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s} +.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%} +.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc} +.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer} +.w3-dropdown-hover:hover .w3-dropdown-content{display:block} +.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000} +.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000} +.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1} +.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px} +.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto} +.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%} +.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%} +.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px} +.w3-main,#main{transition:margin-left .4s} +.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)} +.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px} +.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto} +.w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0} +.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left} +.w3-bar .w3-button{white-space:normal} +.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0} +.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%} +.w3-responsive{display:block;overflow-x:auto} +.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before, +.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both} +.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%} +.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%} +.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%} +.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%} +@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%} +.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%} +.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}} +@media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%} +.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%} +.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}} +.w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px} +.w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px} +.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell} +.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom} +.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important} +@media (max-width:1205px){.w3-auto{max-width:95%}} +@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px} +.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative} +.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center} +.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}} +@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}} +@media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}} +@media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}} +@media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}} +.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0} +.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2} +.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0} +.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0} +.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)} +.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)} +.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)} +.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} +.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} +.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none} +.w3-display-position{position:absolute} +.w3-circle{border-radius:50%} +.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px} +.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px} +.w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px} +.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px} +.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word} +.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%} +.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)} +.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)} +.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}} +.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}} +.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}} +.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}} +.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}} +.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}} +.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}} +.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}} +.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important} +.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1} +.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75} +.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)} +.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)} +.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)} +.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important} +.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important} +.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important} +.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important} +.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important} +.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important} +.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important} +.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important} +.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important} +.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important} +.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important} +.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important} +.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important} +.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important} +.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important} +.w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important} +.w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important} +.w3-left{float:left!important}.w3-right{float:right!important} +.w3-button:hover{color:#000!important;background-color:#ccc!important} +.w3-transparent,.w3-hover-none:hover{background-color:transparent!important} +.w3-hover-none:hover{box-shadow:none!important} +/* Colors */ +.w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important} +.w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important} +.w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important} +.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important} +.w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important} +.w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important} +.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important} +.w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important} +.w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important} +.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important} +.w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important} +.w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important} +.w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important} +.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important} +.w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important} +.w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important} +.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important} +.w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important} +.w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important} +.w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important} +.w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important} +.w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important} +.w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important} +.w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important} +.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important} +.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important} +.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important} +.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important} +.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important} +.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important} +.w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important} +.w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important} +.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important} +.w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important} +.w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important} +.w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important} +.w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important} +.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important} +.w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important} +.w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important} +.w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important} +.w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important} +.w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important} +.w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important} +.w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important} +.w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important} +.w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important} +.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important} +.w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important} +.w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important} +.w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important} +.w3-text-white,.w3-hover-text-white:hover{color:#fff!important} +.w3-text-black,.w3-hover-text-black:hover{color:#000!important} +.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important} +.w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important} +.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important} +.w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important} +.w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important} +.w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important} +.w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important} +.w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important} +.w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important} +.w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important} +.w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important} +.w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important} +.w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important} +.w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important} +.w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important} +.w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important} +.w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important} +.w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important} +.w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important} +.w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important} +.w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important} +.w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important} +.w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important} +.w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important} +.w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important} +.w3-border-black,.w3-hover-border-black:hover{border-color:#000!important} +.w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important} +.w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important} +.w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important} +.w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important} +.w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important}