Beispiel #1
0
    def visitCalibrationDefinition(
            self, ctx: qasm3Parser.CalibrationDefinitionContext):
        # TODO: Possible grammar improvement. The current grammar return the body as a token
        # stream. We reconstruct the body by concat the tokens space delimiter.
        # This will not exactly reproduce the body but it can be parsed by another grammar.
        body_chars = [
        ]  # Python concatenation is slow so we build a list first
        for i in range(ctx.getChildCount() - 2, 0, -1):
            node = ctx.getChild(i)
            if isinstance(node, TerminalNode):
                body_chars.insert(0, node.getText())
            else:
                break

        name = add_span(Identifier(ctx.Identifier().getText()),
                        get_span(ctx.Identifier()))
        return CalibrationDefinition(
            name=name,
            arguments=self.visit(ctx.calibrationArgumentList().getChild(0))
            if ctx.calibrationArgumentList() else [],
            qubits=[
                add_span(Identifier(id.getText()), get_span(id))
                for id in ctx.identifierList().Identifier()
            ],
            return_type=self.visit(ctx.returnSignature().classicalType())
            if ctx.returnSignature() else None,
            body=" ".join(body_chars[1:]),
        )
Beispiel #2
0
def test_header():
    p = """
    OPENQASM 3.1;
    include "qelib1.inc";
    input angle[16] variable1;
    output angle[16] variable2;
    """.strip()
    program = parse(p)
    expected = "3.1"
    assert program.version == expected
    assert program.includes == [Include("qelib1.inc")]
    assert program.io_variables == [
        IODeclaration(
            io_identifier=IOKeyword["input"],
            type=AngleType(size=IntegerLiteral(value=16)),
            identifier=Identifier(name="variable1"),
            init_expression=None,
        ),
        IODeclaration(
            io_identifier=IOKeyword["output"],
            type=AngleType(size=IntegerLiteral(value=16)),
            identifier=Identifier(name="variable2"),
            init_expression=None,
        ),
    ]
def test_concatenation():
    p = """
    let a = b[1:1:10] ++ c;
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        AliasStatement(
            target=Identifier(name="a"),
            value=Concatenation(
                lhs=Slice(
                    name="b",
                    range=RangeDefinition(
                        start=IntegerLiteral(value=1),
                        end=IntegerLiteral(value=10),
                        step=IntegerLiteral(value=1),
                    ),
                ),
                rhs=Identifier(name="c"),
            ),
        )
    ])
    SpanGuard().visit(program)
    slice_ = program.statements[0]
    assert slice_.span == Span(1, 0, 1, 22)
    assert slice_.target.span == Span(1, 4, 1, 4)
    assert slice_.value.span == Span(1, 8, 1, 21)
Beispiel #4
0
def test_box():
    p = """
    box [maxdur] {
        delay[start_stretch] $0;
        x $0;
    }
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        Box(
            duration=Identifier("maxdur"),
            body=[
                DelayInstruction(
                    arguments=[],
                    duration=Identifier("start_stretch"),
                    qubits=[Identifier("$0")],
                ),
                QuantumGate(modifiers=[],
                            name=Identifier("x"),
                            arguments=[],
                            qubits=[Identifier("$0")]),
            ],
        )
    ])
    SpanGuard().visit(program)
def test_slice():
    p = """
    let a = b[1:1:10];
    let c = d[1:10];
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        AliasStatement(
            target=Identifier(name="a"),
            value=Slice(
                name="b",
                range=RangeDefinition(
                    start=IntegerLiteral(value=1),
                    end=IntegerLiteral(value=10),
                    step=IntegerLiteral(value=1),
                ),
            ),
        ),
        AliasStatement(
            target=Identifier(name="c"),
            value=Slice(
                name="d",
                range=RangeDefinition(
                    start=IntegerLiteral(value=1),
                    end=IntegerLiteral(value=10),
                    step=None,
                ),
            ),
        ),
    ])
    SpanGuard().visit(program)
    slice_ = program.statements[0]
    assert slice_.span == Span(1, 0, 1, 17)
    assert slice_.target.span == Span(1, 4, 1, 4)
    assert slice_.value.span == Span(1, 8, 1, 16)
Beispiel #6
0
def test_branch_statement():
    p = """
    if(temp == 1) { ry(pi / 2) q; } else continue;
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        BranchingStatement(
            condition=BinaryExpression(
                op=BinaryOperator["=="],
                lhs=Identifier("temp"),
                rhs=IntegerLiteral(1),
            ),
            if_block=[
                QuantumGate(
                    modifiers=[],
                    name=Identifier("ry"),
                    arguments=[
                        BinaryExpression(
                            op=BinaryOperator["/"],
                            lhs=Constant(ConstantName.pi),
                            rhs=IntegerLiteral(2),
                        )
                    ],
                    qubits=[Identifier("q")],
                ),
            ],
            else_block=[ContinueStatement()],
        )
    ])
    SpanGuard().visit(program)
