コード例 #1
0
ファイル: symboltable.py プロジェクト: stfc/PSyclone
    def deep_copy(self):
        '''Create a copy of the symbol table with new instances of the
        top-level data structures and also new instances of the symbols
        contained in these data structures. Modifying a symbol attribute
        will not affect the equivalent named symbol in the original symbol
        table.

        :returns: a deep copy of this symbol table.
        :rtype: :py:class:`psyclone.psyir.symbols.SymbolTable`

        '''
        # pylint: disable=protected-access
        new_st = SymbolTable(self.node)

        # Make a copy of each symbol in the symbol table
        for symbol in self.symbols:
            new_st.add(symbol.copy())

        # Prepare the new argument list
        new_arguments = []
        for name in [arg.name for arg in self.argument_list]:
            new_arguments.append(new_st.lookup(name))
        new_st.specify_argument_list(new_arguments)

        # Prepare the new tag dict
        for tag, symbol in self._tags.items():
            new_st._tags[tag] = new_st.lookup(symbol.name)

        # Fix the container links for imported symbols
        for symbol in new_st.global_symbols:
            name = symbol.interface.container_symbol.name
            new_container = new_st.lookup(name)
            symbol.interface = GlobalInterface(new_container)

        return new_st
コード例 #2
0
ファイル: datasymbol_test.py プロジェクト: mfkiwl/PSyclone
def test_datasymbol_can_be_printed():
    '''Test that a DataSymbol instance can always be printed. (i.e. is
    initialised fully.)'''
    symbol = DataSymbol("sname", REAL_SINGLE_TYPE)
    assert "sname: <Scalar<REAL, SINGLE>, Local>" in str(symbol)

    sym1 = DataSymbol("s1",
                      INTEGER_SINGLE_TYPE,
                      interface=UnresolvedInterface())
    assert "s1: <Scalar<INTEGER, SINGLE>, Unresolved>" in str(sym1)

    array_type = ArrayType(REAL_SINGLE_TYPE,
                           [ArrayType.Extent.ATTRIBUTE, 2,
                            Reference(sym1)])
    sym2 = DataSymbol("s2", array_type)
    assert ("s2: <Array<Scalar<REAL, SINGLE>, shape=['ATTRIBUTE', "
            "Literal[value:'2', Scalar<INTEGER, UNDEFINED>], "
            "Reference[name:'s1']]>, Local>" in str(sym2))

    my_mod = ContainerSymbol("my_mod")
    sym3 = DataSymbol("s3",
                      REAL_SINGLE_TYPE,
                      interface=GlobalInterface(my_mod))
    assert ("s3: <Scalar<REAL, SINGLE>, Global(container='my_mod')>"
            in str(sym3))

    sym3 = DataSymbol("s3", INTEGER_SINGLE_TYPE, constant_value=12)
    assert ("s3: <Scalar<INTEGER, SINGLE>, Local, "
            "constant_value=Literal"
            "[value:'12', Scalar<INTEGER, SINGLE>]>" in str(sym3))

    sym4 = DataSymbol("s4",
                      INTEGER_SINGLE_TYPE,
                      interface=UnresolvedInterface())
    assert "s4: <Scalar<INTEGER, SINGLE>, Unresolved>" in str(sym4)
コード例 #3
0
def test_globalinterface():
    '''Test that we can create a global interface successfully, that is
    raises the expected exception if the container_symbol attribute is
    of the wrong type, that the container symbol property and str
    method work as expected.

    '''
    container_symbol = ContainerSymbol("my_mod")
    global_interface = GlobalInterface(container_symbol)
    assert global_interface.container_symbol is container_symbol
    assert str(global_interface) == "Global(container='my_mod')"

    with pytest.raises(TypeError) as info:
        _ = GlobalInterface("hello")
    assert ("Global container_symbol parameter must be of type "
            "ContainerSymbol, but found 'str'." in str(info.value))
