Ejemplo n.º 1
0
def test_children_setter():
    ''' Test that the children setter sets-up accepts lists or raises
    the appropriate issue. '''
    testnode = Schedule()

    # children is initialised as a ChildrenList
    assert isinstance(testnode.children, ChildrenList)

    # When is set up with a list, this becomes a ChildrenList
    statement1 = Statement()
    statement2 = Statement()
    testnode.children = [statement1, statement2]
    assert isinstance(testnode.children, ChildrenList)
    assert statement1.parent is testnode
    assert statement2.parent is testnode

    # Other types are not accepted
    with pytest.raises(TypeError) as error:
        testnode.children = Node()
    assert "The 'my_children' parameter of the node.children setter must be" \
           " a list." in str(error.value)

    # If a children list is overwritten, it properly disconnects the previous
    # children
    testnode.children = []
    assert statement1.parent is None
    assert statement2.parent is None
Ejemplo n.º 2
0
def test_replace_with_error2():
    '''Check that the replace_with method raises the expected exceptions
    if either node is invalid.

    '''
    parent = Schedule()
    node1 = Statement()
    node2 = Statement()

    with pytest.raises(TypeError) as info:
        node1.replace_with("hello")
    assert ("The argument node in method replace_with in the Node class "
            "should be a Node but found 'str'." in str(info.value))

    with pytest.raises(GenerationError) as info:
        node1.replace_with(node2)
    assert ("This node should have a parent if its replace_with method "
            "is called." in str(info.value))

    node1.parent = parent
    node2.parent = parent
    parent.children = [node1, node2]
    with pytest.raises(GenerationError) as info:
        node1.replace_with(node2)
    assert ("The parent of argument node in method replace_with in the Node "
            "class should be None but found 'Schedule'." in str(info.value))

    node3 = Container("hello")
    with pytest.raises(GenerationError) as info:
        node1.replace_with(node3)
        assert ("Generation Error: Item 'Container' can't be child 0 of "
                "'Schedule'. The valid format is: '[Statement]*'."
                in str(info.value))
Ejemplo n.º 3
0
def test_handling_literal_precision_1(value, dprecision, intrinsic):
    '''Check that the fparser2 frontend can handle literals with a
    specified precision kind symbol.

    '''
    if intrinsic == ScalarType.Intrinsic.CHARACTER:
        code = "x={0}_{1}".format(dprecision, value)
    else:
        code = "x={0}_{1}".format(value, dprecision)
    reader = FortranStringReader(code)
    astmt = Fortran2003.Assignment_Stmt(reader)
    fake_parent = Schedule()
    # Ensure the symbol table has an entry for "x"
    fake_parent.symbol_table.add(
        DataSymbol("x", ScalarType(ScalarType.Intrinsic.INTEGER, 4)))
    processor = Fparser2Reader()
    processor.process_nodes(fake_parent, [astmt])
    assert not fake_parent.walk(CodeBlock)
    literal = fake_parent.children[0].children[1]
    assert isinstance(literal, Literal)
    assert literal.datatype.intrinsic == intrinsic
    if intrinsic == ScalarType.Intrinsic.BOOLEAN:
        assert ".{0}.".format(literal.value) == value.lower()
    else:
        assert literal.value == value
    assert isinstance(literal.datatype.precision, DataSymbol)
    assert literal.datatype.precision.name == dprecision
    assert isinstance(literal.datatype.precision.datatype, ScalarType)
    assert (literal.datatype.precision.datatype.intrinsic ==
            ScalarType.Intrinsic.INTEGER)
Ejemplo n.º 4
0
def test_node_constructor_with_parent():
    ''' Check that the node constructor parent parameter works as expected. '''
    parent = Schedule()
    wrong_parent = Schedule()

    # By default no parent reference is given
    node = Statement()
    assert node.parent is None
    assert node.has_constructor_parent is False

    # The parent argument can predefine the parent reference
    node = Return(parent=parent)
    assert node.parent is parent
    assert node.has_constructor_parent is True

    # Then only an addition to this predefined parent is accepted
    with pytest.raises(GenerationError) as err:
        wrong_parent.addchild(node)
    assert ("'Schedule' cannot be set as parent of 'Return' because its "
            "constructor predefined the parent reference to a different "
            "'Schedule' node." in str(err.value))

    # Once given the proper parent, it can act as a regular node
    parent.addchild(node)
    assert node.parent is parent
    assert node.has_constructor_parent is False
    wrong_parent.addchild(node.detach())
    assert node.parent is wrong_parent
