Пример #1
0
    def match_mems(self, match, loc, mem1, mem2, V1):

        # Go through all variables
        for var1 in V1 | SPECIAL_VARS:

            # Ignored vars
            if self.ignoreret and var1 == VAR_RET:
                continue
            if self.ignoreio and var1 in [VAR_IN, VAR_OUT]:
                continue

            # If var1 not matched yet, build a list of potential matches
            if var1 not in match:
                if var1 in SPECIAL_VARS:
                    match[var1] = set([var1])
                else:
                    match[var1] = {
                        var2
                        for var2 in mem2.keys() if not isprimed(var2)
                    }

            # Check list of potential matches
            newmatch = set([])
            varp1 = prime(var1)
            for var2 in match[var1]:
                varp2 = prime(var2)

                # Get values
                val1 = mem1.get(varp1, UndefValue())
                val2 = mem2.get(varp2, UndefValue())

                # Debug vars
                if self.debugvar == '%s-%s' % (loc, var1):
                    self.debug('VAR %s = %s', var1, val1)
                    self.debug('VAR %s = %s', var2, val2)
                    if isundef(val1) or val1 == val2:
                        self.debug('VAR equal')
                    else:
                        self.debug('VAR unequal')
                    self.debug('')

                # Check if equal
                # TODO: Different equality?
                if isundef(val1) or val1 == val2:
                    newmatch.add(var2)

            # If no match for then done
            if len(newmatch) == 0:
                self.debug("Couldn find match for %s-%s", loc, var1)
                return False
            # Otherwise replace with new matches
            else:
                match[var1] = newmatch

        return True
Пример #2
0
    def islarge(self):
        '''
        Decides if generated repair is large
        (new variable, new statement, swapped statements)
        '''

        for fnc, (m, repairs, sm) in self.results.items():
            for rep in repairs:

                loc1 = rep.loc1
                var1 = rep.var1
                var2 = rep.var2
                expr1 = rep.expr1

                loc2 = sm[loc1]

                # Added/deleted variable
                if var2 == '*':
                    return True
                if var1 == '-':
                    return False

                # Added stmt
                if self.spec.getfnc(fnc).hasexpr(loc1, var1) \
                   and (not self.impl.getfnc(fnc).hasexpr(loc2, var2)):
                    return True

                # Swapped stmts
                #expr1 = self.spec.getfnc(fnc).getexpr(loc1, var1)
                expr2 = self.impl.getfnc(fnc).getexpr(loc2, var2)
                vars1 = expr1.vars()
                vars2 = expr2.vars()

                for var1 in vars1:
                    if isprimed(var1):
                        var1 = unprime(var1)
                        var2m = m[var1]
                        var2mp = prime(var2m)
                        if var2m in vars2 and var2mp not in vars2:
                            return True
                    else:
                        var2m = m[var1]
                        var2mp = prime(var2m)
                        if var2mp in vars2 and var2m not in vars2:
                            return True

        # Nothing found
        return False
Пример #3
0
    def islarge(self):
        '''
        Decides if generated repair is large
        (new variable, new statement, swapped statements)
        '''
        
        for fnc, (m, repairs, sm) in self.results.items():
            for rep in repairs:
                
                loc1 = rep.loc1
                var1 = rep.var1
                var2 = rep.var2
                expr1 = rep.expr1
                
                loc2 = sm[loc1]

                # Added/deleted variable
                if var2 == '*':
                    return True
                if var1 == '-':
                    return False

                # Added stmt
                if self.spec.getfnc(fnc).hasexpr(loc1, var1) \
                   and (not self.impl.getfnc(fnc).hasexpr(loc2, var2)):
                    return True

                # Swapped stmts
                #expr1 = self.spec.getfnc(fnc).getexpr(loc1, var1)
                expr2 = self.impl.getfnc(fnc).getexpr(loc2, var2)
                vars1 = expr1.vars()
                vars2 = expr2.vars()

                for var1 in vars1:
                    if isprimed(var1):
                        var1 = unprime(var1)
                        var2m = m[var1]
                        var2mp = prime(var2m)
                        if var2m in vars2 and var2mp not in vars2:
                            return True
                    else:
                        var2m = m[var1]
                        var2mp = prime(var2m)
                        if var2mp in vars2 and var2m not in vars2:
                            return True

        # Nothing found
        return False