コード例 #4
0
def test_symbol_interface_setter():
    '''Test that the Symbol interface setter behaves as expected,
    including raising an exception if the input is of the wrong
    type. Also use this to test the is_local, is_global and
    is_argument and is_unresolved properties.

    '''
    symbol = Symbol('sym1')
    assert symbol.is_local
    assert not symbol.is_global
    assert not symbol.is_argument
    assert not symbol.is_unresolved

    symbol.interface = GlobalInterface(ContainerSymbol("my_mod"))
    assert not symbol.is_local
    assert symbol.is_global
    assert not symbol.is_argument
    assert not symbol.is_unresolved

    symbol.interface = ArgumentInterface()
    assert not symbol.is_local
    assert not symbol.is_global
    assert symbol.is_argument
    assert not symbol.is_unresolved

    symbol.interface = UnresolvedInterface()
    assert not symbol.is_local
    assert not symbol.is_global
    assert not symbol.is_argument
    assert symbol.is_unresolved

    with pytest.raises(TypeError) as info:
        symbol.interface = "hello"
    assert ("The interface to a Symbol must be a SymbolInterface but got "
            "'str'" in str(info.value))
コード例 #5
0
ファイル: symbol_test.py プロジェクト: mfkiwl/PSyclone
def test_symbol_copy():
    '''
    Test the Symbol.copy() method.
    '''
    csym = ContainerSymbol("some_mod")
    asym = Symbol("a", visibility=Symbol.Visibility.PRIVATE,
                  interface=GlobalInterface(csym))
    new_sym = asym.copy()
    assert new_sym is not asym
    assert new_sym.name == asym.name
    assert new_sym.interface == asym.interface
    assert new_sym.visibility == asym.visibility
コード例 #6
0
def test_get_external_symbol(monkeypatch):
    ''' Test the get_external_symbol() method. '''
    asym = Symbol("a")
    with pytest.raises(NotImplementedError) as err:
        asym.get_external_symbol()
    assert ("trying to resolve symbol 'a' properties, the lazy evaluation "
            "of 'Local' interfaces is not supported" in str(err.value))
    other_container = ContainerSymbol("some_mod")
    ctable = SymbolTable()
    ctable.add(other_container)
    # Create a Symbol that is imported from the "some_mod" Container
    bsym = Symbol("b", interface=GlobalInterface(other_container))
    ctable.add(bsym)
    _ = Container.create("test", ctable, [KernelSchedule("dummy")])

    # Monkeypatch the container's FortranModuleInterface so that it always
    # appears to be unable to find the "some_mod" module

    def fake_import(name):
        raise SymbolError("Oh dear")

    monkeypatch.setattr(other_container._interface, "import_container",
                        fake_import)
    with pytest.raises(SymbolError) as err:
        bsym.get_external_symbol()
    assert ("trying to resolve the properties of symbol 'b' in module "
            "'some_mod': PSyclone SymbolTable error: Oh dear"
            in str(err.value))
    # Now create a Container for the 'some_mod' module and attach this to
    # the ContainerSymbol
    ctable2 = SymbolTable()
    some_mod = Container.create("some_mod", ctable2,
                                [KernelSchedule("dummy2")])
    other_container._reference = some_mod
    # Currently the Container does not contain an entry for 'b'
    with pytest.raises(SymbolError) as err:
        bsym.get_external_symbol()
    assert ("trying to resolve the properties of symbol 'b'. The interface "
            "points to module 'some_mod' but could not find the definition"
            in str(err.value))
    # Add an entry for 'b' to the Container's symbol table
    ctable2.add(DataSymbol("b", INTEGER_SINGLE_TYPE))
    new_sym = bsym.resolve_deferred()
    assert isinstance(new_sym, DataSymbol)
    assert new_sym.datatype == INTEGER_SINGLE_TYPE