Ejemplo n.º 5
0
def test_scoping_node_copy():
    ''' Test that the ScopingNode copy() method creates a new symbol table
    with copied symbols and updates the children references.'''

    # Since ScopingNode is abstract we will try this with a Schedule
    schedule = Schedule()
    symbol_a = schedule.symbol_table.new_symbol("a")
    symbol_b = schedule.symbol_table.new_symbol("b")

    schedule.addchild(
        Assignment.create(Reference(symbol_a), Reference(symbol_b)))

    new_schedule = schedule.copy()

    # Check that node generic copy() and _refine_copy() have been called
    # (e.g. children are not shallow copies and tree has been copied down
    # recursively)
    assert len(new_schedule.children) == 1
    assert new_schedule[0] is not schedule[0]
    assert new_schedule[0].lhs is not schedule[0].lhs
    assert new_schedule[0].rhs is not schedule[0].rhs

    # Check that the symbol_table has been deep copied
    assert new_schedule.symbol_table is not schedule.symbol_table
    assert new_schedule.symbol_table.lookup("a") is not \
        schedule.symbol_table.lookup("a")
    assert new_schedule.symbol_table.lookup("b") is not \
        schedule.symbol_table.lookup("b")

    # Check that the children references of the copied schedule point to
    # symbols in the new schedule's symbol table
    assert new_schedule[0].lhs.symbol not in schedule.symbol_table.symbols
    assert new_schedule[0].lhs.symbol in new_schedule.symbol_table.symbols
    assert new_schedule[0].rhs.symbol not in schedule.symbol_table.symbols
    assert new_schedule[0].rhs.symbol in new_schedule.symbol_table.symbols
Ejemplo n.º 6
0
def test_handling_literal_precision_2(value, dprecision, intrinsic):
    '''Check that the fparser2 frontend can handle literals with a
    specified precision value.

    TODO #754 fix test so that 'disable_declaration_check' fixture is not
    required.
    '''
    if intrinsic == ScalarType.Intrinsic.CHARACTER:
        code = "x={0}_{1}".format(dprecision, value)
    else:
        code = "x={0}_{1}".format(value, dprecision)
    reader = FortranStringReader(code)
    astmt = Fortran2003.Assignment_Stmt(reader)
    fake_parent = Schedule()
    processor = Fparser2Reader()
    processor.process_nodes(fake_parent, [astmt])
    assert not fake_parent.walk(CodeBlock)
    literal = fake_parent.children[0].children[1]
    assert isinstance(literal, Literal)
    assert literal.datatype.intrinsic == intrinsic
    if intrinsic == ScalarType.Intrinsic.BOOLEAN:
        assert ".{0}.".format(literal.value) == value.lower()
    else:
        assert literal.value == value
    assert isinstance(literal.datatype.precision, int)
    assert literal.datatype.precision == dprecision
Ejemplo n.º 7
0
def test_fusetrans_error_not_same_parent():
    ''' Check that we reject attempts to fuse loops which don't share the
    same parent '''
    from psyclone.transformations import LoopFuseTrans

    sch1 = Schedule()
    sch2 = Schedule()
    loop1 = Loop(variable=DataSymbol("i", INTEGER_TYPE), parent=sch1)
    loop2 = Loop(variable=DataSymbol("j", INTEGER_TYPE), parent=sch2)
    sch1.addchild(loop1)
    sch2.addchild(loop2)

    loop1.addchild(Literal("1", INTEGER_TYPE, parent=loop1))  # start
    loop1.addchild(Literal("10", INTEGER_TYPE, parent=loop1))  # stop
    loop1.addchild(Literal("1", INTEGER_TYPE, parent=loop1))  # step
    loop1.addchild(Schedule(parent=loop1))  # loop body

    loop2.addchild(Literal("1", INTEGER_TYPE, parent=loop2))  # start
    loop2.addchild(Literal("10", INTEGER_TYPE, parent=loop2))  # stop
    loop2.addchild(Literal("1", INTEGER_TYPE, parent=loop2))  # step
    loop2.addchild(Schedule(parent=loop2))  # loop body

    fuse = LoopFuseTrans()

    # Try to fuse loops with different parents
    with pytest.raises(TransformationError) as err:
        fuse.validate(loop1, loop2)
    assert ("Error in LoopFuseTrans transformation. Loops do not have the "
            "same parent" in str(err.value))
