(* Copyright 2019 Chetan Murthy, All rights reserved. *)

#use "topfind";;

#require "camlp5";;
#require "pa_ppx.testutils";;
#require"pa_ppx.runtime_fat" ;;
#require "qc_ocaml";;
#require "oUnit";;
#print_length 1048576 ;;

open Asttools ;;
open Pa_ppx_utils ;;
open Coll ;;
open Std ;;
open Misc_functions ;;
open Qc_misc ;;
open Qc ;;
open Qasm2syntax ;;
open OUnit2 ;;

Pa_ppx_base.Pp_MLast.Ploc.pp_loc_verbose := true ;;
Pa_ppx_runtime_fat.Exceptions.Ploc.pp_loc_verbose := true ;;

#install_printer Fpath.pp ;;

let lexbuf_contents lb =
  let open Lexing in
  let pos = lb.lex_curr_pos in
  let len = lb.lex_buffer_len - lb.lex_curr_pos in
  (Bytes.to_string (Bytes.sub lb.lex_buffer pos len))
;;

let pp_lexbuf lb =
  Format.print_string "#<lexbuf:<";
  Format.print_string (lexbuf_contents lb);
  Format.print_string ">>"
;;
#install_printer pp_lexbuf ;;

let pp_tokenaux (t : Qc_misc.TokenAux.t) = Fmt.(pf stdout "<tokenaux>") ;;
#install_printer pp_tokenaux ;;


open Qlam_syntax ;;
open Qlam_ops ;;
open Qlam_env ;;
module LATEX = Qc_latex ;;

let id_pp x = Fmt.(pf stdout "<:id<%a>>" ID.pp_hum x) ;;
#install_printer id_pp ;;

let qvar_pp x = Fmt.(pf stdout "<:qvar<%a>>" SYN.QV.pp_hum x) ;;
#install_printer qvar_pp ;;

let cvar_pp x = Fmt.(pf stdout "<:cvar<%a>>" SYN.CV.pp_hum x) ;;
#install_printer cvar_pp ;;

let bi_pp x = Fmt.(pf stdout "<:bi< %a >>" SYN.BI.pp_hum x) ;;
#install_printer bi_pp ;;

let qgn_pp x = Fmt.(pf stdout "<:qgn<%a>>" SYN.QG.pp_hum x) ;;
(*
#install_printer qgn_pp ;;
 *)
let qcircuit_pp qc = Fmt.(pf stdout "<:circuit< %a >>" Qlam.Circ.pp_hum qc) ;;
#install_printer qcircuit_pp ;;

let gate_item_pp gi = Fmt.(pf stdout "<:gate_item< %a >>" Qlam.Gate.pp_hum gi) ;;
(*
#install_printer gate_item_pp ;;
 *)
let item_pp gi = Fmt.(pf stdout "<:item< %a >>" PP.item gi) ;;
#install_printer item_pp ;;

let read_file_tolam s0 =
  let (env,instrs) = with_include_path ~path:["testdata"] Qasm2.of_file s0 in
  Qlam.Prog.of_qasm2 (env, instrs)
;;

let pp_qvfvs x = Fmt.(pf stdout "<:qvfvs<%a>>" SYN.QVSet.pp_hum x) ;;
let pp_cvfvs x = Fmt.(pf stdout "<:cvfvs<%a>>" SYN.CVSet.pp_hum x) ;;

let pp_qv_corr l = Fmt.(pf stdout "<:qvcorr<%a>>" (list ~sep:(const string "; ") (parens (pair ~sep:(const string ", ") SYN.QV.pp_hum SYN.QV.pp_hum))) (SYN.QVMap.bindings l)) ;;
let pp_cv_corr l = Fmt.(pf stdout "<:cvcorr<%a>>" (list ~sep:(const string "; ") (parens (pair ~sep:(const string ", ") SYN.CV.pp_hum SYN.CV.pp_hum))) (SYN.CVMap.bindings l)) ;;

#install_printer pp_qvfvs ;;
#install_printer pp_cvfvs ;;
#install_printer pp_qv_corr ;;
#install_printer pp_cv_corr ;;

