Пример #1
0
def add_mixins(mod,
               actname,
               action2,
               assert_to_assume=lambda m: False,
               use_mixin=lambda: True,
               mod_mixin=lambda m: m):
    # TODO: mixins need to be in a fixed order
    assert hasattr(action2, 'lineno'), action2
    assert hasattr(action2, 'formal_params'), action2
    res = action2
    for mixin in mod.mixins[actname]:
        mixin_name = mixin.args[0].relname
        action1 = lookup_action(mixin, mod, mixin_name)
        assert hasattr(action1, 'lineno')
        assert hasattr(action1, 'formal_params'), action1
        if use_mixin(mixin_name):
            if assert_to_assume(mixin):
                action1 = action1.assert_to_assume()
                assert hasattr(action1, 'lineno')
                assert hasattr(action1, 'formal_params'), action1
            action1 = mod_mixin(action1)
            assert hasattr(action1, 'lineno')
            assert hasattr(action1, 'formal_params'), action1
            res = ia.apply_mixin(mixin, action1, res)
    return res
Пример #2
0
def add_mixins(mod,actname,action2,assert_to_assume=lambda m:False,use_mixin=lambda:True,mod_mixin=lambda m:m):
    # TODO: mixins need to be in a fixed order
    assert hasattr(action2,'lineno'), action2
    assert hasattr(action2,'formal_params'), action2
    res = action2
    for mixin in mod.mixins[actname]:
        mixin_name = mixin.args[0].relname
        action1 = lookup_action(mixin,mod,mixin_name)
        assert hasattr(action1,'lineno')
        assert hasattr(action1,'formal_params'), action1
        if use_mixin(mixin_name):
            if assert_to_assume(mixin):
                action1 = action1.assert_to_assume()
                assert hasattr(action1,'lineno')
                assert hasattr(action1,'formal_params'), action1
            action1 = mod_mixin(action1)
            assert hasattr(action1,'lineno')
            assert hasattr(action1,'formal_params'), action1
            res = ia.apply_mixin(mixin,action1,res)
    return res
Пример #3
0
def create_isolate(iso,mod = None,**kwargs):

        mod = mod or im.module

        # check all mixin declarations

        for name,mixins in mod.mixins.iteritems():
            for mixin in mixins:
                with ASTContext(mixins):
                    action1,action2 = (lookup_action(mixin,mod,a.relname) for a in mixin.args)

        # check all the delagate declarations

        for dl in mod.delegates:
            lookup_action(dl.args[0],mod,dl.delegated())
            if dl.delegee() and dl.delegee() not in mod.hierarchy:
                raise iu.IvyError(dl.args[1],"{} is not a module instance".format(name))

        # Determine the mixin order (as a side effect on module.mixins)

        get_mixin_order(iso,mod)

        # Construct an isolate

        if iso:
            isolate_component(mod,iso)
        else:
            # apply all the mixins in no particular order
            for name,mixins in mod.mixins.iteritems():
                for mixin in mixins:
                    action1,action2 = (lookup_action(mixin,mod,a.relname) for a in mixin.args)
                    mixed = ia.apply_mixin(mixin,action1,action2)
                    mod.actions[mixin.args[1].relname] = mixed
            # find the globally exported actions (all if none specified, for compat)
            if mod.exports:
                mod.public_actions.clear()
                for e in mod.exports:
                    if not e.scope(): # global export
                        mod.public_actions.add(e.exported())
            else:
                for a in mod.actions:
                    mod.public_actions.add(a)

        # Create one big external action if requested


        ext = kwargs['ext'] if 'ext' in kwargs else ext_action.get()
        if ext is not None:
            ext_acts = [mod.actions[x] for x in sorted(mod.public_actions)]
            ext_act = ia.EnvAction(*ext_acts)
            mod.public_actions.add(ext);
            mod.actions[ext] = ext_act;

        # Check native interpretations of symbols

        slv.check_compat()

        # Make concept spaces from the conjecture

        for i,cax in enumerate(mod.labeled_conjs):
            fmla = cax.formula
            csname = 'conjecture:'+ str(i)
            variables = list(lu.used_variables_ast(fmla))
            sort = ivy_logic.RelationSort([v.sort for v in variables])
            sym = ivy_logic.Symbol(csname,sort)
            space = ics.NamedSpace(ivy_logic.Literal(0,fmla))
            mod.concept_spaces.append((sym(*variables),space))

        # ith.check_theory()

        if show_compiled.get():
            for x,y in mod.actions.iteritems():
                print iu.pretty("action {} = {}".format(x,y))
