Esempio n. 1
0
    def test_replacer(self):
        look = L.pe('R.smlookup("bu", x)')
        dem1 = L.pe('DEMQUERY(foo, [y], R.smlookup("bu", y))')
        dem2 = L.pe('DEMQUERY(bar, [z], R.smlookup("bu", z))')

        tree = L.pe('x + LOOK + DEM1 + DEM1 + DEM2',
                    subst={
                        'LOOK': look,
                        'DEM1': dem1,
                        'DEM2': dem2
                    })
        namer = L.NameGenerator()
        replacer = LookupReplacer(namer)
        tree, clauses = replacer.process(tree)
        repls = replacer.repls

        exp_tree = L.pe('x + v1 + v2 + v2 + v3')
        exp_clauses = [
            L.Enumerator(L.sn('v1'), L.pe('{R.smlookup("bu", x)}')),
            L.Enumerator(L.sn('v2'),
                         L.pe('DEMQUERY(foo, [y], {R.smlookup("bu", y)})')),
            L.Enumerator(L.sn('v3'),
                         L.pe('DEMQUERY(bar, [z], {R.smlookup("bu", z)})')),
        ]
        exp_repls = {
            look: 'v1',
            dem1: 'v2',
            dem2: 'v3',
        }

        self.assertEqual(tree, exp_tree)
        self.assertEqual(clauses, exp_clauses)
        self.assertEqual(repls, exp_repls)
Esempio n. 2
0
 def test_replacer(self):
     look = L.pe('R.smlookup("bu", x)')
     dem1 = L.pe('DEMQUERY(foo, [y], R.smlookup("bu", y))')
     dem2 = L.pe('DEMQUERY(bar, [z], R.smlookup("bu", z))')
     
     tree = L.pe('x + LOOK + DEM1 + DEM1 + DEM2',
                 subst={'LOOK': look, 'DEM1': dem1, 'DEM2': dem2})
     namer = L.NameGenerator()
     replacer = LookupReplacer(namer)
     tree, clauses = replacer.process(tree)
     repls = replacer.repls
     
     exp_tree = L.pe('x + v1 + v2 + v2 + v3')
     exp_clauses = [
         L.Enumerator(L.sn('v1'),
                      L.pe('{R.smlookup("bu", x)}')),
         L.Enumerator(L.sn('v2'),
                      L.pe('DEMQUERY(foo, [y], {R.smlookup("bu", y)})')),
         L.Enumerator(L.sn('v3'),
                      L.pe('DEMQUERY(bar, [z], {R.smlookup("bu", z)})')),
     ]
     exp_repls = {
         look: 'v1',
         dem1: 'v2',
         dem2: 'v3',
     }
     
     self.assertEqual(tree, exp_tree)
     self.assertEqual(clauses, exp_clauses)
     self.assertEqual(repls, exp_repls)
Esempio n. 3
0
File: aggr.py Progetto: IncOQ/incoq
 def make_addu_maint(self, prefix):
     """Generate code for after an addition to U."""
     incaggr = self.incaggr
     assert incaggr.has_demand
     spec = incaggr.spec
     mv_var = prefix + 'val'
     elemvar = prefix + 'elem'
     
     # If we're using half-demand, there's no demand to propagate
     # to the operand. All we need to do is add an entry with count
     # 0 if one is not already there.
     if incaggr.half_demand:
         return L.pc('''
             S_MV = A.smdeflookup(MASK, KEY, None)
             if MV is None:
                 A.smassignkey(MASK, KEY, ZERO, PREFIX)
             ''', subst={'A': L.ln(incaggr.name),
                         'S_MV': L.sn(mv_var),
                         'MV': L.ln(mv_var),
                         'MASK': incaggr.aggrmask.make_node(),
                         'KEY': L.tuplify(incaggr.params),
                         'ZERO': self.make_zero_mapval_expr(),
                         'PREFIX': L.Str(prefix)})
     
     update_code = self.make_update_state_code(
         L.sn(mv_var), L.ln(mv_var), 'add',
         L.ln(elemvar), prefix)
     
     # Make operand demand function call, if operand uses demand.
     if spec.has_oper_demand:
         demfunc = L.N.demfunc(spec.oper_demname)
         call_demfunc = L.Call(L.ln(demfunc),
                               tuple(L.ln(v) for v in spec.oper_demparams),
                               (), None, None)
         propagate_code = (L.Expr(call_demfunc),)
     else:
         propagate_code = ()  
     
     code = L.pc('''
         S_MV = ZERO
         for S_ELEM in setmatch(R, RELMASK, PARAMS):
             UPDATE_MAPVAL
         A.smassignkey(AGGRMASK, KEY, MV, PREFIX)
         PROPAGATE_DEMAND
         ''', subst={'S_MV': L.sn(mv_var),
                     'ZERO': self.make_zero_mapval_expr(),
                     'S_ELEM': L.sn(elemvar),
                     'R': spec.rel,
                     'RELMASK': spec.relmask.make_node(),
                     'PARAMS': L.tuplify(spec.params),
                     '<c>UPDATE_MAPVAL': update_code,
                     'A': L.ln(incaggr.name),
                     'AGGRMASK': incaggr.aggrmask.make_node(),
                     'KEY': L.tuplify(incaggr.params),
                     'MV': L.ln(mv_var),
                     'PREFIX': L.Str(prefix),
                     '<c>PROPAGATE_DEMAND': propagate_code})
     
     return code
Esempio n. 4
0
 def visit_Tuple(self, node):
     # No need to recurse, that's taken care of by the caller
     # of this visitor.
     tupvar = self.tupvar_namer.next()
     arity = len(node.elts)
     trel = make_trel(arity)
     elts = (L.sn(tupvar), ) + node.elts
     new_cl = L.Enumerator(L.tuplify(elts, lval=True), L.ln(trel))
     self.new_clauses.append(new_cl)
     self.trels.add(trel)
     return L.sn(tupvar)
Esempio n. 5
0
 def visit_Tuple(self, node):
     # No need to recurse, that's taken care of by the caller
     # of this visitor.
     tupvar = self.tupvar_namer.next()
     arity = len(node.elts)
     trel = make_trel(arity)
     elts = (L.sn(tupvar),) + node.elts
     new_cl = L.Enumerator(L.tuplify(elts, lval=True),
                           L.ln(trel))
     self.new_clauses.append(new_cl)
     self.trels.add(trel)
     return L.sn(tupvar)
Esempio n. 6
0
 def visit_SetUpdate(self, node):
     target_ok = LegalUpdateValidator.run(node.target)
     elem_ok = LegalUpdateValidator.run(node.elem)
     if target_ok and elem_ok:
         return node
     
     code = ()
     if not target_ok:
         targetvar = next(self.namegen)
         code += (L.Assign((L.sn(targetvar),), node.target),)
         node = node._replace(target=L.ln(targetvar))
     if not elem_ok:
         elemvar = next(self.namegen)
         code += (L.Assign((L.sn(elemvar),), node.elem),)
         node = node._replace(elem=L.ln(elemvar))
     return code + (node,)
