Beispiel #1
0
    def get_code(self, cl, bindenv, body):
        vars = self.lhs_vars(cl)
        assert_unique(vars)
        mask = L.mask_from_bounds(vars, bindenv)

        comparison = L.Compare(L.Name(cl.tup), L.Eq(), L.tuplify(cl.elts))

        if L.mask_is_allbound(mask):
            code = (L.If(comparison, body, ()), )
            needs_typecheck = True

        elif mask.m.startswith('b'):
            elts_mask = L.mask_from_bounds(cl.elts, bindenv)
            code = L.bind_by_mask(elts_mask, cl.elts, L.Name(cl.tup))
            if L.mask_is_allunbound(elts_mask):
                code += body
            else:
                code += (L.If(comparison, body, ()), )
            needs_typecheck = True

        elif mask == L.mask('u' + 'b' * len(cl.elts)):
            code = (L.Assign(cl.tup, L.tuplify(cl.elts)), )
            code += body
            needs_typecheck = False

        else:
            raise L.TransformationError('Cannot emit code for TUP clause '
                                        'that would require an auxiliary '
                                        'map; use demand filtering')

        if needs_typecheck and self.use_typecheck:
            code = (L.If(L.HasArity(L.Name(cl.tup), len(cl.elts)), code, ()), )

        return code
Beispiel #2
0
    def get_code(self, cl, bindenv, body):
        vars = self.lhs_vars(cl)
        assert_unique(vars)
        mask = L.mask_from_bounds(vars, bindenv)

        lookup_expr = L.DictLookup(L.Name(cl.map), L.Name(cl.key), None)

        if L.mask_is_allbound(mask):
            comparison = L.Compare(L.Name(cl.value), L.Eq(), lookup_expr)
            code = (L.If(comparison, body, ()), )
            needs_typecheck = True

        elif mask == L.mask('bbu'):
            code = (L.Assign(cl.value, lookup_expr), )
            code += body
            needs_typecheck = True

        elif mask == L.mask('buu'):
            items_expr = L.Parser.pe('_MAP.items()', subst={'_MAP': cl.map})
            code = (L.DecompFor([cl.key, cl.value], items_expr, body), )
            needs_typecheck = True

        else:
            code = super().get_code(cl, bindenv, body)
            needs_typecheck = False

        if needs_typecheck and self.use_typecheck:
            code = (L.If(L.IsMap(L.Name(cl.map)), code, ()), )

        return code
Beispiel #3
0
 def visit_AttrAssign(self, node):
     if node.attr not in self.objrels.Fs:
         return
     
     pair = L.Tuple([node.obj, node.value])
     var = next(self.fresh_vars)
     return (L.Assign(var, pair),
             L.RelUpdate(N.F(node.attr), L.SetAdd(), var))
Beispiel #4
0
 def visit_DictAssign(self, node):
     if not self.objrels.MAP:
         return
     
     triple = L.Tuple([node.target, node.key, node.value])
     var = next(self.fresh_vars)
     return (L.Assign(var, triple),
             L.RelUpdate(N.MAP, L.SetAdd(), var))
Beispiel #5
0
 def visit_AttrDelete(self, node):
     if node.attr not in self.objrels.Fs:
         return
     
     lookup = L.Attribute(node.obj, node.attr)
     pair = L.Tuple([node.obj, lookup])
     var = next(self.fresh_vars)
     return (L.Assign(var, pair),
             L.RelUpdate(N.F(node.attr), L.SetRemove(), var))
Beispiel #6
0
 def visit_DictDelete(self, node):
     if not self.objrels.MAP:
         return
     
     lookup = L.DictLookup(node.target, node.key, None)
     triple = L.Tuple([node.target, node.key, lookup])
     var = next(self.fresh_vars)
     return (L.Assign(var, triple),
             L.RelUpdate(N.MAP, L.SetRemove(), var))
Beispiel #7
0
 def visit_SetUpdate(self, node):
     if not isinstance(node.op, (L.SetAdd, L.SetRemove)):
         return
     if not self.objrels.M:
         return
     
     pair = L.Tuple([node.target, node.value])
     var = next(self.fresh_vars)
     return (L.Assign(var, pair),
             L.RelUpdate(N.M, node.op, var))
