def create_convert_shape_node(var_shape_node,
                              slice_node=None,
                              in_control_flow=False):
    assert isinstance(var_shape_node, (gast.Attribute, gast.Subscript))

    if isinstance(var_shape_node, gast.Attribute):
        args = [ast_to_source_code(var_shape_node.value).strip()]
        # (1) A slice can be a simple number such as 1, -2, i.e. gast.Index or gast.Constant
        # (2) A slice can also be represented by bounds such as 2:-1, i.e. not gast.Index or gast.Constant
        # In (1) case, we pass the number as 'idx' argument in convert_var_shape
        # In (2) case, we have to make it like `convert_var_shape(x)[slice]`
        if slice_node is not None and slice_is_num(slice_node):
            args.append(ast_to_source_code(slice_node.slice).strip())

        convert_var_shape_func = "paddle.jit.dy2static.convert_var_shape({}, in_control_flow={})".format(
            ",".join(args), in_control_flow)
        api_shape_node = gast.parse(convert_var_shape_func).body[0].value

        if slice_node is not None and not slice_is_num(slice_node):
            return gast.Subscript(
                value=api_shape_node, slice=slice_node.slice, ctx=gast.Load())
        return api_shape_node

    if isinstance(var_shape_node, gast.Subscript):
        result_node = copy.deepcopy(var_shape_node)
        result_node = create_convert_shape_node(result_node.value, result_node,
                                                in_control_flow)
        return result_node
Example #2
0
    def _replace_pop(self, node):
        """
        Replace a pop statement for a list or dict.
        For example:

            list_a = [0,1,2,3,4]
            x = list_a.pop()  # --> convert_pop(list_a)
            y = list_a.pop(1) # --> convert_pop(list_a, 1)

            dict_a = {"red":0, "blue":1, "yellow":2}
            m = dict_a.pop("red")           # --> convert_pop(dict_a, "red")
            n = dict_a.pop("black", 3)      # --> convert_pop(dict_a, "black", 3)

        """
        assert isinstance(node, gast.Call)
        assert isinstance(node.func, gast.Attribute)

        target_node = node.func.value
        target_str = ast_to_source_code(target_node).strip()

        args_str = [ast_to_source_code(arg).strip() for arg in node.args]

        # NOTE(liym27):
        # 1. pop stmt for a list if len(args_str) == 0
        # 2. pop stmt for a list or dict if len(args_str) == 1
        # 3. pop stmt for a dict if len(args_str) == 2
        if len(args_str) <= 2:
            new_pop_str = "paddle.jit.dy2static.convert_pop({}, {})"\
                .format(target_str, ",".join(args_str))
            new_pop_node = gast.parse(new_pop_str).body[0].value
            return new_pop_node
        else:
            return node
    def visit_Assert(self, node):
        convert_assert_node = gast.parse(
            'fluid.dygraph.dygraph_to_static.convert_operators.convert_assert({test}, {msg})'
            .format(test=ast_to_source_code(node.test),
                    msg=ast_to_source_code(node.msg)
                    if node.msg else "")).body[0].value

        return gast.Expr(value=convert_assert_node)
Example #4
0
    def visit_Assert(self, node):
        convert_assert_node = gast.parse(
            'paddle.jit.dy2static.convert_assert({test}, {msg})'.format(
                test=ast_to_source_code(node.test),
                msg=ast_to_source_code(node.msg)
                if node.msg else "")).body[0].value

        return gast.Expr(value=convert_assert_node)
Example #5
0
 def visit_Call(self, node):
     # Store type var names such as "isinstance(x, some_type_names)" and
     # Remove them later
     if isinstance(node.func, gast.Name) and node.func.id == 'isinstance':
         type_node = node.args[1]
         if isinstance(type_node, gast.Tuple):
             for element in type_node.elts:
                 self.type_vars.add(ast_to_source_code(element).strip())
         else:
             self.type_vars.add(ast_to_source_code(type_node).strip())
     self.generic_visit(node)
Example #6
0
    def visit_Call(self, node):
        self.generic_visit(node)
        func_str = ast_to_source_code(node.func).strip()
        if func_str in self._castable_type and len(node.args) > 0:
            args_str = ast_to_source_code(node.args[0]).strip()
            new_func_str = "fluid.dygraph.dygraph_to_static.convert_operators.convert_var_dtype({}, '{}')".format(
                args_str, func_str)
            new_node = gast.parse(new_func_str).body[0].value
            return new_node

        return node
