From 7b4cbe2cb1b450b40135a6e5a3df56c9835394b8 Mon Sep 17 00:00:00 2001 From: hhugo Date: Wed, 29 Jul 2020 14:46:46 +0200 Subject: [PATCH] Compiler: fix code generation for condition (#1046) * Compiler: fix code generation for condition --- CHANGES.md | 3 +- compiler/lib/js_output.ml | 1 - compiler/lib/js_simpl.ml | 5 ++- compiler/tests-compiler/cond.ml | 66 +++++++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 compiler/tests-compiler/cond.ml diff --git a/CHANGES.md b/CHANGES.md index bf21a12229..1ae6f5ebc7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,7 +10,8 @@ * Compiler: fix code generation for recursive function under for-loops (#1009) * Compiler: the jsoo compiler compiled to javascript was not behaving correctly when parsing constant in the from the bytecode -* Compiled: make sure inline doesn't loop indefinitly (#1043) +* Compiler: make sure inline doesn't loop indefinitly (#1043) +* Compiler: fix bug generating invalid javascript for if-then construct (#1046) * Lib: Rename msg to message in Worker (#1037) * Lib: fix graphics_js when build with separate compilation (#1029) diff --git a/compiler/lib/js_output.ml b/compiler/lib/js_output.ml index 256e1cdc5c..e750634fc3 100644 --- a/compiler/lib/js_output.ml +++ b/compiler/lib/js_output.ml @@ -787,7 +787,6 @@ struct | Debugger_statement -> PP.string f "debugger"; last_semi () - | Expression_statement (EVar _) -> last_semi () | Expression_statement e -> (* Parentheses are required when the expression starts syntactically with "{" or "function" *) diff --git a/compiler/lib/js_simpl.ml b/compiler/lib/js_simpl.ml index 74a2209e7c..f0284295e5 100644 --- a/compiler/lib/js_simpl.ml +++ b/compiler/lib/js_simpl.ml @@ -120,7 +120,10 @@ let rec if_statement_2 e loc iftrue truestop iffalse falsestop = let e = simplify_condition e in match fst iftrue, fst iffalse with (* Empty blocks *) - | J.Block [], J.Block [] -> [ J.Expression_statement e, loc ] + | J.Block [], J.Block [] -> ( + match e with + | J.EVar _ -> [] + | _ -> [ J.Expression_statement e, loc ]) | J.Block [], _ -> if_statement_2 (enot e) loc iffalse falsestop iftrue truestop | _, J.Block [] -> [ J.If_statement (e, iftrue, None), loc ] | _ -> ( diff --git a/compiler/tests-compiler/cond.ml b/compiler/tests-compiler/cond.ml new file mode 100644 index 0000000000..013a16adde --- /dev/null +++ b/compiler/tests-compiler/cond.ml @@ -0,0 +1,66 @@ +(* Js_of_ocaml compiler + * http://www.ocsigen.org/js_of_ocaml/ + * Copyright (C) 2017 Hugo Heuzard + * Copyright (C) 2019 Ty Overby + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, with linking exception; + * either version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + *) + +open Util + +let%expect_test "conditional" = + let program = + compile_and_parse + {| + let f a b c d e f = + let x = match a,b,c,d,e,f with + | true, false, false, false ,false, false -> 1 + | false, false, false, true, false, false -> 4 + | false, true, false, false, false ,false -> 2 + | false, false, true, false, false, false -> 3 + | false, false, false, false, true, false -> 5 + | false, false, false, false, false, true -> 6 + | false, false, false, false, false, false -> 100 + | true, true, _, _, _, _ + | _, true, _, true, _, _ + | _ -> -1 + in x + 2 + |} + in + print_fun_decl program (Some "f"); + [%expect + {| + function f(a,b,c,d,e,f) + {var switch$0=0; + if(a) + {if(! b && ! c && ! d && ! e && ! f){var x=1;switch$0 = 1}} + else + if(b) + {var switch$1=0; + if(! c && ! d) + if(e || f)switch$1 = 1;else{var x=2;switch$0 = 1;switch$1 = 1}} + else + if(c) + {if(! d && ! e && ! f){var x=3;switch$0 = 1}} + else + if(d) + {if(! e && ! f){var x=4;switch$0 = 1}} + else + if(e) + {if(! f){var x=5;switch$0 = 1}} + else + if(f){var x=6;switch$0 = 1}else{var x=100;switch$0 = 1} + if(! switch$0)var x=- 1; + return x + 2 | 0} |}]