# Path: pykit/ir/value.py
# class Value(object):
# class Module(Value):
# class Function(Value):
# class GlobalValue(Value):
# class Block(Value):
# class Local(Value):
# class FuncArg(Local):
# class Operation(Local):
# class Constant(Value):
# class Undef(Value):
#     def __init__(self, globals=None, functions=None, temper=None):
#     def add_function(self, function):
#     def add_global(self, globalvalue):
#     def get_function(self, funcname):
#     def get_global(self, gvname):
#     def __init__(self, name, argnames, type, temper=None):
#     def args(self):
#     def startblock(self):
#     def exitblock(self):
#     def ops(self):
#     def new_block(self, label, ops=None, after=None):
#     def add_block(self, block, after=None):
#     def get_block(self, label):
#     def del_block(self, block):
#     def get_arg(self, argname):
#     def result(self):
#     def add_op(self, op):
#     def reset_uses(self):
#     def __repr__(self):
#     def __init__(self, name, type, external=False, address=None, value=None):
#     def result(self):
#     def __init__(self, name, parent=None, ops=None):
#     def opcodes(self):
#     def optypes(self):
#     def __iter__(self):
#     def append(self, op):
#     def extend(self, ops):
#     def result(self):
#     def leaders(self):
#     def terminator(self):
#     def is_terminated(self):
#     def __lt__(self, other):
#     def __repr__(self):
#     def function(self):
#     def replace_uses(self, dst):
#             def replace(op):
#     def __init__(self, func, name, type):
#     def function(self):
#     def __repr__(self):
#     def __init__(self, opcode, type, args, result=None, parent=None):
#     def uses(self):
#     def args(self):
#     def insert_before(self, op):
#     def insert_after(self, op):
#     def replace_op(self, opcode, args, type=None):
#     def replace_args(self, replacements):
#     def replace(self, op):
#     def replace_list(self, op):
#     def set_args(self, args):
#     def delete(self):
#     def unlink(self):
#     def add_metadata(self, metadata):
#     def function(self):
#     def block(self):
#     def operands(self):
#     def symbols(self):
#     def _set_registers(self, *ops):
#     def __repr__(self):
#     def __iter__(self):
# def _add_args(uses, newop, args):
#     def add(arg):
# def _del_args(uses, oldop, args):
#     def remove(arg):
#     def __init__(self, pyval, type=None):
#     def replace_op(self, opcode, args, type=None):
#     def replace(self, newop):
#     def const(self):
#     def __repr__(self):
#     def __init__(self, type):
#     def __eq__(self, other):
#     def __hash__(self):
# 
# Path: pykit/utils/convenience.py
# def nestedmap(f, args):
#     """
#     Map `f` over `args`, which contains elements or nested lists
#     """
#     result = []
#     for arg in args:
#         if isinstance(arg, list):
#             result.append(list(map(f, arg)))
#         else:
#             result.append(f(arg))
# 
#     return result
# 
# def make_temper():
#     """Return a function that returns temporary names"""
#     temps = collections.defaultdict(int)
# 
#     def temper(name=""):
#         varname = name.rstrip(string.digits)
#         count = temps[varname]
#         temps[varname] += 1
#         if varname and count == 0:
#             return varname
#         return varname + str(count)
# 
#     return temper


from functools import partial
from pykit.ir import (Module, Value, Function, Block, Constant, Op,
                      GlobalValue, Undef, FuncArg)
from pykit.utils import nestedmap, make_temper
# ______________________________________________________________________

def copy_module(module, temper=None):
    raise NotImplementedError("not finished, needs to insert all functions"
                              "in valuemap first")

    new_module = Module(temper=temper)
    valuemap = {}

    ### Copy Globals
    for name, gv in module.globals.iteritems():
        name = new_module.temp(name)
        new_global = GlobalValue(name, gv.type, gv.external, gv.address, gv.value)
        new_module.add_global(new_global)

        valuemap[gv] = new_global

    ### Copy Functions
    for name, func in module.functions.iteritems():
        new_func = copy_function(func, module=new_module)
        new_func.name = new_module.temp(name)
        new_module.add_function(new_func)

        valuemap[func] = new_func

    return new_module

def copy_function(func, temper=None, module=None):
    """Copy a Function. `temper` may be given to"""
    temper = temper or make_temper()