Пример #4
0
    def execute_FuncCall(self, f, mem):
        name = f.args[0].name
        try:
            fnc = self.getfnc(name)
        except KeyError:
            raise RuntimeErr("Unknown function: '%s'" % (name, ))

        args = map(lambda x: self.execute(x, mem), f.args[1:])

        newmem = {
            VAR_IN: mem.get(VAR_IN, UndefValue()),
            VAR_OUT: mem.get(VAR_OUT, UndefValue()),
        }

        if len(fnc.params) != len(args):
            raise RuntimeErr("Wrong number of args: expected %s, got %s" %
                             (len(fnc.params), len(args)))
        for (var, _), arg in zip(fnc.params, args):
            newmem[var] = deepcopy(arg)

        oldfnc = self.fnc
        oldloc = self.loc
        trace = self.execute(fnc, newmem)
        self.fnc = oldfnc
        self.loc = oldloc

        return trace[-1][2].get(prime(VAR_RET), self.DEFAULT_RETURN)
Пример #5
0
    def execute_FuncCall(self, f, mem):
        name = f.args[0].name
        try:
            fnc = self.getfnc(name)
        except KeyError:
            raise RuntimeErr("Unknown function: '%s'" % (name,))

        args = map(lambda x: self.execute(x, mem), f.args[1:])

        newmem = {
            VAR_IN: mem.get(VAR_IN, UndefValue()),
            VAR_OUT: mem.get(VAR_OUT, UndefValue()),
        }

        if len(fnc.params) != len(args):
            raise RuntimeErr("Wrong number of args: expected %s, got %s" % (
                len(fnc.params), len(args)
            ))
        for (var, _), arg in zip(fnc.params, args):
            newmem[var] = deepcopy(arg)

        oldfnc = self.fnc
        oldloc = self.loc
        trace = self.execute(fnc, newmem)
        self.fnc = oldfnc
        self.loc = oldloc
        
        return trace[-1][2].get(prime(VAR_RET), self.DEFAULT_RETURN)
Пример #6
0
    def procmem(self, mem):
        newmem = dict()

        for var, val in mem.items():
            if isprimed(var):
                var = unprime(var)
                newmem[var] = deepcopy(val)
            else:
                varp = prime(var)
                if varp not in mem:
                    newmem[var] = deepcopy(val)
                    mem[varp] = deepcopy(val)

        return newmem, mem
Пример #7
0
    def procmem(self, mem):
        newmem = dict()

        for var, val in mem.items():
            if isprimed(var):
                var = unprime(var)
                newmem[var] = deepcopy(val)
            else:
                varp = prime(var)
                if varp not in mem:
                    newmem[var] = deepcopy(val)
                    mem[varp] = deepcopy(val)

        return newmem, mem
Пример #8
0
    def execute_Function(self, fnc, mem):

        self.fnc = fnc.name
        self.loc = fnc.initloc

        while True:

            # Execute all exprs
            for (var, expr) in fnc.exprs(self.loc):

                val = self.execute(expr, mem)

                if var == VAR_COND:
                    val = not not val

                varp = prime(var)
                vtype = (fnc.rettype if var == VAR_RET else
                         (fnc.gettype(var) or '*'))
                mem[varp] = self.convert(val, vtype)

                if var == VAR_RET and not isundef(val):
                    break

            # Save memory
            (newmem, mem) = self.procmem(mem)
            self.trace.append((self.fnc, self.loc, mem))
            mem = newmem

            # Check return
            if not isundef(mem.get(VAR_RET, UndefValue())):
                break

            # Find new location
            numtrans = fnc.numtrans(self.loc)
            if numtrans == 0:  # Done
                break

            elif numtrans == 1:  # Trivially choose True
                self.loc = fnc.trans(self.loc, True)

            else:
                self.loc = fnc.trans(self.loc, mem.get(VAR_COND))

        return self.trace