Esempio n. 7
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, )))
Esempio n. 8
0
    def visit_SetUpdate(self, node):
        target_ok = LegalUpdateValidator.run(node.target)
        elem_ok = LegalUpdateValidator.run(node.elem)
        if target_ok and elem_ok:
            return node

        code = ()
        if not target_ok:
            targetvar = next(self.namegen)
            code += (L.Assign((L.sn(targetvar), ), node.target), )
            node = node._replace(target=L.ln(targetvar))
        if not elem_ok:
            elemvar = next(self.namegen)
            code += (L.Assign((L.sn(elemvar), ), node.elem), )
            node = node._replace(elem=L.ln(elemvar))
        return code + (node, )
Esempio n. 9
0
    def make_update_state_code(self, state_snode, state_lnode, op, val_node,
                               prefix):
        add_template = L.trim('''
            S_TREE, _ = STATE
            TREE[VAL] = None
            S_STATE = (TREE, TREE.MINMAX())
            ''')

        remove_template = L.trim('''
            S_TREE, _ = STATE
            del TREE[VAL]
            S_STATE = (TREE, TREE.MINMAX())
            ''')

        template = {'add': add_template, 'remove': remove_template}[op]

        treevar = prefix + 'tree'
        minmax = {'min': '__min__', 'max': '__max__'}[self.kind]
        code = L.pc(template,
                    subst={
                        'S_TREE': L.sn(treevar),
                        'TREE': L.ln(treevar),
                        '@MINMAX': minmax,
                        'STATE': state_lnode,
                        'S_STATE': state_snode,
                        'VAL': val_node
                    })
        return code
Esempio n. 10
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,)))
Esempio n. 11
0
File: aggr.py Progetto: IncOQ/incoq
 def make_update_state_code(self, state_snode, state_lnode,
                      op, val_node, prefix):
     add_template = L.trim('''
         S_TREE, _ = STATE
         TREE[VAL] = None
         S_STATE = (TREE, TREE.MINMAX())
         ''')
     
     remove_template = L.trim('''
         S_TREE, _ = STATE
         del TREE[VAL]
         S_STATE = (TREE, TREE.MINMAX())
         ''')
     
     template = {'add': add_template, 'remove': remove_template}[op]
     
     treevar = prefix + 'tree'
     minmax = {'min': '__min__', 'max': '__max__'}[self.kind] 
     code = L.pc(template,
                 subst={'S_TREE': L.sn(treevar),
                        'TREE': L.ln(treevar),
                        '@MINMAX': minmax,
                        'STATE': state_lnode,
                        'S_STATE': state_snode,
                        'VAL': val_node})
     return code
Esempio n. 12
0
 def visit_DemQuery(self, node):
     self.demwrapped_nodes.add(node.value)
     node = self.generic_visit(node)
     
     if not isinstance(node.value, L.SMLookup):
         return node
     sm = node.value
     assert sm.default is None
     
     v = self.repls.get(node, None)
     if v is not None:
         # Reuse existing entry.
         var = v
     else:
         # Create new entry.
         self.repls[node] = var = next(self.namer)
         # Create accompanying clause. Has form
         #    var in DEMQUERY(..., {smlookup})
         # The clause constructor logic will later rewrite that,
         # or else fail if there's a syntax problem.
         cl_target = L.sn(var)
         cl_iter = node._replace(value=L.Set((sm,)))
         new_cl = L.Enumerator(cl_target, cl_iter)
         self.new_clauses.append(new_cl)
     
     return L.ln(var)
Esempio n. 13
0
 def visit_DelKey(self, node):
     target_ok = LegalUpdateValidator.run(node.target)
     key_ok = LegalUpdateValidator.run(node.key)
     if target_ok and key_ok:
         return node
     
     code = ()
     if not target_ok:
         targetvar = next(self.namegen)
         code += (L.Assign((L.sn(targetvar),), node.target),)
         node = node._replace(target=L.ln(targetvar))
     if not key_ok:
         keyvar = next(self.namegen)
         code += (L.Assign((L.sn(keyvar),), node.key),)
         node = node._replace(key=L.ln(keyvar))
     
     return code + (node,)
Esempio n. 14
0
    def visit_DelKey(self, node):
        target_ok = LegalUpdateValidator.run(node.target)
        key_ok = LegalUpdateValidator.run(node.key)
        if target_ok and key_ok:
            return node

        code = ()
        if not target_ok:
            targetvar = next(self.namegen)
            code += (L.Assign((L.sn(targetvar), ), node.target), )
            node = node._replace(target=L.ln(targetvar))
        if not key_ok:
            keyvar = next(self.namegen)
            code += (L.Assign((L.sn(keyvar), ), node.key), )
            node = node._replace(key=L.ln(keyvar))

        return code + (node, )
Esempio n. 15
0
    def make_update_mapval_code(self, mv_snode, mv_lnode, op, val_node,
                                prefix):
        """Produce code to make a new mapval, given an update to
        the corresponding operand. The mapval is read from mv_lnode
        and written to mv_snode.
        """
        # If we don't track counts, the mapvals are the same as
        # the states.
        if not self.incaggr.tracks_counts:
            return self.make_update_state_code(mv_snode, mv_lnode, op,
                                               val_node, prefix)

        statevar = prefix + 'state'
        state_lnode = L.ln(statevar)
        state_snode = L.sn(statevar)
        countvar = prefix + 'count'

        updatestate_code = self.make_update_state_code(state_snode,
                                                       state_lnode, op,
                                                       val_node, prefix)

        if op == 'add':
            template = 'COUNTVAR + 1'
        elif op == 'remove':
            template = 'COUNTVAR - 1'
        else:
            assert ()
        new_count_node = L.pe(template, subst={'COUNTVAR': L.ln(countvar)})

        return L.pc('''
            S_STATE, S_COUNTVAR = MV
            UPDATE_STATE
            S_MV = STATE, NEW_COUNT
            ''',
                    subst={
                        'S_STATE': state_snode,
                        'S_COUNTVAR': L.sn(countvar),
                        'MV': mv_lnode,
                        '<c>UPDATE_STATE': updatestate_code,
                        'STATE': state_lnode,
                        'NEW_COUNT': new_count_node,
                        'S_MV': mv_snode
                    })
Esempio n. 16
0
 def visit_Module(self, node):
     node = self.generic_visit(node)
     
     decls = ()
     if self.use_mset:
         decls += L.pc('''
             M = MSet()
             ''', subst={'M': L.sn(make_mrel())})
     for field in self.fields:
         decls += L.pc('''
             F = FSet()
             ''', subst={'F': L.sn(make_frel(field))})
     if self.use_mapset:
         decls += L.pc('''
             MAP = MAPSet()
             ''', subst={'MAP': L.sn(make_maprel())})
     
     node = node._replace(body=decls + node.body)
     return node
