예제 #1
0
    def test_spec(self):
        # Aggregate of a relation.
        node = L.pe('count(R)')
        spec = AggrSpec.from_node(node)

        self.assertEqual(spec.aggrop, 'count')
        self.assertEqual(spec.rel, 'R')
        self.assertEqual(spec.relmask, Mask('u'))
        self.assertEqual(spec.params, ())
        self.assertEqual(spec.oper_demname, None)
        self.assertEqual(spec.oper_demparams, None)

        constrs = spec.get_domain_constraints('A')
        exp_constrs = []
        self.assertEqual(constrs, exp_constrs)

        # Aggregate of a setmatch, with demand.
        node = L.pe('count(DEMQUERY(foo, [c1], '
                    'setmatch(R, "bub", (c1, c2))))')
        spec = AggrSpec.from_node(node)

        self.assertEqual(spec.aggrop, 'count')
        self.assertEqual(spec.rel, 'R')
        self.assertEqual(spec.relmask, Mask('bub'))
        self.assertEqual(spec.params, ('c1', 'c2'))
        self.assertEqual(spec.oper_demname, 'foo')
        self.assertEqual(spec.oper_demparams, ('c1', ))

        constrs = spec.get_domain_constraints('A')
        exp_constrs = [('A.1', 'R.1'), ('A.2', 'R.3')]
        self.assertEqual(constrs, exp_constrs)
예제 #2
0
    def test_trel_bindmatch(self):
        code = trel_bindmatch('_TUP2',
                              Mask('bbu'), ['t', 'x', 'y'],
                              L.pc('pass'),
                              typecheck=True)
        exp_code = L.pc('''
            if (isinstance(t, tuple) and (len(t) == 2)):
                if (t[1] == x):
                    for y in setmatch({(t, t[0], t[1])}, 'bbu', (t, x)):
                        pass
            ''')
        self.assertEqual(code, exp_code)

        code = trel_bindmatch('_TUP2',
                              Mask('bbu'), ['t', 'x', 'y'],
                              L.pc('pass'),
                              typecheck=False)
        exp_code = L.pc('''
            if (t[1] == x):
                for y in setmatch({(t, t[0], t[1])}, 'bbu', (t, x)):
                    pass
            ''')
        self.assertEqual(code, exp_code)

        code = trel_bindmatch('_TUP2',
                              Mask('ubw'), ['t', 'x', 'y'],
                              L.pc('pass'),
                              typecheck=True)
        exp_code = L.pc('''
            for t in setmatch(_TUP2, 'ubw', x):
                pass
            ''')
        self.assertEqual(code, exp_code)
예제 #3
0
    def from_AST(cls, node, factory):
        """Construct from an Enumerator node of form
        
            <vars> in <rel>
        
        Alternatively, the rhs may be a setmatch of a rel, where
        the mask is a lookupmask and the key is a vartuple.
        """
        checktype(node, L.Enumerator)

        lhs = L.get_vartuple(node.target)
        rhs = node.iter

        if L.is_name(rhs):
            rel = L.get_name(rhs)

        elif isinstance(rhs, L.SetMatch) and L.is_vartuple(rhs.key):
            keyvars = L.get_vartuple(rhs.key)
            # Make sure we're dealing with a lookupmask and that the
            # key vars agree with the mask.
            mask = Mask(rhs.mask)
            assert mask.is_lookupmask
            assert mask.lookup_arity == len(keyvars)

            lhs = keyvars + lhs
            rel = L.get_name(rhs.target)

        else:
            raise TypeError

        return cls(lhs, rel)
예제 #4
0
 def to_AST(self):
     mask = Mask.from_keylen(len(self.lhs) - 1)
     keyvars = self.lhs[:-1]
     var = self.lhs[-1]
     sm = L.SMLookup(L.ln(self.rel),
                     mask.make_node().s, L.tuplify(keyvars), None)
     return L.Enumerator(L.sn(var), L.Set((sm, )))