Пример #9
0
    def execute_Function(self, fnc, mem):

        self.fnc = fnc.name
        self.loc = fnc.initloc

        while True:

            # Execute all exprs
            for (var, expr) in fnc.exprs(self.loc):
                
                val = self.execute(expr, mem)
                
                if var == VAR_COND:
                    val = not not val
                    
                varp = prime(var)
                vtype = (fnc.rettype if var == VAR_RET
                         else (fnc.gettype(var) or '*'))
                mem[varp] = self.convert(val, vtype)

                if var == VAR_RET and not isundef(val):
                    break

            # Save memory
            (newmem, mem) = self.procmem(mem)
            self.trace.append((self.fnc, self.loc, mem))
            mem = newmem

            # Check return
            if not isundef(mem.get(VAR_RET, UndefValue())):
                break

            # Find new location
            numtrans = fnc.numtrans(self.loc)
            if numtrans == 0:  # Done
                break
            
            elif numtrans == 1:  # Trivially choose True
                self.loc = fnc.trans(self.loc, True)

            else:
                self.loc = fnc.trans(self.loc, mem.get(VAR_COND))

        return self.trace
Пример #10
0
    def f(l1, l2):
        if not l1:
            return 0 if (not l2) else 1
        if not l2:
            return 0 if (not l1) else 1

        (t1, v1) = l1
        (t2, v2) = l2

        if t1 != t2:
            return 1

        if t2 == 'V':
            if isprimed(v2):
                v2 = prime(m.get(unprime(v2), 'X'))
            else:
                v2 = m.get(v2, 'X')

        return 0 if v1 == v2 else 1
Пример #11
0
    def f(l1, l2):
        if not l1:
            return 0 if (not l2) else 1
        if not l2:
            return 0 if (not l1) else 1

        (t1, v1) = l1
        (t2, v2) = l2

        if t1 != t2:
            return 1

        if t2 == 'V':
            if isprimed(v2):
                v2 = prime(m.get(unprime(v2), 'X'))
            else:
                v2 = m.get(v2, 'X')

        return 0 if v1 == v2 else 1
