def code_gen(self):

        if getattr(self, 'struct_code', False):
            return self.struct_code

        no_recycling = self.no_recycling

        c_support_code_apply = []
        c_init_code_apply = []

        symbol = {}

        # (init_)tasks contains a list of pairs (Op/Variable, task_name)
        # e.g. (x, 'get') or (x+y, 'code')
        init_tasks = []
        tasks = []

        # (init_)blocks contain CodeBlock instances. There is a direct
        # correspondance with (init_)tasks.
        init_blocks = []
        blocks = []

        failure_var = "__failure"
        id = 1

        for variable in self.variables:
            sub = dict(failure_var=failure_var)

            # it might be possible to inline constant variables as C literals
            # policy = [[what to declare in the struct,
            #            what to do at construction,
            #            what to do at destruction],
            #           [what to declare in each run,
            #            what to do at the beginning of each run,
            #            what to do at the end of each run]]
            if variable in self.consts:
                symbol[variable] = ("(" + variable.type.c_literal(
                    variable.data) + ")")
                continue
            elif variable in self.inputs:
                # We need to extract the new inputs at each run
                # they do not need to be relayed to Python, so we don't sync.
                # If the variable is both an input and an output, there is
                # no need to synchronize either, it is already up-to-date.
                policy = [[get_nothing, get_nothing, get_nothing],
                          [get_c_declare, get_c_extract, get_c_cleanup]]
            elif variable in self.orphans:
                if not isinstance(variable, graph.Constant):
                    raise TypeError("All orphans to CLinker must be Constant"
                                    " instances.", variable)
                # orphans are not inputs so we'll just get fetch them
                # when we initialize the struct and assume they stay
                # the same
                policy = [[get_c_declare, get_c_extract, get_c_cleanup],
                          [get_nothing, get_nothing, get_nothing]]
            elif variable in self.temps:
                # temps don't need to be extracted from Python, so we
                # call c_init rather than c_extract they do not need
                # to be relayed to Python, so we don't sync
                if variable.type.c_is_simple() or variable in no_recycling:
                    policy = [[get_nothing, get_nothing, get_nothing],
                              [get_c_declare, get_c_init, get_c_cleanup]]
                else:
                    # it is useful for complex temps to reuse storage
                    # at each run, so we only clean up in the
                    # destructor
                    policy = [[get_c_declare, get_c_init, get_c_cleanup],
                              [get_nothing, get_nothing, get_nothing]]
            elif variable in self.outputs:
                if variable.type.c_is_simple() or variable in no_recycling:
                    # Do not extract output from Python
                    policy = [[get_nothing, get_nothing, get_nothing],
                              [get_c_declare, get_c_init,
                                  (get_c_sync, get_c_cleanup)]]
                else:
                    # We try to use the output that is pre-allocated.
                    # The linker will usually just reuse the storage
                    # from last run, but in the first execution,
                    # it will be None.
                    # We clean-up at each run to enable garbage collection
                    # in the Linker.
                    policy = [[get_nothing, get_nothing, get_nothing],
                              [get_c_declare, get_c_extract_out,
                                  (get_c_sync, get_c_cleanup)]]
            else:
                raise Exception("what the fuck")

            builder, block = struct_variable_codeblocks(variable, policy,
                                                        id, symbol, sub)

            # each Variable generates two CodeBlocks, one to
            # declare/initialize/destroy struct variables and the
            # other to declare/extract/cleanup each time the function
            # is run.
            # Typically, only one of the two actually does anything
            # (see all the possible combinations above)

            init_tasks.append((variable, 'init', id))
            init_blocks.append(builder)

            tasks.append((variable, 'get', id + 1))
            blocks.append(block)

            id += 2

        for node_num, node in enumerate(self.node_order):

            sub = dict(failure_var=failure_var)

            params = node.run_params()
            if params is not graph.NoParams:
                params_var = symbol[self.node_params[params]]

            # The placeholder will be replaced by a hash of the entire
            # code (module + support code) in DynamicModule.code.
            # This ensures that, when defining functions in support code,
            # we cannot have two different functions, in different modules,
            # that have the same name.
            # It was problematic, in particular, on Mac OS X (10.6 and 10.7)
            # when defining CUDA kernels (with Cuda 4.2 and 5.0). See gh-1172.
            name = "node_<<<<HASH_PLACEHOLDER>>>>_%i" % node_num
            isyms = [symbol[r] for r in node.inputs]
            osyms = [symbol[r] for r in node.outputs]

            # Make the CodeBlock for c_code
            sub['id'] = id
            sub['fail'] = failure_code(sub)
            if params is not graph.NoParams:
                sub['params'] = params_var

            sub_struct = dict()
            sub_struct['id'] = id + 1
            sub_struct['fail'] = failure_code_init(sub)
            if params is not graph.NoParams:
                # Since params inputs are always constants they are
                # guaranteed to be available in the struct init code.
                sub_struct['params'] = params_var

            struct_support = ""
            struct_init = ""
            struct_cleanup = ""

            op = node.op
            # type-specific support code
            try:
                c_support_code_apply.append(op.c_support_code_apply(node,
                                                                    name))
            except utils.MethodNotDefined:
                pass
            else:
                # The following will be executed if the "try" block succeeds
                assert isinstance(c_support_code_apply[-1], string_types), (
                    str(node.op) +
                    " didn't return a string for c_support_code_apply")

            try:
                c_init_code_apply.append(op.c_init_code_apply(node, name))
            except utils.MethodNotDefined:
                pass
            else:
                assert isinstance(c_init_code_apply[-1], string_types), (
                    str(node.op) +
                    " didn't return a string for c_init_code_apply")

            try:
                struct_init = op.c_init_code_struct(node, name, sub_struct)
                assert isinstance(struct_init, string_types), (
                    str(node.op) +
                    " didn't return a string for c_init_code_struct")
            except utils.MethodNotDefined:
                pass

            try:
                struct_support = op.c_support_code_struct(node, name)
                assert isinstance(struct_support, string_types), (
                    str(node.op) +
                    " didn't return a string for c_support_code_struct")
            except utils.MethodNotDefined:
                pass

            try:
                struct_cleanup = op.c_cleanup_code_struct(node, name)
                assert isinstance(struct_cleanup, string_types), (
                    str(node.op) +
                    " didn't return a string for c_cleanup_code_struct")
            except utils.MethodNotDefined:
                pass

            # emit c_code
            try:
                behavior = op.c_code(node, name, isyms, osyms, sub)
            except utils.MethodNotDefined:
                raise NotImplementedError("%s cannot produce C code" % op)
            assert isinstance(behavior, string_types), (
                str(node.op) + " didn't return a string for c_code")
            # To help understand what is following. It help read the c code.
            # This prevent different op that generate the same c code
            # to be merged, I suppose this won't happen...
            behavior = ("// Op class " + node.op.__class__.__name__ + "\n" +
                        behavior)

            try:
                cleanup = op.c_code_cleanup(node, name, isyms, osyms, sub)
            except utils.MethodNotDefined:
                cleanup = ""

            _logger.info('compiling un-versioned Apply %s', str(node))

            blocks.append(CodeBlock("", behavior, cleanup, sub))
            tasks.append((node, 'code', id))
            id += 1

            init_blocks.append(CodeBlock(struct_support, struct_init,
                                         struct_cleanup, {'id': id}))
            init_tasks.append((node, 'init', id))
            id += 1

        # List of arg names for use in struct_gen. Note the call to
        # uniq: duplicate inputs must only be passed once because they
        # are mapped to the same name.  Duplicates are defined by (a
        # is b), rather than (a==b) since Constant instances can
        # compare equal to equivalent Constant instances.
        args = []
        args += ["storage_%s" % symbol[variable] for variable
                 in utils.uniq(self.inputs + self.outputs + self.orphans)]

        # <<<<HASH_PLACEHOLDER>>>> will be replaced by a hash of the whole
        # code in the file, including support code, in DynamicModule.code.
        struct_name = '__struct_compiled_op_%s' % '<<<<HASH_PLACEHOLDER>>>>'
        struct_code = struct_gen(args, init_blocks, blocks,
                                 dict(failure_var=failure_var,
                                      name=struct_name))

        self.struct_code = struct_code
        self.struct_name = struct_name
        self.args = args
        self.r2symbol = symbol
        self.init_blocks = init_blocks
        self.init_tasks = init_tasks
        self.blocks = blocks
        self.tasks = tasks
        all_info = self.inputs + self.outputs + self.orphans
        self.c_support_code_apply = c_support_code_apply
        self.c_init_code_apply = c_init_code_apply

        if (self.init_tasks, self.tasks) != self.get_init_tasks():
            print("init_tasks\n", self.init_tasks, file=sys.stderr)
            print(self.get_init_tasks()[0], file=sys.stderr)
            print("tasks\n", self.tasks, file=sys.stderr)
            print(self.get_init_tasks()[1], file=sys.stderr)
            assert (self.init_tasks, self.tasks) == self.get_init_tasks()

        # List of indices that should be ignored when passing the arguments
        # (basically, everything that the previous call to uniq eliminated)
        self.dupidx = [i for i, x in enumerate(all_info)
                       if all_info.count(x) > 1 and all_info.index(x) != i]
        return self.struct_code
WRITEME
dataset/ETHPy150Open rizar/attention-lvcsr/libs/Theano/theano/gof/cc.py/CLinker.code_gen