Esempio n. 17
0
    def visit_SetUpdate(self, node):
        if not (isinstance(node.target, L.Name)
                and node.target.id == self.rel):
            return

        fresh = next(self.namegen)
        tvar = '_t' + fresh
        ftvar = '_ft' + fresh
        code = make_flattup_code(self.tuptype, node.elem, L.sn(ftvar), tvar)
        update = node._replace(elem=L.ln(ftvar))
        return code + (update, )
Esempio n. 18
0
 def visit_SetUpdate(self, node):
     if not (isinstance(node.target, L.Name) and
             node.target.id == self.rel):
         return
     
     fresh = next(self.namegen)
     tvar = '_t' + fresh
     ftvar = '_ft' + fresh
     code = make_flattup_code(self.tuptype, node.elem,
                              L.sn(ftvar), tvar)
     update = node._replace(elem=L.ln(ftvar))
     return code + (update,)
Esempio n. 19
0
File: aggr.py Progetto: IncOQ/incoq
 def make_update_mapval_code(self, mv_snode, mv_lnode,
                            op, val_node, prefix):
     """Produce code to make a new mapval, given an update to
     the corresponding operand. The mapval is read from mv_lnode
     and written to mv_snode.
     """
     # If we don't track counts, the mapvals are the same as
     # the states.
     if not self.incaggr.tracks_counts:
         return self.make_update_state_code(mv_snode, mv_lnode,
                                            op, val_node, prefix)
     
     statevar = prefix + 'state'
     state_lnode = L.ln(statevar)
     state_snode = L.sn(statevar)
     countvar = prefix + 'count'
     
     updatestate_code = self.make_update_state_code(
                         state_snode, state_lnode,
                         op, val_node, prefix)
     
     if op == 'add':
         template = 'COUNTVAR + 1'
     elif op == 'remove':
         template = 'COUNTVAR - 1'
     else:
         assert()
     new_count_node = L.pe(template, subst={'COUNTVAR': L.ln(countvar)})
     
     return L.pc('''
         S_STATE, S_COUNTVAR = MV
         UPDATE_STATE
         S_MV = STATE, NEW_COUNT
         ''', subst={'S_STATE': state_snode,
                     'S_COUNTVAR': L.sn(countvar),
                     'MV': mv_lnode,
                     '<c>UPDATE_STATE': updatestate_code,
                     'STATE': state_lnode,
                     'NEW_COUNT': new_count_node,
                     'S_MV': mv_snode})
Esempio n. 20
0
    def visit_Module(self, node):
        node = self.generic_visit(node)

        decls = ()
        if self.use_mset:
            decls += L.pc('''
                M = MSet()
                ''',
                          subst={'M': L.sn(make_mrel())})
        for field in self.fields:
            decls += L.pc('''
                F = FSet()
                ''',
                          subst={'F': L.sn(make_frel(field))})
        if self.use_mapset:
            decls += L.pc('''
                MAP = MAPSet()
                ''',
                          subst={'MAP': L.sn(make_maprel())})

        node = node._replace(body=decls + node.body)
        return node
Esempio n. 21
0
    def make_removeu_maint(self, prefix):
        """Generate code for before a removal from U."""
        incaggr = self.incaggr
        assert incaggr.has_demand
        spec = incaggr.spec
        mv_var = prefix + 'val'

        # If we're using half-demand, there's no demand to propagate
        # to the operand. All we need to do is determine whether to
        # do the removal by checking whether the count is 0.
        if incaggr.half_demand:
            return L.pc('''
                S_MV = A.smlookup(MASK, KEY)
                if COUNT == 0:
                    A.smdelkey(MASK, KEY, PREFIX)
                ''',
                        subst={
                            'S_MV': L.sn(mv_var),
                            'COUNT': self.mapval_proj_count(L.ln(mv_var)),
                            'A': incaggr.name,
                            'MASK': incaggr.aggrmask.make_node(),
                            'KEY': L.tuplify(incaggr.params),
                            'PREFIX': L.Str(prefix)
                        })

        # Generate operand undemand function call, if operand
        # uses demand.
        if spec.has_oper_demand:
            undemfunc = L.N.undemfunc(spec.oper_demname)
            call_undemfunc = L.Call(
                L.ln(undemfunc), tuple(L.ln(v) for v in spec.oper_demparams),
                (), None, None)
            propagate_code = (L.Expr(call_undemfunc), )
        else:
            propagate_code = ()

        code = L.pc('''
            PROPAGATE_DEMAND
            A.smdelkey(MASK, KEY, PREFIX)
            ''',
                    subst={
                        'A': incaggr.name,
                        'MASK': incaggr.aggrmask.make_node(),
                        'KEY': L.tuplify(incaggr.params),
                        'PREFIX': L.Str(prefix),
                        '<c>PROPAGATE_DEMAND': propagate_code
                    })

        return code
Esempio n. 22
0
 def test_flattup_code(self):
     in_node = L.ln('x')
     out_node = L.sn('y')
     code = make_flattup_code(self.tuptype, in_node, out_node, 't')
     exp_code = L.pc('''
         y = (x[0], x[1][0], x[1][1])
         ''')
     self.assertEqual(code, exp_code)
     
     in_node = L.pe('x.a')
     code = make_flattup_code(self.tuptype, in_node, out_node, 't')
     exp_code = L.pc('''
         t = x.a
         y = (t[0], t[1][0], t[1][1])
         ''')
     self.assertEqual(code, exp_code)
Esempio n. 23
0
    def test_flattup_code(self):
        in_node = L.ln('x')
        out_node = L.sn('y')
        code = make_flattup_code(self.tuptype, in_node, out_node, 't')
        exp_code = L.pc('''
            y = (x[0], x[1][0], x[1][1])
            ''')
        self.assertEqual(code, exp_code)

        in_node = L.pe('x.a')
        code = make_flattup_code(self.tuptype, in_node, out_node, 't')
        exp_code = L.pc('''
            t = x.a
            y = (t[0], t[1][0], t[1][1])
            ''')
        self.assertEqual(code, exp_code)
Esempio n. 24
0
 def test_parseclause(self):
     comp = L.pe('''
         COMP({... for (a, b) in _M for (c, d) in _F_e
                   for (f, g, h) in _MAP if x > 5}, [], {})
         ''')
     
     res1 = get_menum(comp.clauses[0])
     exp_res1 = (L.sn('a'), L.sn('b'))
     res2 = get_fenum(comp.clauses[1])
     exp_res2 = (L.sn('c'), L.sn('d'), 'e')
     res3 = get_mapenum(comp.clauses[2])
     exp_res3 = (L.sn('f'), L.sn('g'), L.sn('h'))
     
     self.assertEqual(res1, exp_res1)
     self.assertEqual(res2, exp_res2)
     self.assertEqual(res3, exp_res3)