Пример #12
0
    def gethint(self, expr1, expr2, first=False):
        '''
        Tries to generate some useful hints
        '''

        #  Output
        if self.isout(expr1):
            return self.getouthint(expr1, expr2)

        # Constant
        if isinstance(expr1, Const):
            if isinstance(expr2, Const):
                if expr1.value != expr2.value:
                    return "use the constant '%s' intead of '%s'" % (
                        expr1.value,
                        expr2.value,
                    )
                else:
                    return
            elif isinstance(expr2, Var):
                return "use some constant instead of the variable '%s'" % (
                    expr2.name, )

            else:
                if first:
                    return 'use a just constant'
                else:
                    return

        # Check for changing an order of statement
        vars1 = expr1.vars()
        vars2 = expr2.vars()
        for var1 in vars1:
            if isprimed(var1):
                if unprime(var1) in vars2:
                    return "try changing the order of statements by moving it after the assignment to '%s', or vice-versa" % (
                        unprime(var1), )
            else:
                if prime(var1) in vars2:
                    return "try changing the order of statements by moving it before the assignment to '%s', or vice-versa" % (
                        var1, )

        # Different variable name
        if isinstance(expr1, Var):
            if isinstance(expr2, Var):
                if expr1.name != expr2.name:
                    if expr1.name.startswith('$new'):
                        return "use a different variable instead of '%s'" % (
                            expr2.name, )
                    else:
                        return "use the variable '%s', instead of '%s'" % (
                            expr1.name,
                            expr2.name,
                        )
                else:
                    return
            else:
                if isinstance(expr2, Const):
                    return "replace the constant '%s' by some variable" % (
                        expr2.value, )

                if first:
                    return 'use just a variable'
                else:
                    return

        # Operation comparison
        if isinstance(expr1, Op):

            if isinstance(expr2, Op):

                # Operators
                for opname, ops in self.opdefs:
                    if expr1.name in ops and len(expr1.args) == 2:
                        if expr2.name in ops and len(expr2.args) == 2:

                            same1 = self.issame(expr1.args[0], expr2.args[0])
                            same2 = self.issame(expr1.args[1], expr2.args[1])

                            # Different operators
                            if same1 and same2 and expr1.name != expr2.name:
                                return "use a different %s operator instead of '%s'" % (
                                    opname,
                                    expr2.name,
                                )

                            # Different right side
                            if same1 and expr1.name == expr2.name:
                                h = self.gethint(expr1.args[1], expr2.args[1])
                                if h:
                                    return h

                            # Different left side
                            if same2 and expr1.name == expr2.name:
                                h = self.gethint(expr1.args[0], expr2.args[0])
                                if h:
                                    return h

                            # if first and expr1.name == expr2.name:
                            #     h1 = self.gethint(expr1.args[0], expr2.args[0])
                            #     h2 = self.gethint(expr1.args[1], expr2.args[1])
                            #     if h1 and h2:
                            #         return '%s and %s' % (h1, h2)

            if first and expr1.name == 'ite':
                h = self.ite_hint(expr1, expr2)
                if h:
                    return h

        # Nothing else to do, except to generate a template
        if first:
            t = self.gettemplate(expr1, expr2, outer=True)
            if t:
                return self.templatetext(t)
