import util

class JittedVersion:

    """
    
    A structure for holding the generated code for one instance of a
    jitted function.  There may be many JittedVersions for each
    function, because we may have jitted different versions that
    operate on different assumptions about the types of their
    parameters and the like.

    The fields are broken into groups that are used at different periods
    throughout the lifetime of the compiler.
    
    """

    def __init__ (self, log, funcname, paramass, startblk, stopblk):
        
        ### Fields used prior to code generation

        self.log = log
        self.funcname = funcname
        self.startblk = startblk               # the basic block graph
        self.stopblk = stopblk
        self.params = paramass                 # assumptions about params
        self.assumptions = util.ObjectSet ()   # list of KEdge objects

        ### Fields are used during code generation before final linking: 
        
        # Pointer to the FunctionInfo object.  This exists only while this
        # particular function is being generated.
        self.funcinfo = None
        
        # Pointer to list of pending patches to this function.  This
        # occurs when a generated function A tries to call generated
        # function B but B has not yet been completed.  In that case,
        # a "pending link" object is added to this vector, and the
        # link is later completed by calling
        # Generated_code.complete_link().  See that function for more
        # information.
        self.pending = ()

        ### Result:

        # A machinedefn.Generated_code object.
        self.generated_code = None
        
        pass

    def add_assumption (self, assumption):
        self.assumptions += assumption
        return

    def get_assumptions (self):
        return self.assumptions

    def get_start_block (self):
        return self.startblk

    def set_start_block (self, startblk):
        self.startblk = startblk
        return

    def get_stop_block (self):
        return self.stopblk

    def get_param_assumptions (self):

        """ Returns a list of KEdge objects encoding our assumptions about
        the types of our parameters. """
        
        return self.params

    def get_function_info (self):
        """ Access the function info from the machine def'n.  See
        codegen.py."""
        return self.funcinfo

    def set_function_info (self, funcinfo):
        
        """ Set the function info object from the machine definition.
        Set in codegen.py. """
        
        self.funcinfo = funcinfo
        return

    def add_pending (self, obj):

        """ Adds a link to the list of pending links.  When the generated
        code is completed, we will call self.generated_code.complete_link()
        with each of these objects.  This function must not be called
        after set_generated_code() has been called. """

        assert not self.generated_code
        if not self.pending:
            self.pending = [ obj ]
        else:
            self.pending.append (obj)
            pass
        pass

    def set_generated_code (self, gencode):
        
        """ Set the generated code information.  Also clears any pending
        links that have accumulated.  Called from codegen.py. """

        ind = self.log.indent ("set_generated_code")

        for link in self.pending:
            self.log.low ("complete_link gencode=%s link=%s", gencode, link)
            gencode.complete_link (link)
            pass

        self.generated_code = gencode

        # clear out the fields that were used while this code was being
        # generated, but are now no longer relevant:
        self.pending = None
        self.startblk = None
        self.stopblk = None
        self.funcinfo = None

        del ind
        
        return

    def get_callable_object (self):
        return self.generated_code.callable

    def __str__ (self):

        # Construct a string describing the assumptions etc
        return "<Jitted:%s:%x>" % (self.funcname, id (self))

    pass
