Ejemplo n.º 1
0
 def clone(self):
     # Use node factory? (add as a field to node)
     decl = self.decl  # immutable?
     imports = collections.clone_collection(self.imports)
     payloads = collections.clone_collection(self.payloads)
     globalps = collections.clone_collection(self.globalps)
     localps = collections.clone_collection(self.localps)
     clone = Module(self.decl, imports, payloads, globalps, localps)
     return clone
Ejemplo n.º 2
0
 def clone(self):
     # Use node factory? (add as a field to node)
     decl = self.decl  # immutable?
     imports = collections.clone_collection(self.imports)
     payloads = collections.clone_collection(self.payloads)
     globalps = collections.clone_collection(self.globalps)
     localps = collections.clone_collection(self.localps)
     clone = Module(self.decl, imports, payloads, globalps, localps)
     return clone
Ejemplo n.º 3
0
def check_wellformedness_visit(checker, node_):
    #context_ = checker.get_context()
    visited = _context_visit_children_and_cache_contexts(checker, node_)
    contexts = _peek_cached_contexts(visited)
    subj = get_subject(visited)  # string

    # Here we first do the checks involving just the information collected from
    # this choice (push_globalchoice clears enabledroles). Information from
    # parent is carried over to the new context later below.
    #
    # Map from role_ name (string) to set of enabling op (Section 4.6.6 --
    # initial operators) names (strings) -- values set in globalmessagetransfer
    enabled = collections.clone_collection(contexts[0].get_enabled_roles())
    for c in contexts[1:]:
        tmp = c.get_enabled_roles()
        # Section 4.6.6 -- same set of roles occur in each block
        if set(tmp.keys()) != set(enabled.keys()):
            util.report_error("Bad choice block: " + ' ' +
                              str(enabled.keys()) + str(tmp.keys()))
            # + "\n" + util.pretty_print(c.getnode()))
        for role_, ops in tmp.items():
            #if not(ops == None):
            if role_ != subj:
                # Should be generalised for all roles that are already enabled,
                # not just the subject?  # No: already taken care of by the fact
                # that enabled records only the initial enabling ops (added in
                # globalmessagetransfer), not all operators  # So here maybe
                # better to use "if not enabled"?
                for op in ops:
                    # Section 4.6.6 -- initial operators in each block for each
                    # role_ are disjoint
                    if op in enabled[role_]:
                        util.report_error("Bad choice operator: " + op)
                    enabled[role_].add(op)
    return visited
Ejemplo n.º 4
0
def check_wellformedness_visit(checker, node_):
    #context_ = checker.get_context()
    visited = _context_visit_children_and_cache_contexts(checker, node_)
    contexts = _peek_cached_contexts(visited)
    subj = get_subject(visited)         # string

    # Here we first do the checks involving just the information collected from
    # this choice (push_globalchoice clears enabledroles). Information from
    # parent is carried over to the new context later below.
    #
    # Map from role_ name (string) to set of enabling op (Section 4.6.6 --
    # initial operators) names (strings) -- values set in globalmessagetransfer
    enabled = collections.clone_collection(contexts[0].get_enabled_roles())
    for c in contexts[1:]:
        tmp = c.get_enabled_roles()
        # Section 4.6.6 -- same set of roles occur in each block
        if set(tmp.keys()) != set(enabled.keys()):
            util.report_error("Bad choice block: " + ' '
                             + str(enabled.keys()) + str(tmp.keys()))
                             # + "\n" + util.pretty_print(c.getnode()))
        for role_, ops in tmp.items():
            #if not(ops == None):
            if role_ != subj:
                # Should be generalised for all roles that are already enabled,
                # not just the subject?  # No: already taken care of by the fact
                # that enabled records only the initial enabling ops (added in
                # globalmessagetransfer), not all operators  # So here maybe
                # better to use "if not enabled"?
                for op in ops:
                    # Section 4.6.6 -- initial operators in each block for each
                    # role_ are disjoint
                    if op in enabled[role_]:
                        util.report_error("Bad choice operator: " + op)
                    enabled[role_].add(op)
    return visited