Пример #13
0
    def potential(self, f1, f2, loc1, var1, loc2):

        varp1 = prime(var1)
        expr1 = self.E1[loc1][var1]
        isid = (isinstance(expr1, Var) and expr1.name == var1
                and expr1.primed == False)
        tree1 = self.T1[loc1][var1]
        vars1 = list(set(map(unprimes, expr1.vars())) | set([var1]))
        vars1.sort()
        
        V1 = list(self.V1 - set(['-']))
        V1.sort()
        V2 = list(self.V2)
        V2.sort()
        
        for var2 in V2:

            sofar = set()

            # Special vars can be only mapped to special vars
            if (var1 in SPECIAL_VARS or var2 in SPECIAL_VARS) and var1 != var2:
                continue

            # other special variables
            if var2 != '*':
                if var1.startswith('ind#') != var2.startswith('ind#'):
                    continue
                if var1.startswith('iter#') != var2.startswith('iter#'):
                    continue

            # Params can only be mapped to params
            if ((var1 in self.pmap or var2 in self.pmap.keys())
                and var2 != self.pmap.get(var1)):
                continue

            # Cannot delete new variable
            if var1 == '-' and var2 == '*':
                continue

            expr2 = self.E2[loc2][var2]
            tree2 = self.T2[loc2][var2]
            vars2 = list(set(map(unprimes, expr2.vars())) | set([var2]))
            vars2.sort()

            # (0) Deletes are special
            if var1 == '-':
                delexpr = Var(var2)
                deltree = self.totree(delexpr)
                delcost = self.distance(tree2, deltree, {var2: var2})
                if delcost:
                    yield ([(var1, var2)], delcost, (), None)
                continue

            # (1) Generate corrects (if not new variable)
            if var2 != '*':
                for m in self.one_to_ones(vars2, V1, var2, var1):
                    m = [(s2, s1) for (s1, s2) in m]
                    ok = True
                    for mem1 in self.trace.get(f1.name, {}).get(loc1, []):
                        val1 = mem1.get(varp1)
                        
                        if isundef(val1) and (var1 != VAR_RET):
                            continue
                        
                        if isinstance(val1, str) and self.cleanstrings:
                            val1 = val1.strip()
                            
                        mem2 = {v2: mem1.get(v1) for (v1, v2) in m}
                        mem2.update({prime(v2): mem1.get(prime(v1))
                                     for (v1, v2) in m})
                        try:
                            val2 = self.inter.execute(expr2, mem2)
                            if isinstance(val2, str) and self.cleanstrings:
                                val2 = val2.strip()

                            if not equals(val2, val1):
                                ok = False
                                break
                        except RuntimeErr:
                            ok = False
                            break
                    if ok:
                        order = self.getorder(var2, expr2,
                                              {v: v for v in vars2})
                        if order is None:
                            assert False, 'order error %s %s' % (var2, expr2)
                        ms = list(m)
                        ms.sort()
                        sofar.add((tuple(ms), tuple(order)))
                        yield (m, 0, set(order), None)

            # (2) Generate repairs
            tmprepairs = {}
            #for rexpr, rtree in zip([self.E1[loc1][var1]], [self.T1[loc1][var1]]):
            for idx, ((rexpr, _), rtree) in enumerate(zip(self.ER[loc1][var1], self.TR[loc1][var1])):
                
                risid = (isinstance(rexpr, Var) and rexpr.name == var1
                        and rexpr.primed == False)
                rvars = list(set(map(unprimes, rexpr.vars())) | set([var1]))
                
                for m in self.one_to_ones(rvars, V2, var1, var2):
                    order = self.getorder(var2, rexpr, dict(m))
                    
                    if order is None:
                        self.debug(
                            'skipping repair %s := %s (%s) because impossible order',
                            var1, expr1, m)
                        continue
                    
                    if risid and var2 == '*':
                        cost = 0
                    else:
                        cost = self.distance(tree2, rtree, dict(m))
                    
                    # Account for *declaring* a new variable
                    if var2 == '*' and loc1 == 1:
                        cost += 1
                
                    ms = list(m)
                    ms.sort()

                    tms = tuple(ms)
                    torder = tuple(order)
                
                    if (tms, torder) in sofar:
                        continue

                    # From each 'm'-'order' pair we first remember all pairs
                    # and later yield only the one with the smallest cost
                    # since other ones have no sense
                    tmp = (tms, torder)
                    if tmp not in tmprepairs:
                        tmprepairs[tmp] = []
                    tmprepairs[tmp].append((cost, (m, cost, set(order), idx)))

                    #yield (m, cost, set(order))
                
            for treps in tmprepairs.values():
                treps.sort()
                #print treps[0][1]
                yield treps[0][1]
Пример #14
0
    def match_mems(self, match, loc, mem1, mem2, V1):

        V2 = ({var2 for var2 in mem2.keys() if not isprimed(var2)}
              - SPECIAL_VARS)

        if self.bijective:
            if len(V1 | SPECIAL_VARS) != len(V2 | SPECIAL_VARS):
                self.debug('Not bijective - different number of variables')
                return False

        # Go through all variables
        for var1 in V1 | SPECIAL_VARS:

            # Ignored vars
            if self.ignoreret and var1 == VAR_RET:
                continue
            if self.ignoreio and var1 in [VAR_IN, VAR_OUT]:
                continue

            # If var1 not matched yet, build a list of potential matches
            if var1 not in match:
                if var1 in SPECIAL_VARS:
                    match[var1] = set([var1])
                else:
                    match[var1] = set(V2)

            # Check list of potential matches
            newmatch = set([])
            varp1 = prime(var1)
            for var2 in match[var1]:
                varp2 = prime(var2)

                if var1.startswith('ind#') != var2.startswith('ind#'):
                    continue

                if var1.startswith('iter#') != var2.startswith('iter#'):
                    continue

                # Get values
                val1 = mem1.get(varp1, UndefValue())
                val2 = mem2.get(varp2, UndefValue())

                # Debug vars
                if self.debugvar == '%s-%s' % (loc, var1):
                    self.debug('VAR %s = %s', var1, val1)
                    self.debug('VAR %s = %s', var2, val2)
                    if isundef(val1) or equals(val1, val2):
                        self.debug('VAR equal')
                    else:
                        self.debug('VAR unequal')
                    self.debug('')
                
                # Check if equal
                if isundef(val1) or equals(val1, val2):
                    newmatch.add(var2)

            # If no match for then done
            if len(newmatch) == 0:
                self.debug("Couldn find match for %s-%s", loc, var1)
                return False
            # Otherwise replace with new matches
            else:
                match[var1] = newmatch

        return True