Beispiel #7
0
def test_measurement():
    p = """
    measure q;
    measure q -> c[0];
    c[0] = measure q[0];
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        QuantumMeasurementAssignment(target=None,
                                     measure_instruction=QuantumMeasurement(
                                         qubit=Identifier("q"))),
        QuantumMeasurementAssignment(
            target=IndexedIdentifier(
                name=Identifier(name="c"),
                indices=[[IntegerLiteral(value=0)]],
            ),
            measure_instruction=QuantumMeasurement(qubit=Identifier("q")),
        ),
        QuantumMeasurementAssignment(
            target=IndexedIdentifier(
                name=Identifier(name="c"),
                indices=[[IntegerLiteral(value=0)]],
            ),
            measure_instruction=QuantumMeasurement(qubit=IndexedIdentifier(
                name=Identifier("q"),
                indices=[[IntegerLiteral(value=0)]],
            ), ),
        ),
    ])
    SpanGuard().visit(program)
Beispiel #8
0
def test_gate_calls():
    p = """
    qubit q;
    qubit r;
    h q;
    cx q, r;
    inv @ h q;
    """.strip()
    # TODO Add "ctrl @ pow(power) @ phase(theta) q, r;" after we complete expressions
    program = parse(p)
    assert program == Program(statements=[
        QubitDeclaration(qubit=Identifier(name="q"), size=None),
        QubitDeclaration(qubit=Identifier(name="r"), size=None),
        QuantumGate(modifiers=[],
                    name=Identifier("h"),
                    arguments=[],
                    qubits=[Identifier(name="q")]),
        QuantumGate(
            modifiers=[],
            name=Identifier("cx"),
            arguments=[],
            qubits=[Identifier(name="q"),
                    Identifier(name="r")],
        ),
        QuantumGate(
            modifiers=[
                QuantumGateModifier(modifier=GateModifierName["inv"],
                                    argument=None)
            ],
            name=Identifier("h"),
            arguments=[],
            qubits=[Identifier(name="q")],
        ),
    ], )
    SpanGuard().visit(program)
Beispiel #9
0
def test_qubit_and_bit_declaration():
    p = """
    bit c;
    qubit a;
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        ClassicalDeclaration(BitType(None), Identifier("c"), None),
        QubitDeclaration(qubit=Identifier(name="a"), size=None),
    ])
    SpanGuard().visit(program)
Beispiel #10
0
def test_array_declaration():
    p = """
    array[uint[8], 2] a;
    array[int[8], 2] a = {1, 1};
    array[bit, 2] a = b;
    array[float[32], 2, 2] a;
    array[complex[float[64]], 2, 2] a = {{1, 1}, {2, 2}};
    array[uint[8], 2, 2] a = {b, b};
    """.strip()
    program = parse(p)
    a, b = Identifier("a"), Identifier("b")
    one, two, eight = IntegerLiteral(1), IntegerLiteral(2), IntegerLiteral(8)
    SpanGuard().visit(program)
    assert program == Program(statements=[
        ClassicalDeclaration(
            type=ArrayType(base_type=UintType(eight), dimensions=[two]),
            identifier=a,
            init_expression=None,
        ),
        ClassicalDeclaration(
            type=ArrayType(base_type=IntType(eight), dimensions=[two]),
            identifier=a,
            init_expression=ArrayLiteral([one, one]),
        ),
        ClassicalDeclaration(
            type=ArrayType(base_type=BitType(size=None), dimensions=[two]),
            identifier=a,
            init_expression=b,
        ),
        ClassicalDeclaration(
            type=ArrayType(
                base_type=FloatType(IntegerLiteral(32)),
                dimensions=[two, two],
            ),
            identifier=a,
            init_expression=None,
        ),
        ClassicalDeclaration(
            type=ArrayType(
                base_type=ComplexType(FloatType(IntegerLiteral(64))),
                dimensions=[two, two],
            ),
            identifier=a,
            init_expression=ArrayLiteral(
                [ArrayLiteral([one, one]),
                 ArrayLiteral([two, two])], ),
        ),
        ClassicalDeclaration(
            type=ArrayType(base_type=UintType(eight), dimensions=[two, two]),
            identifier=a,
            init_expression=ArrayLiteral([b, b]),
        ),
    ], )
