def test_find_or_create_imported_symbol_2(): ''' Check that the _find_or_create_imported_symbol() method creates new symbols when appropriate. ''' # Create some suitable PSyIR from scratch symbol_table = SymbolTable() symbol_table.add(DataSymbol("tmp", REAL_TYPE)) kernel1 = KernelSchedule.create("mod_1", SymbolTable(), []) container = Container.create("container_name", symbol_table, [kernel1]) xvar = DataSymbol("x", REAL_TYPE) xref = Reference(xvar) assign = Assignment.create(xref, Literal("1.0", REAL_TYPE)) kernel1.addchild(assign) # We have no wildcard imports so there can be no symbol named 'undefined' with pytest.raises(SymbolError) as err: _ = _find_or_create_imported_symbol(assign, "undefined") assert "No Symbol found for name 'undefined'" in str(err.value) # We should be able to find the 'tmp' symbol in the parent Container sym = _find_or_create_imported_symbol(assign, "tmp") assert sym.datatype.intrinsic == ScalarType.Intrinsic.REAL # Add a wildcard import to the SymbolTable of the KernelSchedule new_container = ContainerSymbol("some_mod") new_container.wildcard_import = True kernel1.symbol_table.add(new_container) # Symbol not in any container but we do have wildcard imports so we # get a new symbol back new_symbol = _find_or_create_imported_symbol(assign, "undefined") assert new_symbol.name == "undefined" assert isinstance(new_symbol.interface, UnresolvedInterface) # pylint: disable=unidiomatic-typecheck assert type(new_symbol) == Symbol assert "undefined" not in container.symbol_table assert kernel1.symbol_table.lookup("undefined") is new_symbol
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)
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))
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
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
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))
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)
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
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)
constant_value=8) # Shorthand for a scalar type with REAL_KIND precision SCALAR_TYPE = ScalarType(ScalarType.Intrinsic.REAL, REAL_KIND) # 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)
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))
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
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
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
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, [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