Esempio n. 25
0
    def test_parseclause(self):
        comp = L.pe('''
            COMP({... for (a, b) in _M for (c, d) in _F_e
                      for (f, g, h) in _MAP if x > 5}, [], {})
            ''')

        res1 = get_menum(comp.clauses[0])
        exp_res1 = (L.sn('a'), L.sn('b'))
        res2 = get_fenum(comp.clauses[1])
        exp_res2 = (L.sn('c'), L.sn('d'), 'e')
        res3 = get_mapenum(comp.clauses[2])
        exp_res3 = (L.sn('f'), L.sn('g'), L.sn('h'))

        self.assertEqual(res1, exp_res1)
        self.assertEqual(res2, exp_res2)
        self.assertEqual(res3, exp_res3)
Esempio n. 26
0
 def helper(self, node, no_update=False):
     fresh = next(self.namegen)
     
     if no_update:
         template = L.trim('''
             S_VAR = Set()
             ''')
     else:
         template = L.trim('''
             S_VAR = Set()
             L_VAR.update(EXPR)
             ''')
     new_code = L.pc(template, subst={'L_VAR': L.ln(fresh),
                                      'S_VAR': L.sn(fresh),
                                      'EXPR': node})
     
     self.pre_stmts.extend(new_code)
     return L.ln(fresh)
Esempio n. 27
0
def make_flattup_code(tuptype, in_node, out_node, tempvar):
    """Given a tuple tree type, make code to take the tuple given by the
    expression in_node and store the flattened form in the tuple given
    by out_node.
    """
    def leaf_to_expr(root, path):
        """Turn a leaf path into a series of subscript expressions
        that obtain the leaf value from the root value.
        """
        node = root
        for i in path:
            node = L.Subscript(node, L.Index(L.Num(i)), L.Load())
        return node

    leaves = tuptype_leaves(tuptype)
    code = ()

    # If in_expr is just a variable name, use it as is.
    # Otherwise store it in a temporary variable to avoid redundant
    # evaluation of in_expr.
    if isinstance(in_node, L.Name):
        root_node = in_node
    else:
        rootname = tempvar
        code += L.pc('''
            ROOT = IN_NODE
            ''',
                     subst={
                         'IN_NODE': in_node,
                         'ROOT': L.sn(rootname)
                     })
        root_node = L.ln(rootname)

    flattuple_expr = L.Tuple(
        tuple(leaf_to_expr(root_node, leaf) for leaf in leaves), L.Load())
    code += L.pc('''
        OUT_NODE = FLATTUP
        ''',
                 subst={
                     'FLATTUP': flattuple_expr,
                     'OUT_NODE': out_node
                 })

    return code
Esempio n. 28
0
File: aggr.py Progetto: IncOQ/incoq
 def make_removeu_maint(self, prefix):
     """Generate code for before a removal from U."""
     incaggr = self.incaggr
     assert incaggr.has_demand
     spec = incaggr.spec
     mv_var = prefix + 'val'
     
     # If we're using half-demand, there's no demand to propagate
     # to the operand. All we need to do is determine whether to
     # do the removal by checking whether the count is 0.
     if incaggr.half_demand:
         return L.pc('''
             S_MV = A.smlookup(MASK, KEY)
             if COUNT == 0:
                 A.smdelkey(MASK, KEY, PREFIX)
             ''', subst={'S_MV': L.sn(mv_var),
                         'COUNT': self.mapval_proj_count(L.ln(mv_var)),
                         'A': incaggr.name,
                         'MASK': incaggr.aggrmask.make_node(),
                         'KEY': L.tuplify(incaggr.params),
                         'PREFIX': L.Str(prefix)})
     
     # Generate operand undemand function call, if operand
     # uses demand.
     if spec.has_oper_demand:
         undemfunc = L.N.undemfunc(spec.oper_demname)
         call_undemfunc = L.Call(L.ln(undemfunc),
                                 tuple(L.ln(v) for v in spec.oper_demparams),
                                 (), None, None)
         propagate_code = (L.Expr(call_undemfunc),)
     else:
         propagate_code = ()  
     
     code = L.pc('''
         PROPAGATE_DEMAND
         A.smdelkey(MASK, KEY, PREFIX)
         ''', subst={'A': incaggr.name,
                     'MASK': incaggr.aggrmask.make_node(),
                     'KEY': L.tuplify(incaggr.params),
                     'PREFIX': L.Str(prefix),
                     '<c>PROPAGATE_DEMAND': propagate_code})
     
     return code
Esempio n. 29
0
 def visit_SMLookup(self, node):
     node = self.generic_visit(node)
     
     if node in self.demwrapped_nodes:
         return node
     
     sm = node
     assert sm.default is None
     
     v = self.repls.get(node, None)
     if v is not None:
         var = v
     else:
         self.repls[node] = var = next(self.namer)
         cl_target = L.sn(var)
         cl_iter = L.Set((sm,))
         new_cl = L.Enumerator(cl_target, cl_iter)
         self.new_clauses.append(new_cl)
     
     return L.ln(var)
Esempio n. 30
0
    def test_lookupclause(self):
        cl = LookupClause(('x', 'y', 'z'), 'R')

        # AST round-trip.
        clast = cl.to_AST()
        sm = L.SMLookup(L.ln('R'), 'bbu', L.tuplify(['x', 'y']), None)
        exp_clast = L.Enumerator(L.sn('z'), L.Set((sm, )))
        self.assertEqual(clast, exp_clast)
        cl2 = LookupClause.from_AST(exp_clast, DummyFactory)
        self.assertEqual(cl2, cl)

        # Attributes.
        self.assertEqual(cl.enumvars, ('x', 'y', 'z'))

        # Rewriting.
        cl2 = cl.rewrite_subst({'x': 'xx', 'z': 'zz'}, DummyFactory)
        self.assertEqual(cl2, LookupClause(('xx', 'y', 'zz'), 'R'))

        # Rating.
        self.assertEqual(cl.rate(['x']), Rate.NORMAL)
        self.assertEqual(cl.rate(['x', 'y']), Rate.CONSTANT)
Esempio n. 31
0
 def test_lookupclause(self):
     cl = LookupClause(('x', 'y', 'z'), 'R')
     
     # AST round-trip.
     clast = cl.to_AST()
     sm = L.SMLookup(L.ln('R'), 'bbu', L.tuplify(['x', 'y']), None)
     exp_clast = L.Enumerator(L.sn('z'), L.Set((sm,)))
     self.assertEqual(clast, exp_clast)
     cl2 = LookupClause.from_AST(exp_clast, DummyFactory)
     self.assertEqual(cl2, cl)
     
     # Attributes.
     self.assertEqual(cl.enumvars, ('x', 'y', 'z'))
     
     # Rewriting.
     cl2 = cl.rewrite_subst({'x': 'xx', 'z': 'zz'}, DummyFactory)
     self.assertEqual(cl2, LookupClause(('xx', 'y', 'zz'), 'R'))
     
     # Rating.
     self.assertEqual(cl.rate(['x']), Rate.NORMAL)
     self.assertEqual(cl.rate(['x', 'y']), Rate.CONSTANT)