Ejemplo n.º 8
0
    def _insert_schedule(self, children=None, ast=None):
        '''
        Utility method to insert a Schedule between this Node and the
        supplied list of children.

        :param children: nodes which will become children of the \
                         new Schedule.
        :type children: list of :py:class:`psyclone.psyir.nodes.Node`
        :param ast: reference to fparser2 parse tree for associated \
                    Fortran code.
        :type ast: :py:class:`fparser.two.utils.Base`

        :returns: the new Schedule node.
        :rtype: :py:class:`psyclone.psyir.nodes.Schedule`
        '''
        from psyclone.psyir.nodes import Schedule
        sched = Schedule(children=children, parent=self)
        if children:
            # If we have children then set the Schedule's AST pointer to
            # point to the AST associated with them.
            sched.ast = children[0].ast
            for child in children:
                child.parent = sched
        else:
            sched.ast = ast
        return sched
Ejemplo n.º 9
0
def test_psyirvisitor_lower_dsl_concepts():
    ''' Test that DSL concepts are lowered by the visitors but the node is not
    modified after the visitor has finished. '''
    class MyDSLNode(Statement):
        ''' DSL Concept that lowers to a return statement '''
        _text_name = "MyDSLNode"

        def lower_to_language_level(self):
            ''' MyDSLNode lowers to a return statement and adds a symbol
            if it is inside an scoping region. '''
            # This will break if this Node does not have a parent with
            # a scope. This is intentional to cause an error during the
            # lowering step.
            self.scope.symbol_table.add(DataSymbol("val", REAL_TYPE))
            self.replace_with(Return())

    class MyVisitor(PSyIRVisitor):
        ''' Simple Visitor for Schedules and Return statements '''
        def return_node(self, _):
            ''' Return node visitor '''
            return "return"

        def schedule_node(self, node):
            ''' Schedule node visitor '''
            return "schedule(" + self._visit(node.children[0]) + ")"

    # Create a custom visitor and dsl-level node
    visitor = MyVisitor(indent_string=" ", initial_indent_depth=4)
    schedule = Schedule()
    my_dsl_node = MyDSLNode()
    schedule.addchild(my_dsl_node)

    # Visit DSL Node in a tree (the tree should not be modified)
    assert visitor(schedule) == "schedule(return)"
    assert isinstance(schedule.children[0], MyDSLNode)
    assert schedule.children[0] is my_dsl_node
    assert len(schedule.symbol_table.symbols) == 0

    # Visit DSL Node directly (the tree is also not modified)
    assert visitor(my_dsl_node) == "return"
    assert isinstance(my_dsl_node, MyDSLNode)
    assert isinstance(schedule.children[0], MyDSLNode)
    assert len(my_dsl_node.scope.symbol_table.symbols) == 0

    # Visit DSL node without a parent, which is an invalid state to
    # lower this node
    my_dsl_node.detach()
    with pytest.raises(VisitorError) as excinfo:
        visitor(my_dsl_node)
    assert (
        "Failed to lower 'MyDSLNode[]'. Note that some nodes need to be "
        "lowered from an ancestor in order to properly apply their in-tree "
        "modifications." in str(excinfo.value))
