def map_Comment(self, node): stripped_comment_line = node.content.strip() begin_tag_match = self.begin_tag_re.match(stripped_comment_line) end_tag_match = self.end_tag_re.match(stripped_comment_line) faulty_loopy_pragma_match = self.faulty_loopy_pragma.match( stripped_comment_line) if begin_tag_match: tag = begin_tag_match.group(1) if tag in self.instruction_tags: raise TranslationError("nested begin tag for tag '%s'" % tag) self.instruction_tags.append(tag) elif end_tag_match: tag = end_tag_match.group(1) if tag not in self.instruction_tags: raise TranslationError( "end tag without begin tag for tag '%s'" % tag) self.instruction_tags.remove(tag) elif faulty_loopy_pragma_match is not None: from warnings import warn warn("The comment line '%s' was not recognized as a loopy directive" % stripped_comment_line)
def map_EndIfThen(self, node): if not self.block_nest: raise TranslationError("no if block started at end do") if self.block_nest.pop() != "if": raise TranslationError("mismatched end if") self.conditions.pop()
def map_EndSubroutine(self, node): if not self.block_nest: raise TranslationError("no subroutine started at this point") if self.block_nest.pop() != "sub": raise TranslationError("mismatched end subroutine") return []
def map_subscript(self, expr): from pymbolic.primitives import Variable assert isinstance(expr.aggregate, Variable) name = expr.aggregate.name dims = self.scope.dim_map.get(name) if dims is None: return IdentityMapper.map_subscript(self, expr) subscript = expr.index if not isinstance(subscript, tuple): subscript = (subscript,) subscript = list(subscript) if len(dims) != len(subscript): raise TranslationError("inconsistent number of indices " "to '%s'" % name) for i in range(len(dims)): if len(dims[i]) == 2: # has a base index subscript[i] -= dims[i][0] elif len(dims[i]) == 1: # base index is 1 implicitly subscript[i] -= 1 return expr.aggregate[self.rec(tuple(subscript))]
def parse_postfix(self, pstate, min_precedence, left_exp): from pymbolic.parser import ( _PREC_CALL, _PREC_COMPARISON, _openpar, _PREC_LOGICAL_OR, _PREC_LOGICAL_AND) from pymbolic.primitives import ( Comparison, LogicalAnd, LogicalOr) next_tag = pstate.next_tag() if next_tag is _openpar and _PREC_CALL > min_precedence: raise TranslationError("parenthesis operator only works on names") elif next_tag in self.COMP_MAP and _PREC_COMPARISON > min_precedence: pstate.advance() left_exp = Comparison( left_exp, self.COMP_MAP[next_tag], self.parse_expression(pstate, _PREC_COMPARISON)) did_something = True elif next_tag is _and and _PREC_LOGICAL_AND > min_precedence: pstate.advance() left_exp = LogicalAnd((left_exp, self.parse_expression(pstate, _PREC_LOGICAL_AND))) did_something = True elif next_tag is _or and _PREC_LOGICAL_OR > min_precedence: pstate.advance() left_exp = LogicalOr((left_exp, self.parse_expression(pstate, _PREC_LOGICAL_OR))) did_something = True else: left_exp, did_something = ExpressionParserBase.parse_postfix( self, pstate, min_precedence, left_exp) return left_exp, did_something
def parse_postfix(self, pstate, min_precedence, left_exp): from pymbolic.parser import (_PREC_CALL, _PREC_COMPARISON, _openpar, _PREC_LOGICAL_OR, _PREC_LOGICAL_AND) from pymbolic.primitives import (Comparison, LogicalAnd, LogicalOr) next_tag = pstate.next_tag() if next_tag is _openpar and _PREC_CALL > min_precedence: raise TranslationError("parenthesis operator only works on names") elif next_tag in self.COMP_MAP and _PREC_COMPARISON > min_precedence: pstate.advance() left_exp = Comparison( left_exp, self.COMP_MAP[next_tag], self.parse_expression(pstate, _PREC_COMPARISON)) did_something = True elif next_tag is _and and _PREC_LOGICAL_AND > min_precedence: pstate.advance() left_exp = LogicalAnd( (left_exp, self.parse_expression(pstate, _PREC_LOGICAL_AND))) did_something = True elif next_tag is _or and _PREC_LOGICAL_OR > min_precedence: pstate.advance() left_exp = LogicalOr( (left_exp, self.parse_expression(pstate, _PREC_LOGICAL_OR))) did_something = True else: left_exp, did_something = ExpressionParserBase.parse_postfix( self, pstate, min_precedence, left_exp) if isinstance(left_exp, tuple) and min_precedence < self._PREC_FUNC_ARGS: # this must be a complex literal if len(left_exp) != 2: raise TranslationError("complex literals must have " "two entries") r, i = left_exp dtype = (r.dtype.type(0) + i.dtype.type(0)) if dtype == np.float32: dtype = np.complex64 else: dtype = np.complex128 left_exp = dtype(float(r) + float(i) * 1j) return left_exp, did_something
def get_type(self, name, none_ok=False): try: return self.type_map[name] except KeyError: if self.implicit_types is None: if none_ok: return None raise TranslationError( "no type for '%s' found in 'implict none' routine" % name) return self.implicit_types.get(name[0], np.dtype(np.int32))
def map_Implicit(self, node): scope = self.scope_stack[-1] if not node.items: assert not scope.implicit_types scope.implicit_types = None for stmt, specs in node.items: if scope.implict_types is None: raise TranslationError("implicit decl not allowed after " "'implicit none'") tp = self.dtype_from_stmt(stmt) for start, end in specs: for char_code in range(ord(start), ord(end)+1): scope.implicit_types[chr(char_code)] = tp return []
def tuple_to_complex_literal(expr): if len(expr) != 2: raise TranslationError("complex literals must have " "two entries") r, i = expr r = np.array(r)[()] i = np.array(i)[()] dtype = (r.dtype.type(0) + i.dtype.type(0)) if dtype == np.float32: dtype = np.complex64 else: dtype = np.complex128 return dtype(float(r) + float(i)*1j)
def map_Assignment(self, node): scope = self.scope_stack[-1] lhs = scope.process_expression_for_loopy( self.parse_expr(node, node.variable)) from pymbolic.primitives import Subscript, Call if isinstance(lhs, Call): raise TranslationError("function call (to '%s') on left hand side of" "assignment--check for misspelled variable name" % lhs) elif isinstance(lhs, Subscript): lhs_name = lhs.aggregate.name else: lhs_name = lhs.name scope.use_name(lhs_name) rhs = scope.process_expression_for_loopy(self.parse_expr(node, node.expr)) self.add_expression_instruction(lhs, rhs)
def get_loopy_shape(self, name): dims = self.dim_map.get(name, ()) shape = [] for i, dim in enumerate(dims): if len(dim) == 1: if isinstance(dim[0], Wildcard): shape.append(None) else: shape.append(dim[0]) elif len(dim) == 2: if isinstance(dim[0], Wildcard): shape.append(None) else: shape.append(dim[1]-dim[0]+1) else: raise TranslationError("dimension axis %d " "of '%s' not understood: %s" % (i, name, dim)) return tuple(shape)
def map_EndDo(self, node): if not self.block_nest: raise TranslationError("no do loop started at end do") if self.block_nest.pop() != "do": raise TranslationError("mismatched end do")
def map_Do(self, node): scope = self.scope_stack[-1] if not node.loopcontrol: raise NotImplementedError("unbounded do loop") loop_var, loop_bounds = node.loopcontrol.split("=") loop_var = loop_var.strip() iname_dtype = scope.get_type(loop_var) if self.index_dtype is None: self.index_dtype = iname_dtype else: if self.index_dtype != iname_dtype: raise LoopyError("type of '%s' (%s) does not agree with prior " "index type (%s)" % (loop_var, iname_dtype, self.index_dtype)) scope.use_name(loop_var) loop_bounds = self.parse_expr( node, loop_bounds, min_precedence=self.expr_parser._PREC_FUNC_ARGS) if len(loop_bounds) == 2: start, stop = loop_bounds step = 1 elif len(loop_bounds) == 3: start, stop, step = loop_bounds else: raise RuntimeError("loop bounds not understood: %s" % node.loopcontrol) if step != 1: raise NotImplementedError( "do loops with non-unit stride") if not isinstance(step, int): raise TranslationError( "non-constant steps not supported: %s" % step) from loopy.symbolic import get_dependencies loop_bound_deps = ( get_dependencies(start) | get_dependencies(stop) | get_dependencies(step)) # {{{ find a usable loopy-side loop name loopy_loop_var = loop_var loop_var_suffix = None while True: already_used = False for iset in scope.index_sets: if loopy_loop_var in iset.get_var_dict(dim_type.set): already_used = True break if not already_used: break if loop_var_suffix is None: loop_var_suffix = 0 loop_var_suffix += 1 loopy_loop_var = loop_var + "_%d" % loop_var_suffix loopy_loop_var = intern(loopy_loop_var) # }}} space = isl.Space.create_from_names(isl.DEFAULT_CONTEXT, set=[loopy_loop_var], params=list(loop_bound_deps)) from loopy.isl_helpers import iname_rel_aff from loopy.symbolic import aff_from_expr index_set = ( isl.BasicSet.universe(space) .add_constraint( isl.Constraint.inequality_from_aff( iname_rel_aff(space, loopy_loop_var, ">=", aff_from_expr(space, 0)))) .add_constraint( isl.Constraint.inequality_from_aff( iname_rel_aff(space, loopy_loop_var, "<=", aff_from_expr(space, stop-start))))) from pymbolic import var scope.active_iname_aliases[loop_var] = \ var(loopy_loop_var) + start scope.active_loopy_inames.add(loopy_loop_var) scope.index_sets.append(index_set) self.block_nest.append("do") for c in node.content: self.rec(c) del scope.active_iname_aliases[loop_var] scope.active_loopy_inames.remove(loopy_loop_var)
def map_subscript(self, expr): from pymbolic.primitives import Variable assert isinstance(expr.aggregate, Variable) name = expr.aggregate.name dims = self.scope.dim_map.get(name) if dims is None: return IdentityMapper.map_subscript(self, expr) subscript = expr.index if not isinstance(subscript, tuple): subscript = (subscript, ) if len(dims) != len(subscript): raise TranslationError("inconsistent number of indices " "to '%s'" % name) new_subscript = [] for i in range(len(dims)): if len(dims[i]) == 2: # has an explicit base index base_index, end_index = dims[i] elif len(dims[i]) == 1: base_index = 1 end_index, = dims[i] sub_i = subscript[i] if isinstance(sub_i, Slice): start = sub_i.start if start is None: start = base_index step = sub_i.step if step is None: step = 1 stop = sub_i.stop if stop is None: stop = end_index if step == 1: sub_i = Slice(( start - base_index, # FIXME This is only correct for unit strides stop - base_index + 1, step)) elif step == -1: sub_i = Slice(( start - base_index, # FIXME This is only correct for unit strides stop - base_index - 1, step)) else: # FIXME raise NotImplementedError("Fortran slice processing for " "non-unit strides") else: sub_i = sub_i - base_index new_subscript.append(sub_i) return expr.aggregate[self.rec(tuple(new_subscript))]