def visitClassicalType(self, ctx: qasm3Parser.ClassicalTypeContext): # TODO: due to the way classical argument is declared, there some duplication # Consider refactor classical argument grammar 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 errors. raise ValueError(f"Type name {type_name} not found.") return add_span( type_node, combine_span(get_span(ctx.singleDesignatorType()), get_span(ctx.designator())), ) elif ctx.noDesignatorType(): return self.visit(ctx.noDesignatorType()) elif ctx.bitType(): return BitType( self.visit(ctx.designator()) if ctx.designator() else None, ) elif ctx.numericType(): return ComplexType(base_type=self.visit(ctx.numericType()))
def visitComplexDeclaration(self, ctx: qasm3Parser.ComplexDeclarationContext): return ClassicalDeclaration( add_span( ComplexType(base_type=self.visit(ctx.numericType())), get_span(ctx), ), add_span(Identifier(ctx.Identifier().getText()), get_span(ctx.Identifier())), self.visit(ctx.equalsExpression().expression()) if ctx.equalsExpression() else None, )
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]), ), ], )
def visitClassicalArgument(self, ctx: qasm3Parser.ClassicalArgumentContext): if ctx.CONST(): access = AccessControl.CONST elif ctx.MUTABLE(): access = AccessControl.MUTABLE else: access = None 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.") classical_type = add_span( type_node, combine_span(get_span(ctx.singleDesignatorType()), get_span(ctx.designator())), ) elif ctx.noDesignatorType(): classical_type = self.visit(ctx.noDesignatorType()) elif ctx.COMPLEX(): classical_type = add_span( ComplexType(base_type=self.visit(ctx.numericType())), combine_span(get_span(ctx.COMPLEX()), get_span(ctx.RBRACKET())), ) elif ctx.arrayReferenceType(): classical_type = self.visit(ctx.arrayReferenceType()) else: classical_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( type=classical_type, name=identifier, access=access, )
def test_complex_declaration(): p = """ complex[int[24]] iq; """.strip() program = parse(p) assert program == Program(statements=[ ClassicalDeclaration( ComplexType(base_type=IntType(IntegerLiteral(24))), Identifier("iq"), None, ), ]) SpanGuard().visit(program) context_declaration = program.statements[0] assert context_declaration.span == Span(1, 0, 1, 19)
def test_subroutine_signatures(): p = """ def a(int[8] b) {} def a(complex[float[32]] b, qubit c) -> int[32] {} def a(bit[5] b, qubit[2] c) -> complex[float[64]] {} def a(qubit b, const array[uint[8], 2, 3] c) {} def a(mutable array[uint[8], #dim=5] b, const array[uint[8], 5] c) {} """.strip() program = parse(p) a, b, c = Identifier(name="a"), Identifier(name="b"), Identifier(name="c") SpanGuard().visit(program) assert program == Program(statements=[ SubroutineDefinition( name=a, arguments=[ClassicalArgument(IntType(IntegerLiteral(8)), b)], return_type=None, body=[], ), SubroutineDefinition( name=a, arguments=[ ClassicalArgument( type=ComplexType(FloatType(IntegerLiteral(32))), name=b, ), QuantumArgument(qubit=c, size=None), ], return_type=IntType(IntegerLiteral(32)), body=[], ), SubroutineDefinition( name=a, arguments=[ ClassicalArgument( type=BitType(size=IntegerLiteral(5)), name=b, ), QuantumArgument(qubit=c, size=IntegerLiteral(2)), ], return_type=ComplexType(FloatType(IntegerLiteral(64))), body=[], ), SubroutineDefinition( name=a, arguments=[ QuantumArgument(qubit=b, size=None), ClassicalArgument( type=ArrayReferenceType( base_type=UintType(IntegerLiteral(8)), dimensions=[IntegerLiteral(2), IntegerLiteral(3)], ), name=c, access=AccessControl.CONST, ), ], return_type=None, body=[], ), SubroutineDefinition( name=a, arguments=[ # Note that the first ArrayReferenceType has dimensions of # IntegerLiteral(5) referring to the number of dimensions, # but the second has dimensions [IntegerLiteral(5)] (with a # list), because the sizes of the dimensions are given # explicitly. ClassicalArgument( type=ArrayReferenceType( base_type=UintType(IntegerLiteral(8)), dimensions=IntegerLiteral(5), ), name=b, access=AccessControl.MUTABLE, ), ClassicalArgument( type=ArrayReferenceType( base_type=UintType(IntegerLiteral(8)), dimensions=[IntegerLiteral(5)], ), name=c, access=AccessControl.CONST, ), ], return_type=None, body=[], ), ])