Ejemplo n.º 10
0
def test_profile_trans_invalid_name(value):
    '''Invalid name supplied to options argument.'''
    profile_trans = ProfileTrans()

    # We need to have a schedule as parent, otherwise the node
    # (with no parent) will not be allowed.
    sched = Schedule()
    node = Statement(parent=sched)
    sched.addchild(node)
    with pytest.raises(TransformationError) as excinfo:
        _ = profile_trans.apply(node, options={"region_name": value})
    assert ("User-supplied region name must be a tuple containing "
            "two non-empty strings." in str(excinfo.value))
Ejemplo n.º 11
0
def test_set_lower_bound_functions():
    ''' Test that we raise appropriate exceptions when the lower bound of
    a DynLoop is set to invalid values. '''
    schedule = Schedule()
    my_loop = DynLoop(parent=schedule)
    schedule.children = [my_loop]
    with pytest.raises(GenerationError) as excinfo:
        my_loop.set_lower_bound("invalid_loop_bounds_name")
    assert "lower bound loop name is invalid" in str(excinfo.value)
    with pytest.raises(GenerationError) as excinfo:
        my_loop.set_lower_bound("inner", index=0)
    assert "specified index" in str(excinfo.value)
    assert "lower loop bound is invalid" in str(excinfo.value)
Ejemplo n.º 12
0
def test_fusetrans_error_not_same_parent():
    ''' Check that we reject attempts to fuse loops which don't share the
    same parent '''

    loop1 = Loop.create(DataSymbol("i", INTEGER_TYPE),
                        Literal("1",
                                INTEGER_TYPE), Literal("10", INTEGER_TYPE),
                        Literal("1", INTEGER_TYPE), [Return()])
    sch1 = Schedule()
    sch1.addchild(loop1)

    sch2 = Schedule()
    loop2 = Loop.create(DataSymbol("j", INTEGER_TYPE),
                        Literal("1",
                                INTEGER_TYPE), Literal("10", INTEGER_TYPE),
                        Literal("1", INTEGER_TYPE), [Return()])

    sch2.addchild(loop2)

    fuse = LoopFuseTrans()

    # Try to fuse loops with different parents
    with pytest.raises(TransformationError) as err:
        fuse.validate(loop1, loop2)
    assert ("Error in LoopFuseTrans transformation. Loops do not have the "
            "same parent" in str(err.value))
Ejemplo n.º 13
0
def test_replace_with():
    '''Check that the replace_with method behaves as expected.'''

    parent_node = Schedule()
    node1 = Statement()
    node2 = Statement()
    node3 = Statement()
    parent_node.children = [node1, node2, node3]
    new_node = Assignment()

    node2.replace_with(new_node)

    assert parent_node.children[1] is new_node
    assert new_node.parent is parent_node
    assert node2.parent is None
Ejemplo n.º 14
0
def test_goloop_no_parent():
    ''' Attempt to generate code for a loop that has no GOInvokeSchedule
    as a parent '''
    # First create with a schedule as one is required to declare the
    # loop variable
    schedule = Schedule()
    goloop = GOLoop(loop_type="inner", parent=schedule)
    schedule.children = [goloop]
    # Now remove parent and children
    goloop.parent = None
    goloop.children = None
    # Try and generate the code for this loop even though it
    # has no parent schedule and no children
    with pytest.raises(GenerationError):
        goloop.gen_code(None)
Ejemplo n.º 15
0
def test_call_noargs():
    '''Test that fparser2reader transforms a Fortran subroutine call with
    no arguments into the equivalent PSyIR Call node. Also test that a
    new RoutineSymbol is added to the symbol table (with an unresolved
    interface) when one does not already exist. Also test that the
    Call node ast property is set to reference the original fparser2
    call node.

    '''
    reader = FortranStringReader(" call kernel()")
    ast = Fortran2003.Call_Stmt(reader)
    fake_parent = Schedule()
    processor = Fparser2Reader()
    processor.process_nodes(fake_parent, [ast])

    call_node = fake_parent.children[0]
    assert isinstance(call_node, Call)
    assert not call_node.children

    routine_symbol = call_node.routine
    assert isinstance(routine_symbol, RoutineSymbol)
    assert isinstance(routine_symbol.interface, UnresolvedInterface)
    assert routine_symbol.name == "kernel"
    assert routine_symbol in call_node.scope.symbol_table.symbols

    assert (str(call_node)) == "Call[name='kernel']"

    assert call_node.ast == ast