Beispiel #11
0
def test_alias_statement():
    p = """
    let a = b;
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        AliasStatement(target=Identifier(name="a"), value=Identifier(name="b"))
    ])
    SpanGuard().visit(program)
    alias_statement = program.statements[0]
    assert alias_statement.span == Span(1, 0, 1, 9)
    assert alias_statement.target.span == Span(1, 4, 1, 4)
    assert alias_statement.value.span == Span(1, 8, 1, 8)
Beispiel #12
0
def test_delay_instruction():
    p = """
    delay[start_stretch] $0;
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        DelayInstruction(
            arguments=[],
            duration=Identifier("start_stretch"),
            qubits=[Identifier("$0")],
        )
    ])
    SpanGuard().visit(program)
Beispiel #13
0
def test_single_gatecall():
    p = """
    h q;
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        QuantumGate(modifiers=[],
                    name=Identifier("h"),
                    arguments=[],
                    qubits=[Identifier(name="q")])
    ])
    SpanGuard().visit(program)
    quantum_gate = program.statements[0]
    assert quantum_gate.span == Span(1, 0, 1, 3)
    assert quantum_gate.qubits[0].span == Span(1, 2, 1, 2)
Beispiel #14
0
def test_no_designator_type():
    p = """
    duration a;
    stretch b;
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        ClassicalDeclaration(
            DurationType(),
            Identifier("a"),
            None,
        ),
        ClassicalDeclaration(StretchType(), Identifier("b"), None),
    ])
    SpanGuard().visit(program)
Beispiel #15
0
def test_pramga():
    p = """
    #pragma {verbatim;}
    #pragma {my_statement1; my_statement2;}
    end;
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        Pragma(statements=[ExpressionStatement(Identifier("verbatim"))]),
        Pragma(statements=[
            ExpressionStatement(Identifier("my_statement1")),
            ExpressionStatement(Identifier("my_statement2")),
        ]),
        EndStatement(),
    ])
    SpanGuard().visit(program)
Beispiel #16
0
def test_durationof():
    p = """
    durationof({x $0;})
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        ExpressionStatement(expression=DurationOf(target=[
            QuantumGate(
                modifiers=[],
                name=Identifier("x"),
                arguments=[],
                qubits=[Identifier("$0")],
            ),
        ]))
    ])
    SpanGuard().visit(program)
Beispiel #17
0
 def visitBuiltInCall(self, ctx: qasm3Parser.BuiltInCallContext):
     if ctx.builtInMath():
         return FunctionCall(
             self.visit(ctx.builtInMath()),
             [
                 self.visit(expression)
                 for expression in ctx.expressionList().expression()
             ],
         )
     if ctx.SIZEOF():
         name = add_span(Identifier(name=ctx.SIZEOF().getText()),
                         get_span(ctx.SIZEOF()))
         return FunctionCall(
             name,
             [
                 self.visit(expression)
                 for expression in ctx.expressionList().expression()
             ],
         )
     if ctx.castOperator():
         return Cast(
             self.visit(ctx.castOperator().classicalType()),
             [
                 self.visit(expression)
                 for expression in ctx.expressionList().expression()
             ],
         )
Beispiel #18
0
    def visitClassicalArgument(self,
                               ctx: qasm3Parser.ClassicalArgumentContext):
        if ctx.singleDesignatorType():
            type_name = ctx.singleDesignatorType().getText()
            if type_name in _TYPE_NODE_INIT:
                type_size = self.visit(ctx.designator())
                type_node = _TYPE_NODE_INIT[type_name](type_size)
            else:
                # To capture potential parser error.
                raise ValueError("Type name {type_name} not found.")

            classcal_type = add_span(
                type_node,
                combine_span(get_span(ctx.singleDesignatorType()),
                             get_span(ctx.designator())),
            )

        elif ctx.noDesignatorType():
            classcal_type = self.visit(ctx.noDesignatorType())

        else:
            classcal_type = add_span(
                BitType(
                    self.visit(ctx.designator())
                    if ctx.designator() else None, ),
                get_span(ctx.getChild(0)),
            )

        identifier = add_span(Identifier(ctx.Identifier().getText()),
                              get_span(ctx.Identifier()))
        return ClassicalArgument(classcal_type, identifier)
