(* Js_of_ocaml tests
 * http://www.ocsigen.org/js_of_ocaml/
 * Copyright (C) 2019 Ty Overby
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 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 _ =
  let program =
    compile_and_parse
      ~flags:[ "--enable"; "use-js-string" ]
      {|
    type js_string
    external js_string : string -> js_string = "caml_jsstring_of_string"
    type r = {x: int; y: string; z : string}
    let ex = {x = 5; y = "hello"; z = "the • and › characters"} ;;
    let sx = js_string "hello2", js_string "the • and › characters (2)"
    let ax = [|1;2;3;4|] ;;
    let bx = [|1.0;2.0;3.0;4.0|] ;;
    let cx = [|0./.0.;-0./.0.;1./.0.;-1./.0.;0.;-0.|] ;;

    let (>>=) a b = a * b
    let (>>|) a b = a + b
    let (>>?=) a b = a / b
    let symbol_op = (>>=), (>>|), (>>?=);;
    |}
  in
  print_var_decl program "ex";
  print_var_decl program "sx";
  print_var_decl program "ax";
  print_var_decl program "bx";
  print_var_decl program "cx";
  print_var_decl program "symbol_op";
  [%expect
    {|
    var ex = [0,5,"hello","the \xe2\x80\xa2 and \xe2\x80\xba characters"];
    var sx = [0,
     "hello2",
     runtime.caml_jsstring_of_string
      ("the \xe2\x80\xa2 and \xe2\x80\xba characters (2)")];
    var ax = [0,1,2,3,4];
    var bx = [254,1.,2.,3.,4.];
    var cx = [254,NaN,NaN,Infinity,- Infinity,0.,- 0.];
    var symbol_op = [0,symbol_bind,symbol_map,symbol]; |}]

let%expect_test _ =
  let program =
    compile_and_parse
      ~flags:[ "--disable"; "use-js-string" ]
      {|
    type js_string
    external js_string : string -> js_string = "caml_jsstring_of_string"
    type r = {x: int; y: string; z : string}
    let ex = {x = 5; y = "hello"; z = "the • and › characters"} ;;
    let sx = "hello2", js_string "the • and › characters (2)"
    let ax = [|1;2;3;4|] ;;
    let bx = [|1.0;2.0;3.0;4.0|] ;;
    let cx = [|0./.0.;-0./.0.;1./.0.;-1./.0.;0.;-0.|] ;;
    let (>>=) a b = a * b
    let (>>|) a b = a + b
    let (>>?=) a b = a / b
    let symbol_op = (>>=), (>>|), (>>?=);;
    |}
  in
  print_var_decl program "ex";
  print_var_decl program "sx";
  print_var_decl program "ax";
  print_var_decl program "bx";
  print_var_decl program "cx";
  print_var_decl program "symbol_op";
  [%expect
    {|
    var ex = [0,
     5,
     caml_string_of_jsbytes("hello"),
     caml_string_of_jsbytes("the \xe2\x80\xa2 and \xe2\x80\xba characters")];
    var sx = [0,cst_hello2,runtime.caml_jsstring_of_string(cst_the_and_characters_2)];
    var ax = [0,1,2,3,4];
    var bx = [254,1.,2.,3.,4.];
    var cx = [254,NaN,NaN,Infinity,- Infinity,0.,- 0.];
    var symbol_op = [0,symbol_bind,symbol_map,symbol]; |}]

let%expect_test _ =
  let compile ~enable s =
    let enable_disable = if enable then "--enable" else "--disable" in
    let flags = [ enable_disable; "vardecl" ] in
    compile_and_parse ~flags s
  in
  let program ~enable =
    compile
      ~enable
      {|
    let match_expr = function
      | [] | [None] | _ :: None :: _ -> 1
      | [ Some None ] -> 2
      | [ Some (Some 2) ] -> 3
      | _ -> 4
    |}
  in
  with_temp_dir ~f:(fun () -> print_fun_decl (program ~enable:true) (Some "match_expr"));
  [%expect
    {|
    function match_expr(param)
     {var switch$1,switch$0,_c_,_b_,_a_;
      if(param)
       {_a_ = param[1];
        switch$0 = 0;
        if(_a_)
         {_b_ = _a_[1];
          if(_b_)
           {if(2 === _b_[1] && ! param[2])return 3}
          else
           if(! param[2])return 2}
        else
         if(! param[2])switch$0 = 1;
        if(! switch$0)
         {_c_ = param[2];
          switch$1 = 0;
          if(! _c_ || _c_[1])switch$1 = 1;
          if(switch$1)return 4}}
      return 1} |}];
  with_temp_dir ~f:(fun () -> print_fun_decl (program ~enable:false) (Some "match_expr"));
  [%expect
    {|
    function match_expr(param)
     {if(param)
       {var _a_=param[1],switch$0=0;
        if(_a_)
         {var _b_=_a_[1];
          if(_b_)
           {if(2 === _b_[1] && ! param[2])return 3}
          else
           if(! param[2])return 2}
        else
         if(! param[2])switch$0 = 1;
        if(! switch$0)
         {var _c_=param[2],switch$1=0;
          if(! _c_ || _c_[1])switch$1 = 1;
          if(switch$1)return 4}}
      return 1} |}]