Example #7
0
 def _need_transform(self, var_node, print_node):
     if isinstance(var_node, gast.Name):
         if self._is_tensor_node(var_node):
             return True
         else:
             _logger.warning(
                 "ProgramTranslator could not transform printing value that are not Tensor like < %s > now and will run it as-is."
                 % ast_to_source_code(print_node).strip())
     else:
         _logger.warning(
             "ProgramTranslator could not transform < %s > now and will run it as-is."
             % ast_to_source_code(print_node).strip())
     return False
Example #8
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
Example #9
0
    def transfer_from_node_type(self, node_wrapper):
        self.translator_logger.log(
            1, "Source code: \n{}".format(ast_to_source_code(self.root)))
        # Generic transformation
        self.visit(node_wrapper.node)

        transformers = [
            BasicApiTransformer,  # Basic Api
            TensorShapeTransformer,  # Tensor.shape -> layers.shape(Tensor)
            ListTransformer,  # List used in control flow
            BreakTransformOptimizer,  # optimize transfromation of break in loops
            BreakContinueTransformer,  # break/continue in loops
            ReturnTransformer,  # return in functions
            LogicalTransformer,  # logical and/or/not
            LoopTransformer,  # for/while -> while_op
            IfElseTransformer,  # if/else -> cond_op
            AssertTransformer,  # assert statement
            PrintTransformer,  # print statement
            CallTransformer,  # transform call recursively
            CastTransformer,  # type casting statement
            GradTransformer,  # transform paddle.grad to paddle.gradients
        ]

        for index, transformer in enumerate(transformers):
            self._apply(transformer, node_wrapper, log_level=index + 1)

        self.translator_logger.log_transformed_code(
            logging_utils.LOG_AllTransformer, self.root, "All Transformers")
    def _create_bool_op_node(self, nodes, api_type):
        '''
        NOTE(liym27):
           The arguments of function convert_logical_XX should be callable so that they can be run
          according to the actual order. In `convert_logical_and(lambda:x>1, lambda:y<1)`, `lambda:y<1`
          must be run after `lambda:x>1`, If `x>1` is False, `y<1` should NOT be run.
        '''
        assert len(
            nodes
        ) > 1, "The length of BoolOp should be at least 2, but received {}.".format(
            len(nodes))
        if len(nodes) > 2:
            # Creates logic_and/logic_or node recursively.
            pre_logic_node = self._create_bool_op_node(nodes[:2], api_type)
            if len(nodes[2:]) == 1:
                post_logic_node = nodes[2]
            else:
                post_logic_node = self._create_bool_op_node(
                    nodes[2:], api_type)
            nodes = [pre_logic_node] + [post_logic_node]

        args = [ast_to_source_code(child) for child in nodes]
        new_node_str = "paddle.jit.dy2static.convert_logical_{}(lambda:{}, lambda:{})".format(
            api_type, args[0], args[1])
        # NOTE: gast.parse return Module(body=[expr(...)])
        new_node = gast.parse(new_node_str).body[0].value
        return new_node
Example #11
0
    def _replace_after_node_to_if_in_stmt_list(self, stmt_list, node,
                                               return_name,
                                               parent_node_of_return):
        i = index_in_list(stmt_list, node)
        if i < 0 or i >= len(stmt_list):
            return False
        if i == len(stmt_list) - 1:
            # No need to add, we consider this as added successfully
            return True

        if_stmt = gast.If(test=gast.UnaryOp(op=gast.Not(),
                                            operand=gast.Name(
                                                id=return_name,
                                                ctx=gast.Store(),
                                                annotation=None,
                                                type_comment=None)),
                          body=stmt_list[i + 1:],
                          orelse=[])

        stmt_list[i + 1:] = [if_stmt]

        # Here assume that the parent node of return is gast.If
        if isinstance(parent_node_of_return, gast.If):
            # Prepend control flow boolean nodes such as '__return@1 = False'
            node_str = "{} = _jst.create_bool_as_type({}, False)".format(
                return_name,
                ast_to_source_code(parent_node_of_return.test).strip())
            assign_false_node = gast.parse(node_str).body[0]

            stmt_list[i:i] = [assign_false_node]
        return True
Example #12
0
 def _create_tensor_array(self, value_node):
     # Although `dtype='float32'`, other types such as `int32` can also be supported
     init_value = ast_to_source_code(value_node).strip()
     func_code = "paddle.tensor.create_array('float32', {})".format(
         init_value)
     func_node = gast.parse(func_code).body[0].value
     return func_node
Example #13
0
    def _replace_list_pop(self, node):
        assert isinstance(node, gast.Call)
        assert isinstance(node.func, gast.Attribute)

        target_node = node.func.value
        target_str = ast_to_source_code(target_node).strip()

        if node.args:
            idx_node = node.args[0]
            idx_str = ast_to_source_code(idx_node).strip()
        else:
            idx_str = "None"

        new_call_str = "fluid.dygraph.dygraph_to_static.list_transformer.convert_list_pop({}, {})".format(
            target_str, idx_str)
        new_call_node = gast.parse(new_call_str).body[0].value
        return new_call_node