Beispiel #19
0
 def visitExpressionTerminator(
         self, ctx: qasm3Parser.ExpressionTerminatorContext):
     if ctx.Constant():
         const_text = ctx.Constant().getText()
         if const_text == "π":
             const_name = ConstantName.pi
         elif const_text == "𝜏":
             const_name = ConstantName.tau
         elif const_text == "ℇ":
             const_name = ConstantName.euler
         else:
             const_name = ConstantName[const_text]
         return Constant(const_name)
     elif ctx.Integer():
         return IntegerLiteral(int(ctx.Integer().getText()))
     elif ctx.RealNumber():
         return RealLiteral(float(ctx.RealNumber().getText()))
     elif ctx.booleanLiteral():
         return BooleanLiteral(True if ctx.booleanLiteral().getText() ==
                               "true" else False)
     elif ctx.Identifier():
         return Identifier(ctx.Identifier().getText())
     elif ctx.StringLiteral():
         return StringLiteral(ctx.StringLiteral().getText()[1:-1])
     elif ctx.builtInCall():
         return self.visit(ctx.builtInCall())
     elif ctx.externOrSubroutineCall():
         return self.visit(ctx.externOrSubroutineCall())
     elif ctx.timingIdentifier():
         return self.visit(ctx.timingIdentifier())
     elif ctx.LPAREN():
         return self.visit(ctx.expression())
     elif ctx.expressionTerminator():
         return IndexExpression(self.visit(ctx.expressionTerminator()),
                                self.visit(ctx.expression()))
Beispiel #20
0
 def visitTimingIdentifier(self, ctx: qasm3Parser.TimingIdentifierContext):
     if ctx.TimingLiteral():
         # parse timing literal
         s = ctx.TimingLiteral().getText()
         if s[-2:] in ["dt", "ns", "us", "ms"]:
             duration_literal = DurationLiteral(float(s[:-2]),
                                                TimeUnit[s[-2:]])
         elif s[-2:] == "µs":
             duration_literal = DurationLiteral(float(s[:-2]),
                                                TimeUnit["us"])
         else:
             # Must be "s"
             duration_literal = DurationLiteral(float(s[:-1]),
                                                TimeUnit["s"])
         return duration_literal
     elif ctx.Identifier():
         return DurationOf(
             target=add_span(Identifier(ctx.Identifier().getText()),
                             get_span(ctx.Identifier())))
     else:
         child_count = ctx.quantumBlock().getChildCount()
         return DurationOf(target=[
             self.visit(ctx.quantumBlock().getChild(i))
             for i in range(1, child_count - 1)
         ])
Beispiel #21
0
 def visitConstantDeclaration(self,
                              ctx: qasm3Parser.ConstantDeclarationContext):
     return ConstantDeclaration(
         identifier=add_span(Identifier(name=ctx.Identifier().getText()),
                             get_span(ctx.Identifier())),
         init_expression=self.visit(ctx.equalsExpression().expression()),
     )
Beispiel #22
0
    def visitIndexIdentifier(self, ctx: qasm3Parser.IndexIdentifierContext):
        if ctx.Identifier():
            name = ctx.Identifier().getText()

            if ctx.expressionList():
                expr_list = []
                for expr in ctx.expressionList().expression():
                    expr_list.append(self.visit(expr))
                if len(expr_list) > 1:
                    subscript = Selection(name=name, indices=expr_list)
                else:
                    subscript = Subscript(name=name, index=expr_list[0])

            elif ctx.rangeDefinition():
                subscript = Slice(name=name,
                                  range=self.visit(ctx.rangeDefinition()))

            else:
                return add_span(Identifier(name=ctx.Identifier().getText()),
                                get_span(ctx))

        else:
            id0 = self.visit(ctx.indexIdentifier()[0])
            id1 = self.visit(ctx.indexIdentifier()[1])

            return Concatenation(lhs=id0, rhs=id1)

        return subscript
