Beispiel #1
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 #2
0
    def get_code(self, cl, bindenv, body):
        assert_unique(cl.vars)
        mask = L.mask_from_bounds(cl.vars, bindenv)
        check_eq = L.Compare(L.tuplify(cl.vars), L.Eq(), cl.value)

        if L.mask_is_allbound(mask):
            code = (L.If(check_eq, body, ()), )

        elif L.mask_is_allunbound(mask):
            code = (L.DecompAssign(cl.vars, cl.value), )
            code += body

        else:
            code = L.bind_by_mask(mask, cl.vars, cl.value)
            code += (L.If(check_eq, body, ()), )

        return code
Beispiel #3
0
def make_auxmap_maint_func(fresh_vars, auxmap: AuxmapInvariant, op: L.setupop):
    """Make maintenance function for auxiliary map."""
    # Fresh variables for components of the element.
    vars = N.get_subnames('_elem', len(auxmap.mask.m))

    decomp_code = (L.DecompAssign(vars, L.Name('_elem')), )

    key, value = L.split_by_mask(auxmap.mask, vars)
    key = L.tuplify(key, unwrap=auxmap.unwrap_key)
    value = L.tuplify(value, unwrap=auxmap.unwrap_value)
    fresh_var_prefix = next(fresh_vars)
    key_var = fresh_var_prefix + '_key'
    value_var = fresh_var_prefix + '_value'

    decomp_code += L.Parser.pc('''
        _KEY_VAR = _KEY
        _VALUE_VAR = _VALUE
        ''',
                               subst={
                                   '_KEY_VAR': key_var,
                                   '_KEY': key,
                                   '_VALUE_VAR': value_var,
                                   '_VALUE': value
                               })

    img_func = {
        L.SetAdd: make_imgadd,
        L.SetRemove: make_imgremove
    }[op.__class__]
    img_code = img_func(fresh_vars, auxmap.map, key_var, value_var)

    func_name = auxmap.get_maint_func_name(op)

    func = L.Parser.ps('''
        def _FUNC(_elem):
            _DECOMP
            _IMGCODE
        ''',
                       subst={
                           '_FUNC': func_name,
                           '<c>_DECOMP': decomp_code,
                           '<c>_IMGCODE': img_code
                       })

    return func
Beispiel #4
0
def make_aggr_oper_maint_func(fresh_vars, aggrinv, op):
    """Make the maintenance function for an aggregate invariant and a
    given set update operation (add or remove) to the operand.
    """
    assert isinstance(op, (L.SetAdd, L.SetRemove))

    # Decompose the argument tuple into key and value components,
    # just like in auxmap.py.

    vars = N.get_subnames('_elem', len(aggrinv.mask.m))
    kvars, vvars = L.split_by_mask(aggrinv.mask, vars)
    ktuple = L.tuplify(kvars)
    vtuple = L.tuplify(vvars)
    fresh_var_prefix = next(fresh_vars)
    key = fresh_var_prefix + '_key'
    value = fresh_var_prefix + '_value'
    state = fresh_var_prefix + '_state'

    if aggrinv.unwrap:
        assert len(vvars) == 1
        value_expr = L.Name(vvars[0])
    else:
        value_expr = vtuple

    # Logic specific to aggregate operator.
    handler = aggrinv.get_handler()
    zero = handler.make_zero_expr()
    updatestate_code = handler.make_update_state_code(fresh_var_prefix, state,
                                                      op, value)

    subst = {
        '_KEY': key,
        '_KEY_EXPR': ktuple,
        '_VALUE': value,
        '_VALUE_EXPR': value_expr,
        '_MAP': aggrinv.map,
        '_STATE': state,
        '_ZERO': zero
    }

    if aggrinv.uses_demand:
        subst['_RESTR'] = aggrinv.restr
    else:
        # Empty conditions are only used when we don't have a
        # restriction set.
        subst['_EMPTY'] = handler.make_empty_cond(state)

    decomp_code = (L.DecompAssign(vars, L.Name('_elem')), )
    decomp_code += L.Parser.pc('''
        _KEY = _KEY_EXPR
        _VALUE = _VALUE_EXPR
        ''',
                               subst=subst)

    # Determine what kind of get/set state code to generate.
    if isinstance(op, L.SetAdd):
        definitely_preexists = aggrinv.uses_demand
        setstate_mayremove = False
    elif isinstance(op, L.SetRemove):
        definitely_preexists = True
        setstate_mayremove = not aggrinv.uses_demand
    else:
        assert ()

    if definitely_preexists:
        getstate_template = '_STATE = _MAP[_KEY]'
        delstate_template = '_MAP.mapdelete(_KEY)'
    else:
        getstate_template = '_STATE = _MAP.get(_KEY, _ZERO)'
        delstate_template = '''
            if _KEY in _MAP:
                _MAP.mapdelete(_KEY)
            '''

    if setstate_mayremove:
        setstate_template = '''
            if not _EMPTY:
                _MAP.mapassign(_KEY, _STATE)
            '''
    else:
        setstate_template = '_MAP.mapassign(_KEY, _STATE)'

    getstate_code = L.Parser.pc(getstate_template, subst=subst)
    delstate_code = L.Parser.pc(delstate_template, subst=subst)
    setstate_code = L.Parser.pc(setstate_template, subst=subst)

    maint_code = (getstate_code + updatestate_code + delstate_code +
                  setstate_code)

    # Guard in test if we have a restriction set.
    if aggrinv.uses_demand:
        maint_subst = dict(subst)
        maint_subst['<c>_MAINT'] = maint_code
        maint_code = L.Parser.pc('''
            if _KEY in _RESTR:
                _MAINT
            ''',
                                 subst=maint_subst)

    func_name = aggrinv.get_oper_maint_func_name(op)

    func = L.Parser.ps('''
        def _FUNC(_elem):
            _DECOMP
            _MAINT
        ''',
                       subst={
                           '_FUNC': func_name,
                           '<c>_DECOMP': decomp_code,
                           '<c>_MAINT': maint_code
                       })

    return func
