Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
:returns: the Fortran code as a string.
:rtype: str
:raises VisitorError: if an unexpected Unary op is encountered.
'''
content = self._visit(node.children[0])
try:
fort_oper = get_fortran_operator(node.operator)
if is_fortran_intrinsic(fort_oper):
# This is a unary intrinsic function.
return "{0}({1})".format(fort_oper, content)
return "{0}{1}".format(fort_oper, content)
except KeyError:
raise VisitorError("Unexpected unary op '{0}'.".format(
node.operator))
:type node: :py:class:`psyclone.psyir.nodes.NaryOperation`
:returns: the Fortran code as a string.
:rtype: str
:raises VisitorError: if an unexpected N-ary operator is found.
'''
arg_list = []
for child in node.children:
arg_list.append(self._visit(child))
try:
fort_oper = get_fortran_operator(node.operator)
return "{0}({1})".format(fort_oper, ", ".join(arg_list))
except KeyError:
raise VisitorError("Unexpected N-ary op '{0}'".
format(node.operator))
if isinstance(child, Reference):
dims.append("0")
elif isinstance(child, BinaryOperation):
if isinstance(child.children[0], Reference) and \
isinstance(child.children[1], Literal):
if child.operator == BinaryOperation.Operator.SUB:
dims.append("-"+child.children[1].value)
elif child.operator == BinaryOperation.Operator.ADD:
dims.append(child.children[1].value)
else:
raise VisitorError(
"gen_stencil unsupported stencil operator found "
"'{0}'. Expecting '+' or '-'."
"".format(child.operator.name))
else:
raise VisitorError(
"gen_stencil unsupported stencil index found '{0}'."
"".format(str(child)))
else:
raise VisitorError(
"gen_stencil unsupported (non-stencil) index found '{0}'."
"".format(str(child)))
return "[{0}]".format(", ".join(dims))
:raises VisitorError: if one of the symbols is a RoutineSymbol \
and it does not have a GlobalInterface interface as this \
is not supported by this backend.
:raises VisitorError: if args_allowed is False and one or more \
argument declarations exist in symbol_table.
:raises VisitorError: if any symbols representing variables (i.e. \
not kind parameters) without an explicit declaration or 'use' \
are encountered.
'''
declarations = ""
if not all([isinstance(symbol.interface, GlobalInterface)
for symbol in symbol_table.symbols
if isinstance(symbol, RoutineSymbol)]):
raise VisitorError(
"Routine symbols without a global interface are unsupported "
"by the Fortran back-end.")
# Does the symbol table contain any symbols with a deferred
# interface (i.e. we don't know how they are brought into scope) that
# are not KIND parameters?
unresolved_datasymbols = symbol_table.get_unresolved_datasymbols(
ignore_precision=True)
if unresolved_datasymbols:
symbols_txt = ", ".join(
["'" + sym + "'" for sym in unresolved_datasymbols])
raise VisitorError(
"The following symbols are not explicitly declared or imported"
" from a module (in the local scope) and are not KIND "
"parameters: {0}".format(symbols_txt))
# We need brackets to enforce precedence
return "({0} {1} {2})".format(lhs, fort_oper, rhs)
if precedence(fort_oper) == precedence(parent_fort_oper):
# We still may need to enforce precedence
if (isinstance(parent, UnaryOperation) or
(isinstance(parent, BinaryOperation) and
parent.children[1] == node)):
# We need brackets to enforce precedence
# as a) a unary operator is performed
# before a binary operator and b) floating
# point operations are not actually
# associative due to rounding errors.
return "({0} {1} {2})".format(lhs, fort_oper, rhs)
return "{0} {1} {2}".format(lhs, fort_oper, rhs)
except KeyError:
raise VisitorError("Unexpected binary op '{0}'."
"".format(node.operator))
if not (len(loop_content) == 1 and
isinstance(loop_content[0], NemoLoop)):
raise VisitorError("Child of loop should be a single loop.")
# Check second loop has a single loop as a child.
loop_content = loop_content[0].loop_body.children
if not (len(loop_content) == 1 and
isinstance(loop_content[0], NemoLoop)):
raise VisitorError(
"Child of child of loop should be a single loop.")
# Check third loop has a single NemoKern as a child.
loop_content = loop_content[0].loop_body.children
if not (len(loop_content) == 1 and
isinstance(loop_content[0], NemoKern)):
raise VisitorError(
"Child of child of child of loop should be a NemoKern.")
# The interval values are hardcoded for the moment (see #470).
result = ("{0}interval = make_interval(Interval.Start, Interval.End, "
"0, 0)\n".format(self._nindent))
result += ("{0}body_ast = make_ast([\n".format(self._nindent))
self._depth += 1
result += self.nemokern_node(loop_content[0])
self._depth -= 1
# Remove the trailing comma if there is one as this is the
# last entry in make_ast.
result = result.rstrip(",\n") + "\n"
result += "{0}])\n".format(self._nindent)
# For the moment there is a hard coded assumption that the
# vertical looping is in the forward (1..n) direction (see
# #470).
a literal (as only - is currently supported).
'''
# Currently only '-' is supported in the SIR mapping.
unary_operators = {
UnaryOperation.Operator.MINUS: '-'}
try:
oper = unary_operators[node.operator]
except KeyError:
raise VisitorError(
"Method unaryoperation_node in class SIRWriter, unsupported "
"operator '{0}' found.".format(str(node.operator)))
# Currently only '-' is supported in the SIR mapping.
if not (len(node.children) == 1 and
isinstance(node.children[0], Literal)):
raise VisitorError(
"Currently, unary operators can only be applied to literals.")
literal = node.children[0]
if literal.datatype not in [DataType.REAL, DataType.INTEGER]:
# The '-' operator can only be applied to REAL and INTEGER
# datatypes.
raise VisitorError(
"PSyIR type '{0}' does not work with the '-' operator."
"".format(str(literal.datatype)))
result = literal.value
datatype = TYPE_MAP_TO_SIR[literal.datatype]
return ("{0}make_literal_access_expr(\"{1}{2}\", {3})"
"".format(self._nindent, oper, result, datatype))
access and return it in the form expected by the SIR as a
string. Raise an exception if the array access is not a recognised
stencil access.
:param node: an array access.
:type node: :py:class:`psyclone.psyir.nodes.Array`
:returns: the SIR stencil access format for the array access.
:rtype: str
:raises VisitorError: if the node is not the expected type or the \
array access is not in a recognised stencil form.
'''
if not isinstance(node, Array):
raise VisitorError(
"gen_stencil expected an Array as input but found '{0}'."
"".format(type(node)))
dims = []
for child in node.children:
if isinstance(child, Reference):
dims.append("0")
elif isinstance(child, BinaryOperation):
if isinstance(child.children[0], Reference) and \
isinstance(child.children[1], Literal):
if child.operator == BinaryOperation.Operator.SUB:
dims.append("-"+child.children[1].value)
elif child.operator == BinaryOperation.Operator.ADD:
dims.append(child.children[1].value)
else:
raise VisitorError(
"gen_stencil unsupported stencil operator found "
precision = symbol.datatype.precision
if isinstance(precision, int):
if fortrantype not in ['real', 'integer', 'logical']:
raise VisitorError("Explicit precision not supported for datatype "
"'{0}' in symbol '{1}' in Fortran backend."
"".format(fortrantype, symbol.name))
if fortrantype == 'real' and precision not in [4, 8, 16]:
raise VisitorError(
"Datatype 'real' in symbol '{0}' supports fixed precision of "
"[4, 8, 16] but found '{1}'.".format(symbol.name,
precision))
if fortrantype in ['integer', 'logical'] and precision not in \
[1, 2, 4, 8, 16]:
raise VisitorError(
"Datatype '{0}' in symbol '{1}' supports fixed precision of "
"[1, 2, 4, 8, 16] but found '{2}'."
"".format(fortrantype, symbol.name, precision))
# Precision has an an explicit size. Use the "type*size" Fortran
# extension for simplicity. We could have used
# type(kind=selected_int|real_kind(size)) or, for Fortran 2008,
# ISO_FORTRAN_ENV; type(type64) :: MyType.
return "{0}*{1}".format(fortrantype, precision)
if isinstance(precision, ScalarType.Precision):
# The precision information is not absolute so is either
# machine specific or is specified via the compiler. Fortran
# only distinguishes relative precision for single and double
# precision reals.
if fortrantype.lower() == "real" and \
precision == ScalarType.Precision.DOUBLE: