Exemple #1
0
    def _update_name_to_var_shape(self, node):
        assert isinstance(node, gast.Assign)
        target_node = node.targets[0]
        value_node = node.value

        if isinstance(target_node, gast.Tuple):
            has_updated = False
            for idx, element in enumerate(target_node.elts):
                target_id = ast_to_source_code(element).strip()

                if isinstance(value_node, gast.Name):
                    if value_node.id in self.name_to_var_shape:
                        index_value_node = gast.Constant(value=idx, kind=None)
                        slice_index_node = gast.Index(value=index_value_node)
                        var_shape_node = self.name_to_var_shape[value_node.id]
                        sub_node = gast.Subscript(value=var_shape_node,
                                                  slice=slice_index_node,
                                                  ctx=gast.Load())
                        self.name_to_var_shape[target_id] = sub_node
                        has_updated = True
                if isinstance(value_node, gast.Attribute):
                    if self.is_var_shape(value_node):  # eg: x.shape
                        index_value_node = gast.Constant(value=idx, kind=None)
                        slice_index_node = gast.Index(value=index_value_node)
                        sub_node = gast.Subscript(value=value_node,
                                                  slice=slice_index_node,
                                                  ctx=gast.Load())
                        self.name_to_var_shape[target_id] = sub_node
                        has_updated = True

            return has_updated
        else:
            target_id = ast_to_source_code(target_node).strip()

            if isinstance(value_node, gast.Name):
                if value_node.id in self.name_to_var_shape:
                    self.name_to_var_shape[target_id] = self.name_to_var_shape[
                        value_node.id]
                    return True
            if isinstance(value_node, gast.Attribute):
                if self.is_var_shape(value_node):  # eg: x.shape
                    self.name_to_var_shape[target_id] = value_node
                    return True
            if isinstance(value_node, gast.Subscript):
                if isinstance(value_node.value, gast.Attribute):
                    if self.is_var_shape(value_node.value):  # eg: x.shape[0]
                        self.name_to_var_shape[target_id] = value_node
                        return True
        return False
Exemple #2
0
 def visit_Assign(self, node):
     self.src = quoting.unquote(node)
     self.mark(node)
     self.trivializing = True
     self.namer.target = node.targets[0]
     if isinstance(node.targets[0], (gast.Subscript, gast.Attribute)):
         node.value = self.trivialize(node.value)
         node.targets[0] = self.visit(node.targets[0])
     elif isinstance(node.targets[0], gast.Tuple):
         node.value = self.visit(node.value)
         name = self.namer.name(node.targets[0])
         target = gast.Name(id=name, ctx=gast.Store(), annotation=None)
         for i, elt in enumerate(node.targets[0].elts):
             stmt = gast.Assign(targets=[elt],
                                value=gast.Subscript(
                                    value=gast.Name(id=name,
                                                    ctx=gast.Load(),
                                                    annotation=None),
                                    slice=gast.Index(value=gast.Num(n=i)),
                                    ctx=gast.Load()))
             self.mark(stmt)
             self.append(stmt)
         node.targets[0] = target
     elif not isinstance(node.targets[0], gast.Name):
         raise ValueError
     node = self.generic_visit(node)
     self.namer.target = None
     self.trivializing = False
     return node
Exemple #3
0
    def visit_For(self, node):
        target = node.target
        if isinstance(target, ast.Tuple) or isinstance(target, ast.List):
            renamings = OrderedDict()
            self.traverse_tuples(target, (), renamings)
            if renamings:
                gtarget = self.get_new_id()
                node.target = ast.Name(gtarget, node.target.ctx, None)
                for rename, state in renamings.items():
                    nnode = reduce(
                        lambda x, y: ast.Subscript(
                            x,
                            ast.Index(ast.Num(y)),
                            ast.Load()),
                        state,
                        ast.Name(gtarget, ast.Load(), None))
                    if isinstance(rename, str):
                        node.body.insert(0,
                                         ast.Assign(
                                             [ast.Name(rename,
                                                       ast.Store(),
                                                       None)],
                                             nnode)
                                         )
                    else:
                        node.body.insert(0, ast.Assign([rename], nnode))

        self.generic_visit(node)
        return node
Exemple #4
0
 def visit_Assign(self, node):
     self.generic_visit(node)
     # if the rhs is an identifier, we don't need to duplicate it
     # otherwise, better duplicate it...
     no_tmp = isinstance(node.value, ast.Name)
     extra_assign = [] if no_tmp else [node]
     for i, t in enumerate(node.targets):
         if isinstance(t, ast.Tuple) or isinstance(t, ast.List):
             renamings = OrderedDict()
             self.traverse_tuples(t, (), renamings)
             if renamings:
                 gtarget = node.value.id if no_tmp else self.get_new_id()
                 node.targets[i] = ast.Name(gtarget,
                                            node.targets[i].ctx,
                                            None)
                 for rename, state in renamings.items():
                     nnode = reduce(
                         lambda x, y: ast.Subscript(
                             x,
                             ast.Index(ast.Num(y)),
                             ast.Load()),
                         state,
                         ast.Name(gtarget, ast.Load(), None))
                     if isinstance(rename, str):
                         extra_assign.append(
                             ast.Assign(
                                 [ast.Name(rename, ast.Store(), None)],
                                 nnode))
                     else:
                         extra_assign.append(ast.Assign([rename], nnode))
     return extra_assign or node
Exemple #5
0
    def _process_variable_assignment(self, source, targets):
        if isinstance(source, gast.Call):
            func = source.func
            if anno.hasanno(func, 'live_val'):
                func_obj = anno.getanno(func, 'live_val')
                if tf_inspect.isclass(func_obj):
                    anno.setanno(source, 'is_constructor', True)
                    anno.setanno(source, 'type', func_obj)
                    anno.setanno(source, 'type_fqn', anno.getanno(func, 'fqn'))
                    # TODO(mdan): Raise an error if constructor has side effects.
                    # We can have a whitelist of no-side-effects constructors.
                    # We can also step inside the constructor and further analyze.

        for t in targets:
            if isinstance(t, gast.Tuple):
                for i, e in enumerate(t.elts):
                    self.scope.setval(
                        anno.getanno(e, anno.Basic.QN),
                        gast.Subscript(source, gast.Index(i),
                                       ctx=gast.Store()))
            elif isinstance(t, (gast.Name, gast.Attribute)):
                self.scope.setval(anno.getanno(t, anno.Basic.QN), source)
            else:
                raise ValueError('Dont know how to handle assignment to %s' %
                                 t)
Exemple #6
0
    def visit_Assign(self, node):
        self.generic_visit(node)
        if isinstance(node.value, gast.Call):
            target = node.value.func
            if anno.hasanno(target, 'live_val'):
                target_obj = anno.getanno(target, 'live_val')
                if tf_inspect.isclass(target_obj):
                    # This is then a constructor.
                    anno.setanno(node.value, 'type', target_obj)
                    anno.setanno(node.value, 'type_fqn',
                                 anno.getanno(target, 'fqn'))
                    # TODO (mdan): Raise an error if constructor has side effects. id:2153 gh:2154
                    # We can have a whitelist of no-side-effects constructors.
                    # We can also step inside the constructor and further analyze.

        for n in node.targets:
            if isinstance(n, gast.Tuple):
                for i, e in enumerate(n.elts):
                    self.scope.setval(
                        e.id,
                        gast.Subscript(node.value,
                                       gast.Index(i),
                                       ctx=gast.Store()))
            else:
                self.scope.setval(n.id, node.value)

        return node
Exemple #7
0
    def ast(self):
        """AST representation."""
        # The caller must adjust the context appropriately.
        if self.has_subscript():
            return gast.Subscript(value=self.parent.ast(),
                                  slice=gast.Index(self.qn[-1].ast()),
                                  ctx=CallerMustSetThis)
        if self.has_attr():
            return gast.Attribute(value=self.parent.ast(),
                                  attr=self.qn[-1],
                                  ctx=CallerMustSetThis)

        base = self.qn[0]
        if isinstance(base, str):
            return gast.Name(base,
                             ctx=CallerMustSetThis,
                             annotation=None,
                             type_comment=None)
        elif isinstance(base, StringLiteral):
            return gast.Constant(base.value, kind=None)
        elif isinstance(base, NumberLiteral):
            return gast.Constant(base.value, kind=None)
        else:
            assert False, ('the constructor should prevent types other than '
                           'str, StringLiteral and NumberLiteral')
Exemple #8
0
 def _process_tuple_assignment(self, source, t):
     for i, e in enumerate(t.elts):
         if isinstance(e, gast.Tuple):
             self._process_tuple_assignment(source, e)
         else:
             self.scope.setval(
                 anno.getanno(e, anno.Basic.QN),
                 gast.Subscript(source, gast.Index(i), ctx=gast.Store()))
Exemple #9
0
 def _build_var_slice_node(self):
     return gast.Subscript(
         value=self.iter_node,
         slice=gast.Index(value=gast.Name(
             id=self.iter_idx_name,
             ctx=gast.Load(),
             annotation=None,
             type_comment=None)),
         ctx=gast.Load())
 def visit_Name(self, node):
     if node.id in self.renamings:
         nnode = reduce(
             lambda x, y: ast.Subscript(x, ast.Index(ast.Num(y)), ast.Load(
             )), self.renamings[node.id],
             ast.Name(self.tuple_id, ast.Load(), None))
         nnode.ctx = node.ctx
         return nnode
     return node
Exemple #11
0
    def slice2list(self):
        # TODO(hamaji): Use 2**63-1 instead.
        int_max = 2**31 - 1
        if isinstance(self, gast.Slice):
            assert self.step is None

            def f(x, v):
                if x is None:
                    return Value(np.array([v])).to_tensor(env)
                x = eval_ast(x, env)
                if x.is_tensor():
                    return unsqueeze(x.value)
                else:
                    return Value(np.array([x.value])).to_tensor(env)

            lower = f(self.lower, 0)
            upper = f(self.upper, int_max)
            squeeze = [False]
        elif isinstance(self, gast.Index):
            idx = eval_ast(self.value, env)
            if isinstance(idx.value, tuple):  # ここにTupleが来うる
                # TODO(satos) もっとうまくやったほうがいいかも
                vs = [
                    gast.Index(gast.NameConstant(value=v)) for v in idx.value
                ]
                lower, upper, squeeze = slice2list(gast.ExtSlice(dims=vs))
            elif not idx.is_py:
                lower = unsqueeze(idx.value)
                ot = totensor(1, env)
                upper = env.calc(
                    "Add",
                    inputs=[idx.to_tensor(env).name, ot.name],
                )
                upper = unsqueeze(upper)
                squeeze = [True]
            else:
                lower = totensor(np.array([idx.value]), env)
                upper_value = idx.value + 1 if idx.value != -1 else int_max
                upper = totensor(np.array([upper_value]), env)
                squeeze = [True]
        elif isinstance(self, gast.ExtSlice):
            ds = list(map(slice2list, self.dims))
            lower = _concat(
                tuple(map(lambda x: castto(x[0], TensorProto.INT64, env), ds)),
                0, env)
            upper = _concat(
                tuple(map(lambda x: castto(x[1], TensorProto.INT64, env), ds)),
                0, env)
            squeeze = sum(map(lambda x: x[2], ds), [])
        else:
            raise Exception(self, " is not Python slice")

        return lower, upper, squeeze
Exemple #12
0
    def visit_Subscript(self, node):
        new_slice = self._visit(node.slice)
        if isinstance(node.slice, ast.Ellipsis):
            new_slice = gast.Index(new_slice)

        new_node = gast.Subscript(
            self._visit(node.value),
            new_slice,
            self._visit(node.ctx),
        )
        gast.copy_location(new_node, node)
        new_node.end_lineno = new_node.end_col_offset = None
        return new_node