コード例 #7
0
def test_psy_data_node_incorrect_container():
    ''' Check that the PSyDataNode constructor raises the expected error if
    the symbol table already contains an entry for the PSyDataType that is
    not associated with the PSyData container. '''
    _, invoke = get_invoke("test11_different_iterates_over_one_invoke.f90",
                           "gocean1.0",
                           idx=0,
                           dist_mem=False)
    schedule = invoke.schedule
    csym = schedule.symbol_table.new_symbol("some_mod",
                                            symbol_type=ContainerSymbol)
    schedule.symbol_table.new_symbol("PSyDataType",
                                     interface=GlobalInterface(csym))
    data_trans = PSyDataTrans()
    with pytest.raises(TransformationError) as err:
        data_trans.apply(schedule[0].loop_body)
    assert ("already a symbol named 'PSyDataType' which clashes with one of "
            "those used by the PSyclone PSyData API" in str(err.value))
コード例 #8
0
def test_datasymbol_resolve_deferred(monkeypatch):
    ''' Test the datasymbol resolve_deferred method '''
    symbola = DataSymbol('a', INTEGER_SINGLE_TYPE)
    new_sym = symbola.resolve_deferred()
    # For a DataSymbol (unlike a Symbol), resolve_deferred should always
    # return the object on which it was called.
    assert new_sym is symbola
    module = ContainerSymbol("dummy_module")
    symbolb = DataSymbol('b', visibility=Symbol.Visibility.PRIVATE,
                         datatype=DeferredType(),
                         interface=GlobalInterface(module))
    # Monkeypatch the get_external_symbol() method so that it just returns
    # a new DataSymbol
    monkeypatch.setattr(symbolb, "get_external_symbol",
                        lambda: DataSymbol("b", INTEGER_SINGLE_TYPE))
    new_sym = symbolb.resolve_deferred()
    assert new_sym is symbolb
    assert new_sym.datatype == INTEGER_SINGLE_TYPE
    assert new_sym.visibility == Symbol.Visibility.PRIVATE
    assert isinstance(new_sym.interface, GlobalInterface)
コード例 #9
0
ファイル: symbol_test.py プロジェクト: mfkiwl/PSyclone
def test_symbol_resolve_deferred(monkeypatch):
    ''' Test the resolve_deferred method. '''
    # resolve_deferred() for a local symbol has nothing to do so should
    # just return itself.
    asym = Symbol("a")
    assert asym.resolve_deferred() is asym
    # Now test for a symbol that is imported from another Container
    other_container = ContainerSymbol("some_mod")
    bsym = Symbol("b", visibility=Symbol.Visibility.PRIVATE,
                  interface=GlobalInterface(other_container))
    # Monkeypatch the get_external_symbol() method so that it just returns
    # a new DataSymbol
    monkeypatch.setattr(bsym, "get_external_symbol",
                        lambda: DataSymbol("b", INTEGER_SINGLE_TYPE))
    new_sym = bsym.resolve_deferred()
    # We should have a brand new symbol but with some of the properties
    # of the original 'bsym' symbol.
    assert new_sym is not bsym
    assert new_sym.datatype == INTEGER_SINGLE_TYPE
    assert new_sym.visibility == Symbol.Visibility.PRIVATE
    assert new_sym.is_global
コード例 #10
0
    def create_psylayer_symbols(self):
        '''If the PSy-layer routine and container symbols have not been
        created, then create them. The names are based on the position
        of this node (compared to other nodes of the same type) in the
        PSyIR tree.

        '''
        if self.psylayer_routine_symbol:
            # The language-level symbols have already been created
            return

        routine_root_name = self._def_routine_root_name()

        symbol_table = self.scope.symbol_table
        routine_name = symbol_table.next_available_name(
            root_name=routine_root_name)

        container_root_name = "{0}_mod".format(routine_name)
        container_name = symbol_table.next_available_name(
            root_name=container_root_name)

        interface = GlobalInterface(ContainerSymbol(container_name))
        self.psylayer_routine_symbol = RoutineSymbol(routine_name,
                                                     interface=interface)
コード例 #11
0
# Derived-type definition in container
GRID_TYPE = StructureType.create([
    ("dx", SCALAR_TYPE, Symbol.Visibility.PUBLIC),
    ("dy", SCALAR_TYPE, Symbol.Visibility.PUBLIC)])
