# -*- coding:UTF-8 -*-
#   Copyright (c) 2020  PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

NO_OUTPUT_COUNT = 0


def gen_codes(code_list, indent=0):
    indent_blank = "    " * indent
    codes = []
    for code_line in code_list:
        if code_line.strip() == "":
            codes.append('\n')
        else:
            codes.append(indent_blank + code_line + '\n')
    return codes


def get_value(layer, key, layer_id=None, different_attrs=None):
    """ 进行optimizer后可能把inputs的value直接用数值代替（ConstantFuser），
        会把input换成attr，所以需要此处的操作。
    """
    if key in layer.inputs:
        return layer.inputs[key]
    else:
        if different_attrs is None:
            return str(layer.attrs[key])
        else:
            key_name = "{}_{}".format(layer.outputs[0], key)
            if key_name in different_attrs:
                return key_name
            else:
                if layer_id is None:
                    return str(layer.attrs[key])
                key_name = "{}_{}".format("layer_id/{}".format(layer_id), key)
                if key_name in different_attrs:
                    new_key_name = "attr_{}".format(NO_OUTPUT_COUNT)
                    NO_OUTPUT_COUNT += 1
                    diff_index = different_attrs.index(key_name)
                    different_attrs[diff_index] = new_key_name
                    return new_key_name
                else:
                    return str(layer.attrs[key])


