@@ -665,3 +665,177 @@ end
665665 end
666666 @test has_break || has_continue # At least one should be found
667667end
668+ @testset " QASM 3.0 print_qasm coverage" begin
669+ # Test classical type printing
670+ @testset " Classical types" begin
671+ @test sprint (Types. print_qasm, IntType ()) == " int"
672+ @test sprint (Types. print_qasm, IntType (Token {:int} (" 32" ))) == " int[32]"
673+ @test sprint (Types. print_qasm, UIntType ()) == " uint"
674+ @test sprint (Types. print_qasm, UIntType (Token {:int} (" 64" ))) == " uint[64]"
675+ @test sprint (Types. print_qasm, FloatType ()) == " float"
676+ @test sprint (Types. print_qasm, FloatType (Token {:int} (" 64" ))) == " float[64]"
677+ @test sprint (Types. print_qasm, BitType ()) == " bit"
678+ @test sprint (Types. print_qasm, BitType (Token {:int} (" 5" ))) == " bit[5]"
679+ @test sprint (Types. print_qasm, AngleType ()) == " angle"
680+ @test sprint (Types. print_qasm, AngleType (Token {:int} (" 20" ))) == " angle[20]"
681+ end
682+
683+ # Test classical declarations
684+ @testset " Classical declarations" begin
685+ decl1 = ClassicalDecl (false , IntType (Token {:int} (" 32" )), Token {:id} (" x" ), nothing )
686+ @test occursin (" int[32]" , sprint (Types. print_qasm, decl1))
687+ @test occursin (" x" , sprint (Types. print_qasm, decl1))
688+
689+ decl2 = ClassicalDecl (true , FloatType (Token {:int} (" 64" )), Token {:id} (" y" ), Token {:float64} (" 3.14" ))
690+ @test occursin (" const" , sprint (Types. print_qasm, decl2))
691+ @test occursin (" float[64]" , sprint (Types. print_qasm, decl2))
692+ @test occursin (" y" , sprint (Types. print_qasm, decl2))
693+ @test occursin (" 3.14" , sprint (Types. print_qasm, decl2))
694+ end
695+
696+ # Test qubit declarations
697+ @testset " Qubit declarations" begin
698+ decl1 = QubitDecl (nothing , Token {:id} (" q" ))
699+ @test occursin (" qubit" , sprint (Types. print_qasm, decl1))
700+ @test occursin (" q" , sprint (Types. print_qasm, decl1))
701+
702+ decl2 = QubitDecl (Token {:id} (" q" ), Token {:int} (" 2" ))
703+ @test occursin (" qubit[2]" , sprint (Types. print_qasm, decl2))
704+ @test occursin (" q" , sprint (Types. print_qasm, decl2))
705+ end
706+
707+ # Test control flow statements
708+ @testset " If-else statements" begin
709+ # If without else
710+ if_stmt = IfElseStmt (Token {:id} (" c" ), [Token {:id} (" x" )], nothing )
711+ output = sprint (Types. print_qasm, if_stmt)
712+ @test occursin (" if" , output)
713+ @test occursin (" c" , output)
714+
715+ # If with else
716+ if_else = IfElseStmt (Token {:id} (" c" ), [Token {:id} (" x" )], [Token {:id} (" y" )])
717+ output2 = sprint (Types. print_qasm, if_else)
718+ @test occursin (" if" , output2)
719+ @test occursin (" else" , output2)
720+ end
721+
722+ @testset " While statements" begin
723+ while_stmt = WhileStmt (Token {:id} (" c" ), [Token {:id} (" x" )])
724+ output = sprint (Types. print_qasm, while_stmt)
725+ @test occursin (" while" , output)
726+ @test occursin (" c" , output)
727+ end
728+
729+ @testset " For statements" begin
730+ # For with range
731+ range = RangeExpr (Token {:int} (" 0" ), Token {:int} (" 10" ))
732+ for_stmt = ForStmt (IntType (), Token {:id} (" i" ), range, [Token {:id} (" x" )])
733+ output = sprint (Types. print_qasm, for_stmt)
734+ @test occursin (" for" , output)
735+ @test occursin (" int" , output)
736+ @test occursin (" i" , output)
737+ @test occursin (" in" , output)
738+
739+ # For with discrete set
740+ set = DiscreteSet ([Token {:int} (" 1" ), Token {:int} (" 5" ), Token {:int} (" 10" )])
741+ for_stmt2 = ForStmt (IntType (), Token {:id} (" i" ), set, [Token {:id} (" x" )])
742+ output2 = sprint (Types. print_qasm, for_stmt2)
743+ @test occursin (" for" , output2)
744+ @test occursin (" {" , output2)
745+ @test occursin (" 1" , output2)
746+ @test occursin (" 5" , output2)
747+ @test occursin (" 10" , output2)
748+ end
749+
750+ @testset " Range and set printing" begin
751+ # Range without step
752+ range1 = RangeExpr (Token {:int} (" 0" ), Token {:int} (" 10" ))
753+ @test occursin (" [0:10]" , sprint (Types. print_qasm, range1))
754+
755+ # Range with step
756+ range2 = RangeExpr (Token {:int} (" 0" ), Token {:int} (" 2" ), Token {:int} (" 10" ))
757+ @test occursin (" [0:2:10]" , sprint (Types. print_qasm, range2))
758+
759+ # Discrete set
760+ set = DiscreteSet ([Token {:int} (" 1" ), Token {:int} (" 5" )])
761+ output = sprint (Types. print_qasm, set)
762+ @test occursin (" {" , output)
763+ @test occursin (" 1" , output)
764+ @test occursin (" 5" , output)
765+ @test occursin (" }" , output)
766+ end
767+
768+ @testset " Break and continue" begin
769+ @test sprint (Types. print_qasm, BreakStmt ()) == " break;"
770+ @test sprint (Types. print_qasm, ContinueStmt ()) == " continue;"
771+ end
772+
773+ @testset " Gate modifiers" begin
774+ @test sprint (Types. print_qasm, GateModifier (:inv )) == " inv"
775+ @test sprint (Types. print_qasm, GateModifier (:ctrl )) == " ctrl"
776+ @test sprint (Types. print_qasm, GateModifier (:negctrl )) == " negctrl"
777+
778+ pow_mod = GateModifier (:pow , Token {:int} (" 2" ))
779+ output = sprint (Types. print_qasm, pow_mod)
780+ @test occursin (" pow" , output)
781+ @test occursin (" 2" , output)
782+ end
783+
784+ @testset " Modified gates" begin
785+ bit = Bit (Token {:id} (" q" ), Token {:int} (" 0" ))
786+ inst = Instruction (" h" , Any[], Any[bit])
787+ mod_gate = ModifiedGate ([GateModifier (:inv )], inst)
788+
789+ output = sprint (Types. print_qasm, mod_gate)
790+ @test occursin (" inv" , output)
791+ @test occursin (" @" , output)
792+ @test occursin (" h" , output)
793+ end
794+
795+ @testset " Input/Output declarations" begin
796+ input_decl = InputDecl (FloatType (Token {:int} (" 64" )), Token {:id} (" theta" ))
797+ output = sprint (Types. print_qasm, input_decl)
798+ @test occursin (" input" , output)
799+ @test occursin (" float[64]" , output)
800+ @test occursin (" theta" , output)
801+ @test occursin (" ;" , output)
802+
803+ output_decl = OutputDecl (BitType (Token {:int} (" 2" )), Token {:id} (" c" ))
804+ output2 = sprint (Types. print_qasm, output_decl)
805+ @test occursin (" output" , output2)
806+ @test occursin (" bit[2]" , output2)
807+ @test occursin (" c" , output2)
808+ @test occursin (" ;" , output2)
809+ end
810+
811+ # Test round-trip: parse -> print -> parse
812+ @testset " Round-trip tests" begin
813+ qasm1 = """
814+ OPENQASM 3.0;
815+ int[32] x = 5;
816+ """
817+ ast1 = OpenQASM. parse (qasm1)
818+ printed1 = sprint (Types. print_qasm, ast1)
819+ ast1_reparsed = OpenQASM. parse (printed1)
820+ @test ast1_reparsed isa MainProgram
821+
822+ qasm2 = """
823+ OPENQASM 3.0;
824+ qubit[2] q;
825+ """
826+ ast2 = OpenQASM. parse (qasm2)
827+ printed2 = sprint (Types. print_qasm, ast2)
828+ ast2_reparsed = OpenQASM. parse (printed2)
829+ @test ast2_reparsed isa MainProgram
830+
831+ qasm3 = """
832+ OPENQASM 3.0;
833+ input float[64] theta;
834+ output bit c;
835+ """
836+ ast3 = OpenQASM. parse (qasm3)
837+ printed3 = sprint (Types. print_qasm, ast3)
838+ ast3_reparsed = OpenQASM. parse (printed3)
839+ @test ast3_reparsed isa MainProgram
840+ end
841+ end
0 commit comments