Example #14
0
    def _transform_slice_to_tensor_write(self, node):
        assert isinstance(node, gast.Assign)
        target_node = node.targets[0]
        target_name = target_node.value.id
        slice_node = target_node.slice

        if isinstance(slice_node, gast.Slice):
            pass
        elif isinstance(slice_node, gast.Index):
            value_code = ast_to_source_code(node.value)
            i = "paddle.cast(" \
                "x=paddle.jit.dy2static.to_static_variable({})," \
                "dtype='int64')".format(ast_to_source_code(slice_node))
            assign_code = "{} = fluid.layers.array_write(x={}, i={}, array={})" \
                .format(target_name, value_code, i, target_name)
            assign_node = gast.parse(assign_code).body[0]
        return assign_node
Example #15
0
 def _is_builtin_call(self, node):
     assert isinstance(node, gast.Call)
     func_str = ast_to_source_code(node.func).strip()
     try:
         from paddle.fluid.dygraph.dygraph_to_static.convert_call_func import is_builtin
         return eval("is_builtin({})".format(func_str))
     except Exception:
         return False
 def visit_Attribute(self, node):
     if node.attr == 'shape':
         args = ast_to_source_code(node.value).strip()
         convert_var_shape_func = "paddle.jit.dy2static.convert_var_shape_simple({})".format(
             args)
         api_shape_node = gast.parse(convert_var_shape_func).body[0].value
         return api_shape_node
     return node
Example #17
0
    def log_transformed_code(self, level, ast_node, transformer_name, *args,
                             **kwargs):
        if self.has_code_level(level):
            source_code = ast_to_source_code(ast_node)
            header_msg = "After the level {} ast transformer: '{}', the transformed code:\n"\
                .format(level, transformer_name)

            msg = header_msg + source_code
            self.logger.info(msg, *args, **kwargs)
Example #18
0
 def visit_UnaryOp(self, node):
     self.generic_visit(node)
     if isinstance(node.op, gast.Not):
         arg = ast_to_source_code(node.operand)
         new_node_str = "fluid.layers.logical_not({})".format(arg)
         # gast.parse returns Module(body=[expr(value=...)])
         new_node = gast.parse(new_node_str).body[0].value
         return new_node
     return node
 def visit_Attribute(self, node):
     if self._used_by_paddle_api(node):
         name = ast_to_source_code(node).strip()
         if name in self.name_to_var_shape:
             return create_choose_shape_node(name,
                                             self.name_to_var_shape[name])
         if self._is_var_shape(node):
             return create_convert_shape_node(node)
     return node
Example #20
0
def is_candidate_node(node):
    """
    Nodes with specified type will be dependent on tensor.
    """
    is_compare_node = isinstance(node,
                                 (gast.Compare, gast.BoolOp, gast.UnaryOp))
    # TODO(Aurelius84): `.numpy()` may be an customized function,
    # and should consider a more elegant way to solve this problem.
    has_numpy_attr = ".numpy()" in ast_to_source_code(node)
    return is_compare_node or has_numpy_attr
 def visit_UnaryOp(self, node):
     self.generic_visit(node)
     if isinstance(node.op, gast.Not):
         arg = ast_to_source_code(node.operand)
         new_node_str = "paddle.jit.dy2static.convert_logical_not({})".format(
             arg)
         # NOTE: gast.parse returns Module(body=[expr(value=...)])
         new_node = gast.parse(new_node_str).body[0].value
         return new_node
     return node
Example #22
0
def is_to_variable(node):
    assert isinstance(node, gast.Call)
    api_name = utils.ast_to_source_code(node.func).strip()

    if utils.is_dygraph_api(node):
        return api_name.endswith("to_variable")

    if utils.is_paddle_api(node):
        return api_name.endswith("to_tensor")

    return False