Пример #4
0
def create_isolate(iso, mod=None, **kwargs):

    mod = mod or im.module

    # treat initializers as exports
    after_inits = mod.mixins["init"]
    del mod.mixins["init"]
    mod.exports.extend(
        ivy_ast.ExportDef(ivy_ast.Atom(a.mixer()), ivy_ast.Atom(''))
        for a in after_inits)

    # check all mixin declarations

    for name, mixins in mod.mixins.iteritems():
        for mixin in mixins:
            with ASTContext(mixins):
                action1, action2 = (lookup_action(mixin, mod, a.relname)
                                    for a in mixin.args)

    # check all the delagate declarations

    for dl in mod.delegates:
        lookup_action(dl.args[0], mod, dl.delegated())
        if dl.delegee() and dl.delegee() not in mod.hierarchy:
            raise iu.IvyError(dl.args[1],
                              "{} is not a module instance".format(name))

    # check all the export declarations
    for exp in mod.exports:
        expname = exp.args[0].rep
        if expname not in mod.actions:
            raise iu.IvyError(exp, "undefined action: {}".format(expname))

    # create the import actions, if requested

    extra_with = []
    extra_strip = {}
    if create_imports.get():
        newimps = []
        for imp in mod.imports:
            if imp.args[1].rep == '':
                impname = imp.args[0].rep
                if impname not in mod.actions:
                    raise iu.IvyError(imp,
                                      "undefined action: {}".format(impname))
                action = mod.actions[impname]
                if not (type(action) == ia.Sequence and not action.args):
                    raise iu.IvyError(
                        imp,
                        "cannot import implemented action: {}".format(impname))
                extname = 'imp__' + impname
                call = ia.CallAction(
                    *([ivy_ast.Atom(extname, action.formal_params)] +
                      action.formal_returns))
                call.formal_params = action.formal_params
                call.formal_returns = action.formal_returns
                call.lineno = action.lineno
                mod.actions[impname] = call
                mod.actions[extname] = action
                newimps.append(
                    ivy_ast.ImportDef(ivy_ast.Atom(extname), imp.args[1]))
                extra_with.append(ivy_ast.Atom(impname))
                #                    extra_with.append(ivy_ast.Atom(extname))
                if iso and iso in mod.isolates:
                    ps = mod.isolates[iso].params()
                    extra_strip[impname] = [a.rep for a in ps]
                    extra_strip[extname] = [a.rep for a in ps]
            else:
                newimps.append(imp)
        mod.imports = newimps

    mixers = set()
    for ms in mod.mixins.values():
        for m in ms:
            mixers.add(m.mixer())

    # Determine the mixin order (as a side effect on module.mixins)

    get_mixin_order(iso, mod)

    # Construct an isolate

    if iso:
        isolate_component(mod,
                          iso,
                          extra_with=extra_with,
                          extra_strip=extra_strip)
    else:
        if mod.isolates and cone_of_influence.get():
            raise iu.IvyError(None, 'no isolate specified on command line')
        # apply all the mixins in no particular order
        for name, mixins in mod.mixins.iteritems():
            for mixin in mixins:
                action1, action2 = (lookup_action(mixin, mod, a.relname)
                                    for a in mixin.args)
                mixed = ia.apply_mixin(mixin, action1, action2)
                mod.actions[mixin.args[1].relname] = mixed
        # find the globally exported actions (all if none specified, for compat)
        if mod.exports:
            mod.public_actions.clear()
            for e in mod.exports:
                if not e.scope():  # global export
                    mod.public_actions.add(e.exported())
        else:
            for a in mod.actions:
                mod.public_actions.add(a)

    # Create one big external action if requested

    for name in mod.public_actions:
        mod.actions[name].label = name
    ext = kwargs['ext'] if 'ext' in kwargs else ext_action.get()
    if ext is not None:
        ext_acts = [mod.actions[x] for x in sorted(mod.public_actions)]
        ext_act = ia.EnvAction(*ext_acts)
        mod.public_actions.add(ext)
        mod.actions[ext] = ext_act

    # Check native interpretations of symbols

    slv.check_compat()

    # Make concept spaces from the conjecture

    for i, cax in enumerate(mod.labeled_conjs):
        fmla = cax.formula
        csname = 'conjecture:' + str(i)
        variables = list(lu.used_variables_ast(fmla))
        sort = ivy_logic.RelationSort([v.sort for v in variables])
        sym = ivy_logic.Symbol(csname, sort)
        space = ics.NamedSpace(ivy_logic.Literal(0, fmla))
        mod.concept_spaces.append((sym(*variables), space))

    ith.check_theory()

    # get rid of useless actions

    cone = get_mod_cone(mod)
    if cone_of_influence.get():
        for a in list(mod.actions):
            if a not in cone:
                del mod.actions[a]
    else:
        for a in list(mod.actions):
            if a not in cone and not a.startswith('ext:') and a not in mixers:
                ea = 'ext:' + a
                if ea in mod.actions and ea not in cone:
                    if ia.has_code(mod.actions[a]):
                        iu.warn(mod.actions[a],
                                "action {} is never called".format(a))

    fix_initializers(mod, after_inits)

    # show the compiled code if requested

    if show_compiled.get():
        ivy_printer.print_module(mod)