def check_wellformedness_visit(checker, node_):
    context = checker.get_context()
    visited = _context_visit_children_and_cache_contexts(checker, node_)
    contexts = _peek_cached_contexts(visited)

    # Section 4.6.8 -- potential operators and sig parameters
    ops = collections.clone_collection(contexts[0].get_operators())
    # includes sig parameters
    for c in contexts[1:]:
        tmp = c.get_operators()
        for (src, dest) in tmp.keys():
            if (src, dest) in ops.keys():
                us = ops[(src, dest)]
                them = tmp[(src, dest)]
                # Section 4.6.8 -- potential operators and parameters disjoint
                # between each block
                if not us.isdisjoint(them):
                    util.report_error("Bad parallel operator(s): " + \
                                      str(us & them))
                ops[(src, dest)] = us | them  # set union
            else:
                ops[(src, dest)] = tmp[(src, dest)]

    return visited
Ejemplo n.º 6
0
def check_wellformedness_visit(checker, node_):
    context = checker.get_context()
    visited = _context_visit_children_and_cache_contexts(checker, node_)
    contexts = _peek_cached_contexts(visited)

    # Section 4.6.8 -- potential operators and sig parameters
    ops = collections.clone_collection(contexts[0].get_operators())
        # includes sig parameters
    for c in contexts[1:]:
        tmp = c.get_operators()
        for (src, dest) in tmp.keys():
            if (src, dest) in ops.keys():
                us = ops[(src, dest)]
                them = tmp[(src, dest)]
                # Section 4.6.8 -- potential operators and parameters disjoint
                # between each block
                if not us.isdisjoint(them):
                    util.report_error("Bad parallel operator(s): " + \
                                      str(us & them))
                ops[(src, dest)] = us | them  # set union
            else:
                ops[(src, dest)] = tmp[(src, dest)]

    return visited
Ejemplo n.º 7
0
def context_visitor_leave(cv, node_):
    # Still the "original context" on entering the Choice (not yet updated with
    # any information from visiting block children)
    #
    # Perhaps instead clone the parent context (the context before entering this
    # choice)?
    clone = cv.get_context().clone()
    subj = get_subject(node_)  # string

    contexts = _remove_cached_contexts(node_)

    # Update enabled roles (initial ops) map (Section 4.6.6 -- initial operators)
    prev = clone.parent.get_enabled_roles()

    # Get information from parent context (enabledroles was originally cleared
    # by push_globalchoice to visit this choice)
    #
    # Can factor out to sequencing? Maybe not: this is an instance of generally
    # carrying information over from the parent context, not just sequencing
    # sitations
    ##clone._enabled_roles = {}  # HACK (1)
    for role_, ops in prev.items():
        for op in ops:
            # Carry "initial ops" over from parent context
            clone = clone.enable_role(role_, op)

    # Update context with information from visiting this choice's blocks
    enabled = collections.clone_collection(contexts[0].get_enabled_roles())
    for c in contexts[1:]:
        tmp = c.get_enabled_roles()
        for role_, ops in tmp.items():
            if role_ != subj:
                enabled[role_] |= ops
    for role_, ops in enabled.items():
        # We only want the "intial ops", so if role_ was already enabled before
        # this choice, we don't need to record the ops we saw here
        if role_ not in prev.keys():
            for op in ops:
                clone = clone.enable_role(role_, op)

    # Update potental operators (Section 4.6.8) map
    #
    # N.B. "potential operators" for parallel well-formedness; not "enabling
    # operators" (already treated above)
    potops = clone.get_operators()
    for c in contexts:
        # New potential operators from visiting blocks, add them all to the
        # existing map
        for (src, dest), ops in c.get_operators().items():
            for op in ops:
                if (src, dest) not in potops.keys() or op not in potops[(src, dest)]:
                    # need to collect all operators (for parallel check) from
                    # each choice block as a set
                    clone = clone.add_operator(src, dest, op)

    #Update reclabs? -- no: don't need to do reclabs because any in-scope
    #contlab should have been declared in an outer context; any contlab declared
    #inside the choice cannot possibly be carried over here
    
    for c in contexts:
        for lab in c.get_continue_labels():
            clone = clone.add_continue_label(lab)

    # Reachability and (tail) recursion checks -- this needs to be revised to
    # properly conform to the langref
    rec_exitable = False  # "Possibly exitable": choice has an exit
    for c in contexts:
        if c.get_rec_exitable(): 
            rec_exitable = True
            break
    clone = clone.set_rec_exitable(rec_exitable)

    do_exitable = True
    for c in contexts:
        if not c.get_do_exitable(): 
            do_exitable = False
            break
    clone = clone.set_do_exitable(do_exitable)

    for c in contexts:
        for contlab in c.get_continue_labels():
            clone = clone.add_continue_label(contlab)

    scopes = clone.get_current_scopes()
    new = []
    for c in contexts:
        for scope in c.get_current_scopes() - scopes:
            if scope in new:
                util.report_error("Bad scope: " + scope)
            new.append(scope)
            clone = clone.add_scope(scope)

    cv.set_context(clone.pop_globalchoice(node_))