Example #23
0
def is_grad_api_node(node):
    assert isinstance(node, gast.Call)
    api_name = utils.ast_to_source_code(node.func).strip()
    if utils.is_paddle_api(node):
        if 'no_grad' in api_name:
            warnings.warn(
                "paddle.no_grad is only supported for inference model, and not supported for training under @to_static."
            )
            return False
        return api_name.endswith("grad")
    return False
    def test_create_fill_constant_node(self):
        node = create_fill_constant_node("a", 1.0)
        source = "a = paddle.fluid.layers.fill_constant(shape=[1], dtype='float64', value=1.0, name='a')"
        self.assertEqual(
            ast_to_source_code(node).replace('\n', '').replace(' ', ''),
            source.replace(' ', ''))

        node = create_fill_constant_node("b", True)
        source = "b = paddle.fluid.layers.fill_constant(shape=[1], dtype='bool', value=True, name='b')"
        self.assertEqual(
            ast_to_source_code(node).replace('\n', '').replace(' ', ''),
            source.replace(' ', ''))

        node = create_fill_constant_node("c", 4293)
        source = "c = paddle.fluid.layers.fill_constant(shape=[1], dtype='int64', value=4293, name='c')"
        self.assertEqual(
            ast_to_source_code(node).replace('\n', '').replace(' ', ''),
            source.replace(' ', ''))

        self.assertIsNone(create_fill_constant_node("e", None))
        self.assertIsNone(create_fill_constant_node("e", []))
Example #25
0
    def _create_node_with_api_template(self, node, template):
        node_code = ast_to_source_code(node)
        new_node_str = template.format(node_code)
        # gast.parse return Module(body=[expr(value=...)])
        new_node = gast.parse(new_node_str).body[0].value
        bool_tensor_name = unique_name.generate(PLAIN_TENSOR_PREFIX)
        assign_name, assign_node = create_assign_node(bool_tensor_name,
                                                      new_node)

        self._new_assign_nodes.append(assign_node)

        return assign_name
Example #26
0
    def visit_Compare(self, node):
        self.generic_visit(node)
        left_str = ast_to_source_code(node.left).strip()
        if left_str.startswith("_jst.convert_var_shape"):
            # check left and comparators are all converted var shape
            compare_arg_strs = left_str
            for i, comparator in enumerate(node.comparators):
                comparator_str = ast_to_source_code(comparator).strip()
                if not comparator_str.startswith("_jst.convert_var_shape"):
                    return node
                op_str = cmpop_node_to_str(node.ops[i])
                compare_arg_strs += (", '" + op_str + "', " + comparator_str)

            # Now all left and comparators are converted shape
            # Replace some comparsion operation because of difference between
            # Python and Paddle
            new_node_str = "_jst.convert_shape_compare({})".format(
                compare_arg_strs)
            new_node = gast.parse(new_node_str).body[0].value
            return new_node
        return node
Example #27
0
    def _create_bool_node(self, node):
        node_code = ast_to_source_code(node)
        new_node_str = "fluid.layers.fill_constant(shape=[1], dtype='bool', value=bool({}))".format(
            node_code)
        # gast.parse return Module(body=[expr(value=...)])
        new_node = gast.parse(new_node_str).body[0].value
        bool_tensor_name = unique_name.generate(PLAIN_TENSOR_PREFIX)
        assign_name, assign_node = create_assign_node(bool_tensor_name,
                                                      new_node)

        self._new_assign_nodes.append(assign_node)

        return assign_name
def create_choose_shape_node(attr_shape_name, api_shape_name, slice_node=None):
    eval_exist_func = "paddle.jit.dy2static.eval_if_exist_else_none('{}', globals())".format(
        api_shape_name)
    args = [attr_shape_name, eval_exist_func]

    if slice_node is not None and slice_is_num(slice_node):
        args.append(ast_to_source_code(slice_node.slice).strip())
    choose_shape_func = "paddle.jit.dy2static.choose_shape_attr_or_api({})".format(
        ",".join(args))
    choose_shape_node = gast.parse(choose_shape_func).body[0].value
    if slice_node is not None and not slice_is_num(slice_node):
        return gast.Subscript(
            value=choose_shape_node, slice=slice_node.slice, ctx=gast.Load())
    return choose_shape_node
Example #29
0
    def visit_UnaryOp(self, node):
        self.generic_visit(node)
        if isinstance(node.op, gast.Not):
            arg = ast_to_source_code(node.operand)
            new_node_str = "fluid.layers.logical_not({})".format(arg)
            # gast.parse returns Module(body=[expr(value=...)])
            new_node = gast.parse(new_node_str).body[0].value
            logic_tensor_name = unique_name.generate(LOGIC_NOT_PREFIX)
            assign_name, assign_node = create_assign_node(
                logic_tensor_name, new_node)
            self._new_assign_nodes.append(assign_node)
            return assign_name

        return node
Example #30
0
    def _need_to_array_write_node(self, node):
        if isinstance(node, gast.Expr):
            if isinstance(node.value, gast.Call):
                if self._is_list_append_tensor(node.value):
                    return True

        if isinstance(node, gast.Assign):
            target_node = node.targets[0]
            if isinstance(target_node, gast.Subscript):
                list_name = ast_to_source_code(target_node.value).strip()
                if list_name in self.list_name_to_updated:
                    if self.list_name_to_updated[list_name] == True:
                        return True
        return False