Пример #5
0
def isolate_component(mod, isolate_name, extra_with=[], extra_strip=None):
    if isolate_name not in mod.isolates:
        raise iu.IvyError(None, "undefined isolate: {}".format(isolate_name))
    isolate = mod.isolates[isolate_name]
    verified = set(a.relname for a in (isolate.verified() + tuple(extra_with)))
    present = set(a.relname for a in isolate.present())
    present.update(verified)
    if not interpret_all_sorts:
        for type_name in list(ivy_logic.sig.interp):
            if not (type_name in present or any(
                    startswith_eq_some(itp.label.rep, present, mod)
                    for itp in mod.interps[type_name] if itp.label)):
                del ivy_logic.sig.interp[type_name]
    delegates = set(s.delegated() for s in mod.delegates if not s.delegee())
    delegated_to = dict(
        (s.delegated(), s.delegee()) for s in mod.delegates if s.delegee())
    derived = set(df.args[0].func.name for df in mod.concepts)
    for name in present:
        if (name not in mod.hierarchy and name not in ivy_logic.sig.sorts
                and name not in derived and name not in ivy_logic.sig.interp
                and name not in mod.actions
                and name not in ivy_logic.sig.symbols):
            raise iu.IvyError(
                None,
                "{} is not an object, action, sort, definition, or interpreted function"
                .format(name))

    impl_mixins = defaultdict(list)
    # delegate all the stub actions to their implementations
    global implementation_map
    implementation_map = {}
    for actname, ms in mod.mixins.iteritems():
        implements = [
            m for m in ms if isinstance(m, ivy_ast.MixinImplementDef)
        ]
        impl_mixins[actname].extend(implements)
        before_after = [
            m for m in ms if not isinstance(m, ivy_ast.MixinImplementDef)
        ]
        del ms[:]
        ms.extend(before_after)
        for m in implements:
            for foo in (m.mixee(), m.mixer()):
                if foo not in mod.actions:
                    raise IvyError(m, 'action {} not defined'.format(foo))
            action = mod.actions[m.mixee()]
            if not (isinstance(action, ia.Sequence) and len(action.args) == 0):
                raise IvyError(
                    m,
                    'multiple implementations of action {}'.format(m.mixee()))
            action = ia.apply_mixin(m, mod.actions[m.mixer()], action)
            mod.actions[m.mixee()] = action
            implementation_map[m.mixee()] = m.mixer()

    new_actions = {}
    use_mixin = lambda name: startswith_some(name, present, mod)
    mod_mixin = lambda m: m if startswith_some(name, verified, mod
                                               ) else m.prefix_calls('ext:')
    all_mixins = lambda m: True
    no_mixins = lambda m: False
    after_mixins = lambda m: isinstance(m, ivy_ast.MixinAfterDef)
    before_mixins = lambda m: isinstance(m, ivy_ast.MixinBeforeDef)
    delegated_to_verified = lambda n: n in delegated_to and startswith_eq_some(
        delegated_to[n], verified, mod)
    ext_assumes = lambda m: before_mixins(m) and not delegated_to_verified(
        m.mixer())
    int_assumes = lambda m: after_mixins(m) and not delegated_to_verified(
        m.mixer())
    ext_assumes_no_ver = lambda m: not delegated_to_verified(m.mixer())
    summarized_actions = set()
    for actname, action in mod.actions.iteritems():
        ver = startswith_eq_some(actname, verified, mod)
        pre = startswith_eq_some(actname, present, mod)
        if pre:
            if not ver:
                assert hasattr(action, 'lineno')
                assert hasattr(action, 'formal_params'), action
                ext_action = action.assert_to_assume().prefix_calls('ext:')
                assert hasattr(ext_action, 'lineno')
                assert hasattr(ext_action, 'formal_params'), ext_action
                if actname in delegates:
                    int_action = action.prefix_calls('ext:')
                    assert hasattr(int_action, 'lineno')
                    assert hasattr(int_action, 'formal_params'), int_action
                else:
                    int_action = ext_action
                    assert hasattr(int_action, 'lineno')
                    assert hasattr(int_action, 'formal_params'), int_action
            else:
                int_action = ext_action = action
                assert hasattr(int_action, 'lineno')
                assert hasattr(int_action, 'formal_params'), int_action
            # internal version of the action has mixins checked
            ea = no_mixins if ver else int_assumes
            new_actions[actname] = add_mixins(mod, actname, int_action, ea,
                                              use_mixin, lambda m: m)
            # external version of the action assumes mixins are ok, unless they
            # are delegated to a currently verified object
            ea = ext_assumes if ver else ext_assumes_no_ver
            new_action = add_mixins(mod, actname, ext_action, ea, use_mixin,
                                    mod_mixin)
            new_actions['ext:' + actname] = new_action
            # TODO: external version is public if action public *or* called from opaque
            # public_actions.add('ext:'+actname)
        else:
            # TODO: here must check that summarized action does not
            # have a call dependency on the isolated module
            summarized_actions.add(actname)
            action = summarize_action(action)
            new_actions[actname] = add_mixins(mod, actname, action,
                                              after_mixins, use_mixin,
                                              mod_mixin)
            new_actions['ext:' + actname] = add_mixins(mod, actname, action,
                                                       all_mixins, use_mixin,
                                                       mod_mixin)

    # figure out what is exported:
    exported = set()
    for e in mod.exports:
        if not e.scope() and startswith_eq_some(e.exported(), present,
                                                mod):  # global scope
            exported.add('ext:' + e.exported())
    for actname, action in mod.actions.iteritems():
        if not startswith_some(actname, present, mod):
            for c in action.iter_calls():
                if (startswith_some(c, present, mod) or any(
                        startswith_some(m.mixer(), present, mod)
                        for m in mod.mixins[c])):
                    exported.add('ext:' + c)