Ejemplo n.º 8
0
    def clone(self):
        # {
        # "Static" info compiled on top-level initialisation (creation, module
        # loading, visibility building) and not modified later
        sources = collections.clone_collection(self._sources)
        modules = collections.clone_collection(self._modules)
        members = collections.clone_collection(self._members)
        visiblemodules = collections.clone_collection(self._visible_modules)
        visiblepayloads = collections.clone_collection(self._visible_payloads)
        visibleglobals = collections.clone_collection(self._visible_globals)
        visibleLocals = collections.clone_collection(self._visible_locals)

        # "Dynamic" info that is modified as the AST is traversed
        parent = self.parent
        ast = self.ast
        module = self.module
        parameters = collections.clone_collection(self._parameters)
        roles = collections.clone_collection(self._roles)
        scope = collections.clone_collection(self._scope)
        scopes = collections.clone_collection(self._scopes)
        annotations = collections.clone_collection(self._annotations)
        enabledroles = collections.clone_collection(self._enabled_roles)
        operators = collections.clone_collection(self._operators)
        reclabs = collections.clone_collection(self._rec_labs)
        contlabs = collections.clone_collection(self._cont_labs)
        rec_exitable = self._rec_exitable
        cont_exitable = self._cont_exitable
        dostack = collections.clone_collection(self._do_stack)
        do_exitable = self._do_exitable

        rec_unfoldings = self._rec_unfoldings
        proto_unfoldings = self._proto_unfoldings
        projections = self._projections

        clone = Context(self.import_path, self.payload_path, sources, modules,
                        members, visiblemodules, visiblepayloads,
                        visibleglobals, visibleLocals, parent, ast, module,
                        parameters, roles, scope, scopes, annotations,
                        enabledroles, operators, reclabs, contlabs,
                        rec_exitable, cont_exitable, dostack, do_exitable,
                        rec_unfoldings, proto_unfoldings, projections)
        return clone