Пример #15
0
    def potential(self, f1, f2, loc1, var1, loc2):

        varp1 = prime(var1)
        expr1 = self.E1[loc1][var1]
        isid = (isinstance(expr1, Var) and expr1.name == var1
                and expr1.primed == False)
        tree1 = self.T1[loc1][var1]
        vars1 = list(set(map(unprimes, expr1.vars())) | set([var1]))
        vars1.sort()

        V1 = list(self.V1 - set(['-']))
        V1.sort()
        V2 = list(self.V2)
        V2.sort()

        for var2 in V2:

            sofar = set()

            # Special vars can be only mapped to special vars
            if (var1 in SPECIAL_VARS or var2 in SPECIAL_VARS) and var1 != var2:
                continue

            # other special variables
            if var2 != '*':
                if var1.startswith('ind#') != var2.startswith('ind#'):
                    continue
                if var1.startswith('iter#') != var2.startswith('iter#'):
                    continue

            # Params can only be mapped to params
            if ((var1 in self.pmap or var2 in self.pmap.keys())
                    and var2 != self.pmap.get(var1)):
                continue

            # Cannot delete new variable
            if var1 == '-' and var2 == '*':
                continue

            expr2 = self.E2[loc2][var2]
            tree2 = self.T2[loc2][var2]
            vars2 = list(set(map(unprimes, expr2.vars())) | set([var2]))
            vars2.sort()

            # (0) Deletes are special
            if var1 == '-':
                delexpr = Var(var2)
                deltree = self.totree(delexpr)
                delcost = self.distance(tree2, deltree, {var2: var2})
                if delcost:
                    yield ([(var1, var2)], delcost, (), None)
                continue

            # (1) Generate corrects (if not new variable)
            if var2 != '*':
                for m in self.one_to_ones(vars2, V1, var2, var1):
                    m = [(s2, s1) for (s1, s2) in m]
                    ok = True
                    for mem1 in self.trace.get(f1.name, {}).get(loc1, []):
                        val1 = mem1.get(varp1)

                        if isundef(val1) and (var1 != VAR_RET):
                            continue

                        if isinstance(val1, str) and self.cleanstrings:
                            val1 = val1.strip()

                        mem2 = {v2: mem1.get(v1) for (v1, v2) in m}
                        mem2.update(
                            {prime(v2): mem1.get(prime(v1))
                             for (v1, v2) in m})
                        try:
                            val2 = self.inter.execute(expr2, mem2)
                            if isinstance(val2, str) and self.cleanstrings:
                                val2 = val2.strip()

                            if not equals(val2, val1):
                                ok = False
                                break
                        except RuntimeErr:
                            ok = False
                            break
                    if ok:
                        order = self.getorder(var2, expr2,
                                              {v: v
                                               for v in vars2})
                        if order is None:
                            assert False, 'order error %s %s' % (var2, expr2)
                        ms = list(m)
                        ms.sort()
                        sofar.add((tuple(ms), tuple(order)))
                        yield (m, 0, set(order), None)

            # (2) Generate repairs
            tmprepairs = {}
            #for rexpr, rtree in zip([self.E1[loc1][var1]], [self.T1[loc1][var1]]):
            for idx, ((rexpr, _), rtree) in enumerate(
                    zip(self.ER[loc1][var1], self.TR[loc1][var1])):

                risid = (isinstance(rexpr, Var) and rexpr.name == var1
                         and rexpr.primed == False)
                rvars = list(set(map(unprimes, rexpr.vars())) | set([var1]))

                for m in self.one_to_ones(rvars, V2, var1, var2):
                    order = self.getorder(var2, rexpr, dict(m))

                    if order is None:
                        self.debug(
                            'skipping repair %s := %s (%s) because impossible order',
                            var1, expr1, m)
                        continue

                    if risid and var2 == '*':
                        cost = 0
                    else:
                        cost = self.distance(tree2, rtree, dict(m))

                    # Account for *declaring* a new variable
                    if var2 == '*' and loc1 == 1:
                        cost += 1

                    ms = list(m)
                    ms.sort()

                    tms = tuple(ms)
                    torder = tuple(order)

                    if (tms, torder) in sofar:
                        continue

                    # From each 'm'-'order' pair we first remember all pairs
                    # and later yield only the one with the smallest cost
                    # since other ones have no sense
                    tmp = (tms, torder)
                    if tmp not in tmprepairs:
                        tmprepairs[tmp] = []
                    tmprepairs[tmp].append((cost, (m, cost, set(order), idx)))

                    #yield (m, cost, set(order))

            for treps in tmprepairs.values():
                treps.sort()
                #print treps[0][1]
                yield treps[0][1]