Esempio n. 32
0
    def helper(self, node, no_update=False):
        fresh = next(self.namegen)

        if no_update:
            template = L.trim('''
                S_VAR = Set()
                ''')
        else:
            template = L.trim('''
                S_VAR = Set()
                L_VAR.update(EXPR)
                ''')
        new_code = L.pc(template,
                        subst={
                            'L_VAR': L.ln(fresh),
                            'S_VAR': L.sn(fresh),
                            'EXPR': node
                        })

        self.pre_stmts.extend(new_code)
        return L.ln(fresh)
Esempio n. 33
0
def make_flattup_code(tuptype, in_node, out_node, tempvar):
    """Given a tuple tree type, make code to take the tuple given by the
    expression in_node and store the flattened form in the tuple given
    by out_node.
    """
    def leaf_to_expr(root, path):
        """Turn a leaf path into a series of subscript expressions
        that obtain the leaf value from the root value.
        """
        node = root
        for i in path:
            node = L.Subscript(node, L.Index(L.Num(i)), L.Load())
        return node
    
    leaves = tuptype_leaves(tuptype)
    code = ()
    
    # If in_expr is just a variable name, use it as is.
    # Otherwise store it in a temporary variable to avoid redundant
    # evaluation of in_expr.
    if isinstance(in_node, L.Name):
        root_node = in_node
    else:
        rootname = tempvar
        code += L.pc('''
            ROOT = IN_NODE
            ''', subst={'IN_NODE': in_node,
                        'ROOT': L.sn(rootname)})
        root_node = L.ln(rootname)
    
    flattuple_expr = L.Tuple(tuple(leaf_to_expr(root_node, leaf)
                                   for leaf in leaves),
                             L.Load())
    code += L.pc('''
        OUT_NODE = FLATTUP
        ''', subst={'FLATTUP': flattuple_expr,
                    'OUT_NODE': out_node})
    
    return code
Esempio n. 34
0
    def visit_Aggregate(self, node):
        node = self.generic_visit(node)

        operand = node.value
        if isinstance(operand, L.Comp):
            return node
        if not is_retrievalchain(operand):
            # Bailout, looks like we won't be able to incrementalize
            # this later anyway.
            return node

        # Replace with {_e for _e in OPERAND}.
        # This case is for both single vars and retrieval chains.
        # The comp's options are inherited from the aggregate.
        params = get_retrieval_params(operand)
        elem = '_e'
        clause = L.Enumerator(target=L.sn(elem), iter=operand)
        node = node._replace(value=L.Comp(resexp=L.ln(elem),
                                          clauses=(clause, ),
                                          params=params,
                                          options=node.options))
        return node
Esempio n. 35
0
 def visit_Aggregate(self, node):
     node = self.generic_visit(node)
     
     operand = node.value
     if isinstance(operand, L.Comp):
         return node
     if not is_retrievalchain(operand):
         # Bailout, looks like we won't be able to incrementalize
         # this later anyway.
         return node
     
     # Replace with {_e for _e in OPERAND}.
     # This case is for both single vars and retrieval chains.
     # The comp's options are inherited from the aggregate.
     params = get_retrieval_params(operand)
     elem = '_e'
     clause = L.Enumerator(target=L.sn(elem),
                           iter=operand)
     node = node._replace(value=L.Comp(resexp=L.ln(elem),
                                       clauses=(clause,),
                                       params=params,
                                       options=node.options))
     return node
Esempio n. 36
0
 def visit_Module(self, node):
     mapname = self.spec.map_name
     addcode = make_auxmap_maint_code(self.manager, self.spec,
                                      L.ln('_e'), 'add')
     removecode = make_auxmap_maint_code(self.manager, self.spec,
                                         L.ln('_e'), 'remove')
     
     code = L.pc('''
         MAP = Map()
         def ADDFUNC(_e):
             ADDCODE
         def REMOVEFUNC(_e):
             REMOVECODE
         ''', subst={'MAP': L.sn(mapname),
                     '<def>ADDFUNC': self.addfunc_name,
                     '<c>ADDCODE': addcode,
                     '<def>REMOVEFUNC': self.removefunc_name,
                     '<c>REMOVECODE': removecode})
     
     node = node._replace(body=code + node.body)
     
     node = self.generic_visit(node)
     
     return node
Esempio n. 37
0
    def make_addu_maint(self, prefix):
        """Generate code for after an addition to U."""
        incaggr = self.incaggr
        assert incaggr.has_demand
        spec = incaggr.spec
        mv_var = prefix + 'val'
        elemvar = prefix + 'elem'

        # If we're using half-demand, there's no demand to propagate
        # to the operand. All we need to do is add an entry with count
        # 0 if one is not already there.
        if incaggr.half_demand:
            return L.pc('''
                S_MV = A.smdeflookup(MASK, KEY, None)
                if MV is None:
                    A.smassignkey(MASK, KEY, ZERO, PREFIX)
                ''',
                        subst={
                            'A': L.ln(incaggr.name),
                            'S_MV': L.sn(mv_var),
                            'MV': L.ln(mv_var),
                            'MASK': incaggr.aggrmask.make_node(),
                            'KEY': L.tuplify(incaggr.params),
                            'ZERO': self.make_zero_mapval_expr(),
                            'PREFIX': L.Str(prefix)
                        })

        update_code = self.make_update_state_code(L.sn(mv_var), L.ln(mv_var),
                                                  'add', L.ln(elemvar), prefix)

        # Make operand demand function call, if operand uses demand.
        if spec.has_oper_demand:
            demfunc = L.N.demfunc(spec.oper_demname)
            call_demfunc = L.Call(L.ln(demfunc),
                                  tuple(L.ln(v) for v in spec.oper_demparams),
                                  (), None, None)
            propagate_code = (L.Expr(call_demfunc), )
        else:
            propagate_code = ()

        code = L.pc('''
            S_MV = ZERO
            for S_ELEM in setmatch(R, RELMASK, PARAMS):
                UPDATE_MAPVAL
            A.smassignkey(AGGRMASK, KEY, MV, PREFIX)
            PROPAGATE_DEMAND
            ''',
                    subst={
                        'S_MV': L.sn(mv_var),
                        'ZERO': self.make_zero_mapval_expr(),
                        'S_ELEM': L.sn(elemvar),
                        'R': spec.rel,
                        'RELMASK': spec.relmask.make_node(),
                        'PARAMS': L.tuplify(spec.params),
                        '<c>UPDATE_MAPVAL': update_code,
                        'A': L.ln(incaggr.name),
                        'AGGRMASK': incaggr.aggrmask.make_node(),
                        'KEY': L.tuplify(incaggr.params),
                        'MV': L.ln(mv_var),
                        'PREFIX': L.Str(prefix),
                        '<c>PROPAGATE_DEMAND': propagate_code
                    })

        return code
