Ejemplo n.º 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
Ejemplo n.º 2
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
Ejemplo n.º 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
Ejemplo n.º 4
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
Ejemplo n.º 5
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
Ejemplo n.º 6
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
Ejemplo n.º 7
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
Ejemplo n.º 8
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