def test_ubound_lbound_arg_error():
    ''' Check that the _copy_full_base_reference utility method raises the
    expected error if the supplied node is of the wrong type. '''
    with pytest.raises(InternalError) as err:
        _copy_full_base_reference(Schedule())
    assert ("supplied node must be an instance of either Reference or "
            "Member but got 'Schedule'" in str(err.value))
Ejemplo n.º 17
0
    def _process_loopbody(self, loop_body, node):
        '''
        Specialized method to process Nemo loop bodies. If the schedule
        matches with a NemoKern, it will add a NemoKern instead of statements
        in the loop_body.

        :param loop_body: schedule representing the body of the loop.
        :type loop_body: :py:class:`psyclone.psyir.nodes.Schedule`
        :param node: fparser loop node being processed.
        :type node: \
            :py:class:`fparser.two.Fortran2003.Block_Nonlabel_Do_Construct`
        '''
        # We create a fake node because we need to parse the children
        # before we decide what to do with them.
        fakeparent = Schedule(parent=loop_body)
        self.process_nodes(parent=fakeparent, nodes=node.content[1:-1])

        if NemoKern.match(fakeparent):
            # Create a new kernel object and make it the only
            # child of this Loop node. The PSyIR of the loop body becomes
            # the schedule of this kernel.
            nemokern = NemoKern(fakeparent.children, node, parent=loop_body)
            loop_body.children.append(nemokern)
        else:
            # Otherwise just connect the new children into the tree.
            loop_body.children.extend(fakeparent.children)
            for child in fakeparent.children:
                child.parent = loop_body
Ejemplo n.º 18
0
    def __init__(self, parent=None, loop_type=""):
        Loop.__init__(self,
                      parent=parent,
                      valid_loop_types=["", "colours", "colour"])
        self.loop_type = loop_type

        # Work out the variable name from  the loop type
        if self._loop_type == "colours":
            tag = "colours_loop_idx"
            suggested_name = "colour"
        elif self._loop_type == "colour":
            tag = "colour_loop_idx"
            suggested_name = "cell"
        else:
            tag = "cell_loop_idx"
            suggested_name = "cell"

        symtab = self.scope.symbol_table
        try:
            data_symbol = symtab.lookup_with_tag(tag)
        except KeyError:
            name = symtab.new_symbol_name(suggested_name)
            data_symbol = DataSymbol(name, INTEGER_TYPE)
            symtab.add(data_symbol, tag=tag)
        self.variable = data_symbol

        # Pre-initialise the Loop children  # TODO: See issue #440
        self.addchild(Literal("NOT_INITIALISED", INTEGER_TYPE,
                              parent=self))  # start
        self.addchild(Literal("NOT_INITIALISED", INTEGER_TYPE,
                              parent=self))  # stop
        self.addchild(Literal("1", INTEGER_TYPE, parent=self))  # step
        self.addchild(Schedule(parent=self))  # loop body
Ejemplo n.º 19
0
def process_where(code, fparser_cls, symbols=None):
    '''
    Utility routine to process the supplied Fortran code and return the
    PSyIR and fparser2 parse trees.

    :param str code: Fortran code to process.
    :param type fparser_cls: the fparser2 class to instantiate to \
                             represent the supplied Fortran.
    :param symbols: list of symbol names that must be added to the symbol \
                    table before constructing the PSyIR.
    :type symbols: list of str

    :returns: 2-tuple of a parent PSyIR Schedule and the created instance of \
              the requested fparser2 class.
    :rtype: (:py:class:`psyclone.psyir.nodes.Schedule`, \
             :py:class:`fparser.two.utils.Base`)
    '''
    sched = Schedule()
    if symbols:
        for sym_name in symbols:
            sched.symbol_table.new_symbol(sym_name)
    processor = Fparser2Reader()
    reader = FortranStringReader(code)
    fparser2spec = fparser_cls(reader)

    if fparser_cls is Fortran2003.Execution_Part:
        processor.process_nodes(sched, fparser2spec.content)
    else:
        processor.process_nodes(sched, [fparser2spec])
    return sched, fparser2spec