Ejemplo n.º 9
0
    def clone(self):
    # {
        # "Static" info compiled on top-level initialisation (creation, module
        # loading, visibility building) and not modified later
        sources = collections.clone_collection(self._sources)
        modules = collections.clone_collection(self._modules)
        members = collections.clone_collection(self._members)
        visiblemodules = collections.clone_collection(self._visible_modules)
        visiblepayloads = collections.clone_collection(self._visible_payloads)
        visibleglobals = collections.clone_collection(self._visible_globals)
        visibleLocals = collections.clone_collection(self._visible_locals)
        
        # "Dynamic" info that is modified as the AST is traversed
        parent = self.parent
        ast = self.ast
        module = self.module
        parameters = collections.clone_collection(self._parameters)
        roles = collections.clone_collection(self._roles)
        scope = collections.clone_collection(self._scope)
        scopes = collections.clone_collection(self._scopes)
        annotations = collections.clone_collection(self._annotations)
        enabledroles = collections.clone_collection(self._enabled_roles)
        operators = collections.clone_collection(self._operators)
        reclabs = collections.clone_collection(self._rec_labs)
        contlabs = collections.clone_collection(self._cont_labs)
        rec_exitable = self._rec_exitable
        cont_exitable = self._cont_exitable
        dostack = collections.clone_collection(self._do_stack)
        do_exitable = self._do_exitable
        
        rec_unfoldings = self._rec_unfoldings
        proto_unfoldings = self._proto_unfoldings
        projections = self._projections

        clone = Context(self.import_path, self.payload_path,
                        sources, modules, members, visiblemodules,
                        visiblepayloads, visibleglobals, visibleLocals,
                        parent, ast, module,
                        parameters, roles, scope, scopes, annotations,
                        enabledroles, operators, reclabs, contlabs,
                        rec_exitable, cont_exitable, dostack, do_exitable,
                        rec_unfoldings, proto_unfoldings, projections)
        return clone
Ejemplo n.º 10
0
def context_visitor_leave(cv, node_):
    clone = cv.get_context().clone()
    # Still the originally pushed context for this parallel (each child was
    # visited with a cloned visitor)
    contexts = _remove_cached_contexts(node_)

    # Section 4.6.8 -- potential operators and sig parameters
    ops = collections.clone_collection(contexts[0].get_operators())
    # includes sig parameters
    for c in contexts[1:]:
        tmp = c.get_operators()
        for (src, dest) in tmp.keys():
            if (src, dest) in ops.keys():
                ops[(src, dest)] |= tmp[(src, dest)]  # set union
            else:
                ops[(src, dest)] = tmp[(src, dest)]

    # Need to do this kind of manual child Context merging every time we process
    # multiple children subcontexts. don't need to do for e.g. recursion (single
    # child subcontext)

    # Add all operators and sig parameters seen in children for each src/dest pair
    for (src, dest) in ops.keys():
        for op in ops[(src, dest)]:
            if not clone.is_operator_seen(src, dest, op):
                clone = clone.add_operator(src, dest, op)

    # Add all operators and sig parameters from parent Context for each src/dest
    # pair
    prev = clone.parent.get_operators()
    for (src, dest) in prev.keys():
        for op in prev[(src, dest)]:
            if not (clone.is_operator_seen(src, dest, op)):
                clone = clone.add_operator(src, dest, op)

    # TODO: Parallel deadlocks not specified in langref (maybe should not be)
    seen = set([])  # Only for used here for checking deadlocks
    for (src, dest) in clone.get_operators().keys():
        if (dest, src) in seen:  # too coarse grained?
            #print '[Warning] Potential deadlock: ', src, dest
            # FIXME: false positive on A -> B; par { B -> A } -- clearing
            # operators on par entry would fix this, but may break something
            # else
            pass
        seen.add((src, dest))

    # Add all enabled role and initial operators (Section 4.6.6) seen in children
    # for each src/dest pair
    current = clone.get_enabled_roles()
    for c in contexts:
        for role, ops in c.get_enabled_roles().items():
            for op in ops:
                # Need enabling ops from all par blocks
                #if not(clone.is_role_enabled(role)):
                clone = clone.enable_role(role, op)

    # recLabs no modifications

    for c in contexts:
        for lab in c.get_continue_labels():
            clone = clone.add_continue_label(lab)

    rec_exitable = True
    for c in contexts:
        if not c.get_rec_exitable():
            # TODO: currently any non-rec_exitable child makes the whole parallel
            # non-rec_exitable. However, this should actually be role-sensitive,
            # e.g. par { rec X A->B. X } and { C->D} C->D. "rec_exitable" will be
            # replaced by local projection reachability
            rec_exitable = False
            break
    clone = clone.set_rec_exitable(rec_exitable)

    do_exitable = True
    for c in contexts:
        if not c.get_do_exitable():
            do_exitable = False
            break
    clone = clone.set_do_exitable(do_exitable)

    for c in contexts:
        for contLab in c.get_continue_labels():
            clone = clone.add_continue_label(contLab)

    # Duplicated from globalchoice
    scopes = clone.get_current_scopes()
    new = []
    for c in contexts:
        for scope in c.get_current_scopes() - scopes:
            if scope in new:
                util.report_error("Bad scope: " + scope)
            new.append(scope)
            clone = clone.add_scope(scope)

    cv.set_context(clone.pop_globalparallel(node_))