Exemple #13
0
 def _build_assign_var_slice_node(self):
     var_slice_node = gast.Subscript(
         value=self.iter_node,
         slice=gast.Index(value=gast.Name(id=self.iter_idx_name,
                                          ctx=gast.Load(),
                                          annotation=None,
                                          type_comment=None)),
         ctx=gast.Load(),
     )
     new_iter_var_name = unique_name.generate(FOR_ITER_VAR_NAME_PREFIX)
     target_node, assign_node = create_assign_node(new_iter_var_name,
                                                   var_slice_node)
     return target_node, assign_node
Exemple #14
0
    def apply_to_single_assignments(self, targets, values, apply_fn):
        """Applies a function to each individual assignment.

    This function can process a possibly-unpacked (e.g. a, b = c, d) assignment.
    It tries to break down the unpacking if possible. In effect, it has the same
    effect as passing the assigned values in SSA form to apply_fn.

    Examples:

    The following will result in apply_fn(a, c), apply_fn(b, d):

        a, b = c, d

    The following will result in apply_fn(a, c[0]), apply_fn(b, c[1]):

        a, b = c

    The following will result in apply_fn(a, (b, c)):

        a = b, c

    It uses the visitor pattern to allow subclasses to process single
    assignments individually.

    Args:
      targets: list, tuple of or individual AST node. Should be used with the
        targets field of an ast.Assign node.
      values: an AST node.
      apply_fn: a function of a single argument, which will be called with the
        respective nodes of each single assignment. The signature is
        apply_fn(target, value), no return value.
    """
        if not isinstance(targets, (list, tuple)):
            targets = (targets, )
        for target in targets:
            if isinstance(target, (gast.Tuple, gast.List)):
                for i in range(len(target.elts)):
                    target_el = target.elts[i]
                    if isinstance(values, (gast.Tuple, gast.List)):
                        value_el = values.elts[i]
                    else:
                        value_el = gast.Subscript(values,
                                                  gast.Index(i),
                                                  ctx=gast.Store())
                    self.apply_to_single_assignments(target_el, value_el,
                                                     apply_fn)
            else:
                # TODO(mdan): Look into allowing to rewrite the AST here.
                apply_fn(target, values)
Exemple #15
0
 def _build_compare_node(self):
     if self.is_for_range_iter():
         compare_node = self.iter_args[
             0] if self.args_length == 1 else self.iter_args[1]
     else:
         compare_node = gast.Subscript(
             value=gast.Name(
                 id=self.iter_var_shape_name,
                 ctx=gast.Load(),
                 annotation=None,
                 type_comment=None),
             slice=gast.Index(value=gast.Constant(
                 value=0, kind=None)),
             ctx=gast.Load())
     return compare_node
Exemple #16
0
 def visit_ExtSlice(self, node):
     has_ellipsis = any(isinstance(d, ast.Ellipsis) for d in node.dims)
     has_slice = any(isinstance(d, ast.Slice) for d in node.dims)
     new_dims = self._visit(node.dims)
     if has_ellipsis and not has_slice:
         new_dims = [
             nd.value if isinstance(nd, gast.Index) else nd
             for nd in new_dims
         ]
         new_node = gast.Index(gast.Tuple(new_dims, gast.Load()))
     else:
         new_node = gast.ExtSlice(new_dims)
     gast.copy_location(new_node, node)
     new_node.end_lineno = new_node.end_col_offset = None
     return new_node
