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
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
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))
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)
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)
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))