Beispiel #8
0
def make_setfrommap_maint_func(fresh_vars, setfrommap: SetFromMapInvariant,
                               op: str):
    mask = setfrommap.mask
    nb = L.break_mapmask(mask)
    # Fresh variables for components of the key and value.
    key_vars = N.get_subnames('_key', nb)

    decomp_code = (L.DecompAssign(key_vars, L.Name('_key')), )

    vars = L.combine_by_mask(mask, key_vars, ['_val'])
    elem = L.tuplify(vars)
    fresh_var_prefix = next(fresh_vars)
    elem_var = fresh_var_prefix + '_elem'

    decomp_code += (L.Assign(elem_var, elem), )

    setopcls = {'assign': L.SetAdd, 'delete': L.SetRemove}[op]
    update_code = (L.RelUpdate(setfrommap.rel, setopcls(), elem_var), )

    func_name = setfrommap.get_maint_func_name(op)

    if op == 'assign':
        func = L.Parser.ps('''
            def _FUNC(_key, _val):
                _DECOMP
                _UPDATE
            ''',
                           subst={
                               '_FUNC': func_name,
                               '<c>_DECOMP': decomp_code,
                               '<c>_UPDATE': update_code
                           })
    elif op == 'delete':
        lookup_expr = L.DictLookup(L.Name(setfrommap.map), L.Name('_key'),
                                   None)
        func = L.Parser.ps('''
            def _FUNC(_key):
                _val = _LOOKUP
                _DECOMP
                _UPDATE
            ''',
                           subst={
                               '_FUNC': func_name,
                               '_LOOKUP': lookup_expr,
                               '<c>_DECOMP': decomp_code,
                               '<c>_UPDATE': update_code
                           })
    else:
        assert ()

    return func
Beispiel #9
0
    def get_maint_code(self,
                       fresh_var_prefix,
                       fresh_join_names,
                       comp,
                       result_var,
                       update,
                       *,
                       selfjoin=SelfJoin.Without,
                       counted):
        """Given a comprehension (not necessarily a join) and an
        update to a relation, return the maintenance code -- i.e.,
        the update to the stored result variable looped for each
        maintenance join.
        
        If counted is False, generate non-counted set updates.
        """
        assert isinstance(update, L.RelUpdate)
        assert isinstance(update.op, (L.SetAdd, L.SetRemove))

        result_elem_var = fresh_var_prefix + '_result'
        # Prefix LHS vars in the comp to guarantee fresh names for their
        # use in maintenance code.
        renamer = lambda x: fresh_var_prefix + '_' + x
        comp = self.comp_rename_lhs_vars(comp, renamer)

        body = ()
        body += (L.Assign(result_elem_var, comp.resexp), )
        body += L.rel_update(result_var,
                             update.op,
                             result_elem_var,
                             counted=counted)

        join = self.make_join_from_comp(comp)
        maint_joins = self.get_maint_join_union(join,
                                                update.rel,
                                                L.Name(update.elem),
                                                selfjoin=selfjoin)

        code = ()
        for maint_join in maint_joins:
            join_name = next(fresh_join_names)
            code += self.get_loop_for_join(maint_join, body, join_name)

        return code
Beispiel #10
0
    def get_code(self, cl, bindenv, body):
        vars = self.lhs_vars(cl)
        assert_unique(vars)
        mask = L.mask_from_bounds(vars, bindenv)

        if L.mask_is_allbound(mask):
            comparison = L.Compare(L.Name(cl.value), L.Eq(),
                                   L.Attribute(L.Name(cl.obj), cl.attr))
            code = (L.If(comparison, body, ()), )
            needs_typecheck = True

        elif mask == L.mask('bu'):
            code = (L.Assign(cl.value, L.Attribute(L.Name(cl.obj), cl.attr)), )
            code += body
            needs_typecheck = True

        else:
            code = super().get_code(cl, bindenv, body)
            needs_typecheck = False

        if needs_typecheck and self.use_typecheck:
            code = (L.If(L.HasField(L.Name(cl.obj), cl.attr), code, ()), )

        return code
Beispiel #11
0
 def make_update_state_code(self, prefix, state, op, value):
     opcls = {L.SetAdd: L.Add, L.SetRemove: L.Sub}[op.__class__]
     by = {'count': L.Num(1), 'sum': L.Name(value)}[self.kind]
     return (L.Assign(state, L.BinOp(L.Name(state), opcls(), by)), )