Пример #16
0
    def gethint(self, expr1, expr2, first=False):
        '''
        Tries to generate some useful hints
        '''

        #  Output
        if self.isout(expr1):
            return self.getouthint(expr1, expr2)

        # Constant
        if isinstance(expr1, Const):
            if isinstance(expr2, Const):    
                if expr1.value != expr2.value:
                    return "use the constant '%s' intead of '%s'" % (
                        expr1.value, expr2.value,)
                else:
                    return
            elif isinstance(expr2, Var):
                return "use some constant instead of the variable '%s'" % (expr2.name,)
            
            else:
                if first:
                    return 'use a just constant'
                else:
                    return

        # Check for changing an order of statement
        vars1 = expr1.vars()
        vars2 = expr2.vars()
        for var1 in vars1:
            if isprimed(var1):
                if unprime(var1) in vars2:
                    return "try changing the order of statements by moving it after the assignment to '%s', or vice-versa" % (unprime(var1),)
            else:
                if prime(var1) in vars2:
                    return "try changing the order of statements by moving it before the assignment to '%s', or vice-versa" % (var1,)

        # Different variable name
        if isinstance(expr1, Var):
            if isinstance(expr2, Var):
                if expr1.name != expr2.name:
                    if expr1.name.startswith('$new'):
                        return "use a different variable instead of '%s'" % (
                            expr2.name,)
                    else:
                        return "use the variable '%s', instead of '%s'" % (
                            expr1.name, expr2.name,)
                else:
                    return
            else:
                if isinstance(expr2, Const):
                    return "replace the constant '%s' by some variable" % (expr2.value,)
                
                if first:
                    return 'use just a variable'
                else:
                    return

        # Operation comparison
        if isinstance(expr1, Op):

            if isinstance(expr2, Op):
                
                # Operators
                for opname, ops in self.opdefs:
                    if expr1.name in ops and len(expr1.args) == 2:
                        if expr2.name in ops and len(expr2.args) == 2:

                            same1 = self.issame(expr1.args[0], expr2.args[0])
                            same2 = self.issame(expr1.args[1], expr2.args[1])
                
                            # Different operators
                            if same1 and same2 and expr1.name != expr2.name:
                                return "use a different %s operator instead of '%s'" % (
                                    opname, expr2.name,)
                            
                            # Different right side
                            if same1 and expr1.name == expr2.name:
                                h = self.gethint(expr1.args[1], expr2.args[1])
                                if h:
                                    return h

                            # Different left side
                            if same2 and expr1.name == expr2.name:
                                h = self.gethint(expr1.args[0], expr2.args[0])
                                if h:
                                    return h
                                
                            # if first and expr1.name == expr2.name:
                            #     h1 = self.gethint(expr1.args[0], expr2.args[0])
                            #     h2 = self.gethint(expr1.args[1], expr2.args[1])
                            #     if h1 and h2:
                            #         return '%s and %s' % (h1, h2)

            if first and expr1.name == 'ite':
                h = self.ite_hint(expr1, expr2)
                if h:
                    return h

        # Nothing else to do, except to generate a template
        if first:
            t = self.gettemplate(expr1, expr2, outer=True)
            if t:
                return self.templatetext(t)