Esempio n. 38
0
File: match.py Progetto: IncOQ/incoq
def fset_bindmatch(field, mask, bvars, uvars, body, *, typecheck):
    """Form code for bindmatch over an F-set."""
    
    # If we had such a thing as a negated field membership clause,
    # then the negative test for hasattr() would actually conflict
    # with the type check.
    
    tc_applicable = False
    
    if mask == Mask.BB:
        tc_applicable = True
        cont, item = bvars
        code = L.pc('''
            if CONT.FIELD == ITEM:
                BODY
            ''', subst={'CONT': L.ln(cont),
                        '@FIELD': field,
                        'ITEM': L.ln(item),
                        '<c>BODY': body})
    
    elif mask == Mask.OUT:
        tc_applicable = True
        (cont,) = bvars
        (item,) = uvars
        code = L.pc('''
            ITEM = CONT.FIELD
            BODY
            ''', subst={'CONT': L.ln(cont),
                        '@FIELD': field,
                        'ITEM': L.sn(item),
                        '<c>BODY': body})
    
    elif mask == Mask.B1:
        tc_applicable = True
        (cont,) = (item,) = bvars
        code = L.pc('''
            if CONT == CONT.FIELD:
                BODY
            ''', subst={'CONT': L.ln(cont),
                        '@FIELD': field,
                        '<c>BODY': body})
    
    elif mask == Mask.BW:
        # Not applicable because the code and the type check
        # are the same thing.
        tc_applicable = False
        (cont,) = bvars
        code = L.pc('''
            if hasattr(CONT, FIELD):
                BODY
            ''', subst={'CONT': L.ln(cont),
                        'FIELD': L.Str(field),
                        '<c>BODY': body})
    
    elif mask == Mask.UU:
        raise AssertionError('No object-domain equivalent for iterating over '
                             'the M-set')
    
    else:
        code = L.pc('''
            for UVARS in setmatch(SET, MASK, BVARS):
                BODY
            ''', subst={'UVARS': L.tuplify(uvars, lval=True),
                        'SET': L.ln('_F_' + field),
                        'MASK': mask.make_node(),
                        'BVARS': L.tuplify(bvars),
                        '<c>BODY': body})
    
    if typecheck and tc_applicable:
        code = L.pc('''
            if hasattr(CONT, FIELD):
                CODE
            ''', subst={'CONT': cont,
                        'FIELD': L.Str(field),
                        '<c>CODE': code})
    
    return code
Esempio n. 39
0
def fset_bindmatch(field, mask, bvars, uvars, body, *, typecheck):
    """Form code for bindmatch over an F-set."""

    # If we had such a thing as a negated field membership clause,
    # then the negative test for hasattr() would actually conflict
    # with the type check.

    tc_applicable = False

    if mask == Mask.BB:
        tc_applicable = True
        cont, item = bvars
        code = L.pc('''
            if CONT.FIELD == ITEM:
                BODY
            ''',
                    subst={
                        'CONT': L.ln(cont),
                        '@FIELD': field,
                        'ITEM': L.ln(item),
                        '<c>BODY': body
                    })

    elif mask == Mask.OUT:
        tc_applicable = True
        (cont, ) = bvars
        (item, ) = uvars
        code = L.pc('''
            ITEM = CONT.FIELD
            BODY
            ''',
                    subst={
                        'CONT': L.ln(cont),
                        '@FIELD': field,
                        'ITEM': L.sn(item),
                        '<c>BODY': body
                    })

    elif mask == Mask.B1:
        tc_applicable = True
        (cont, ) = (item, ) = bvars
        code = L.pc('''
            if CONT == CONT.FIELD:
                BODY
            ''',
                    subst={
                        'CONT': L.ln(cont),
                        '@FIELD': field,
                        '<c>BODY': body
                    })

    elif mask == Mask.BW:
        # Not applicable because the code and the type check
        # are the same thing.
        tc_applicable = False
        (cont, ) = bvars
        code = L.pc('''
            if hasattr(CONT, FIELD):
                BODY
            ''',
                    subst={
                        'CONT': L.ln(cont),
                        'FIELD': L.Str(field),
                        '<c>BODY': body
                    })

    elif mask == Mask.UU:
        raise AssertionError('No object-domain equivalent for iterating over '
                             'the M-set')

    else:
        code = L.pc('''
            for UVARS in setmatch(SET, MASK, BVARS):
                BODY
            ''',
                    subst={
                        'UVARS': L.tuplify(uvars, lval=True),
                        'SET': L.ln('_F_' + field),
                        'MASK': mask.make_node(),
                        'BVARS': L.tuplify(bvars),
                        '<c>BODY': body
                    })

    if typecheck and tc_applicable:
        code = L.pc('''
            if hasattr(CONT, FIELD):
                CODE
            ''',
                    subst={
                        'CONT': cont,
                        'FIELD': L.Str(field),
                        '<c>CODE': code
                    })

    return code
Esempio n. 40
0
 def test_getclausevars(self):
     lhs = L.Tuple((L.sn('x'), L.Tuple((L.sn('y'), L.sn('z')), L.Store())),
                    L.Store())
     vars = get_clause_vars(L.Enumerator(lhs, L.ln('R')), self.tuptype)
     exp_vars = ['x', 'y', 'z']
     self.assertEqual(vars, exp_vars)
Esempio n. 41
0
 def test_getclausevars(self):
     lhs = L.Tuple((L.sn('x'), L.Tuple((L.sn('y'), L.sn('z')), L.Store())),
                   L.Store())
     vars = get_clause_vars(L.Enumerator(lhs, L.ln('R')), self.tuptype)
     exp_vars = ['x', 'y', 'z']
     self.assertEqual(vars, exp_vars)
Esempio n. 42
0
def mapset_bindmatch(mask, bvars, uvars, body, *, typecheck):
    """Form code for bindmatch over the MAP set."""

    tc_applicable = False

    if mask == Mask('bbb'):
        tc_applicable = True
        map, key, value = bvars
        code = L.pc('''
            if KEY in MAP and MAP[KEY] == VALUE:
                BODY
            ''',
                    subst={
                        'MAP': L.ln(map),
                        'KEY': L.ln(key),
                        'VALUE': L.ln(value),
                        '<c>BODY': body
                    })

    elif mask == Mask('bbu'):
        tc_applicable = True
        map, key = bvars
        (value, ) = uvars
        code = L.pc('''
            if KEY in MAP:
                VALUE = MAP[KEY]
                BODY
            ''',
                    subst={
                        'MAP': L.ln(map),
                        'KEY': L.ln(key),
                        'VALUE': L.sn(value),
                        '<c>BODY': body
                    })

    elif mask == Mask('buu'):
        tc_applicable = True
        (map, ) = bvars
        key, value = uvars
        code = L.pc('''
            for KEY, VALUE in MAP.items():
                BODY
            ''',
                    subst={
                        'MAP': L.ln(map),
                        'KEY': L.sn(key),
                        'VALUE': L.sn(value),
                        '<c>BODY': body
                    })

    # Other variations involving wildcards and equalities are possible,
    # but for now they're handled by the general auxmap case.

    elif mask == Mask('uuu'):
        raise AssertionError('No object-domain equivalent for iterating over '
                             'the MAP set')

    else:
        code = L.pc('''
            for UVARS in setmatch(SET, MASK, BVARS):
                BODY
            ''',
                    subst={
                        'UVARS': L.tuplify(uvars, lval=True),
                        'SET': L.ln(make_maprel()),
                        'MASK': mask.make_node(),
                        'BVARS': L.tuplify(bvars),
                        '<c>BODY': body
                    })

    if typecheck and tc_applicable:
        code = L.pc('''
            if isinstance(MAP, Map):
                CODE
            ''',
                    subst={
                        'MAP': map,
                        '<c>CODE': code
                    })

    return code