# Path: pykit/ir/value.py
# class Value(object):
# class Module(Value):
# class Function(Value):
# class GlobalValue(Value):
# class Block(Value):
# class Local(Value):
# class FuncArg(Local):
# class Operation(Local):
# class Constant(Value):
# class Undef(Value):
#     def __init__(self, globals=None, functions=None, temper=None):
#     def add_function(self, function):
#     def add_global(self, globalvalue):
#     def get_function(self, funcname):
#     def get_global(self, gvname):
#     def __init__(self, name, argnames, type, temper=None):
#     def args(self):
#     def startblock(self):
#     def exitblock(self):
#     def ops(self):
#     def new_block(self, label, ops=None, after=None):
#     def add_block(self, block, after=None):
#     def get_block(self, label):
#     def del_block(self, block):
#     def get_arg(self, argname):
#     def result(self):
#     def add_op(self, op):
#     def reset_uses(self):
#     def __repr__(self):
#     def __init__(self, name, type, external=False, address=None, value=None):
#     def result(self):
#     def __init__(self, name, parent=None, ops=None):
#     def opcodes(self):
#     def optypes(self):
#     def __iter__(self):
#     def append(self, op):
#     def extend(self, ops):
#     def result(self):
#     def leaders(self):
#     def terminator(self):
#     def is_terminated(self):
#     def __lt__(self, other):
#     def __repr__(self):
#     def function(self):
#     def replace_uses(self, dst):
#             def replace(op):
#     def __init__(self, func, name, type):
#     def function(self):
#     def __repr__(self):
#     def __init__(self, opcode, type, args, result=None, parent=None):
#     def uses(self):
#     def args(self):
#     def insert_before(self, op):
#     def insert_after(self, op):
#     def replace_op(self, opcode, args, type=None):
#     def replace_args(self, replacements):
#     def replace(self, op):
#     def replace_list(self, op):
#     def set_args(self, args):
#     def delete(self):
#     def unlink(self):
#     def add_metadata(self, metadata):
#     def function(self):
#     def block(self):
#     def operands(self):
#     def symbols(self):
#     def _set_registers(self, *ops):
#     def __repr__(self):
#     def __iter__(self):
# def _add_args(uses, newop, args):
#     def add(arg):
# def _del_args(uses, oldop, args):
#     def remove(arg):
#     def __init__(self, pyval, type=None):
#     def replace_op(self, opcode, args, type=None):
#     def replace(self, newop):
#     def const(self):
#     def __repr__(self):
#     def __init__(self, type):
#     def __eq__(self, other):
#     def __hash__(self):
# 
# Path: pykit/utils/convenience.py
# def nestedmap(f, args):
#     """
#     Map `f` over `args`, which contains elements or nested lists
#     """
#     result = []
#     for arg in args:
#         if isinstance(arg, list):
#             result.append(list(map(f, arg)))
#         else:
#             result.append(f(arg))
# 
#     return result
# 
# def make_temper():
#     """Return a function that returns temporary names"""
#     temps = collections.defaultdict(int)
# 
#     def temper(name=""):
#         varname = name.rstrip(string.digits)
#         count = temps[varname]
#         temps[varname] += 1
#         if varname and count == 0:
#             return varname
#         return varname + str(count)
# 
#     return temper


# Path: pykit/ir/copying.py
from functools import partial
from pykit.ir import (Module, Value, Function, Block, Constant, Op,
                      GlobalValue, Undef, FuncArg)
from pykit.utils import nestedmap, make_temper

# ______________________________________________________________________

def copy_module(module, temper=None):
    raise NotImplementedError("not finished, needs to insert all functions"
                              "in valuemap first")

    new_module = Module(temper=temper)
    valuemap = {}

    ### Copy Globals
    for name, gv in module.globals.iteritems():
        name = new_module.temp(name)
        new_global = GlobalValue(name, gv.type, gv.external, gv.address, gv.value)
        new_module.add_global(new_global)

        valuemap[gv] = new_global

    ### Copy Functions
    for name, func in module.functions.iteritems():
        new_func = copy_function(func, module=new_module)
        new_func.name = new_module.temp(name)
        new_module.add_function(new_func)

        valuemap[func] = new_func

    return new_module

def copy_function(func, temper=None, module=None):
    """Copy a Function. `temper` may be given to"""
    temper = temper or make_temper()

    f = Function(func.name, list(func.argnames), func.type, temper=temper)