#    print "exported: {}".format(exported)

# We allow objects to reference any symbols in global scope, and
# we keep axioms declared in global scope. Because of the way
# thigs are named, this gives a different condition for keeping
# symbols and axioms (in particular, axioms in global scope have
# label None). Maybe this needs to be cleaned up.

    keep_sym = lambda name: (iu.ivy_compose_character not in name or
                             startswith_eq_some(name, present))

    keep_ax = lambda name: (name is None or startswith_eq_some(
        name.rep, present, mod))
    check_pr = lambda name: (name is None or startswith_eq_some(
        name.rep, verified, mod))

    prop_deps = get_prop_dependencies(mod)

    # filter the conjectures

    new_conjs = [c for c in mod.labeled_conjs if keep_ax(c.label)]
    del mod.labeled_conjs[:]
    mod.labeled_conjs.extend(new_conjs)

    # filter the inits

    new_inits = [c for c in mod.labeled_inits if keep_ax(c.label)]
    del mod.labeled_inits[:]
    mod.labeled_inits.extend(new_inits)

    # filter the axioms
    dropped_axioms = [a for a in mod.labeled_axioms if not keep_ax(a.label)]
    mod.labeled_axioms = [a for a in mod.labeled_axioms if keep_ax(a.label)]
    mod.labeled_props = [a for a in mod.labeled_props if keep_ax(a.label)]

    # convert the properties not being verified to axioms
    mod.labeled_axioms.extend(
        [a for a in mod.labeled_props if not check_pr(a.label)])
    mod.labeled_props = [a for a in mod.labeled_props if check_pr(a.label)]

    # filter definitions
    mod.concepts = [
        c for c in mod.concepts
        if startswith_eq_some(c.args[0].func.name, present, mod)
    ]

    # filter the signature
    # keep only the symbols referenced in the remaining
    # formulas

    asts = []
    for x in [
            mod.labeled_axioms, mod.labeled_props, mod.labeled_inits,
            mod.labeled_conjs
    ]:
        asts += [y.formula for y in x]
    asts += mod.concepts
    asts += [action for action in new_actions.values()]
    sym_names = set(x.name for x in lu.used_symbols_asts(asts))

    if filter_symbols.get() or cone_of_influence.get():
        old_syms = list(mod.sig.symbols)
        for sym in old_syms:
            if sym not in sym_names:
                del mod.sig.symbols[sym]

    # check that any dropped axioms do not refer to the isolate's signature
    # and any properties have dependencies present

    def pname(s):
        return s.label if s.label else ""

    if enforce_axioms.get():
        for a in dropped_axioms:
            for x in lu.used_symbols_ast(a.formula):
                if x.name in sym_names:
                    raise iu.IvyError(
                        a, "relevant axiom {} not enforced".format(pname(a)))
        for actname, action in mod.actions.iteritems():
            if startswith_eq_some(actname, present, mod):
                for c in action.iter_calls():
                    called = mod.actions[c]
                    if not startswith_eq_some(c, present, mod):
                        if not (type(called) == ia.Sequence
                                and not called.args):
                            raise iu.IvyError(
                                None,
                                "No implementation for action {}".format(c))
        for p, ds in prop_deps:
            for d in ds:
                if not startswith_eq_some(d, present, mod):
                    raise iu.IvyError(
                        p,
                        "property {} depends on abstracted object {}".format(
                            pname(p), d))