Beispiel #5
0
def make_aggr_restr_maint_func(fresh_vars, aggrinv, op):
    """Make the maintenance function for an aggregate invariant and
    an update to its restriction set.
    """
    assert isinstance(op, (L.SetAdd, L.SetRemove))
    assert aggrinv.uses_demand

    if isinstance(op, L.SetAdd):
        fresh_var_prefix = next(fresh_vars)
        value = fresh_var_prefix + '_value'
        state = fresh_var_prefix + '_state'
        keyvars = N.get_subnames('_key', len(aggrinv.params))

        decomp_key_code = (L.DecompAssign(keyvars, L.Name('_key')), )
        rellookup = L.ImgLookup(L.Name(aggrinv.rel), aggrinv.mask, keyvars)

        handler = aggrinv.get_handler()
        zero = handler.make_zero_expr()
        updatestate_code = handler.make_update_state_code(
            fresh_var_prefix, state, op, value)

        if aggrinv.unwrap:
            loop_template = '''
                for (_VALUE,) in _RELLOOKUP:
                    _UPDATESTATE
                '''
        else:
            loop_template = '''
                for _VALUE in _RELLOOKUP:
                    _UPDATESTATE
                '''

        loop_code = L.Parser.pc(loop_template,
                                subst={
                                    '_VALUE': value,
                                    '_RELLOOKUP': rellookup,
                                    '<c>_UPDATESTATE': updatestate_code
                                })

        maint_code = L.Parser.pc('''
            _STATE = _ZERO
            _DECOMP_KEY
            _LOOP
            _MAP.mapassign(_KEY, _STATE)
            ''',
                                 subst={
                                     '_MAP': aggrinv.map,
                                     '_KEY': '_key',
                                     '_STATE': state,
                                     '_ZERO': zero,
                                     '<c>_DECOMP_KEY': decomp_key_code,
                                     '<c>_LOOP': loop_code
                                 })

    else:
        maint_code = L.Parser.pc('''
            _MAP.mapdelete(_KEY)
            ''',
                                 subst={
                                     '_MAP': aggrinv.map,
                                     '_KEY': '_key'
                                 })

    func_name = aggrinv.get_restr_maint_func_name(op)

    func = L.Parser.ps('''
        def _FUNC(_key):
            _MAINT
        ''',
                       subst={
                           '_FUNC': func_name,
                           '<c>_MAINT': maint_code
                       })

    return func