Ejemplo n.º 20
0
def test_get_node_list():
    '''Test for valid parameters to get_node_list.'''

    my_rt = MyRegionTrans()
    # 1) Provide a schedule
    # ---------------------
    sched = Schedule()
    # get_node_list returns a copy of the list, so it must be a list
    # with the same content, but NOT the same list:
    node_list = my_rt.get_node_list(sched)
    assert sched.children == node_list
    assert node_list is not sched.children

    # 2) Provide a single node
    # ------------------------
    node = Node()
    node_list = my_rt.get_node_list(node)
    assert node_list == [node]

    # 3) Provide a node list
    # ----------------------
    # We use the previously returned node list, and make sure
    # that we get a copy of that list.
    node_list2 = my_rt.get_node_list(node_list)
    assert node_list2 == node_list
    assert node_list2 is not node_list
Ejemplo n.º 21
0
def test_array_notation_rank():
    ''' Check that the _array_notation_rank() utility handles various examples
    of array notation.

    TODO #754 fix test so that 'disable_declaration_check' fixture is not
    required.
    '''
    fake_parent = Schedule()
    processor = Fparser2Reader()
    reader = FortranStringReader("  z1_st(:, 2, :) = ptsu(:, :, 3)")
    fparser2spec = Fortran2003.Assignment_Stmt(reader)
    processor.process_nodes(fake_parent, [fparser2spec])
    assert processor._array_notation_rank(fake_parent[0].lhs) == 2
    reader = FortranStringReader("  z1_st(:, :, 2, :) = ptsu(:, :, :, 3)")
    fparser2spec = Fortran2003.Assignment_Stmt(reader)
    processor.process_nodes(fake_parent, [fparser2spec])
    assert processor._array_notation_rank(fake_parent[1].lhs) == 3
    # We don't support bounds on slices
    reader = FortranStringReader("  z1_st(:, 1:n, 2, :) = ptsu(:, :, :, 3)")
    fparser2spec = Fortran2003.Assignment_Stmt(reader)
    processor.process_nodes(fake_parent, [fparser2spec])
    with pytest.raises(NotImplementedError) as err:
        processor._array_notation_rank(fake_parent[2].lhs)
    assert ("Only array notation of the form my_array(:, :, ...) is "
            "supported." in str(err.value))
Ejemplo n.º 22
0
    def __init__(self, parent=None, topology_name="", loop_type=""):
        Loop.__init__(self, parent=parent, valid_loop_types=["inner", "outer"])
        self.loop_type = loop_type

        if self._loop_type == "inner":
            tag = "inner_loop_idx"
            suggested_name = "i"
        elif self.loop_type == "outer":
            tag = "outer_loop_idx"
            suggested_name = "j"

        symtab = self.scope.symbol_table
        try:
            self.variable = symtab.lookup_with_tag(tag)
        except KeyError:
            self.variable = symtab.new_symbol(suggested_name,
                                              tag,
                                              symbol_type=DataSymbol,
                                              datatype=INTEGER_TYPE)

        # Pre-initialise the Loop children  # TODO: See issue #440
        self.addchild(Literal("NOT_INITIALISED", INTEGER_TYPE,
                              parent=self))  # start
        self.addchild(Literal("NOT_INITIALISED", INTEGER_TYPE,
                              parent=self))  # stop
        self.addchild(Literal("1", INTEGER_TYPE, parent=self))  # step
        self.addchild(Schedule(parent=self))  # loop body