예제 #5
0
파일: aggr.py 프로젝트: dcharkes/incoq
    def from_node(cls, node):
        checktype(node, L.Aggregate)

        if isinstance(node.value, L.DemQuery):
            assert all(isinstance(a, L.Name) for a in node.value.args)
            oper_demparams = tuple(a.id for a in node.value.args)
            oper_demname = node.value.demname
            oper = node.value.value
        else:
            oper_demparams = None
            oper_demname = None
            oper = node.value

        if isinstance(oper, L.Name):
            rel = oper.id
            relmask = Mask.U
            params = ()

        elif (isinstance(oper, L.SetMatch) and isinstance(oper.target, L.Name)
              and L.is_vartuple(oper.key)):
            rel = oper.target.id
            relmask = Mask(oper.mask)
            params = L.get_vartuple(oper.key)

        else:
            raise L.ProgramError('Bad aggregate operand', node=node)

        return cls(node.op, rel, relmask, params, oper_demname, oper_demparams)
예제 #6
0
 def handle_ms_smnsassignkey(self, f, target, maskstr: 'Str', key, elem,
                             prefix: 'Str'):
     from incoq.compiler.set import Mask
     mask = Mask(maskstr)
     assert mask.is_keymask
     # vars for each bound component ((len(mask) - 1) many).
     vars = [prefix + str(i) for i in range(1, len(mask))]
     # var for element component
     evar = prefix + 'elem'
     return self.pc('''
         S_VARS = KEY
         if not setmatch(TARGET, MASK, KEY).isempty():
             S_EVAR = TARGET.smlookup(MASK, KEY)
             TARGET.remove(PARTS_OLD)
         TARGET.add(PARTS_NEW)
         ''',
                    subst={
                        'S_VARS': tuplify(vars, lval=True),
                        'KEY': key,
                        'TARGET': target,
                        'MASK': Str(maskstr),
                        'S_EVAR': evar,
                        'PARTS_OLD': tuplify(vars + [evar]),
                        'PARTS_NEW': tuplify(vars + [elem])
                    })
예제 #7
0
파일: clause.py 프로젝트: IncOQ/incoq
 def to_AST(self):
     mask = Mask.from_keylen(len(self.lhs) - 1)
     keyvars = self.lhs[:-1]
     var = self.lhs[-1]
     sm = L.SMLookup(L.ln(self.rel), mask.make_node().s,
                     L.tuplify(keyvars), None)
     return L.Enumerator(L.sn(var), L.Set((sm,)))
예제 #8
0
파일: tags.py 프로젝트: dcharkes/incoq
def get_used_filters(ds, ordering, use_tag_checks):
    """Take in the demand structures for a query, and an ordering of
    clauses for one of the query's maintenance comps. Return a set of
    the clause indices for which filter relations are used.
    """
    # Ignore conditions.
    ordering = [(i, cl, bindenv) for i, cl, bindenv in ordering
                if cl.kind is Clause.KIND_ENUM]
    
    filters = ds.filters
    filters_by_index = {f.i: f for f in filters}
    
    used_indices = set()
    for i, cl, bindenv in ordering:
        if cl.kind is Clause.KIND_COND:
            continue
        if i not in filters_by_index:
            continue
        
        # Singleton clauses are filtered if we're doing tag checks.
        deltamask = Mask.from_vars(cl.enumlhs, cl.enumlhs)
        if cl.isdelta and (use_tag_checks or deltamask.has_wildcards):
            used_indices.add(i)
        
        # Consult clause rules.
        elif cl.needs_filtering(bindenv):
            used_indices.add(i)
    
    return used_indices
예제 #9
0
파일: objclause.py 프로젝트: dcharkes/incoq
 def rate(self, bindenv):
     mask = Mask.from_vars(self.lhs, bindenv)
     if mask.is_allunbound:
         return Rate.UNRUNNABLE
     elif mask == Mask.OUT:
         return Rate.CONSTANT
     return super().rate(bindenv)
예제 #10
0
 def test_inc_relmatch(self):
     spec = AuxmapSpec('R', Mask('bu'))
     
     tree = L.p('''
         R.add((1, 2))
         print(setmatch(R, 'bu', 1))
         ''')
     
     tree = inc_relmatch(tree, self.manager, spec)
     
     exp_tree = L.p('''
         _m_R_out = Map()
         def _maint__m_R_out_add(_e):
             (v1_1, v1_2) = _e
             if (v1_1 not in _m_R_out):
                 _m_R_out.assignkey(v1_1, set())
             _m_R_out[v1_1].add(v1_2)
         
         def _maint__m_R_out_remove(_e):
             (v2_1, v2_2) = _e
             _m_R_out[v2_1].remove(v2_2)
             if _m_R_out[v2_1].isempty():
                 _m_R_out.delkey(v2_1)
         
         with MAINT(_m_R_out, 'after', 'R.add((1, 2))'):
             R.add((1, 2))
             _maint__m_R_out_add((1, 2))
         print(_m_R_out.imglookup(1))
         ''')
     
     self.assertEqual(tree, exp_tree)