def prim_add(layer,
             indent=1,
             init_func=[],
             forward_func=[],
             layer_id=None,
             different_attrs=None):
    line = "{} = {} + {}".format(layer.outputs[0],
                                 get_value(layer, "x", different_attrs),
                                 get_value(layer, "y", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_add_(layer,
              indent=1,
              init_func=[],
              forward_func=[],
              layer_id=None,
              different_attrs=None):
    if abs(layer.attrs["alpha"] - 1.) < 1e-6:
        line = "{} = {} + {}".format(layer.outputs[0],
                                     get_value(layer, "x", different_attrs),
                                     get_value(layer, "y", different_attrs))
    else:
        line = "{} = {} + {} * {}".format(
            layer.outputs[0],
            get_value(layer, "x", different_attrs), layer.attrs["alpha"],
            get_value(layer, "y", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_and(layer,
             indent=1,
             init_func=[],
             forward_func=[],
             layer_id=None,
             different_attrs=None,
             is_return_line=False):
    line = "{} = {} and {}".format(layer.outputs[0],
                                   get_value(layer, "x", different_attrs),
                                   get_value(layer, "y", different_attrs))
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_append(layer,
                indent=1,
                init_func=[],
                forward_func=[],
                layer_id=None,
                different_attrs=None):
    line = "{}.append({})".format(
        get_value(layer, "list", layer_id, different_attrs),
        get_value(layer, "element", layer_id, different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_assert(layer,
                indent=1,
                init_func=[],
                forward_func=[],
                layer_id=None,
                different_attrs=None):
    if layer.attrs["type"] == "eq":
        values = get_value(layer, "key")
        if "value" in layer.attrs:
            values = layer.attrs["value"]
        if isinstance(values, list):
            s = ""
            for v in values:
                s += "{} == {} or ".format(get_value(layer, "key"), v)
            if len(s) > 0:
                s = s[:-4]
            lc = locals()
            exec("assert_result = {}".format(s))
            assert_result = lc['assert_result']
            line = "assert {}, \'The {} must be {}!\'".format(
                s, get_value(layer, "key"), get_value(layer, "value"))
        else:
            s = "{} == {}".format(
                get_value(layer, "key"), get_value(layer, "value"))
            lc = locals()
            exec("assert_result = {}".format(s))
            assert_result = lc['assert_result']
            line = "assert {}, \'The {} must be {}!\'".format(
                s, get_value(layer, "key"), get_value(layer, "value"))
    else:
        raise Exception("Not implement yet!")
    if not assert_result:
        forward_func.extend(gen_codes([line], indent=indent))


def prim_check_dim(layer,
                   indent=1,
                   init_func=[],
                   forward_func=[],
                   layer_id=None,
                   different_attrs=None):
    lines = []
    dim = get_value(layer, "dim", different_attrs)
    lines.append("if {} < 0:".format(dim))
    lines.append("    {} = {} + {}".format(layer.outputs[
        0], dim, get_value(layer, "len", different_attrs)))
    lines.append("else:")
    lines.append("    {} = {}".format(layer.outputs[0], dim))
    forward_func.extend(gen_codes(lines, indent=indent))


def prim_constant(layer,
                  indent=1,
                  init_func=[],
                  forward_func=[],
                  layer_id=None,
                  different_attrs=None):
    line = "{} = {}".format(layer.outputs[0], layer.attrs["value"])
    forward_func.extend(gen_codes([line], indent=indent))


def prim_contain(layer,
                 indent=1,
                 init_func=[],
                 forward_func=[],
                 layer_id=None,
                 different_attrs=None,
                 is_return_line=False):
    line = "{} = {} in {}".format(layer.outputs[0],
                                  get_value(layer, "element", different_attrs),
                                  get_value(layer, "input", different_attrs))
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_dict(layer,
              indent=1,
              init_func=[],
              forward_func=[],
              layer_id=None,
              different_attrs=None):
    line = "{} = dict()".format(layer.outputs[0])
    forward_func.extend(gen_codes([line], indent=indent))


def prim_dict_construct(layer,
                        indent=1,
                        init_func=[],
                        forward_func=[],
                        layer_id=None,
                        different_attrs=None):
    lines = list()
    line = "{} = dict()".format(layer.outputs[0])
    lines.append(line)
    for i in range(len(layer.inputs)):
        line = "{}[{}] = {}".format(
            layer.outputs[0],
            get_value(layer, "key{}".format(i), different_attrs),
            get_value(layer, "value{}".format(i), different_attrs))
        lines.append(line)
    forward_func.extend(gen_codes(lines, indent=indent))


def prim_dict2values(layer,
                     indent=1,
                     init_func=[],
                     forward_func=[],
                     layer_id=None,
                     different_attrs=None):
    line = "{} = list({}.values())".format(
        layer.outputs[0], get_value(layer, "x", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_div(layer,
             indent=1,
             init_func=[],
             forward_func=[],
             layer_id=None,
             different_attrs=None):
    line = "{} = {} / {}".format(layer.outputs[0],
                                 get_value(layer, "x", different_attrs),
                                 get_value(layer, "y", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_eq(layer,
            indent=1,
            init_func=[],
            forward_func=[],
            layer_id=None,
            different_attrs=None,
            is_return_line=False):
    line = "{} = {} == {}".format(layer.outputs[0],
                                  get_value(layer, "x", different_attrs),
                                  get_value(layer, "y", different_attrs))
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_equal(layer,
               indent=1,
               init_func=[],
               forward_func=[],
               layer_id=None,
               different_attrs=None):
    line = "{} = {}".format(layer.outputs[0],
                            get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_exception(layer,
                   indent=1,
                   init_func=[],
                   forward_func=[],
                   layer_id=None,
                   different_attrs=None):
    line = "raise Exception({})".format(
        get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_float(layer,
               indent=1,
               init_func=[],
               forward_func=[],
               layer_id=None,
               different_attrs=None):
    line = "{} = float({})".format(layer.outputs[0],
                                   get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_floor(layer,
               indent=1,
               init_func=[],
               forward_func=[],
               layer_id=None,
               different_attrs=None):
    line = "{} = math.floor({})".format(layer.outputs[0],
                                        get_value(layer, "x", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_floordiv(layer,
                  indent=1,
                  init_func=[],
                  forward_func=[],
                  layer_id=None,
                  different_attrs=None):
    line = "{} = {} // {}".format(layer.outputs[0],
                                  get_value(layer, "x", different_attrs),
                                  get_value(layer, "y", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_format(layer,
                indent=1,
                init_func=[],
                forward_func=[],
                layer_id=None,
                different_attrs=None):
    line = ""
    if len(layer.inputs) == 3:
        line = "{} = {}.format({}, {})".format(
            layer.outputs[0],
            get_value(layer, "input0", different_attrs),
            get_value(layer, "input1", different_attrs),
            get_value(layer, "input2", different_attrs))
    elif len(layer.inputs) == 2:
        line = "{} = {}.format({})".format(
            layer.outputs[0],
            get_value(layer, "input0", different_attrs),
            get_value(layer, "input1", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_getitem(layer,
                 indent=1,
                 init_func=[],
                 forward_func=[],
                 layer_id=None,
                 different_attrs=None):
    line = "{} = {}[{}]".format(layer.outputs[0],
                                get_value(layer, "list", different_attrs),
                                get_value(layer, "index", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_gt(layer,
            indent=1,
            init_func=[],
            forward_func=[],
            layer_id=None,
            different_attrs=None,
            is_return_line=False):
    line = "{} = {} > {}".format(layer.outputs[0],
                                 get_value(layer, "x", different_attrs),
                                 get_value(layer, "y", different_attrs))
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_if(layer,
            indent=1,
            init_func=[],
            forward_func=[],
            layer_id=None,
            different_attrs=None):
    try:
        exec_s = None
        for line in forward_func:
            s = line.replace("    ", "")
            if s.startswith("{} = ".format(
                    get_value(layer, "input", different_attrs))):
                exec_s = s.split(" = ")[1]
        lc = locals()
        if exec_s is not None:
            exec("if_result = {}".format(exec_s))
        else:
            exec("if_result = {}".format(
                get_value(layer, "input", different_attrs)))
        if_result = lc['if_result']
        if if_result:
            block = layer.blocks[0]
        else:
            block = layer.blocks[1]
        if len(block.layers) > 0:
            b_init_lines, b_forward_lines = block.gen_code(indent=indent)
            init_func.extend(b_init_lines)
            forward_func.extend(b_forward_lines)
    except:
        line = "if {} :".format(get_value(layer, "input", different_attrs))
        forward_func.extend(gen_codes([line], indent=indent))
        block = layer.blocks[0]
        if len(block.layers) == 0:
            line = "pass"
            forward_func.extend(gen_codes([line], indent=indent + 1))
        else:
            b_init_lines, b_forward_lines = block.gen_code(indent=indent + 1)
            init_func.extend(b_init_lines)
            forward_func.extend(b_forward_lines)
        block = layer.blocks[1]
        if len(block.layers) > 0:
            b_init_lines, b_forward_lines = block.gen_code(indent=indent + 1)
            if len(b_forward_lines) != 0:
                line = "else:"
                forward_func.extend(gen_codes([line], indent=indent))
            init_func.extend(b_init_lines)
            forward_func.extend(b_forward_lines)


def prim_int(layer,
             indent=1,
             init_func=[],
             forward_func=[],
             layer_id=None,
             different_attrs=None):
    line = "{} = int({})".format(layer.outputs[0],
                                 get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_is(layer,
            indent=1,
            init_func=[],
            forward_func=[],
            layer_id=None,
            different_attrs=None,
            is_return_line=False):
    line = "{} = {} is {}".format(layer.outputs[0],
                                  get_value(layer, "x", different_attrs),
                                  get_value(layer, "y", different_attrs))
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_isinstance(layer,
                    indent=1,
                    init_func=[],
                    forward_func=[],
                    layer_id=None,
                    different_attrs=None,
                    is_return_line=False):
    line = "{} = isinstance({}, {})".format(
        layer.outputs[0],
        get_value(layer, "input", different_attrs), layer.attrs["cls"])
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_isnot(layer,
               indent=1,
               init_func=[],
               forward_func=[],
               layer_id=None,
               different_attrs=None,
               is_return_line=False):
    line = "{} = {} is not {}".format(layer.outputs[0],
                                      get_value(layer, "x", different_attrs),
                                      get_value(layer, "y", different_attrs))
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_le(layer,
            indent=1,
            init_func=[],
            forward_func=[],
            layer_id=None,
            different_attrs=None,
            is_return_line=False):
    line = "{} = {} <= {}".format(layer.outputs[0],
                                  get_value(layer, "x", different_attrs),
                                  get_value(layer, "y", different_attrs))
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_len(layer,
             indent=1,
             init_func=[],
             forward_func=[],
             layer_id=None,
             different_attrs=None):
    line = "{} = len({})".format(layer.outputs[0],
                                 get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_len2list(layer,
                  indent=1,
                  init_func=[],
                  forward_func=[],
                  layer_id=None,
                  different_attrs=None):
    lines = []
    lines.append("{} = []".format(layer.outputs[0]))
    lines.append("for i in range({}):".format(
        get_value(layer, "len", different_attrs)))
    lines.append("    {}.append(i)".format(layer.outputs[0]))
    forward_func.extend(gen_codes(lines, indent=indent))


def prim_lt(layer,
            indent=1,
            init_func=[],
            forward_func=[],
            layer_id=None,
            different_attrs=None,
            is_return_line=False):
    line = "{} = {} < {}".format(layer.outputs[0],
                                 get_value(layer, "x", different_attrs),
                                 get_value(layer, "y", different_attrs))
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_list(layer,
              indent=1,
              init_func=[],
              forward_func=[],
              layer_id=None,
              different_attrs=None):
    input_len = len(layer.inputs) + len(layer.attrs)
    inputs_list = list()
    for i in range(input_len):
        inputs_list.append(
            get_value(layer, "input{}".format(i), different_attrs))
    inputs_str = ', '.join(inputs_list)
    line = "{} = [{}]".format(layer.outputs[0], inputs_str)
    forward_func.extend(gen_codes([line], indent=indent))


def prim_list_unpack(layer,
                     indent=1,
                     init_func=[],
                     forward_func=[],
                     layer_id=None,
                     different_attrs=None):
    line = "{} = {}".format(", ".join(layer.outputs),
                            get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_loop(layer,
              indent=1,
              init_func=[],
              forward_func=[],
              layer_id=None,
              different_attrs=None):
    loop_range = get_value(layer, "input", different_attrs)
    line = "for {} in range({}):".format(layer.outputs[1], loop_range)
    forward_func.extend(gen_codes([line], indent=indent))
    block = layer.blocks[0]
    b_init_lines, b_forward_lines = block.gen_code(indent=indent + 1)
    init_func.extend(b_init_lines)
    forward_func.extend(b_forward_lines)


def prim_min(layer,
             indent=1,
             init_func=[],
             forward_func=[],
             layer_id=None,
             different_attrs=None):
    line = "{} = min({})".format(layer.outputs[0],
                                 get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_mul(layer,
             indent=1,
             init_func=[],
             forward_func=[],
             layer_id=None,
             different_attrs=None):
    line = "{} = {} * {}".format(layer.outputs[0],
                                 get_value(layer, "x", different_attrs),
                                 get_value(layer, "y", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_ne(layer,
            indent=1,
            init_func=[],
            forward_func=[],
            layer_id=None,
            different_attrs=None,
            is_return_line=False):
    line = "{} = {} != {}".format(layer.outputs[0],
                                  get_value(layer, "x", different_attrs),
                                  get_value(layer, "y", different_attrs))
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_neg(layer,
             indent=1,
             init_func=[],
             forward_func=[],
             layer_id=None,
             different_attrs=None):
    line = "{} = -{}".format(layer.outputs[0],
                             get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_not(layer,
             indent=1,
             init_func=[],
             forward_func=[],
             layer_id=None,
             different_attrs=None,
             is_return_line=False):
    line = "{} = not {}".format(layer.outputs[0],
                                get_value(layer, "input", different_attrs))
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_or(layer,
            indent=1,
            init_func=[],
            forward_func=[],
            layer_id=None,
            different_attrs=None,
            is_return_line=False):
    line = "{} = {} or {}".format(layer.outputs[0],
                                  get_value(layer, "x", different_attrs),
                                  get_value(layer, "y", different_attrs))
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_remainder(layer,
                   indent=1,
                   init_func=[],
                   forward_func=[],
                   layer_id=None,
                   different_attrs=None,
                   is_return_line=False):
    line = "{} = {} % {}".format(layer.outputs[0],
                                 get_value(layer, "x", different_attrs),
                                 get_value(layer, "y", different_attrs))
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_replaceitem(layer,
                     indent=1,
                     init_func=[],
                     forward_func=[],
                     layer_id=None,
                     different_attrs=None):
    line = "{}[{}] = {}".format(
        get_value(layer, "list", layer_id, different_attrs),
        get_value(layer, "index", layer_id, different_attrs),
        get_value(layer, "item", layer_id, different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_requires_grad(layer,
                       indent=1,
                       init_func=[],
                       forward_func=[],
                       layer_id=None,
                       different_attrs=None):
    line = "{} = not {}.stop_gradient".format(
        layer.outputs[0], get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_rsub(layer,
              indent=1,
              init_func=[],
              forward_func=[],
              layer_id=None,
              different_attrs=None):
    line = "{} = {} - {} * {}".format(
        layer.outputs[0],
        get_value(layer, "y", different_attrs),
        get_value(layer, "x", different_attrs),
        get_value(layer, "alpha", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_select(layer,
                indent=1,
                init_func=[],
                forward_func=[],
                layer_id=None,
                different_attrs=None):
    line = "{} = {}[".format(layer.outputs[0],
                             get_value(layer, "input", different_attrs))
    for dim in range(layer.attrs["dim"]):
        line += ":, "
    line += (get_value(layer, "index", different_attrs) + "]")
    forward_func.extend(gen_codes([line], indent=indent))


def prim_set_attr(layer,
                  indent=1,
                  init_func=[],
                  forward_func=[],
                  layer_id=None,
                  different_attrs=None):
    line = "{} = {}".format(layer.outputs[0],
                            get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_set_item(layer,
                  indent=1,
                  init_func=[],
                  forward_func=[],
                  layer_id=None,
                  different_attrs=None):
    line = "{}[{}] = {}".format(
        get_value(layer, "dict", different_attrs),
        get_value(layer, "key", different_attrs),
        get_value(layer, "value", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_shape(layer,
               indent=1,
               init_func=[],
               forward_func=[],
               layer_id=None,
               different_attrs=None):
    line = "{} = {}.shape".format(layer.outputs[0],
                                  get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_shape_dim(layer,
                   indent=1,
                   init_func=[],
                   forward_func=[],
                   layer_id=None,
                   different_attrs=None):
    line = "{} = {}.shape[{}]".format(
        layer.outputs[0],
        get_value(layer, "input", different_attrs),
        get_value(layer, "dim", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_slice(layer,
               indent=1,
               init_func=[],
               forward_func=[],
               layer_id=None,
               different_attrs=None):
    line = "{} = {}[{}: {}: {}]".format(
        layer.outputs[0],
        get_value(layer, "input", different_attrs),
        get_value(layer, "start", different_attrs),
        get_value(layer, "end", different_attrs),
        get_value(layer, "step", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_startswith(layer,
                    indent=1,
                    init_func=[],
                    forward_func=[],
                    layer_id=None,
                    different_attrs=None,
                    is_return_line=False):
    line = "{} = {}.startswith({})".format(
        layer.outputs[0],
        get_value(layer, "input", different_attrs),
        get_value(layer, "start_str", different_attrs))
    if is_return_line:
        return line.split(" = ")[1]
    forward_func.extend(gen_codes([line], indent=indent))


def prim_str(layer,
             indent=1,
             init_func=[],
             forward_func=[],
             layer_id=None,
             different_attrs=None):
    line = "{} = str({})".format(layer.outputs[0],
                                 get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_sub(layer,
             indent=1,
             init_func=[],
             forward_func=[],
             layer_id=None,
             different_attrs=None):
    if int(float(get_value(layer, "alpha", different_attrs))) == 1:
        line = "{} = {} - {}".format(layer.outputs[0],
                                     get_value(layer, "x", different_attrs),
                                     get_value(layer, "y", different_attrs))
    else:
        line = "{} = {} - {} * {}".format(
            layer.outputs[0],
            get_value(layer, "x", different_attrs),
            get_value(layer, "alpha", different_attrs),
            get_value(layer, "y", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_tuple(layer,
               indent=1,
               init_func=[],
               forward_func=[],
               layer_id=None,
               different_attrs=None):
    input_len = len(layer.inputs) + len(layer.attrs)
    inputs_list = list()
    for i in range(input_len):
        inputs_list.append(
            get_value(layer, "input{}".format(i), different_attrs))
    inputs_str = ', '.join(inputs_list)
    line = "{} = ({})".format(layer.outputs[0], inputs_str)
    forward_func.extend(gen_codes([line], indent=indent))


def prim_tuple_unpack(layer,
                      indent=1,
                      init_func=[],
                      forward_func=[],
                      layer_id=None,
                      different_attrs=None):
    outputs_str = ', '.join(layer.outputs)
    line = "{} = {}".format(outputs_str,
                            get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_type(layer,
              indent=1,
              init_func=[],
              forward_func=[],
              layer_id=None,
              different_attrs=None):
    line = "{} = {}.dtype".format(layer.outputs[0],
                                  get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_var2list(layer,
                  indent=1,
                  init_func=[],
                  forward_func=[],
                  layer_id=None,
                  different_attrs=None):
    line = "{} = {}.numpy().tolist()".format(
        layer.outputs[0], get_value(layer, "input", different_attrs))
    forward_func.extend(gen_codes([line], indent=indent))


def prim_warnings(layer,
                  indent=1,
                  init_func=[],
                  forward_func=[],
                  layer_id=None,
                  different_attrs=None):
    lines = ["import warnings"]
    line = "warnings.warn({}, stacklevel={})".format(
        get_value(layer, "input", different_attrs), layer.attrs["stacklevel"])
    lines.append(line)
    forward_func.extend(gen_codes(lines, indent=indent))
