Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
# Create if-body as second child
ifbody = Schedule(parent=ifblock)
ifbody.ast = node.content[start_idx + 1]
ifbody.ast_end = node.content[end_idx - 1]
newifblock.addchild(ifbody)
self.process_nodes(parent=ifbody,
nodes=node.content[start_idx + 1:end_idx])
currentparent = newifblock
elif isinstance(clause, Fortran2003.Else_Stmt):
if not idx == num_clauses - 1:
raise InternalError(
"Else clause should only be found next to last "
"clause, but found {0}".format(node.content))
elsebody = Schedule(parent=currentparent)
currentparent.addchild(elsebody)
elsebody.ast = node.content[start_idx]
elsebody.ast_end = node.content[end_idx]
self.process_nodes(parent=elsebody,
nodes=node.content[start_idx + 1:end_idx])
else:
raise InternalError(
"Only fparser2 If_Then_Stmt, Else_If_Stmt and Else_Stmt "
"are expected, but found {0}.".format(clause))
return ifblock
for node in node_list:
# Check that ExtractNode is not inserted between a Kernel or
# a BuiltIn call and its parent Loop.
if isinstance(node, (Kern, BuiltIn)) and \
isinstance(node.parent.parent, Loop):
raise TransformationError(
"Error in {0}: Extraction of a Kernel or a Built-in "
"call without its parent Loop is not allowed."
.format(str(self.name)))
# Check that ExtractNode is not inserted between a Loop and its
# parent Directive when optimisations are applied, as this may
# result in including the end Directive for extraction but
# not the beginning.
if isinstance(node, Loop) and isinstance(node.parent, Schedule) \
and isinstance(node.parent.parent, Directive):
raise TransformationError(
"Error in {0}: Extraction of a Loop without its parent "
"Directive is not allowed.".format(str(self.name)))
# Check that ExtractNode is not inserted within a thread
# parallel region when optimisations are applied. For instance,
# this may be between an orphaned Directive (e.g. OMPDoDirective,
# ACCLoopDirective) and its ancestor Directive (e.g. ACC or OMP
# Parallel Directive) or within an OMPParallelDoDirective.
if node.ancestor((OMPParallelDirective, ACCParallelDirective)):
raise TransformationError(
"Error in {0}: Extraction of Nodes enclosed within "
"a thread-parallel region is not allowed."
.format(str(self.name)))
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
# of the loops we've just created.
self._array_syntax_to_indexed(ifblock.children[0], loop_vars)
# Now construct the body of the IF using the body of the WHERE
sched = Schedule(parent=ifblock)
ifblock.addchild(sched)
if not was_single_stmt:
# Do we have an ELSE WHERE?
for idx, child in enumerate(node.content):
if isinstance(child, Fortran2003.Elsewhere_Stmt):
self.process_nodes(sched, node.content[1:idx])
self._array_syntax_to_indexed(sched, loop_vars)
# Add an else clause to the IF block for the ELSEWHERE
# clause
sched = Schedule(parent=ifblock)
ifblock.addchild(sched)
self.process_nodes(sched, node.content[idx+1:-1])
break
else:
# No elsewhere clause was found
self.process_nodes(sched, node.content[1:-1])
else:
# We only had a single-statement WHERE
self.process_nodes(sched, node.items[1:])
# Convert all uses of array syntax to indexed accesses
self._array_syntax_to_indexed(sched, loop_vars)
# Return the top-level loop generated by this handler
return root_loop
elsebody = Schedule(parent=currentparent)
currentparent.addchild(elsebody)
newifblock = IfBlock(parent=elsebody,
annotations=['was_elseif'])
elsebody.addchild(newifblock)
# Keep pointer to fpaser2 AST
elsebody.ast = node.content[start_idx]
newifblock.ast = node.content[start_idx]
# Create condition as first child
self.process_nodes(parent=newifblock,
nodes=[clause.items[0]])
# Create if-body as second child
ifbody = Schedule(parent=ifblock)
ifbody.ast = node.content[start_idx + 1]
ifbody.ast_end = node.content[end_idx - 1]
newifblock.addchild(ifbody)
self.process_nodes(parent=ifbody,
nodes=node.content[start_idx + 1:end_idx])
currentparent = newifblock
elif isinstance(clause, Fortran2003.Else_Stmt):
if not idx == num_clauses - 1:
raise InternalError(
"Else clause should only be found next to last "
"clause, but found {0}".format(node.content))
elsebody = Schedule(parent=currentparent)
currentparent.addchild(elsebody)
elsebody.ast = node.content[start_idx]
entity_shape[idx] = ArrayType.Extent.ATTRIBUTE
elif not isinstance(extent, ArrayType.Extent) and \
allocatable:
# We have an allocatable array with a defined extent.
# This is invalid Fortran.
raise InternalError(
"Invalid Fortran: '{0}'. An array with defined "
"extent cannot have the ALLOCATABLE attribute.".
format(str(decl)))
if initialisation:
if has_constant_value:
# If it is a parameter parse its initialization into
# a dummy Assignment inside a Schedule which temporally
# hijacks the parent's node symbol table
tmp_sch = Schedule(symbol_table=parent.symbol_table)
dummynode = Assignment(parent=tmp_sch)
tmp_sch.addchild(dummynode)
expr = initialisation.items[1]
self.process_nodes(parent=dummynode, nodes=[expr])
ct_expr = dummynode.children[0]
else:
raise NotImplementedError(
"Could not process {0}. Initialisations on the"
" declaration statements are only supported for "
"parameter declarations.".format(decl.items))
if char_len is not None:
raise NotImplementedError(
"Could not process {0}. Character length "
"specifications are not supported."
"".format(decl.items))
:type fp2_nodes: list of :py:class:`fparser.two.utils.Base`
:returns: a CodeBlock instance.
:rtype: :py:class:`psyclone.CodeBlock`
'''
if not fp2_nodes:
return None
# Determine whether this code block is a statement or an
# expression. Statements always have a `Schedule` as parent
# and expressions do not. The only unknown at this point are
# directives whose structure are in discussion. Therefore, for
# the moment, an exception is raised if a directive is found
# as a parent.
if isinstance(parent, Schedule):
structure = CodeBlock.Structure.STATEMENT
elif isinstance(parent, Directive):
raise InternalError(
"Fparser2Reader:nodes_to_code_block: A CodeBlock with "
"a Directive as parent is not yet supported.")
else:
structure = CodeBlock.Structure.EXPRESSION
code_block = CodeBlock(fp2_nodes, structure, parent=parent)
parent.addchild(code_block)
del fp2_nodes[:]
return code_block
def abs_position(self):
'''
Find a Node's absolute position in the tree (starting with 0 if
it is the root). Needs to be computed dynamically from the
starting position (0) as its position may change.
:returns: absolute position of a Node in the tree
:rtype: int
:raises InternalError: if the absolute position cannot be found
'''
from psyclone.psyir.nodes import Schedule
if self.root == self and isinstance(self.root, Schedule):
return self.START_POSITION
found, position = self._find_position(self.root.children,
self.START_POSITION)
if not found:
raise InternalError("Error in search for Node position "
"in the tree")
return position
are not of the expected type.
'''
if not isinstance(var_name, str):
raise GenerationError(
"var_name argument in create method of Loop class "
"should be a string but found '{0}'."
"".format(type(var_name).__name__))
if not isinstance(children, list):
raise GenerationError(
"children argument in create method of Loop class "
"should be a list but found '{0}'."
"".format(type(children).__name__))
loop = Loop(variable_name=var_name)
schedule = Schedule(parent=loop, children=children)
loop.children = [start, stop, step, schedule]
for child in children:
child.parent = schedule
start.parent = loop
stop.parent = loop
step.parent = loop
return loop
start_idx = clause_indices[idx]
end_idx = clause_indices[idx+1]
clause = node.content[start_idx]
if isinstance(clause, (Fortran2003.If_Then_Stmt,
Fortran2003.Else_If_Stmt)):
# If it's an 'IF' clause just create an IfBlock, otherwise
# it is an 'ELSE' clause and it needs an IfBlock annotated
# with 'was_elseif' inside a Schedule.
newifblock = None
if isinstance(clause, Fortran2003.If_Then_Stmt):
ifblock = IfBlock(parent=currentparent)
ifblock.ast = node # Keep pointer to fpaser2 AST
newifblock = ifblock
else:
elsebody = Schedule(parent=currentparent)
currentparent.addchild(elsebody)
newifblock = IfBlock(parent=elsebody,
annotations=['was_elseif'])
elsebody.addchild(newifblock)
# Keep pointer to fpaser2 AST
elsebody.ast = node.content[start_idx]
newifblock.ast = node.content[start_idx]
# Create condition as first child
self.process_nodes(parent=newifblock,
nodes=[clause.items[0]])
# Create if-body as second child
ifbody = Schedule(parent=ifblock)
ifbody.ast = node.content[start_idx + 1]