예제 #11
0
파일: objclause.py 프로젝트: IncOQ/incoq
 def rate(self, bindenv):
     mask = Mask.from_vars(self.lhs, bindenv)
     if mask.is_allunbound:
         return Rate.UNRUNNABLE
     elif mask == Mask.OUT:
         return Rate.CONSTANT
     return super().rate(bindenv)
예제 #12
0
 def test_queryfinder(self):
     code = L.p('''
         print(setmatch(R, 'bu', a))
         print(setmatch(R, 'ub', a))
         print(setmatch(R, 'bu', b))
         print(setmatch({(1, 2)}, 'bu', 1))
         S.add((3, 4, 5))
         print(S.smlookup('bbu', (3, 4)))
         ''')
     auxmap_specs = RelmatchQueryFinder.run(code)
     
     exp_specs = {AuxmapSpec('R', Mask('bu')),
                  AuxmapSpec('R', Mask('ub')),
                  AuxmapSpec('S', Mask('bbu'))}
     
     self.assertCountEqual(auxmap_specs, exp_specs)
예제 #13
0
파일: comptrans.py 프로젝트: dcharkes/incoq
    def get_res_code(self):
        """Return code (expression) to lookup the result."""
        params = self.inccomp.comp.params

        if len(params) > 0:
            resexp = self.inccomp.spec.resexp
            assert isinstance(resexp, L.Tuple)
            resexp_arity = len(resexp.elts)
            n_rescomponents = resexp_arity - len(params)

            maskstr = 'b' * len(params) + 'u' * n_rescomponents
            masknode = Mask(maskstr).make_node()
            paramsnode = L.tuplify(params)

            code = L.pe('''
                setmatch(RES, MASK, PARAMS)
                ''',
                        subst={
                            'RES': L.ln(self.inccomp.name),
                            'MASK': masknode,
                            'PARAMS': paramsnode
                        })

        else:
            code = L.ln(self.inccomp.name)

        return code
예제 #14
0
 def test_resexp_vars(self):
     resexp = L.pe('(a + b, (c, d), (a, c, e, f))')
     bounds, unbounds = split_resexp_vars(resexp, Mask('bbu'))
     exp_bounds = {'c', 'd'}
     exp_unbounds = {'a', 'e', 'f'}
     self.assertEqual(bounds, exp_bounds)
     self.assertEqual(unbounds, exp_unbounds)
예제 #15
0
파일: clause.py 프로젝트: IncOQ/incoq
 def rate(self, bindenv):
     mask = Mask.from_vars(self.lhs, bindenv)
     if mask.is_allbound:
         return Rate.CONSTANT_MEMBERSHIP
     elif mask.is_allunbound:
         return Rate.NOTPREFERRED
     else:
         return Rate.NORMAL
예제 #16
0
파일: tupclause.py 프로젝트: dcharkes/incoq
 def get_code(self, bindenv, body):
     mask = Mask.from_vars(self.lhs, bindenv)
     assert not mask.is_allunbound
     return trel_bindmatch(make_trel(self.arity),
                           mask,
                           self.lhs,
                           body,
                           typecheck=self.typecheck)
예제 #17
0
파일: objclause.py 프로젝트: dcharkes/incoq
 def rate(self, bindenv):
     mask = Mask.from_vars(self.lhs, bindenv)
     if mask.is_allunbound:
         return Rate.UNRUNNABLE
     elif (mask.parts[0] == 'b'
           and (mask.parts[1] == 'b' or mask.parts[1] == '1')):
         return Rate.CONSTANT
     return super().rate(bindenv)
예제 #18
0
 def rate(self, bindenv):
     mask = Mask.from_vars(self.lhs, bindenv)
     if mask.is_allbound:
         return Rate.CONSTANT_MEMBERSHIP
     elif mask.is_allunbound:
         return Rate.NOTPREFERRED
     else:
         return Rate.NORMAL
예제 #19
0
파일: objclause.py 프로젝트: dcharkes/incoq
 def get_code(self, bindenv, body):
     mask = Mask.from_vars(self.lhs, bindenv)
     bvars, uvars, _eqs = mask.split_vars(self.lhs)
     return mset_bindmatch(mask,
                           bvars,
                           uvars,
                           body,
                           typecheck=self.typecheck)