#    for x,y in new_actions.iteritems():
#        print iu.pretty(ia.action_def_to_str(x,y))

# check for interference

#    iu.dbg('list(summarized_actions)')
    check_interference(mod, new_actions, summarized_actions)

    # After checking, we can put in place the new action definitions

    mod.public_actions.clear()
    mod.public_actions.update(exported)
    mod.actions.clear()
    mod.actions.update(new_actions)

    # TODO: need a better way to filter signature
    # new_syms = set(s for s in mod.sig.symbols if keep_sym(s))
    # for s in list(mod.sig.symbols):
    #     if s not in new_syms:
    #         del mod.sig.symbols[s]

    # strip the isolate parameters

    strip_isolate(mod, isolate, impl_mixins, extra_strip)

    # collect the initial condition

    init_cond = ivy_logic.And(*(lf.formula for lf in mod.labeled_inits))
    mod.init_cond = lu.formula_to_clauses(init_cond)
Пример #6
0
def create_isolate(iso,mod = None,**kwargs):

        mod = mod or im.module

        # check all mixin declarations

        for name,mixins in mod.mixins.iteritems():
            for mixin in mixins:
                with ASTContext(mixins):
                    action1,action2 = (lookup_action(mixin,mod,a.relname) for a in mixin.args)

        # check all the delagate declarations

        for dl in mod.delegates:
            lookup_action(dl.args[0],mod,dl.delegated())
            if dl.delegee() and dl.delegee() not in mod.hierarchy:
                raise iu.IvyError(dl.args[1],"{} is not a module instance".format(name))

        # Determine the mixin order (as a side effect on module.mixins)

        get_mixin_order(iso,mod)

        # Construct an isolate

        if iso:
            isolate_component(mod,iso)
        else:
            if mod.isolates:
                raise iu.IvyError(None,'no isolate specified on command line')
            # apply all the mixins in no particular order
            for name,mixins in mod.mixins.iteritems():
                for mixin in mixins:
                    action1,action2 = (lookup_action(mixin,mod,a.relname) for a in mixin.args)
                    mixed = ia.apply_mixin(mixin,action1,action2)
                    mod.actions[mixin.args[1].relname] = mixed
            # find the globally exported actions (all if none specified, for compat)
            if mod.exports:
                mod.public_actions.clear()
                for e in mod.exports:
                    if not e.scope(): # global export
                        mod.public_actions.add(e.exported())
            else:
                for a in mod.actions:
                    mod.public_actions.add(a)

        # Create one big external action if requested


        ext = kwargs['ext'] if 'ext' in kwargs else ext_action.get()
        if ext is not None:
            ext_acts = [mod.actions[x] for x in sorted(mod.public_actions)]
            ext_act = ia.EnvAction(*ext_acts)
            mod.public_actions.add(ext);
            mod.actions[ext] = ext_act;

        # Check native interpretations of symbols

        slv.check_compat()

        # Make concept spaces from the conjecture

        for i,cax in enumerate(mod.labeled_conjs):
            fmla = cax.formula
            csname = 'conjecture:'+ str(i)
            variables = list(lu.used_variables_ast(fmla))
            sort = ivy_logic.RelationSort([v.sort for v in variables])
            sym = ivy_logic.Symbol(csname,sort)
            space = ics.NamedSpace(ivy_logic.Literal(0,fmla))
            mod.concept_spaces.append((sym(*variables),space))

        ith.check_theory()

        if show_compiled.get():
            for x,y in mod.actions.iteritems():
                print iu.pretty("action {} = {}".format(x,y))