Exemple #1
0
def transitive_add(v, end, assignment):
    visited = set()
    while v in assignment:
        if v in visited or v == end:
            from lamb import meta
            from lamb.meta import logger
            logger.error("breaking loop (v: '%s', end: '%s', visited: '%s', assignment: '%s')" % (v, end, visited, assignment))
            break
        visited |= {v}
        next_v = assignment[v]
        assignment[v] = end
        v = next_v
    return assignment
Exemple #2
0
def transitive_find_end(v, assignment):
    # TODO: delete the loop checking from these functions once it's solid
    start_v = v
    visited = set()
    last_v = None
    while isinstance(v, VariableType) and v in assignment:
        if v in visited:
            from lamb import meta
            from lamb.meta import logger
            logger.error("breaking loop (start_v: '%s', v: '%s', visited: '%s', assignment: '%s')" % (start_v, v, visited, assignment))
            break
        visited |= {v}
        last_v = v
        v = assignment[v]
    return (v, last_v)
Exemple #3
0
 def sub_type_vars(self, assignment, trans_closure=False):
     if self in assignment:
         x = assignment[self]
         if trans_closure:
             visited = {self}
             while x in assignment:
                 if x in visited:
                     from lamb import meta
                     from lamb.meta import logger
                     logger.error("breaking loop in substitution (x: '%s', visited: '%s', , assignment: '%s')" % (x, visited, assignment))
                     break
                 visited |= {x}
                 x = assignment[x]
         return x
     else:
         return self
Exemple #4
0
 def unify_r(self, t1, t2, assignment):
     # nearly the same as for strict types: just enforces that if either type is a variable, we call
     # that type's unify function (since only it knows what to do with variables.)
     if self.occurs_check(t1, t2):
         from lamb import meta
         from lamb.meta import logger
         logger.error("Failed occurs check: can't unify recursive types %s and %s" % (t1,t2))
         return (None, None)
     if isinstance(t1, VariableType):
         if isinstance(t2, VariableType):
             return t2.unify(t1, self.unify_r, assignment)
         else:
             return t1.unify(t2, self.unify_r, assignment)            
     elif isinstance(t2, VariableType):
         return t2.unify(t1, self.unify_r, assignment)
     else:
         (result, r_assign) = t1.unify(t2, self.unify_r, assignment)
         if result is None:
             return (None, None)
         return (result, r_assign)
Exemple #5
0
 def unify(self, t2, unify_control_fun, assignment):
     if self == t2:
         return (self, assignment)
     # find the principal type in the equivalence class identified by self.  May return self if there's a loop.
     #  (Other sorts of loops should be ruled out?)
     if self in assignment:
         (start, prev) = transitive_find_end(self, assignment)
     else:
         start = self
         prev = None
     # find the principal type in the equivalence class identified by t2.
     if isinstance(t2, VariableType) and t2 in assignment:
         (t2_principal, t2_prev) = transitive_find_end(t2, assignment)
     else:
         t2_principal = t2
         t2_prev = None
     new_principal = start
     if PolyTypeSystem.occurs_check(new_principal, t2_principal):
         from lamb import meta
         from lamb.meta import logger
         logger.error("Failed occurs check: can't unify recursive types %s and %s" % (new_principal, t2_principal))
         return (None, None)
     if isinstance(start, VariableType):
         if not isinstance(t2_principal, VariableType):
             t2_principal = t2_principal.sub_type_vars(assignment, trans_closure=True)
         assignment = replace_in_assign(start, t2_principal, assignment)
         if start != t2_principal:
             assignment[start] = t2_principal
             new_principal = t2_principal
     if isinstance(t2_principal, VariableType):
         if not isinstance(start, VariableType):
             start = start.sub_type_vars(assignment, trans_closure=True)
         assignment = replace_in_assign(t2_principal, start, assignment)
         if t2_principal != start:
             assignment[t2_principal] = start
             new_principal = start
     if not (isinstance(start, VariableType) or isinstance(t2_principal, VariableType)):
         new_principal, assignment = unify_control_fun(start, t2_principal, assignment)
         if new_principal is None:
             return (None, None)
     return (new_principal, assignment)