예제 #20
0
파일: objclause.py 프로젝트: IncOQ/incoq
 def rate(self, bindenv):
     mask = Mask.from_vars(self.lhs, bindenv)
     if mask.is_allunbound:
         return Rate.UNRUNNABLE
     elif (mask.parts[0] == 'b' and
           (mask.parts[1] == 'b' or mask.parts[1] == '1')):
         return Rate.CONSTANT
     return super().rate(bindenv)
예제 #21
0
파일: interact.py 프로젝트: dcharkes/incoq
def split_resexp_vars(resexp, mask):
    """Given a result expression of a comprehension and a mask over
    the comprehension result, determine which variables appearing in
    the result expression are bound and unbound. Return the set of
    bounds and unbounds respectively.
    
    A variable is considered bound if it occurs somewhere within any
    subexpression corresponding to a bound part of the mask, where this
    subexpression is injective. Otherwise it is unbound.
    
    For example, if the result expression is ((x, y), z) and the mask
    if 'bu', then x and y are bound and z is unbound. However, if the
    result expression were (x + y, z) then they would all be unbound.
    
    E.g., if the result expression is ((x, y), z) and the mask is
    'bu', then x and y are bound. But if the result expression is
    (x + y, z), then no variables are bound.
    """
    find = partial(L.VarsFinder.run, ignore_functions=True)
    boundvars = set()
    unboundvars = set()

    if isinstance(resexp, L.Tuple):
        boundexps, unboundexps, _ = mask.split_vars(resexp.elts)
        # Determine bound vars.
        for e in boundexps:
            # Injective expressions include simple variable names and
            # tuple trees of variable names.
            if L.is_injective(e):
                boundvars.update(find(e))
        # Determine unbound vars.
        for e in unboundexps:
            unboundvars.update(find(e))
        unboundvars.difference_update(boundvars)

    else:
        # Special case: If the result expression is not a tuple,
        # then the mask is either a single bound or single unbound.
        if mask == Mask('b'):
            boundvars = find(resexp)
        elif mask == Mask.U or mask == Mask('w'):
            unboundvars = find(resexp)
        else:
            assert ()

    return boundvars, unboundvars
예제 #22
0
    def rate(self, bindenv):
        # Require demand parameters to be bound.
        mask = Mask.from_vars(self.enumlhs, bindenv)
        bounds, _unbounds, _eqs = mask.split_vars(self.cl.lhs)

        if not set(bounds).issuperset(set(self.demparams)):
            return Rate.UNRUNNABLE

        return self.cl.rate(bindenv)
예제 #23
0
 def mainttest_helper(self, maskstr):
     spec = AuxmapSpec('R', Mask(maskstr))
     
     # Make the prefix '_' so it's easier to read/type.
     self.manager.namegen.next_prefix = lambda: '_'
     
     code = make_auxmap_maint_code(self.manager, spec, L.ln('e'), 'add')
     
     return code
예제 #24
0
파일: clause.py 프로젝트: IncOQ/incoq
 def get_code(self, bindenv, body):
     deltamask = Mask.from_vars(self.lhs, self.lhs)
     mask = Mask.from_vars(self.lhs, bindenv)
     bvars, uvars, _eqs = mask.split_vars(self.lhs)
     if mask.has_wildcards:
         # Can this be streamlined into something more readable,
         # like expressing the deltamatch as an If-guard? 
         val = L.DeltaMatch(L.ln(self.rel), deltamask.make_node().s,
                            self.val, self.limit)
         return L.pc('''
             for UVARS in setmatch(VAL, MASK, BVARS):
                 BODY
             ''', subst={'VAL': val,
                         'MASK': mask.make_node(),
                         'BVARS': L.tuplify(bvars),
                         'UVARS': L.tuplify(uvars, lval=True),
                         '<c>BODY': body})
     else:
         return make_tuplematch(self.val, mask, bvars, uvars, body)