Ejemplo n.º 23
0
def test_loop_navigation_properties():
    # pylint: disable=too-many-statements
    ''' Tests the start_expr, stop_expr, step_expr and loop_body
    setter and getter properties.

    '''
    loop = Loop()

    # Properties return an error if the node is incomplete
    error_str = ("Loop is incomplete. It should have exactly 4 "
                 "children, but found")
    with pytest.raises(InternalError) as err:
        _ = loop.start_expr
    assert error_str in str(err.value)

    loop.addchild(Literal("start", INTEGER_SINGLE_TYPE))
    loop.addchild(Literal("stop", INTEGER_SINGLE_TYPE))
    loop.addchild(Literal("step", INTEGER_SINGLE_TYPE))

    # If it's not fully complete, it still returns an error
    with pytest.raises(InternalError) as err:
        _ = loop.start_expr
    assert error_str in str(err.value)
    with pytest.raises(InternalError) as err:
        _ = loop.stop_expr
    assert error_str in str(err.value)
    with pytest.raises(InternalError) as err:
        _ = loop.step_expr
    assert error_str in str(err.value)
    with pytest.raises(InternalError) as err:
        _ = loop.loop_body
    assert error_str in str(err.value)
    with pytest.raises(InternalError) as err:
        loop.start_expr = Literal("invalid", INTEGER_SINGLE_TYPE)
    assert error_str in str(err.value)
    with pytest.raises(InternalError) as err:
        loop.stop_expr = Literal("invalid", INTEGER_SINGLE_TYPE)
    assert error_str in str(err.value)
    with pytest.raises(InternalError) as err:
        loop.step_expr = Literal("invalid", INTEGER_SINGLE_TYPE)
    assert error_str in str(err.value)

    # Check that Getters properties work
    loop.addchild(Schedule(parent=loop))
    loop.loop_body.addchild(Return(parent=loop.loop_body))

    assert loop.start_expr.value == "start"
    assert loop.stop_expr.value == "stop"
    assert loop.step_expr.value == "step"
    assert isinstance(loop.loop_body[0], Return)

    # Test Setters
    loop.start_expr = Literal("newstart", INTEGER_SINGLE_TYPE)
    loop.stop_expr = Literal("newstop", INTEGER_SINGLE_TYPE)
    loop.step_expr = Literal("newstep", INTEGER_SINGLE_TYPE)

    assert loop.start_expr.value == "newstart"
    assert loop.stop_expr.value == "newstop"
    assert loop.step_expr.value == "newstep"
Ejemplo n.º 24
0
def test_number_handler():
    ''' Check that the number_handler raises a NotImplementedError for an
    unrecognised fparser2 node. '''
    processor = Fparser2Reader()
    fake_parent = Schedule()
    reader = FortranStringReader("(1.0, 1.0)")
    with pytest.raises(NotImplementedError):
        processor._number_handler(Fortran2003.Complex_Literal_Constant(reader),
                                  fake_parent)
Ejemplo n.º 25
0
def test_cw_ifblock():
    '''Check the CWriter class ifblock method correctly prints out the
    C representation.

    '''
    from psyclone.psyir.nodes import IfBlock

    # Try with just an IfBlock node
    ifblock = IfBlock()
    cwriter = CWriter()
    with pytest.raises(VisitorError) as err:
        _ = cwriter(ifblock)
    assert ("IfBlock malformed or incomplete. It should have "
            "at least 2 children, but found 0." in str(err.value))

    # Add the if condition
    ifblock.addchild(Reference(DataSymbol('a', REAL_TYPE), parent=ifblock))
    with pytest.raises(VisitorError) as err:
        _ = cwriter(ifblock)
    assert ("IfBlock malformed or incomplete. It should have "
            "at least 2 children, but found 1." in str(err.value))

    # Fill the if_body and else_body
    ifblock.addchild(Schedule(parent=ifblock))
    ifblock.addchild(Schedule(parent=ifblock))
    ifblock.if_body.addchild(Return(parent=ifblock.if_body))

    condition = Reference(DataSymbol('b', REAL_TYPE))
    then_content = [Return()]
    else_content = [Return()]
    ifblock2 = IfBlock.create(condition, then_content, else_content)
    ifblock2.parent = ifblock.if_body
    ifblock.else_body.addchild(ifblock2)

    result = cwriter(ifblock)
    assert result == ("if (a) {\n"
                      "  return;\n"
                      "} else {\n"
                      "  if (b) {\n"
                      "    return;\n"
                      "  } else {\n"
                      "    return;\n"
                      "  }\n"
                      "}\n")