GRID_TYPE_SYMBOL = TypeSymbol("grid_type", GRID_TYPE)
CONTAINER_SYMBOL_TABLE.add(GRID_TYPE_SYMBOL)

# Kernel symbol table, symbols and scalar datatypes
SYMBOL_TABLE = SymbolTable()

CONT = ContainerSymbol("kernel_mod")
SYMBOL_TABLE.add(CONT)

DTYPE_SYMBOL = TypeSymbol("other_type", DeferredType(),
                          interface=GlobalInterface(CONT))
SYMBOL_TABLE.add(DTYPE_SYMBOL)

# Create the definition of the 'field_type'
FIELD_TYPE_DEF = StructureType.create(
    [("data", ArrayType(SCALAR_TYPE, [10]), Symbol.Visibility.PUBLIC),
     ("grid", GRID_TYPE_SYMBOL, Symbol.Visibility.PUBLIC),
     ("sub_meshes", ArrayType(GRID_TYPE_SYMBOL, [3]),
      Symbol.Visibility.PUBLIC),
     ("flag", INTEGER4_TYPE, Symbol.Visibility.PUBLIC)])
FIELD_TYPE_SYMBOL = TypeSymbol("field_type", FIELD_TYPE_DEF)
CONTAINER_SYMBOL_TABLE.add(FIELD_TYPE_SYMBOL)