예제 #25
0
파일: interact.py 프로젝트: dcharkes/incoq
    def visit_IndefImgsetCost(self, cost):
        rel = cost.rel

        inv_cost = None
        if rel in self.invs:
            spec = self.invs[rel].spec

            if isinstance(spec, CompSpec):
                boundvars, _ = split_resexp_vars(spec.resexp, cost.mask)
                info = get_nondet_info(spec, boundvars)
                memconstrs = spec.get_membership_constraints()
                inv_cost = self.assemble_nondet_cost(info, memconstrs)

            elif isinstance(spec, AggrSpec):
                # As above for NameCost, but exclude the parameters that
                # are bound. First determine what parameters are bound
                # by the mask in this cost.
                vars = list(spec.params) + [object()]
                bounds, _unbounds, _eqs = cost.mask.split_vars(vars)
                # Now modify the parameter projection mask to project
                # them away.
                mask = spec.relmask.make_param_proj_mask()
                assert (len(spec.params) == len(
                    [True for p in mask.parts if p == 'u']))
                params = iter(spec.params)
                new_parts = []
                for part in mask.parts:
                    if part == 'u':
                        p = next(params)
                        if p in bounds:
                            new_parts.append('w')
                            continue
                    new_parts.append(part)

                new_mask = Mask(new_parts)
                inv_cost = IndefImgsetCost(spec.rel, new_mask)
                inv_cost = self.visit(inv_cost)

            else:
                assert ()

        # Get the dompath for each unbound component and multiply
        # them together. If any domain is unknown, the whole cost
        # is left alone.
        dom_cost = None
        dompaths = self.dompaths_for_mask(rel, cost.mask)
        if dompaths is not None:
            factors = [self.dompath_to_size(s) for s in dompaths]
            # Check for None again since there could've been a
            # deeper nested dompath missing.
            if all(c is not None for c in factors):
                dom_cost = ProductCost(factors)

        cost = self.make_min((inv_cost, dom_cost))
        return cost
예제 #26
0
    def from_AST(cls, node, factory):
        """Construct from Enumerator node of form
        
            <vars> in deltamatch(<rel>, <mask>, <val>, <limit>)
        """
        checktype(node, L.Enumerator)

        lhs = L.get_vartuple(node.target)
        checktype(node.iter, L.DeltaMatch)
        rel = L.get_name(node.iter.target)
        mask = Mask(node.iter.mask)
        val = node.iter.elem
        limit = node.iter.limit
        if limit not in [0, 1]:
            raise TypeError

        inferred_mask = Mask.from_vars(lhs, lhs)
        assert mask == inferred_mask

        return cls(lhs, rel, val, limit)
예제 #27
0
    def from_AST(cls, node, factory):
        """Construct from an Enumerator node of form
        
            var in {<rel>.smlookup(<mask>, <key vars>)}
        
        """
        checktype(node, L.Enumerator)

        var = L.get_name(node.target)
        sm = L.get_singletonset(node.iter)
        checktype(sm, L.SMLookup)
        rel = L.get_name(sm.target)
        mask = Mask(sm.mask)
        keyvars = L.get_vartuple(sm.key)
        # Ensure the mask is consistent with how it's used.
        if mask != Mask.from_keylen(len(keyvars)):
            raise TypeError

        lhs = keyvars + (var, )
        return cls(lhs, rel)
예제 #28
0
 def get_code(self, bindenv, body):
     deltamask = Mask.from_vars(self.lhs, self.lhs)
     mask = Mask.from_vars(self.lhs, bindenv)
     bvars, uvars, _eqs = mask.split_vars(self.lhs)
     if mask.has_wildcards:
         # Can this be streamlined into something more readable,
         # like expressing the deltamatch as an If-guard?
         val = L.DeltaMatch(L.ln(self.rel),
                            deltamask.make_node().s, self.val, self.limit)
         return L.pc('''
             for UVARS in setmatch(VAL, MASK, BVARS):
                 BODY
             ''',
                     subst={
                         'VAL': val,
                         'MASK': mask.make_node(),
                         'BVARS': L.tuplify(bvars),
                         'UVARS': L.tuplify(uvars, lval=True),
                         '<c>BODY': body
                     })
     else:
         return make_tuplematch(self.val, mask, bvars, uvars, body)