Exemple #17
0
def apply_to_single_assignments(targets, values, apply_fn):
    """Applies a function to each individual assignment.

  This function can process a possibly-unpacked (e.g. a, b = c, d) assignment.
  It tries to break down the unpacking if possible. In effect, it has the same
  effect as passing the assigned values in SSA form to apply_fn.

  Examples:

  The following will result in apply_fn(a, c), apply_fn(b, d):

      a, b = c, d

  The following will result in apply_fn(a, c[0]), apply_fn(b, c[1]):

      a, b = c

  The following will result in apply_fn(a, (b, c)):

      a = b, c

  It uses the visitor pattern to allow subclasses to process single
  assignments individually.

  Args:
    targets: Union[List[ast.AST, ...], Tuple[ast.AST, ...], ast.AST, should be
      used with the targets field of an ast.Assign node
    values: ast.AST
    apply_fn: Callable[[ast.AST, ast.AST], None], called with the respective
      nodes of each single assignment
  """
    if not isinstance(targets, (list, tuple)):
        targets = (targets, )
    for target in targets:
        if isinstance(target, (gast.Tuple, gast.List)):
            for i in range(len(target.elts)):
                target_el = target.elts[i]
                if isinstance(values, (gast.Tuple, gast.List)):
                    value_el = values.elts[i]
                else:
                    idx = parsing.parse_expression(str(i))
                    value_el = gast.Subscript(values,
                                              gast.Index(idx),
                                              ctx=gast.Load())
                apply_to_single_assignments(target_el, value_el, apply_fn)
        else:
            apply_fn(target, values)
Exemple #18
0
    def ast(self):
        # The caller must adjust the context appropriately.
        if self.has_subscript():
            return gast.Subscript(self.parent.ast(),
                                  gast.Index(self.qn[-1].ast()), None)
        if self.has_attr():
            return gast.Attribute(self.parent.ast(), self.qn[-1], None)

        base = self.qn[0]
        if isinstance(base, str):
            return gast.Name(base, None, None)
        elif isinstance(base, StringLiteral):
            return gast.Str(base.value)
        elif isinstance(base, NumberLiteral):
            return gast.Num(base.value)
        else:
            assert False, ('the constructor should prevent types other than '
                           'str, StringLiteral and NumberLiteral')
Exemple #19
0
 def generic_visit(self, node):
     if node in self.constant_expressions:
         try:
             fake_node = ast.Expression(
                 node.value if isinstance(node, ast.Index) else node)
             code = compile(ast.gast_to_ast(fake_node),
                            '<constant folding>', 'eval')
             value = eval(code, self.env)
             new_node = to_ast(value)
             if(isinstance(node, ast.Index) and
                not isinstance(new_node, ast.Index)):
                 new_node = ast.Index(new_node)
             try:
                 if not ASTMatcher(node).search(new_node):
                     self.update = True
                     return new_node
             except DamnTooLongPattern as e:
                 print("W: ", e, " Assume no update happened.")
             return Transformation.generic_visit(self, node)
         except ConversionError as e:
             print('error in constant folding: ', e)
             raise
         except ToNotEval:
             return Transformation.generic_visit(self, node)
         except AttributeError as e:
             # FIXME union_ function is not handle by constant folding
             if "union_" in e.args[0]:
                 return Transformation.generic_visit(self, node)
             elif "pythran" in e.args[0]:
                 # FIXME: Can be fix giving a Python implementation for
                 # these functions.
                 return Transformation.generic_visit(self, node)
             raise
         except NameError as e:
             # FIXME dispatched function are not processed by constant
             # folding
             if "__dispatch__" in e.args[0]:
                 return Transformation.generic_visit(self, node)
             raise
         except Exception as e:
             raise PythranSyntaxError(str(e), node)
     else:
         return Transformation.generic_visit(self, node)
Exemple #20
0
  def _process_variable_assignment(self, source, targets):
    if isinstance(source, gast.Call):
      func = source.func
      if anno.hasanno(func, 'live_val'):
        func_obj = anno.getanno(func, 'live_val')
        if tf_inspect.isclass(func_obj):
          # This is then a constructor.
          anno.setanno(source, 'type', func_obj)
          anno.setanno(source, 'type_fqn', anno.getanno(func, 'fqn'))
          # TODO(mdan): Raise an error if constructor has side effects.
          # We can have a whitelist of no-side-effects constructors.
          # We can also step inside the constructor and further analyze.

    for t in targets:
      if isinstance(t, gast.Tuple):
        for i, e in enumerate(t.elts):
          self.scope.setval(e.id,
                            gast.Subscript(
                                source, gast.Index(i), ctx=gast.Store()))
      else:
        self.scope.setval(t.id, source)