# Create an argument of this derived type. At this point we know only that
# DTYPE_SYMBOL refers to a type defined in the CONT container.
FIELD_SYMBOL = DataSymbol("wind", FIELD_TYPE_SYMBOL,
コード例 #12
0
ファイル: symboltable.py プロジェクト: xyuan/PSyclone
    def copy_external_global(self, globalvar, tag=None):
        '''
        Copy the given global variable (and its referenced ContainerSymbol if
        needed) into the SymbolTable.

        :param globalvar: the variable to be copied in.
        :type globalvar: :py:class:`psyclone.psyir.symbols.DataSymbol`
        :param str tag: a tag identifier for the new copy, by default no tag \
            is given.

        :raises TypeError: if the given variable is not a global variable.
        :raises KeyError: if the given variable name already exists in the \
            symbol table.

        '''
        if not isinstance(globalvar, DataSymbol):
            raise TypeError(
                "The globalvar argument of SymbolTable.copy_external_global"
                " method should be a DataSymbol, but found '{0}'."
                "".format(type(globalvar).__name__))

        if not globalvar.is_global:
            raise TypeError(
                "The globalvar argument of SymbolTable.copy_external_"
                "global method should have a GlobalInterface interface, "
                "but found '{0}'.".format(type(globalvar.interface).__name__))

        external_container_name = globalvar.interface.container_symbol.name

        # If the Container is not yet in the SymbolTable we need to
        # create one and add it.
        if external_container_name not in self:
            self.add(ContainerSymbol(external_container_name))
        container_ref = self.lookup(external_container_name)

        # Copy the variable into the SymbolTable with the appropriate interface
        if globalvar.name not in self:
            new_symbol = globalvar.copy()
            # Update the interface of this new symbol
            new_symbol.interface = GlobalInterface(container_ref)
            self.add(new_symbol, tag)
        else:
            # If it already exists it must refer to the same Container and have
            # the same tag.
            local_instance = self.lookup(globalvar.name)
            if not (local_instance.is_global
                    and local_instance.interface.container_symbol.name
                    == external_container_name):
                raise KeyError("Couldn't copy '{0}' into the SymbolTable. The"
                               " name '{1}' is already used by another symbol."
                               "".format(globalvar, globalvar.name))
            if tag:
                # If the symbol already exists and a tag is provided
                try:
                    self.lookup_with_tag(tag)
                except KeyError:
                    # If the tag was not used, it will now be attached
                    # to the symbol.
                    self._tags[tag] = self.lookup(globalvar.name)

                # The tag should not refer to a different symbol
                if self.lookup(globalvar.name) != self.lookup_with_tag(tag):
                    raise KeyError(
                        "Couldn't copy '{0}' into the SymbolTable. The"
                        " tag '{1}' is already used by another symbol."
                        "".format(globalvar, tag))
コード例 #13
0
ファイル: create.py プロジェクト: hiker/PSyclone
def create_psyir_tree():
    ''' Create an example PSyIR Tree.

    :returns: an example PSyIR tree.
    :rtype: :py:class:`psyclone.psyir.nodes.Container`

    '''
    # Symbol table, symbols and scalar datatypes
    symbol_table = SymbolTable()
    arg1 = symbol_table.new_symbol(symbol_type=DataSymbol,
                                   datatype=REAL_TYPE,
                                   interface=ArgumentInterface(
                                       ArgumentInterface.Access.READWRITE))
    symbol_table.specify_argument_list([arg1])
    tmp_symbol = symbol_table.new_symbol(symbol_type=DataSymbol,
                                         datatype=REAL_DOUBLE_TYPE)
    index_symbol = symbol_table.new_symbol(root_name="i",
                                           symbol_type=DataSymbol,
                                           datatype=INTEGER4_TYPE)
    real_kind = symbol_table.new_symbol(root_name="RKIND",
                                        symbol_type=DataSymbol,
                                        datatype=INTEGER_TYPE,
                                        constant_value=8)
    routine_symbol = RoutineSymbol("my_sub")

    # Array using precision defined by another symbol
    scalar_type = ScalarType(ScalarType.Intrinsic.REAL, real_kind)
    array = symbol_table.new_symbol(root_name="a",
                                    symbol_type=DataSymbol,
                                    datatype=ArrayType(scalar_type, [10]))

    # Make generators for nodes which do not have other Nodes as children,
    # with some predefined scalar datatypes
    def zero():
        return Literal("0.0", REAL_TYPE)

    def one():
        return Literal("1.0", REAL4_TYPE)

    def two():
        return Literal("2.0", scalar_type)

    def int_zero():
        return Literal("0", INTEGER_SINGLE_TYPE)

    def int_one():
        return Literal("1", INTEGER8_TYPE)

    def tmp1():
        return Reference(arg1)

    def tmp2():
        return Reference(tmp_symbol)

    # Unary Operation
    oper = UnaryOperation.Operator.SIN
    unaryoperation = UnaryOperation.create(oper, tmp2())

    # Binary Operation
    oper = BinaryOperation.Operator.ADD
    binaryoperation = BinaryOperation.create(oper, one(), unaryoperation)

    # Nary Operation
    oper = NaryOperation.Operator.MAX
    naryoperation = NaryOperation.create(oper, [tmp1(), tmp2(), one()])

    # Array reference using a range
    lbound = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                    Reference(array), int_one())
    ubound = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                    Reference(array), int_one())
    my_range = Range.create(lbound, ubound)
    tmparray = ArrayReference.create(array, [my_range])

    # Assignments
    assign1 = Assignment.create(tmp1(), zero())
    assign2 = Assignment.create(tmp2(), zero())
    assign3 = Assignment.create(tmp2(), binaryoperation)
    assign4 = Assignment.create(tmp1(), tmp2())
    assign5 = Assignment.create(tmp1(), naryoperation)
    assign6 = Assignment.create(tmparray, two())

    # Call
    call = Call.create(routine_symbol, [tmp1(), binaryoperation.copy()])

    # If statement
    if_condition = BinaryOperation.create(BinaryOperation.Operator.GT, tmp1(),
                                          zero())
    ifblock = IfBlock.create(if_condition, [assign3, assign4])

    # Loop
    loop = Loop.create(index_symbol, int_zero(), int_one(), int_one(),
                       [ifblock])

    # KernelSchedule
    kernel_schedule = KernelSchedule.create(
        "work", symbol_table, [assign1, call, assign2, loop, assign5, assign6])

    # Container
    container_symbol_table = SymbolTable()
    container = Container.create("CONTAINER", container_symbol_table,
                                 [kernel_schedule])

    # Import data from another container
    external_container = ContainerSymbol("some_mod")
    container_symbol_table.add(external_container)
    external_var = DataSymbol("some_var",
                              INTEGER_TYPE,
                              interface=GlobalInterface(external_container))
    container_symbol_table.add(external_var)
    routine_symbol.interface = GlobalInterface(external_container)
    container_symbol_table.add(routine_symbol)
    return container