예제 #29
0
 def test_mapset(self):
     code = mapset_bindmatch(Mask('bbb'), ['x', 'y', 'z'], [],
                             L.pc('pass'), typecheck=True)
     exp_code = L.pc('''
         if isinstance(x, Map):
             if y in x and x[y] == z:
                 pass
         ''')
     self.assertEqual(code, exp_code)
     
     code = mapset_bindmatch(Mask('bbu'), ['x', 'y'], ['z'],
                             L.pc('pass'), typecheck=False)
     exp_code = L.pc('''
         if y in x:
             z = x[y]
             pass
     ''')
     self.assertEqual(code, exp_code)
     
     code = mapset_bindmatch(Mask('buu'), ['x'], ['y', 'z'],
                             L.pc('pass'), typecheck=False)
     exp_code = L.pc('''
         for y, z in x.items():
             pass
     ''')
     self.assertEqual(code, exp_code)
     
     with self.assertRaises(AssertionError):
         mapset_bindmatch(Mask('uuu'), [], ['x', 'y', 'z'],
                          L.pc('pass'), typecheck=True)
     
     code = mapset_bindmatch(Mask('ubb'), ['y', 'z'], ['x'],
                             L.pc('pass'), typecheck=True)
     exp_code = L.pc('''
         for x in setmatch(_MAP, 'ubb', (y, z)):
             pass
         ''')
     self.assertEqual(code, exp_code)
예제 #30
0
파일: analyze.py 프로젝트: dcharkes/incoq
    def expr_tosizecost(self, expr):
        """Turn an iterated expression into a cost bound for its
        cardinality.
        """
        if isinstance(expr, L.Name):
            return NameCost(expr.id)

        # Catch case of iterating over a delta set.
        # We'll just say O(delta set), even though it can have
        # duplicates.
        elif (isinstance(expr, L.Call) and isinstance(expr.func, L.Attribute)
              and isinstance(expr.func.value, L.Name)
              and expr.func.attr == 'elements'):
            return NameCost(expr.func.value.id)

        elif isinstance(expr, L.SetMatch):
            if isinstance(expr.target, (L.Set, L.DeltaMatch)):
                return UnitCost()
            elif (isinstance(expr.target, L.Name) and L.is_vartuple(expr.key)):
                keys = L.get_vartuple(expr.key)
                if all(k in self.args for k in keys):
                    return DefImgsetCost(expr.target.id, Mask(expr.mask),
                                         L.get_vartuple(expr.key))
                else:
                    return IndefImgsetCost(expr.target.id, Mask(expr.mask))
            else:
                return self.WarnUnknownCost(expr)

        elif isinstance(expr, L.DeltaMatch):
            return UnitCost()

        elif isinstance(expr, (L.Set, L.List, L.Tuple, L.Dict)):
            return UnitCost()

        else:
            return self.WarnUnknownCost(expr)
예제 #31
0
 def handle_ms_smassignkey(self, f, target, maskstr: 'Str', key, elem,
                           prefix: 'Str'):
     from incoq.compiler.set import Mask
     mask = Mask(maskstr)
     assert mask.is_keymask
     # vars for each bound component ((len(mask) - 1) many).
     vars = [prefix + str(i) for i in range(1, len(mask))]
     return self.pc('''
         S_VARS = KEY
         TARGET.add(PARTS)
         ''',
                    subst={
                        'S_VARS': tuplify(vars, lval=True),
                        'KEY': key,
                        'TARGET': target,
                        'PARTS': tuplify(vars + [elem])
                    })
예제 #32
0
파일: aggr.py 프로젝트: IncOQ/incoq
 def __init__(self, aggr, spec, name, demname, uset_lru, half_demand):
     self.params = params = tuple(spec.params)
     """Aggregate parameters (same as operand parameters).
     Also same as aggregate demand parameters.
     """
     
     self.aggrmask = Mask.from_keylen(len(params))
     """Aggregate result retrieval mask."""
     
     self.oper_deltamask = spec.relmask.make_delta_mask()
     """Mask for doing delta test upon change to aggregate operand."""
     
     assert not (spec.has_oper_demand and not self.has_demand), \
         'Can\'t have non-demand-driven aggregate over demand-driven ' \
         'operand'
     
     assert not (half_demand and not self.has_demand), \
         'Can\'t use half-demand strategy when not using demand at all'
예제 #33
0
    def test_VarRewriter(self):
        ST, TT, OT = L.SetType, L.TupleType, L.ObjType
        t = ST(TT([OT('A'), OT('B'), TT([OT('C'), OT('D')])]))
        self.manager.vartypes['R'] = t

        cost = NameCost('R')
        cost = VarRewriter.run(cost, self.manager)
        exp_cost = ProductCost(
            [NameCost('A'),
             NameCost('B'),
             NameCost('C'),
             NameCost('D')])
        self.assertEqual(cost, exp_cost)

        cost = IndefImgsetCost('R', Mask('buu'))
        cost = VarRewriter.run(cost, self.manager)
        exp_cost = ProductCost([NameCost('B'), NameCost('C'), NameCost('D')])
        self.assertEqual(cost, exp_cost)