Exemple #21
0
    def _process_variable_assignment(self, source, targets):
        # Special case: constructors.
        if isinstance(source, gast.Call):
            func = source.func
            if anno.hasanno(func, 'live_val'):
                func_obj = anno.getanno(func, 'live_val')
                if tf_inspect.isclass(func_obj):
                    anno.setanno(source, 'is_constructor', True)
                    anno.setanno(source, 'type', func_obj)
                    anno.setanno(source, 'type_fqn', anno.getanno(func, 'fqn'))
                    # TODO (mdan): Raise an error if constructor has side effects. id:554
                    # https://github.com/imdone/tensorflow/issues/555
                    # We can have a whitelist of no-side-effects constructors.
                    # We can also step inside the constructor and further analyze.

        # Multiple targets mean multiple assignment.
        for target in targets:
            # Tuple target means unpacking.
            if isinstance(target, (gast.Tuple, gast.List)):
                for i, target_item in enumerate(target.elts):
                    # Two cases here:
                    #   1. Static unpacking, e.g. a, b = c, d
                    #   2. Dynamic unpacking, e.g. a, b = c
                    # The former case is optimized away.
                    if isinstance(source, (gast.Tuple, gast.List)):
                        source_item = source.elts[i]
                    else:
                        source_item = gast.Subscript(source,
                                                     gast.Index(i),
                                                     ctx=None)
                    self._process_variable_assignment(source_item,
                                                      (target_item, ))
            elif isinstance(target, (gast.Name, gast.Attribute)):
                target_symbol = anno.getanno(target, anno.Basic.QN)
                self.scope.setval(target_symbol, source)
            else:
                raise ValueError('assignment target has unknown type: %s' %
                                 target)
Exemple #22
0
 def visit_Subscript(self, node):
   if self.trivializing:
     node.value = self.trivialize(node.value)
     if isinstance(node.slice, gast.Index):
       node.slice.value = self.trivialize(node.slice.value)
     elif isinstance(node.slice, gast.Slice):
       name = self.namer.name(node.slice)
       target = gast.Name(id=name, ctx=gast.Store(), annotation=None)
       stmt = gast.Assign(targets=[target], value=None)
       self.prepend(stmt)
       stmt.value = gast.Call(
           func=gast.Name(id='slice', ctx=gast.Load(), annotation=None),
           args=[
               self.trivialize(arg) if arg else
               gast.Name(id='None', ctx=gast.Load(), annotation=None)
               for arg in [node.slice.lower, node.slice.upper,
                           node.slice.step]],
           keywords=[])
       node.slice = gast.Index(value=gast.Name(id=name, ctx=gast.Load(),
                                               annotation=None))
     else:
       raise ValueError
   return node
Exemple #23
0
     MethodIntr(),
     "keys":
     MethodIntr(),
     "pop":
     MethodIntr(),
     "popitem":
     MethodIntr(),
     "setdefault":
     MethodIntr(lambda self, node: len(node.args) == 3 and self.combine(
         node.args[0],
         node.args[1],
         unary_op=lambda x: cxxtypes.DictType(x, self.result[node.args[2]]),
         register=True,
         aliasing_type=True),
                return_alias=lambda args: {
                    ast.Subscript(args[0], ast.Index(args[1]), ast.Load())
                }.union({args[2]} if len(args) == 3 else set())),
     "update":
     MethodIntr(update_effects),
     "values":
     MethodIntr(),
     "viewitems":
     MethodIntr(),
     "viewkeys":
     MethodIntr(),
     "viewvalues":
     MethodIntr(),
 },
 "file": {
     # Member variables
     "closed": AttributeIntr(return_type=NamedType("bool")),
Exemple #24
0
 def visit_Subscript(self, node):
     if self.trivializing:
         node.value = self.trivialize(node.value)
         node.slice = gast.Index(value=self.trivialize_slice(node.slice))
     return node
Exemple #25
0
 def visit_Index(self, node):
     value = self.visit(node.value)
     if value is not node.value:
         return ast.Index(value)
     else:
         return node