コード例 #14
0
    def create(cls, children, symbol_table, ast=None, options=None):
        '''
        Creates a new (sub-class of a) PSyData node with the supplied
        'children' nodes as its children. The symbols used by the PSyData API
        are added to the supplied symbol table. This is a class method so that
        it acts as a factory for the various sub-classes of PSyDataNode.

        :param children: the PSyIR nodes that will become children of the \
            new PSyData node.
        :type children: list of :py:class:`psyclone.psyir.nodes.Node`
        :param symbol_table: the associated SymbolTable to which symbols \
            must be added.
        :type symbol_table: :py:class:`psyclone.psyir.symbols.SymbolTable`
        :parent ast: reference to fparser2 parse tree for the routine being \
            instrumented with PSyData calls.
        :type ast: :py:class:`fparser.two.Fortran2003.Base`
        :param options: a dictionary with options for transformations.
        :type options: dictionary of string:values or None
        :param str options[prefix"]: a prefix to use for the PSyData module \
            name (``prefix_psy_data_mod``) and the PSyDataType \
            (``prefix_PSyDataType``) - a "_" will be added automatically. \
            It defaults to "", which means the module name used will just be \
            ``psy_data_mod``, and the data type ``PSyDataType``.
        :param (str,str) options["region_name"]: an optional name to use for \
            this PSyDataNode, provided as a 2-tuple containing a module name \
            followed by a local name. The pair of strings should uniquely \
             identify a region unless aggregate information is required \
            (and is supported by the runtime library).

        :raises TypeError: if the supplied children or symbol table are not \
            of the correct type.

        '''
        if not isinstance(children, list):
            raise TypeError("Error in PSyDataNode.create(). The 'children' "
                            "argument must be a list (of PSyIR nodes) but got "
                            "'{0}'".format(type(children).__name__))
        if children and not all(isinstance(child, Node) for child in children):
            raise TypeError(
                "Error in PSyDataNode.create(). The 'children' argument must "
                "be a list of PSyIR nodes but it contains: {0}".format(
                    [type(child).__name__ for child in children]))
        if not isinstance(symbol_table, SymbolTable):
            raise TypeError(
                "Error in PSyDataNode.create(). The 'symbol_table' argument "
                "must be an instance of psyir.symbols.SymbolTable but got "
                "'{0}'.".format(type(symbol_table).__name__))

        data_node = cls(ast=ast, options=options)

        # Ensure that we have a container symbol for the API access
        try:
            csym = symbol_table.lookup_with_tag(data_node.fortran_module)
        except KeyError:
            # The tag doesn't exist which means that we haven't already added
            # this Container as part of a PSyData transformation.
            csym = ContainerSymbol(data_node.fortran_module)
            symbol_table.add(csym, tag=data_node.fortran_module)

        # A PSyData node always contains a Schedule
        # TODO 435 we can probably get rid of _insert_schedule() once we
        # do away with the ast argument?
        # pylint: disable=protected-access
        sched = data_node._insert_schedule(children=children, ast=ast)
        data_node.addchild(sched)

        # The use statement that will be inserted by the update() method. Any
        # use of a module of the same name that doesn't match this will result
        # in a NotImplementedError at code-generation time.
        # TODO #435 remove this when removing the update() method
        data_node.use_stmt = "use {0}, only: ".format(
            data_node.fortran_module) + ", ".join(symbol.name for symbol in
                                                  data_node.imported_symbols)
        # Add the symbols that will be imported from the module. Use the
        # PSyData names as tags to ensure we don't attempt to add them more
        # than once if multiple transformations are applied.
        for sym in data_node.imported_symbols:
            symbol_table.symbol_from_tag(sym.name, symbol_type=sym.symbol_type,
                                         interface=GlobalInterface(csym),
                                         datatype=DeferredType())

        # Store the name of the PSyData variable that is used for this
        # PSyDataNode. This allows the variable name to be shown in str
        # (and also, calling create_name in gen() would result in the name
        # being changed every time gen() is called).
        data_node._var_name = symbol_table.next_available_name(
            data_node._psy_data_symbol_with_prefix)
        psydata_type = UnknownFortranType(
            "type({0}), save, target :: {1}".format(data_node.type_name,
                                                    data_node._var_name))
        symbol_table.new_symbol(data_node._var_name, symbol_type=DataSymbol,
                                datatype=psydata_type)
        return data_node