예제 #34
0
파일: aggr.py 프로젝트: dcharkes/incoq
    def __init__(self, aggr, spec, name, demname, uset_lru, half_demand):
        self.params = params = tuple(spec.params)
        """Aggregate parameters (same as operand parameters).
        Also same as aggregate demand parameters.
        """

        self.aggrmask = Mask.from_keylen(len(params))
        """Aggregate result retrieval mask."""

        self.oper_deltamask = spec.relmask.make_delta_mask()
        """Mask for doing delta test upon change to aggregate operand."""

        assert not (spec.has_oper_demand and not self.has_demand), \
            'Can\'t have non-demand-driven aggregate over demand-driven ' \
            'operand'

        assert not (half_demand and not self.has_demand), \
            'Can\'t use half-demand strategy when not using demand at all'
예제 #35
0
 def test_dompaths_for_mask(self):
     dompaths = self.trans.dompaths_for_mask('R', Mask.IN)
     exp_dompaths = ('R.1',)
     self.assertEqual(dompaths, exp_dompaths)
     
     dompaths = self.trans.dompaths_for_mask('R', Mask.UU)
     exp_dompaths = ('R.1', 'R.2')
     self.assertEqual(dompaths, exp_dompaths)
     
     dompaths = self.trans.dompaths_for_mask('R.2', Mask.U)
     exp_dompaths = ('R.2',)
     self.assertEqual(dompaths, exp_dompaths)
     
     dompaths = self.trans.dompaths_for_mask('R.2', Mask('b'))
     exp_dompaths = ()
     self.assertEqual(dompaths, exp_dompaths)
     
     dompaths = self.trans.dompaths_for_mask('S', Mask.IN)
     exp_dompaths = None
     self.assertEqual(dompaths, exp_dompaths)
예제 #36
0
파일: clause.py 프로젝트: IncOQ/incoq
 def from_AST(cls, node, factory):
     """Construct from Enumerator node of form
     
         <vars> in deltamatch(<rel>, <mask>, <val>, <limit>)
     """
     checktype(node, L.Enumerator)
     
     lhs = L.get_vartuple(node.target)
     checktype(node.iter, L.DeltaMatch)
     rel = L.get_name(node.iter.target)
     mask = Mask(node.iter.mask)
     val = node.iter.elem
     limit = node.iter.limit
     if limit not in [0, 1]:
         raise TypeError
     
     inferred_mask = Mask.from_vars(lhs, lhs)
     assert mask == inferred_mask
     
     return cls(lhs, rel, val, limit)
예제 #37
0
파일: clause.py 프로젝트: IncOQ/incoq
 def from_AST(cls, node, factory):
     """Construct from an Enumerator node of form
     
         var in {<rel>.smlookup(<mask>, <key vars>)}
     
     """
     checktype(node, L.Enumerator)
     
     var = L.get_name(node.target)
     sm = L.get_singletonset(node.iter)
     checktype(sm, L.SMLookup)
     rel = L.get_name(sm.target)
     mask = Mask(sm.mask)
     keyvars = L.get_vartuple(sm.key)
     # Ensure the mask is consistent with how it's used.
     if mask != Mask.from_keylen(len(keyvars)):
         raise TypeError
     
     lhs = keyvars + (var,)
     return cls(lhs, rel)
예제 #38
0
 def handle_ms_smreassignkey(self, f, target, maskstr: 'Str', key, elem,
                             prefix: 'Str'):
     from incoq.compiler.set import Mask
     mask = Mask(maskstr)
     assert mask.is_keymask
     vars = [prefix + str(i) for i in range(1, len(mask))]
     evar = prefix + 'elem'
     return self.pc('''
         S_VARS = KEY
         S_EVAR = TARGET.smlookup(MASK, KEY)
         TARGET.remove(OLD_PARTS)
         TARGET.add(NEW_PARTS)
         ''',
                    subst={
                        'S_VARS': tuplify(vars, lval=True),
                        'KEY': key,
                        'S_EVAR': sn(evar),
                        'TARGET': target,
                        'MASK': Str(maskstr),
                        'OLD_PARTS': tuplify(vars + [evar]),
                        'NEW_PARTS': tuplify(vars + [elem])
                    })