Пример #17
0
    def potential(self, f1, f2, loc1, var1, loc2):

        varp1 = prime(var1)
        expr1 = self.E1[loc1][var1]
        isid = isinstance(expr1, Var) and expr1.name == var1
        tree1 = self.T1[loc1][var1]
        vars1 = list(set(map(unprimes, expr1.vars())) | set([var1]))
        vars1.sort()

        V1 = list(self.V1 - set(['-']))
        V1.sort()
        V2 = list(self.V2)
        V2.sort()

        for var2 in V2:

            sofar = set()

            # Special vars can be only mapped to special vars
            if (var1 in SPECIAL_VARS or var2 in SPECIAL_VARS) and var1 != var2:
                continue

            # Params can only be mapped to params
            if var1 in self.pmap and var2 != self.pmap[var1]:
                continue

            # Cannot delete new variable
            if var1 == '-' and var2 == '*':
                continue

            expr2 = self.E2[loc2][var2]
            tree2 = self.T2[loc2][var2]
            vars2 = list(set(map(unprimes, expr2.vars())) | set([var2]))
            vars2.sort()

            # (0) Deletes are special
            if var1 == '-':
                delexpr = Var(var2)
                deltree = self.totree(delexpr)
                delcost = self.distance(tree2, deltree, {var2: var2})
                if delcost:
                    yield ([(var1, var2)], delcost, ())
                continue

            # (1) Generate corrects (if not new variable)
            if var2 != '*':
                for m in self.one_to_ones(vars2, V1, var2, var1):
                    m = [(s2, s1) for (s1, s2) in m]
                    ok = True
                    for mem1 in self.trace.get(f1.name, {}).get(loc1, []):
                        val1 = mem1.get(varp1)

                        if isundef(val1):
                            continue

                        if isinstance(val1, str) and self.cleanstrings:
                            val1 = val1.strip()

                        mem2 = {v2: mem1.get(v1) for (v1, v2) in m}
                        mem2.update(
                            {prime(v2): mem1.get(prime(v1))
                             for (v1, v2) in m})
                        try:
                            val2 = self.inter.execute(expr2, mem2)
                            if isinstance(val2, str) and self.cleanstrings:
                                val2 = val2.strip()

                            if val2 != val1:
                                ok = False
                                break
                        except RuntimeErr:
                            ok = False
                            break
                    if ok:
                        order = self.getorder(var2, expr2,
                                              {v: v
                                               for v in vars2})
                        if order is None:
                            assert False, 'order error %s %s' % (var2, expr2)
                        ms = list(m)
                        ms.sort()
                        sofar.add((tuple(ms), tuple(order)))
                        yield (m, 0, set(order))

            # (2) Generate repairs
            for m in self.one_to_ones(vars1, V2, var1, var2):
                order = self.getorder(var2, expr1, dict(m))
                if order is None:
                    self.debug(
                        'skipping repair %s := %s (%s) because \
impossible order', var1, expr1, m)
                    continue
                if isid and var2 == '*':
                    cost = 0
                else:
                    cost = self.distance(tree2, tree1, dict(m))

                # Account for *declaring* a new variable
                if var2 == '*' and loc1 == 1:
                    cost += 1

                ms = list(m)
                ms.sort()
                if (tuple(ms), tuple(order)) in sofar:
                    continue
                yield (m, cost, set(order))