コード例 #15
0
def create_psyir_tree():
    ''' Create an example PSyIR Tree.

    :returns: an example PSyIR tree.
    :rtype: :py:class:`psyclone.psyir.nodes.Container`

    '''
    # Symbol table, symbols and scalar datatypes
    symbol_table = SymbolTable()
    arg1 = symbol_table.new_symbol(symbol_type=DataSymbol,
                                   datatype=REAL_TYPE,
                                   interface=ArgumentInterface(
                                       ArgumentInterface.Access.READWRITE))
    symbol_table.specify_argument_list([arg1])
    tmp_symbol = symbol_table.new_symbol(symbol_type=DataSymbol,
                                         datatype=REAL_DOUBLE_TYPE)
    index_symbol = symbol_table.new_symbol(root_name="i",
                                           symbol_type=DataSymbol,
                                           datatype=INTEGER4_TYPE)
    real_kind = symbol_table.new_symbol(root_name="RKIND",
                                        symbol_type=DataSymbol,
                                        datatype=INTEGER_TYPE,
                                        constant_value=8)
    routine_symbol = RoutineSymbol("my_sub")

    # Array using precision defined by another symbol
    scalar_type = ScalarType(ScalarType.Intrinsic.REAL, real_kind)
    array = symbol_table.new_symbol(root_name="a",
                                    symbol_type=DataSymbol,
                                    datatype=ArrayType(scalar_type, [10]))

    # Nodes which do not have Nodes as children and (some) predefined
    # scalar datatypes
    # TODO: Issue #1136 looks at how to avoid all of the _x versions
    zero_1 = Literal("0.0", REAL_TYPE)
    zero_2 = Literal("0.0", REAL_TYPE)
    zero_3 = Literal("0.0", REAL_TYPE)
    one_1 = Literal("1.0", REAL4_TYPE)
    one_2 = Literal("1.0", REAL4_TYPE)
    one_3 = Literal("1.0", REAL4_TYPE)
    two = Literal("2.0", scalar_type)
    int_zero = Literal("0", INTEGER_SINGLE_TYPE)
    int_one_1 = Literal("1", INTEGER8_TYPE)
    int_one_2 = Literal("1", INTEGER8_TYPE)
    int_one_3 = Literal("1", INTEGER8_TYPE)
    int_one_4 = Literal("1", INTEGER8_TYPE)
    tmp1_1 = Reference(arg1)
    tmp1_2 = Reference(arg1)
    tmp1_3 = Reference(arg1)
    tmp1_4 = Reference(arg1)
    tmp1_5 = Reference(arg1)
    tmp1_6 = Reference(arg1)
    tmp2_1 = Reference(tmp_symbol)
    tmp2_2 = Reference(tmp_symbol)
    tmp2_3 = Reference(tmp_symbol)
    tmp2_4 = Reference(tmp_symbol)
    tmp2_5 = Reference(tmp_symbol)
    tmp2_6 = Reference(tmp_symbol)

    # Unary Operation
    oper = UnaryOperation.Operator.SIN
    unaryoperation_1 = UnaryOperation.create(oper, tmp2_1)
    unaryoperation_2 = UnaryOperation.create(oper, tmp2_2)

    # Binary Operation
    oper = BinaryOperation.Operator.ADD
    binaryoperation_1 = BinaryOperation.create(oper, one_1, unaryoperation_1)
    binaryoperation_2 = BinaryOperation.create(oper, one_2, unaryoperation_2)

    # Nary Operation
    oper = NaryOperation.Operator.MAX
    naryoperation = NaryOperation.create(oper, [tmp1_1, tmp2_3, one_3])

    # Array reference using a range
    lbound = BinaryOperation.create(BinaryOperation.Operator.LBOUND,
                                    Reference(array), int_one_1)
    ubound = BinaryOperation.create(BinaryOperation.Operator.UBOUND,
                                    Reference(array), int_one_2)
    my_range = Range.create(lbound, ubound)
    tmparray = ArrayReference.create(array, [my_range])

    # Assignments
    assign1 = Assignment.create(tmp1_2, zero_1)
    assign2 = Assignment.create(tmp2_4, zero_2)
    assign3 = Assignment.create(tmp2_5, binaryoperation_1)
    assign4 = Assignment.create(tmp1_3, tmp2_6)
    assign5 = Assignment.create(tmp1_4, naryoperation)
    assign6 = Assignment.create(tmparray, two)

    # Call
    call = Call.create(routine_symbol, [tmp1_5, binaryoperation_2])

    # If statement
    if_condition = BinaryOperation.create(BinaryOperation.Operator.GT, tmp1_6,
                                          zero_3)
    ifblock = IfBlock.create(if_condition, [assign3, assign4])

    # Loop
    loop = Loop.create(index_symbol, int_zero, int_one_3, int_one_4, [ifblock])

    # KernelSchedule
    kernel_schedule = KernelSchedule.create(
        "work", symbol_table, [assign1, call, assign2, loop, assign5, assign6])

    # Container
    container_symbol_table = SymbolTable()
    container = Container.create("CONTAINER", container_symbol_table,
                                 [kernel_schedule])

    # Import data from another container
    external_container = ContainerSymbol("some_mod")
    container_symbol_table.add(external_container)
    external_var = DataSymbol("some_var",
                              INTEGER_TYPE,
                              interface=GlobalInterface(external_container))
    container_symbol_table.add(external_var)
    routine_symbol.interface = GlobalInterface(external_container)
    container_symbol_table.add(routine_symbol)
    return container