예제 #39
0
파일: interact.py 프로젝트: IncOQ/incoq
def get_nondet_info(spec, bound_vars):
    """Given a comprehension and some bound variables, return
    information to help put a bound on the size of the part of
    the comprehension result that matches the bound variables.
    
    Specifically, we look at the non-determined variables. Choose
    a join order of the comprehension's clauses starting with the
    bound variables. For each clause in order, append to the result
    a triple of
    
        (iterated relation, mask, non-determined variables)
    
    where the non-determined variables are a subset of unbound vars
    in the clause that, together with the bound vars, functionally
    determine the remaining unbound vars in the clause. All the
    unbound variables in a clause become bound for future clauses.
    The mask is the lookup pattern that goes from the bound vars
    and determined unbound vars to the non-determined unbound vars.
    
    This goes on until all variables appearing in the comprehension
    result expression are bound.
    
    For each entry in the result, the newly introduced non-
    determined vars introduce a cost factor, and the overall
    comprehension's cost is bounded by the product of these factors.
    Each factor can itself be bounded in two ways. First, it can be
    considered recursively as an image set lookup over the iterated
    relation. Second, we can take all the membership constraints
    on the non-determined variables and use domain bounds for them.
    Assembling/minimizing these bounds is the caller's
    responsibility.
    """
    goal_vars = L.VarsFinder.run(spec.resexp, ignore_functions=True)
    bound_vars = set(bound_vars)
    result = []
    
    ordering = spec.join.get_ordering(bound_vars)
    for _i, cl, _bindenv in ordering:
        # Skip the remaining clauses if we bound all the
        # variables we need to.
        if bound_vars.issuperset(goal_vars):
            break
        # Ignore condition clauses and clauses that are not over
        # a relation.
        if cl.enumrel is None:
            continue
        
        det_vars = set(cl.get_determined_vars(bound_vars))
        nondet_vars = set(cl.enumvars) - bound_vars - det_vars
        
        # Special case for lower cost bounds: If we happen to be able
        # to span the goal vars by taking some but not all of the nondet
        # vars and no det vars, then do that instead.
        if (bound_vars | nondet_vars).issuperset(goal_vars):
            to_vars = goal_vars - bound_vars
            from_vars = bound_vars
        else:
            to_vars = nondet_vars
            from_vars = bound_vars
        wild_vars = set(cl.enumvars) - from_vars - to_vars
        
        mask = Mask.from_vars(cl.enumlhs, from_vars, wild_vars)
        
        result.append((cl.enumrel, mask, to_vars))
        
        bound_vars.update(cl.enumvars)
    
    return result
예제 #40
0
파일: objclause.py 프로젝트: IncOQ/incoq
 def get_code(self, bindenv, body):
     mask = Mask.from_vars(self.lhs, bindenv)
     bvars, uvars, _eqs = mask.split_vars(self.lhs)
     return mset_bindmatch(mask, bvars, uvars, body,
                           typecheck=self.typecheck)
예제 #41
0
파일: clause.py 프로젝트: IncOQ/incoq
 def to_AST(self):
     mask = Mask.from_vars(self.lhs, self.lhs)
     return L.Enumerator(L.tuplify(self.lhs, lval=True),
                         L.DeltaMatch(L.ln(self.rel), mask.make_node().s,
                                      self.val, self.limit))
예제 #42
0
파일: clause.py 프로젝트: IncOQ/incoq
 def get_code(self, bindenv, body):
     mask = Mask.from_vars(self.lhs, bindenv)
     bvars, uvars, _eqs = mask.split_vars(self.lhs)
     return make_tuplematch(self.val, mask, bvars, uvars, body)
예제 #43
0
파일: clause.py 프로젝트: IncOQ/incoq
 def fits_string(self, bindenv, s):
     mask = Mask.from_vars(self.lhs, bindenv)
     return s == AuxmapSpec(self.rel, mask).lookup_name
예제 #44
0
파일: clause.py 프로젝트: IncOQ/incoq
 def rate(self, bindenv):
     mask = Mask.from_vars(self.lhs, bindenv)
     if mask.is_keymask:
         return Rate.CONSTANT
     return super().rate(bindenv)