Ejemplo n.º 11
0
def context_visitor_leave(cv, node_):
    clone = cv.get_context().clone()
        # Still the originally pushed context for this parallel (each child was
        # visited with a cloned visitor)
    contexts = _remove_cached_contexts(node_)

    # Section 4.6.8 -- potential operators and sig parameters
    ops = collections.clone_collection(contexts[0].get_operators())
        # includes sig parameters
    for c in contexts[1:]:
        tmp = c.get_operators()
        for (src, dest) in tmp.keys():
            if (src, dest) in ops.keys():
                ops[(src, dest)] |= tmp[(src, dest)]  # set union
            else:
                ops[(src, dest)] = tmp[(src, dest)]

    # Need to do this kind of manual child Context merging every time we process
    # multiple children subcontexts. don't need to do for e.g. recursion (single
    # child subcontext)

    # Add all operators and sig parameters seen in children for each src/dest pair
    for (src, dest) in ops.keys():
        for op in ops[(src, dest)]:
            if not clone.is_operator_seen(src, dest, op):
                clone = clone.add_operator(src, dest, op)

    # Add all operators and sig parameters from parent Context for each src/dest
    # pair
    prev = clone.parent.get_operators()
    for (src, dest) in prev.keys():
        for op in prev[(src, dest)]:
            if not(clone.is_operator_seen(src, dest, op)):
                clone = clone.add_operator(src, dest, op)

    # TODO: Parallel deadlocks not specified in langref (maybe should not be)
    seen = set([])  # Only for used here for checking deadlocks
    for (src, dest) in clone.get_operators().keys():
        if (dest, src) in seen:  # too coarse grained?
            #print '[Warning] Potential deadlock: ', src, dest
                # FIXME: false positive on A -> B; par { B -> A } -- clearing
                # operators on par entry would fix this, but may break something
                # else
            pass 
        seen.add((src, dest))

    # Add all enabled role and initial operators (Section 4.6.6) seen in children
    # for each src/dest pair
    current = clone.get_enabled_roles()
    for c in contexts:
        for role, ops in c.get_enabled_roles().items():
            for op in ops:
                # Need enabling ops from all par blocks
                #if not(clone.is_role_enabled(role)): 
                clone = clone.enable_role(role, op)

    # recLabs no modifications
    
    for c in contexts:
        for lab in c.get_continue_labels():
            clone = clone.add_continue_label(lab)

    rec_exitable = True
    for c in contexts:
        if not c.get_rec_exitable(): 
            # TODO: currently any non-rec_exitable child makes the whole parallel
            # non-rec_exitable. However, this should actually be role-sensitive,
            # e.g. par { rec X A->B. X } and { C->D} C->D. "rec_exitable" will be
            # replaced by local projection reachability
            rec_exitable = False
            break
    clone = clone.set_rec_exitable(rec_exitable)

    do_exitable = True
    for c in contexts:
        if not c.get_do_exitable(): 
            do_exitable = False
            break
    clone = clone.set_do_exitable(do_exitable)

    for c in contexts:
        for contLab in c.get_continue_labels():
            clone = clone.add_continue_label(contLab)

    # Duplicated from globalchoice
    scopes = clone.get_current_scopes()
    new = []
    for c in contexts:
        for scope in c.get_current_scopes() - scopes:
            if scope in new:
                util.report_error("Bad scope: " + scope)
            new.append(scope)
            clone = clone.add_scope(scope)

    cv.set_context(clone.pop_globalparallel(node_))