コード例 #16
0
# KernelSchedule
KERNEL_SCHEDULE = KernelSchedule.create(
    "work", SYMBOL_TABLE, [CALL, ASSIGN2, LOOP, ASSIGN5, ASSIGN6])

# Container
CONTAINER_SYMBOL_TABLE = SymbolTable()
CONTAINER = Container.create("CONTAINER", CONTAINER_SYMBOL_TABLE,
                             [KERNEL_SCHEDULE])

# Import data from another container
EXTERNAL_CONTAINER = ContainerSymbol("some_mod")
CONTAINER_SYMBOL_TABLE.add(EXTERNAL_CONTAINER)
EXTERNAL_VAR = DataSymbol("some_var",
                          INTEGER_TYPE,
                          interface=GlobalInterface(EXTERNAL_CONTAINER))
CONTAINER_SYMBOL_TABLE.add(EXTERNAL_VAR)
ROUTINE_SYMBOL.interface = GlobalInterface(EXTERNAL_CONTAINER)
CONTAINER_SYMBOL_TABLE.add(ROUTINE_SYMBOL)

# Write out the code as Fortran
WRITER = FortranWriter()
RESULT = WRITER(CONTAINER)
print(RESULT)

# Write out the code as C. At the moment NaryOperator, KernelSchedule
# and Container are not supported in the C backend so the full example
# can't be output.
WRITER = CWriter()
RESULT = WRITER(LOOP)
print(RESULT)