Ejemplo n.º 26
0
def test_handling_literal_precision_3(value, dprecision):
    '''Check that the fparser2 frontend can handle literals with a
    precision value specified by the exponent. The literal value

    TODO #754 fix test so that 'disable_declaration_check' fixture is not
    required.
    should always use a lower case "e" for the exponent.
    '''
    code = "x={0}".format(value)
    reader = FortranStringReader(code)
    astmt = Fortran2003.Assignment_Stmt(reader)
    fake_parent = Schedule()
    processor = Fparser2Reader()
    processor.process_nodes(fake_parent, [astmt])
    assert not fake_parent.walk(CodeBlock)
    literal = fake_parent.children[0].children[1]
    assert isinstance(literal, Literal)
    assert literal.value.lower() == "0.0e0"
    assert literal.datatype.intrinsic == ScalarType.Intrinsic.REAL
    assert literal.datatype.precision == dprecision
Ejemplo n.º 27
0
def test_sched_init():
    ''' Check the Schedule class is initialised as expected.'''

    # By default Schedule sets parent to None, children to an empty list and
    # initialises its own symbol table.
    sched = Schedule()
    assert isinstance(sched, Schedule)
    assert not sched.parent
    assert not sched.children
    assert isinstance(sched.symbol_table, SymbolTable)

    # A custom symbol table and parent and children nodes can be given as
    # arguments of Schedule.
    symtab = SymbolTable()
    sched2 = Schedule(parent=sched, children=[Statement(), Statement()],
                      symbol_table=symtab)
    assert isinstance(sched2, Schedule)
    assert sched2.parent is sched
    assert len(sched2.children) == 2
    assert sched2.symbol_table is symtab
Ejemplo n.º 28
0
def test_handling_literal(code, dtype):
    ''' Check that the fparser2 frontend can handle literals of all
    supported datatypes. Note that signed literals are represented in the
    PSyIR as a Unary operation on an unsigned literal.

    TODO #754 fix test so that 'disable_declaration_check' fixture is not
    required.
    '''
    reader = FortranStringReader("x=" + code)
    astmt = Fortran2003.Assignment_Stmt(reader)
    fake_parent = Schedule()
    processor = Fparser2Reader()
    processor.process_nodes(fake_parent, [astmt])
    assert not fake_parent.walk(CodeBlock)
    literal = fake_parent.children[0].children[1]
    assert isinstance(literal, Literal)
    assert literal.datatype.intrinsic == dtype
    if dtype != ScalarType.Intrinsic.BOOLEAN:
        assert literal.value == code
    else:
        assert literal.value == code.lower()[1:-1]  # Remove wrapping dots
def test_subscript_triplet_handler_error():
    ''' Check that the subscript-triplet handler raises the expected error if
    the parent PSyIR node is not of the correct type. '''
    processor = Fparser2Reader()
    fake_parent = Schedule()
    reader = FortranStringReader("x(:) = a")
    fp2node = Execution_Part.match(reader)
    triplet = fp2node[0][0].children[0].children[1].children[0]
    with pytest.raises(InternalError) as err:
        processor._subscript_triplet_handler(triplet, fake_parent)
    assert ("Expected parent PSyIR node to be either a Reference or a Member "
            "but got 'Schedule' when processing ':'" in str(err.value))
Ejemplo n.º 30
0
def test_children_setter():
    ''' Test that the children setter sets-up accepts lists or None or raises
    the appropriate issue. '''
    testnode = Schedule()

    # children is initialised as a ChildrenList
    assert isinstance(testnode.children, ChildrenList)

    # When is set up with a list, this becomes a ChildrenList
    testnode.children = [Statement(), Statement()]
    assert isinstance(testnode.children, ChildrenList)

    # It also accepts None
    testnode.children = None
    assert testnode.children is None

    # Other types are not accepted
    with pytest.raises(TypeError) as error:
        testnode.children = Node()
    assert "The 'my_children' parameter of the node.children setter must be" \
           " a list or None." in str(error.value)