Beispiel #23
0
 def visitQuantumArgument(self, ctx: qasm3Parser.QuantumArgumentContext):
     return QuantumArgument(
         add_span(
             Identifier(ctx.Identifier().getText(), ),
             get_span(ctx.Identifier()),
         ),
         self.visit(ctx.designator()) if ctx.designator() else None,
     )
Beispiel #24
0
 def visitIndexedIdentifier(self,
                            ctx: qasm3Parser.IndexedIdentifierContext):
     name = add_span(Identifier(ctx.Identifier().getText()),
                     get_span(ctx.Identifier()))
     if not ctx.indexOperator():
         return name
     indices = [self.visit(operator) for operator in ctx.indexOperator()]
     return IndexedIdentifier(name=name, indices=indices)
Beispiel #25
0
def test_qubit_declaration():
    p = """
    qubit q;
    qubit[4] a;
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        QubitDeclaration(qubit=Identifier(name="q"), size=None),
        QubitDeclaration(
            qubit=Identifier(name="a"),
            size=IntegerLiteral(4),
        ),
    ])
    SpanGuard().visit(program)
    qubit_declaration = program.statements[0]
    assert qubit_declaration.span == Span(1, 0, 1, 7)
    assert qubit_declaration.qubit.span == Span(1, 6, 1, 6)
Beispiel #26
0
def test_subroutine_definition():
    p = """
    def ymeasure(qubit q) -> bit {
        s q;
        h q;
        return measure q;
    }
    """.strip()
    program = parse(p)
    assert program == Program(statements=[
        SubroutineDefinition(
            name=Identifier("ymeasure"),
            arguments=[QuantumArgument(qubit=Identifier("q"), size=None)],
            return_type=BitType(None),
            body=[
                QuantumGate(
                    modifiers=[],
                    name=Identifier("s"),
                    arguments=[],
                    qubits=[Identifier(name="q")],
                ),
                QuantumGate(
                    modifiers=[],
                    name=Identifier("h"),
                    arguments=[],
                    qubits=[Identifier(name="q")],
                ),
                ReturnStatement(expression=QuantumMeasurement(qubit=Identifier(
                    name="q"))),
            ],
        )
    ])
    SpanGuard().visit(program)
Beispiel #27
0
 def visitExternOrSubroutineCall(
         self, ctx: qasm3Parser.ExternOrSubroutineCallContext):
     expressions = ([
         self.visit(expression)
         for expression in ctx.expressionList().expression()
     ] if ctx.expressionList() else [])
     name = add_span(Identifier(ctx.Identifier().getText()),
                     get_span(ctx.Identifier()))
     return FunctionCall(name, expressions)
Beispiel #28
0
 def visitNoDesignatorDeclaration(
         self, ctx: qasm3Parser.NoDesignatorDeclarationContext):
     return ClassicalDeclaration(
         type=self.visit(ctx.noDesignatorType()),
         identifier=add_span(Identifier(ctx.Identifier().getText()),
                             get_span(ctx.Identifier())),
         init_expression=self.visit(ctx.equalsExpression().expression())
         if ctx.equalsExpression() else None,
     )
Beispiel #29
0
 def visitQuantumDeclaration(self,
                             ctx: qasm3Parser.QuantumDeclarationContext):
     return QubitDeclaration(
         add_span(
             Identifier(ctx.Identifier().getText(), ),
             get_span(ctx.Identifier()),
         ),
         self.visit(ctx.designator()) if ctx.designator() else None,
     )
Beispiel #30
0
 def visitQuantumGateDefinition(
         self, ctx: qasm3Parser.QuantumGateDefinitionContext):
     gate_name = self.visit(ctx.quantumGateSignature().quantumGateName())
     gate_arg_lists = ctx.quantumGateSignature().identifierList(
     )  # argument and qubit lists
     arguments = ([
         add_span(Identifier(arg.getText()), get_span(arg))
         for arg in gate_arg_lists[0].Identifier()
     ] if len(gate_arg_lists) == 2 else [])
     qubits = [
         add_span(Identifier(i.getText()), get_span(i))
         for i in gate_arg_lists[-1].Identifier()
     ]
     child_count = ctx.quantumBlock().getChildCount()
     body = [
         self.visit(ctx.quantumBlock().getChild(i))
         for i in range(1, child_count - 1)
     ]
     return QuantumGateDefinition(gate_name, arguments, qubits, body)