Esempio n. 43
0
    def make_oper_maint(self, prefix, op, elem):
        """Generate code for an addition or removal update to the operand."""
        incaggr = self.incaggr
        spec = incaggr.spec
        relmask = spec.relmask
        mv_var = prefix + 'val'
        uset = L.N.uset(incaggr.name)
        vars = tuple(prefix + 'v' + str(i) for i in range(1, len(relmask) + 1))
        bvars, uvars, _ = relmask.split_vars(vars)

        nextmapval_code = self.make_update_mapval_code(L.sn(mv_var),
                                                       L.ln(mv_var), op,
                                                       L.tuplify(uvars),
                                                       prefix)

        subst = {
            'S_VARS': L.tuplify(vars, lval=True),
            'ELEM': elem,
            'KEY': L.tuplify(bvars),
            'ZERO': self.make_zero_mapval_expr(),
            'U': L.ln(uset),
            'S_MV': L.sn(mv_var),
            'A': incaggr.name,
            'MASK': incaggr.aggrmask.make_node(),
            'KEY': L.tuplify(bvars),
            '<c>NEXT_MAPVAL': nextmapval_code,
            'MV': L.ln(mv_var),
            'PREFIX': L.Str(prefix)
        }

        # We break into different cases based on whether we're using
        # demand or not, because the invariants are different in terms
        # of what keys are in the map.

        if incaggr.has_demand and not incaggr.half_demand:
            # If the U-set check passes, the key is definitely in
            # the map, so use strict lookups and updates.
            code = L.pc('''
                S_VARS = ELEM
                if KEY in U:
                    S_MV = A.smlookup(MASK, KEY)
                    NEXT_MAPVAL
                    A.smreassignkey(MASK, KEY, MV, PREFIX)
                ''',
                        subst=subst)

        else:
            # The keys in the map should exist iff the corresponding
            # operand set is non-empty. For addition, use non-strict
            # lookups and updates, since we don't know whether it was
            # empty before. For removal, use strict lookup since we
            # know it's non-empty, but check the count to tell whether
            # to delete it or strictly reassign it. When using half-
            # demand, only delete it if it's not demanded.

            subst['COUNT'] = self.mapval_proj_count(L.ln(mv_var))
            if incaggr.half_demand:
                # Check for a count of 1, not 0, because it's the value
                # of count before the update.
                delete_cond = L.pe('COUNT == 1 and KEY not in U', subst=subst)

            else:
                delete_cond = L.pe('COUNT == 1', subst=subst)
            subst['DELETE_COND'] = delete_cond

            if op == 'add':
                code = L.pc('''
                    S_VARS = ELEM
                    S_MV = A.smdeflookup(MASK, KEY, ZERO)
                    NEXT_MAPVAL
                    A.smnsassignkey(MASK, KEY, MV, PREFIX)
                    ''',
                            subst=subst)
            elif op == 'remove':
                code = L.pc('''
                    S_VARS = ELEM
                    S_MV = A.smlookup(MASK, KEY)
                    if DELETE_COND:
                        A.smdelkey(MASK, KEY, PREFIX)
                    else:
                        NEXT_MAPVAL
                        A.smreassignkey(MASK, KEY, MV, PREFIX)
                    ''',
                            subst=subst)
            else:
                assert ()

        # Guard code in a delta check if necessary.
        if relmask.has_wildcards or relmask.has_equalities:
            code = L.pc('''
                if deltamatch(R, MASK, ELEM, 1):
                    CODE
                ''',
                        subst={
                            'R': spec.rel,
                            'MASK': incaggr.oper_deltamask,
                            'ELEM': elem,
                            '<c>CODE': code
                        })

        return code
Esempio n. 44
0
File: match.py Progetto: IncOQ/incoq
def mapset_bindmatch(mask, bvars, uvars, body, *, typecheck):
    """Form code for bindmatch over the MAP set."""
    
    tc_applicable = False
    
    if mask == Mask('bbb'):
        tc_applicable = True
        map, key, value = bvars
        code = L.pc('''
            if KEY in MAP and MAP[KEY] == VALUE:
                BODY
            ''', subst={'MAP': L.ln(map),
                        'KEY': L.ln(key),
                        'VALUE': L.ln(value),
                        '<c>BODY': body})
    
    elif mask == Mask('bbu'):
        tc_applicable = True
        map, key = bvars
        (value,) = uvars
        code = L.pc('''
            if KEY in MAP:
                VALUE = MAP[KEY]
                BODY
            ''', subst={'MAP': L.ln(map),
                        'KEY': L.ln(key),
                        'VALUE': L.sn(value),
                        '<c>BODY': body})
    
    elif mask == Mask('buu'):
        tc_applicable = True
        (map,) = bvars
        key, value = uvars
        code = L.pc('''
            for KEY, VALUE in MAP.items():
                BODY
            ''', subst={'MAP': L.ln(map),
                        'KEY': L.sn(key),
                        'VALUE': L.sn(value),
                        '<c>BODY': body})
    
    # Other variations involving wildcards and equalities are possible,
    # but for now they're handled by the general auxmap case.
    
    elif mask == Mask('uuu'):
        raise AssertionError('No object-domain equivalent for iterating over '
                             'the MAP set')
    
    else:
        code = L.pc('''
            for UVARS in setmatch(SET, MASK, BVARS):
                BODY
            ''', subst={'UVARS': L.tuplify(uvars, lval=True),
                        'SET': L.ln(make_maprel()),
                        'MASK': mask.make_node(),
                        'BVARS': L.tuplify(bvars),
                        '<c>BODY': body})
    
    if typecheck and tc_applicable:
        code = L.pc('''
            if isinstance(MAP, Map):
                CODE
            ''', subst={'MAP': map,
                        '<c>CODE': code})
    
    return code