let pp_layout l = Fmt.(pf stdout "<:layout< %a >>" Qlam_ops.LO.pp_hum l) ;;
#install_printer pp_layout ;;

let pp_logical2qvar m = Fmt.(pf stdout "<:logical2qvar< %a >>" (SYN.BIMap.pp_hum SYN.QV.pp_hum) m) ;; 
#install_printer pp_logical2qvar ;;

let pp_ab_env x = Fmt.(pf stdout "<:abenv< %a >>" Qlam_ops.AB.Env.pp_hum x) ;;
#install_printer pp_ab_env ;;

#load "test_helpers.cmo";;
#load "qasm2_tests.cmo";;
open Test_helpers ;;
open Qasm2_tests ;;


#load "qlam_tests.cmo";;
open Qlam_tests ;;

#load "qclatex_tests.cmo";;
open Qclatex_tests ;;

let [@warning "-8"] ([], qc) = {| let q = qubit() in let q = tg q in (q) |} |> Qlam.Prog.of_string ;;
let e = {|
gate tg () x = let q = h x in (q) ;
|} |> Qlam.Environ.of_string ;;
#trace BetaReduce.qcircuit ;;
let (genv0, (envitems, qc1)) = Standard.program ~env0:(env0@env1) (e, qc) ;;
Fmt.(pf stdout "%a" Qasm2.pp_hum (Qlam.Prog.to_qasm2 ~env0:(env0@env1) (envitems, qc1)));;

let [@warning "-8"] ([], qc') = {|
let q0 = qubit() in
let q0 = h q0 in
let q1 = qubit() in
let q1 = h q1 in
let (q0, q1) = cx q0 q1 in
let q0 = h q0 in
let q1 = h q1 in
(q0, q1)
|} |> Qlam.Prog.of_string ;;

let p1 = with_include_path ~path:["testdata"] Qasm2.of_file "testdata/example.qasm" in
let p2 = Qlam.Prog.of_qasm2 p1 in
let (genv0,_) = TYCHK.program (env0@(fst p2), snd p2) in
Ops.AssignBits.program genv0 (env0@(fst p2), snd p2) ;;

let l = {|
[
#0 : <physical 0>,
#1 : <physical 1>,
#2 : <physical 2>,
#3 : <physical 3>,
#4 : <physical 4>
]
|} |> Layout.of_string ;;
let cm = GEnv.find_mach genv0 (ID.mk"ibmq_quito") ;;

let p0 = read_tolam "testdata/ghz-bv.qasm";;
let (genv0, p1) = Ops.Standard.program ~env0:env0 p0 ;;
let p2 = Ops.BasicSwap.basic_swap genv0 ~env0 ~coupling_map:cm ~layout:(Ops.LO.mk l) p1;;
Fmt.(pf stdout "%a\n%!" Qasm2.pp_hum (Qlam.Prog.to_qasm2 ~env0 p2)) ;;
p2 |> Ops.Latex.latex genv0 ~env0 |> snd |> LATEX.Matrix.tolatex |> LATEX.Exec.latex ;;

let cm = GEnv.find_mach genv0 (ID.mk"ibm_qx3") ;;
let l = {|
[
#0 : <physical 0>,
#1 : <physical 1>,
#2 : <physical 2>,
#3 : <physical 3>,
#4 : <physical 14>,
#5 : <physical 15>
]
|} |> Layout.of_string ;;
let p0 = read_tolam "testdata/zulehner_4a.qasm" ;;
let (genv0, p1) = Ops.Standard.program ~env0:env0 p0 ;;
p1 |> Ops.Latex.latex genv0 ~env0 |> snd |> LATEX.Matrix.tolatex |> LATEX.Exec.latex ;;
let p2 = Ops.BasicSwap.basic_swap genv0 ~env0 ~coupling_map:cm ~layout:(Ops.LO.mk l) p1;;
p2 |> Ops.Latex.latex genv0 ~env0 |> snd |> LATEX.Matrix.tolatex |> LATEX.Exec.latex ;;



(* Local Variables: *)
(* mode: tuareg *)
(* End: *)