Esempio n. 45
0
File: aggr.py Progetto: IncOQ/incoq
 def make_oper_maint(self, prefix, op, elem):
     """Generate code for an addition or removal update to the operand."""
     incaggr = self.incaggr
     spec = incaggr.spec
     relmask = spec.relmask
     mv_var = prefix + 'val'
     uset = L.N.uset(incaggr.name)
     vars = tuple(prefix + 'v' + str(i)
                  for i in range(1, len(relmask) + 1))
     bvars, uvars, _ = relmask.split_vars(vars)
     
     nextmapval_code = self.make_update_mapval_code(
                         L.sn(mv_var), L.ln(mv_var),
                         op, L.tuplify(uvars), prefix)
     
     subst = {'S_VARS': L.tuplify(vars, lval=True),
              'ELEM': elem,
              'KEY': L.tuplify(bvars),
              'ZERO': self.make_zero_mapval_expr(),
              'U': L.ln(uset),
              'S_MV': L.sn(mv_var),
              'A': incaggr.name,
              'MASK': incaggr.aggrmask.make_node(),
              'KEY': L.tuplify(bvars),
              '<c>NEXT_MAPVAL': nextmapval_code,
              'MV': L.ln(mv_var),
              'PREFIX': L.Str(prefix)}
     
     # We break into different cases based on whether we're using
     # demand or not, because the invariants are different in terms
     # of what keys are in the map.
     
     if incaggr.has_demand and not incaggr.half_demand:
         # If the U-set check passes, the key is definitely in
         # the map, so use strict lookups and updates.
         code = L.pc('''
             S_VARS = ELEM
             if KEY in U:
                 S_MV = A.smlookup(MASK, KEY)
                 NEXT_MAPVAL
                 A.smreassignkey(MASK, KEY, MV, PREFIX)
             ''', subst=subst)
     
     else:
         # The keys in the map should exist iff the corresponding
         # operand set is non-empty. For addition, use non-strict
         # lookups and updates, since we don't know whether it was
         # empty before. For removal, use strict lookup since we
         # know it's non-empty, but check the count to tell whether
         # to delete it or strictly reassign it. When using half-
         # demand, only delete it if it's not demanded.
         
         subst['COUNT'] = self.mapval_proj_count(L.ln(mv_var))
         if incaggr.half_demand:
             # Check for a count of 1, not 0, because it's the value
             # of count before the update.
             delete_cond = L.pe('COUNT == 1 and KEY not in U', subst=subst)
             
         else:
             delete_cond = L.pe('COUNT == 1', subst=subst)
         subst['DELETE_COND'] = delete_cond
         
         if op == 'add':
             code = L.pc('''
                 S_VARS = ELEM
                 S_MV = A.smdeflookup(MASK, KEY, ZERO)
                 NEXT_MAPVAL
                 A.smnsassignkey(MASK, KEY, MV, PREFIX)
                 ''', subst=subst)
         elif op == 'remove':
             code = L.pc('''
                 S_VARS = ELEM
                 S_MV = A.smlookup(MASK, KEY)
                 if DELETE_COND:
                     A.smdelkey(MASK, KEY, PREFIX)
                 else:
                     NEXT_MAPVAL
                     A.smreassignkey(MASK, KEY, MV, PREFIX)
                 ''', subst=subst)
         else:
             assert()
     
     # Guard code in a delta check if necessary.
     if relmask.has_wildcards or relmask.has_equalities:
         code = L.pc('''
             if deltamatch(R, MASK, ELEM, 1):
                 CODE
             ''', subst={'R': spec.rel,
                         'MASK': incaggr.oper_deltamask,
                         'ELEM': elem,
                         '<c>CODE': code})
     
     return code
Esempio n. 46
0
File: match.py Progetto: IncOQ/incoq
def mset_bindmatch(mask, bvars, uvars, body, *, typecheck):
    """Form code for bindmatch over the M-set."""
    
    tc_applicable = False
    
    if mask == Mask.BB:
        tc_applicable = True
        cont, item = bvars
        code = L.pc('''
            if ITEM in CONT:
                BODY
            ''', subst={'CONT': L.ln(cont),
                        'ITEM': L.ln(item),
                        '<c>BODY': body})
    
    elif mask == Mask.OUT:
        tc_applicable = True
        (cont,) = bvars
        (item,) = uvars
        code = L.pc('''
            for ITEM in CONT:
                BODY
            ''', subst={'CONT': L.ln(cont),
                        'ITEM': L.sn(item),
                        '<c>BODY': body})
    
    elif mask == Mask.B1:
        tc_applicable = True
        (cont,) = (item,) = bvars
        code = L.pc('''
            if CONT in CONT:
                BODY
            ''', subst={'CONT': L.ln(cont),
                        '<c>BODY': body})
    
    elif mask == Mask.BW:
        tc_applicable = True
        (cont,) = bvars
        code = L.pc('''
            if not CONT.isempty():
                BODY
            ''', subst={'CONT': L.ln(cont),
                        '<c>BODY': body})
    
    elif mask == Mask.UU:
        raise AssertionError('No object-domain equivalent for iterating over '
                             'the M-set')
    
    else:
        code = L.pc('''
            for UVARS in setmatch(SET, MASK, BVARS):
                BODY
            ''', subst={'UVARS': L.tuplify(uvars, lval=True),
                        'SET': L.ln('_M'),
                        'MASK': mask.make_node(),
                        'BVARS': L.tuplify(bvars),
                        '<c>BODY': body})
    
    if typecheck and tc_applicable:
        code = L.pc('''
            if isinstance(CONT, Set):
                CODE
            ''', subst={'CONT': cont,
                        '<c>CODE': code})
    
    return code
Esempio n. 47
0
def mset_bindmatch(mask, bvars, uvars, body, *, typecheck):
    """Form code for bindmatch over the M-set."""

    tc_applicable = False

    if mask == Mask.BB:
        tc_applicable = True
        cont, item = bvars
        code = L.pc('''
            if ITEM in CONT:
                BODY
            ''',
                    subst={
                        'CONT': L.ln(cont),
                        'ITEM': L.ln(item),
                        '<c>BODY': body
                    })

    elif mask == Mask.OUT:
        tc_applicable = True
        (cont, ) = bvars
        (item, ) = uvars
        code = L.pc('''
            for ITEM in CONT:
                BODY
            ''',
                    subst={
                        'CONT': L.ln(cont),
                        'ITEM': L.sn(item),
                        '<c>BODY': body
                    })

    elif mask == Mask.B1:
        tc_applicable = True
        (cont, ) = (item, ) = bvars
        code = L.pc('''
            if CONT in CONT:
                BODY
            ''',
                    subst={
                        'CONT': L.ln(cont),
                        '<c>BODY': body
                    })

    elif mask == Mask.BW:
        tc_applicable = True
        (cont, ) = bvars
        code = L.pc('''
            if not CONT.isempty():
                BODY
            ''',
                    subst={
                        'CONT': L.ln(cont),
                        '<c>BODY': body
                    })

    elif mask == Mask.UU:
        raise AssertionError('No object-domain equivalent for iterating over '
                             'the M-set')

    else:
        code = L.pc('''
            for UVARS in setmatch(SET, MASK, BVARS):
                BODY
            ''',
                    subst={
                        'UVARS': L.tuplify(uvars, lval=True),
                        'SET': L.ln('_M'),
                        'MASK': mask.make_node(),
                        'BVARS': L.tuplify(bvars),
                        '<c>BODY': body
                    })

    if typecheck and tc_applicable:
        code = L.pc('''
            if isinstance(CONT, Set):
                CODE
            ''',
                    subst={
                        'CONT': cont,
                        '<c>CODE': code
                    })

    return code