def compile_app(self): args = [a.compile() for a in self.args] # handle action calls in rhs of assignment if expr_context and top_context and self.rep in top_context.actions: returns = top_context.actions[self.rep] if len(returns) != 1: raise IvyError(self, "wrong number of return values") # TODO: right now we can't do anything with multiple returns sorts = [find_sort(r.sort) for r in returns] ress = [] for sort in sorts: res = ivy_logic.Symbol( 'loc:' + str(len(expr_context.local_syms)), sort) expr_context.local_syms.append(res) ress.append(res()) expr_context.code.append( CallAction(*([ivy_ast.Atom(self.rep, args)] + ress))) return ivy_ast.Tuple(*ress) sort = find_sort(returns[0].sort) res = ivy_logic.Symbol('loc:' + str(len(expr_context.local_syms)), sort) expr_context.local_syms.append(res) expr_context.code.append(CallAction(ivy_ast.Atom(self.rep, args), res)) return res() return (ivy_logic.Equals if self.rep == '=' else ivy_logic.find_polymorphic_symbol(self.rep))(*args)
def compile_app(self): args = [a.compile() for a in self.args] # handle action calls in rhs of assignment if expr_context and top_context and self.rep in top_context.actions: params, returns = top_context.actions[self.rep] if len(returns) != 1: raise IvyError(self, "wrong number of return values") # TODO: right now we can't do anything with multiple returns sorts = [cmpl_sort(r.sort) for r in returns] ress = [] for sort in sorts: res = ivy_logic.Symbol( 'loc:' + str(len(expr_context.local_syms)), sort) expr_context.local_syms.append(res) ress.append(res()) expr_context.code.append( CallAction(*([ivy_ast.Atom(self.rep, args)] + ress))) return ivy_ast.Tuple(*ress) sort = cmpl_sort(returns[0].sort) res = ivy_logic.Symbol('loc:' + str(len(expr_context.local_syms)), sort) expr_context.local_syms.append(res) with ASTContext(self): if len(params) != len(args): raise iu.IvyError( self, "wrong number of input parameters (got {}, expecting {})". format(len(args), len(params))) args = [ sort_infer(a, cmpl_sort(p.sort)) for a, p in zip(args, params) ] expr_context.code.append(CallAction(ivy_ast.Atom(self.rep, args), res)) return res() return (ivy_logic.Equals if self.rep == '=' else ivy_logic.find_polymorphic_symbol(self.rep))(*args)
def compile_inline_call(self, args): params, returns = top_context.actions[self.rep] if len(returns) != 1: raise IvyError(self, "wrong number of return values") # TODO: right now we can't do anything with multiple returns sorts = [cmpl_sort(r.sort) for r in returns] ress = [] for sort in sorts: res = ivy_logic.Symbol('loc:' + str(len(expr_context.local_syms)), sort) expr_context.local_syms.append(res) ress.append(res()) expr_context.code.append( CallAction(*([ivy_ast.Atom(self.rep, args)] + ress))) return ivy_ast.Tuple(*ress) sort = cmpl_sort(returns[0].sort) res = ivy_logic.Symbol('loc:' + str(len(expr_context.local_syms)), sort) expr_context.local_syms.append(res) with ASTContext(self): if len(params) != len(args): raise iu.IvyError( self, "wrong number of input parameters (got {}, expecting {})". format(len(args), len(params))) args = [ sort_infer_contravariant(a, cmpl_sort(p.sort)) for a, p in zip(args, params) ] expr_context.code.append(CallAction(ivy_ast.Atom(self.rep, args), res)) return res()
def get_model_constant(m,t): s = t.get_sort() if isinstance(s,ivy_logic.EnumeratedSort) and not use_z3_enums: for v in s.defines(): w = ivy_logic.Constant(ivy_logic.Symbol(v,s)) if z3.is_true(m.eval(encode_equality(t,w))): return w # print "model: {}".format(m.sexpr()) # print "term: {}".format(t) res = ivy_logic.Constant(ivy_logic.Symbol(s.defines()[0],s)) print "warning: model doesn't give a value for enumerated term {}. returning {}.".format(t,res) return res # assert False # model doesn't give a value for enumerated term return constant_from_z3(s,m.eval(term_to_z3(t),model_completion=True))
def decode_val(self,bits,v): interp = thy.get_sort_theory(v.sort) if il.is_enumerated_sort(interp): num = self.bindec(bits) vals = v.sort.defines() val = vals[num] if num < len(vals) else vals[-1] val = il.Symbol(val,v.sort) elif isinstance(interp,thy.BitVectorTheory): num = self.bindec(bits) val = il.Symbol(str(num),v.sort) elif il.is_boolean_sort(interp): val = bits[0] else: assert False,'variable has unexpected sort: {} {}'.format(v,s.sort) return val
def check_compat(): for name,value in ivy_logic.sig.interp.iteritems(): if name in ivy_logic.sig.symbols: sym = ivy_logic.sig.symbols[name] sorts = sym.sort.sorts if isinstance(sym.sort,ivy_logic.UnionSort) else [sym.sort] for sort in sorts: check_native_compat_sym(ivy_logic.Symbol(name,sort))
def aiger_witness_to_ivy_trace(aiger,witnessfilename,action,stvarset,ext_act,annot,consts,decoder): with open(witnessfilename,'r') as f: res = f.readline().strip() if res != '1': badwit() tr = None aiger.sub.reset() lines = [] for line in f: if line.endswith('\n'): line = line[:-1] lines.append(line) print '\nCounterexample follows:' print 80*'-' current = dict() count = 0 for line in lines: if tr: print '' cols = line.split(' ') # iu.dbg('cols') if len(cols) != 4: badwit() pre,inp,out,post = cols aiger.sub.step(inp) count += 1 if count == len(lines): invar_fail = il.Symbol('invar__fail',il.find_sort('bool')) if il.is_true(aiger.get_sym(invar_fail)): break # print 'inputs:' # for v in aiger.inputs: # if v in decoder: # print ' {} = {}'.format(decoder[v],aiger.get_sym(v)) print 'path:' match_annotation(action,annot,AigerMatchHandler(aiger,decoder,consts,stvarset,current)) aiger.sub.next() post = aiger.sub.latch_vals() # use this, since file can be wrong! stvals = [] stmap = aiger.get_state(post) # iu.dbg('stmap') current = dict() for v in aiger.latches: # last two are used for encoding if v in decoder and v.name != '__init': val = stmap[v] if val is not None: stvals.append(il.Equals(decoder[v],val)) current[decoder[v]] = val print 'state:' for stval in stvals: print ' {}'.format(stval) if not tr: tr = IvyMCTrace(stvals) # first transition is initialization else: tr.add_state(stvals,ext_act) # remainder are exported actions print 80*'-' if tr is None: badwit() return tr
def sort_size_constraint(sort,size): if isinstance(sort,ivy_logic.UninterpretedSort): syms = [ivy_logic.Symbol('__'+sort.name+'$'+str(i),sort) for i in range(size)] v = ivy_logic.Variable('X'+sort.name,sort) res = ivy_logic.Or(*[ivy_logic.Equals(v,s) for s in syms]) # print "sort_size_constraint : {}".format(res) return res return ivy_logic.And()
def strip_action(ast, strip_map, strip_binding): if isinstance(ast, ia.CallAction): name = canon_act(ast.args[0].rep) args = [ strip_action(arg, strip_map, strip_binding) for arg in ast.args[0].args ] strip_params = get_strip_params(name, ast.args[0].args, strip_map, strip_binding, ast) call = ast.args[0].clone(args[len(strip_params):]) return ast.clone([call] + [ strip_action(arg, strip_map, strip_binding) for arg in ast.args[1:] ]) if isinstance(ast, ia.AssignAction): if ast.args[0].rep.name in ivy_logic.sig.symbols: lhs_params = strip_map_lookup(ast.args[0].rep.name, strip_map) if len(lhs_params) != num_isolate_params: raise iu.IvyError(ast, "assignment may be interfering") if (ivy_logic.is_constant(ast) or ivy_logic.is_variable(ast)) and ast in strip_binding: sname = strip_binding[ast] if sname not in ivy_logic.sig.symbols: ivy_logic.add_symbol(sname, ast.sort) strip_added_symbols.append(ivy_logic.Symbol(sname, ast.sort)) return ivy_logic.Symbol(sname, ast.sort) args = [strip_action(arg, strip_map, strip_binding) for arg in ast.args] if ivy_logic.is_app(ast): name = ast.rep.name strip_params = get_strip_params(name, ast.args, strip_map, strip_binding, ast) if strip_params: new_sort = strip_sort(ast.rep.sort, strip_params) new_args = args[len(strip_params):] new_symbol = ivy_logic.Symbol(name, new_sort) return new_symbol(*new_args) if isinstance(ast, ivy_ast.Atom): name = ast.rep strip_params = get_strip_params(name, ast.args, strip_map, strip_binding, ast) if strip_params: new_args = args[len(strip_params):] return ast.clone(new_args) return ast.clone(args)
def update_conjs(self): mod = self for i, cax in enumerate(mod.labeled_conjs): fmla = cax.formula csname = 'conjecture:' + str(i) variables = list(lu.used_variables_ast(fmla)) sort = il.RelationSort([v.sort for v in variables]) sym = il.Symbol(csname, sort) space = ics.NamedSpace(il.Literal(0, fmla)) mod.concept_spaces.append((sym(*variables), space))
def compile_native_symbol(arg): name = arg.rep if name in ivy_logic.sig.symbols: sym = ivy_logic.sig.symbols[name] if not isinstance(sym, ivy_logic.UnionSort): return sym if name in ivy_logic.sig.sorts: return ivy_logic.Variable('X', ivy_logic.sig.sorts[name]) if ivy_logic.is_numeral_name(name): return ivy_logic.Symbol(name, ivy_logic.TopS) raise iu.IvyError(arg, '{} is not a declared symbol or type'.format(name))
def emit_derived(header, impl, df, classname): name = df.defines().name sort = df.defines().sort retval = il.Symbol("ret:val", sort) vs = df.args[0].args ps = [ilu.var_to_skolem('p:', v) for v in vs] mp = dict(zip(vs, ps)) rhs = ilu.substitute_ast(df.args[1], mp) action = ia.AssignAction(retval, rhs) action.formal_params = ps action.formal_returns = [retval] emit_some_action(header, impl, name, action, classname)
def conjecture(self, ax): fmla = sortify_with_inference(ax) try: self.domain.conjs.append(formula_to_clauses(fmla)) except ValueError: raise IvyError(ax, "conjecture must be a clause") # Make a conecpt space from the conjecture csname = 'conjecture:' + str(len(self.domain.conjs)) variables = list(lu.used_variables_ast(fmla)) sort = ivy_logic.RelationSort([v.sort for v in variables]) sym = ivy_logic.Symbol(csname, sort) space = NamedSpace(ivy_logic.Literal(0, fmla)) self.domain.concept_spaces.append((sym(*variables), space))
def function_model_to_clauses(h,f): sort = f.sort rng = sort.rng res = [] fterm = fun_inst(f) if isinstance(rng,ivy_logic.EnumeratedSort) and not use_z3_enums: for c in rng.defines(): eq = ivy_logic._eq_lit(fterm,ivy_logic.Constant(ivy_logic.Symbol(c,rng))) # print "function_model_to_clauses: {}".format(eq) get_lit_facts(h,eq,res) # non-enumerated function types else: lit = ivy_logic.Literal(1,fun_eq_inst(f)) get_lit_facts(h,lit,res) # print "fun facts: {}".format([str(r) for r in res]) return res
def elim_ite(expr,cnsts): if isinstance(expr,il.Ite): global ite_ctr c,x,y = expr.args if not is_finite_sort(x.sort): v = il.Symbol('__ite[{}]'.format(ite_ctr),x.sort) ite_ctr += 1 cnsts.append(il.Ite(elim_ite(c,cnsts),elim_ite(il.Equals(v,x),cnsts),elim_ite(il.Equals(v,y),cnsts))) return v if il.is_eq(expr): v,e = expr.args if isinstance(e,il.Ite): c,x,y = e.args if not is_finite_sort(x.sort): return il.Ite(elim_ite(c,cnsts),elim_ite(il.Equals(v,x),cnsts),elim_ite(il.Equals(v,y),cnsts)) return expr.clone([elim_ite(e,cnsts) for e in expr.args])
def __init__(self,inputs,latches,outputs): # iu.dbg('inputs') # iu.dbg('latches') # iu.dbg('outputs') inputs = inputs + [il.Symbol('%%bogus%%',il.find_sort('bool'))] # work around abc bug self.inputs = inputs self.latches = latches self.outputs = outputs self.gates = [] self.map = dict() self.next_id = 1 self.values = dict() for x in inputs + latches: self.map[x] = self.next_id * 2 # print 'var: {} = {}'.format(x,self.next_id * 2) self.next_id += 1
def sorted_sort_universe(self, sort): elems = self.constants[sort] # print "elems: {}".format(map(str,elems)) vs = [ivy_logic.Variable(s, sort) for s in ["X", "Y"]] order = ivy_logic.Symbol("<", ivy_logic.RelationSort([sort, sort])) order_atom = atom_to_z3(order(*vs)) z3_vs = map(term_to_z3, vs) # print "order_atom: {}".format(order_atom) try: fun = z3.Function self.model[order.to_z3()] # print "sorting..." elems = sorted(elems, SortOrder(z3_vs, order_atom, self.model)) except IndexError: pass # print "elems: {}".format(map(str,elems)) return map(constant_from_z3, elems)
def assign_symbol_from_model(header, sym, m): if slv.solver_name(sym) == None: return # skip interpreted symbols name, sort = sym.name, sym.sort if hasattr(sort, 'dom'): for args in itertools.product( *[range(sort_card(s)) for s in sym.sort.dom]): term = sym( *[il.Symbol(str(a), s) for a, s in zip(args, sym.sort.dom)]) val = m.eval_to_constant(term) header.append( varname(sym.name) + ''.join('[' + str(a) + ']' for a in args) + ' = ') header.append(str(val) + ';\n') else: header.append( varname(sym.name) + ' = ' + m.eval_to_constant(sym) + ';\n')
def new_prop(expr): res = prop_abs.get(expr,None) if res is None: prev = prev_expr(stvarset,expr,sort_constants) if prev is not None: # print 'stvar: old: {} new: {}'.format(prev,expr) pva = new_prop(prev) res = tr.new(pva) new_stvars.append(pva) prop_abs[expr] = res # prevent adding this again to new_stvars else: global prop_abs_ctr res = il.Symbol('__abs[{}]'.format(prop_abs_ctr),expr.sort) # print '{} = {}'.format(res,expr) prop_abs[expr] = res prop_abs_ctr += 1 return res
def property_tactic(self, decls, proof): cut = proof.args[0] goal = decls[0] subgoal = goal_subst(goal, cut, cut.lineno) lhs = proof.args[1] if not isinstance(lhs, ia.NoneAST): fmla = il.drop_universals(cut.formula) if not il.is_exists(fmla) or len(fmla.variables) != 1: raise IvyError(proof, 'property is not existential') evar = list(fmla.variables)[0] rng = evar.sort vmap = dict((x.name, x) for x in lu.variables_ast(fmla)) used = set() args = lhs.args targs = [] for a in args: if a.name in used: raise IvyError(lhs, 'repeat parameter: {}'.format(a.name)) used.add(a.name) if a.name in vmap: v = vmap[a.name] targs.append(v) if not (il.is_topsort(a.sort) or a.sort != v.sort): raise IvyError(lhs, 'bad sort for {}'.format(a.name)) else: if il.is_topsort(a.sort): raise IvyError( lhs, 'cannot infer sort for {}'.format(a.name)) targs.append(a) for x in vmap: if x not in used: raise IvyError( lhs, '{} must be a parameter of {}'.format(x, lhs.rep)) dom = [x.sort for x in targs] sym = il.Symbol(lhs.rep, il.FuncConstSort(*(dom + [rng]))) if sym in self.stale or sym in goal_defns(goal): raise iu.IvyError(lhs, '{} is not fresh'.format(sym)) term = sym(*targs) if targs else sym fmla = lu.substitute_ast(fmla.body, {evar.name: term}) cut = clone_goal(cut, [], fmla) goal = goal_add_prem(goal, ia.ConstantDecl(sym), goal.lineno) return [goal_add_prem(goal, cut, cut.lineno)] + decls[1:] + [subgoal]
def constant_from_z3(c): return ivy_logic.Constant(ivy_logic.Symbol(repr(c), sort_from_z3(c.sort())))
def constant_from_z3(sort, c): if z3.is_true(c): return ivy_logic.And() if z3.is_false(c): return ivy_logic.Or() return ivy_logic.Constant(ivy_logic.Symbol(repr(c), sort))
def from_z3_numeral(z3term, sort): name = str(z3term) assert name[0].isdigit() return ivy_logic.Symbol(name, sort)
def witness(v): return lg.Symbol('@' + v.name, v.sort)
def emit_templates(self): add_impl( """ int CLASSNAME::temp_counter = 0; std::ostream &operator <<(std::ostream &s, const CLASSNAME &t){ s << "{"; switch (t.tag) { """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var add_impl(' case {}: s << "{}:" << {}; break;\n'.format(idx,sort.name,self.downcast(idx,'t'))) add_impl( """ } s << "}"; return s; } template <> CLASSNAME _arg<CLASSNAME>(std::vector<ivy_value> &args, unsigned idx, long long bound) { if (args[idx].atom.size()) throw out_of_bounds("unexpected value for sort SORTNAME: " + args[idx].atom,args[idx].pos); if (args[idx].fields.size() == 0) return CLASSNAME(); if (args[idx].fields.size() != 1) throw out_of_bounds("too many fields for sort SORTNAME (expected one)",args[idx].pos); """.replace('CLASSNAME',self.short_name()).replace('SORTNAME',self.sort.name)) for idx,var in enumerate(self.variants): sort,ctype = var add_impl(' if (args[idx].fields[0].atom == "{}") return {};\n'.format(sort.name,self.upcast(idx,'_arg<{}>(args[idx].fields[0].fields,0,0)'.format(ctype)))) add_impl( """ throw out_of_bounds("unexpected field sort SORTNAME: " + args[idx].fields[0].atom, args[idx].pos); } template <> void __ser<CLASSNAME>(ivy_ser &res, const CLASSNAME &inp) { """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var add_impl(' if (inp.tag == {}) {{res.open_tag({},"{}"); __ser(res,{}); res.close_tag();}}\n'.format(idx,idx,sort.name,self.downcast(idx,'inp'))) add_impl( """ } template <> void __deser<CLASSNAME>(ivy_deser &res, CLASSNAME &inp) { std::vector<std::string> tags; """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var add_impl(' tags.push_back("{}");\n'.format(sort.name)) add_impl( """ int tag = res.open_tag(tags); switch (tag) { """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var add_impl(' case {}: {{{} tmp; __deser(res,tmp); inp = {}; break;}} \n'.format(idx,ctype,self.upcast(idx,'tmp'))) add_impl( """ } res.close_tag(); } #ifdef Z3PP_H_ template <> void __from_solver<CLASSNAME>( gen &g, const z3::expr &v, CLASSNAME &res) { """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var pto = ivy_solver.solver_name(ivy_logic.Symbol('*>',ivy_logic.RelationSort([self.sort,sort]))) add_impl(' {\n') add_impl(' z3::sort sort = g.sort("{}");\n'.format(sort.name)) add_impl(' z3::func_decl pto = g.ctx.function("{}",g.sort("{}"),g.sort("{}"),g.ctx.bool_sort());\n'.format(pto,self.sort.name,sort.name)) add_impl(' // std::cout << g.model << std::endl;\n') add_impl(' Z3_ast_vector av = Z3_model_get_sort_universe(g.ctx, g.model, sort);\n') add_impl(' if (av) {\n') add_impl(' z3::expr_vector univ(g.ctx,av);\n') add_impl(' for (unsigned i = 0; i < univ.size(); i++){\n') add_impl(' if (eq(g.model.eval(pto(v,univ[i]),true),g.ctx.bool_val(true))){\n') add_impl(' {} tmp;\n'.format(ctype)) add_impl(' __from_solver(g,univ[i],tmp);') add_impl(' res = {};\n'.format(self.upcast(idx,'tmp'))) add_impl(' }\n') add_impl(' }\n') add_impl(' }\n') add_impl(' }\n') add_impl( """ } template <> z3::expr __to_solver<CLASSNAME>( gen &g, const z3::expr &v, CLASSNAME &val) { // std::cout << v << ":" << v.get_sort() << std::endl; """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var pto = ivy_solver.solver_name(ivy_logic.Symbol('*>',ivy_logic.RelationSort([self.sort,sort]))) add_impl(' if (val.tag == {}) {{\n'.format(idx)) add_impl(' z3::func_decl pto = g.ctx.function("{}",g.sort("{}"),g.sort("{}"),g.ctx.bool_sort());\n'.format(pto,self.sort.name,sort.name)) add_impl(' z3::expr X = g.ctx.constant("X",g.sort("{}"));\n'.format(sort.name)) add_impl(' {} tmp = {};\n'.format(ctype,self.downcast(idx,'val'))) add_impl(' return exists(X,pto(v,X) && __to_solver(g,X,tmp));\n') add_impl(' }\n') add_impl( """ z3::expr conj = g.ctx.bool_val(false); """.replace('CLASSNAME',self.short_name())) for idx,var in enumerate(self.variants): sort,ctype = var pto = ivy_solver.solver_name(ivy_logic.Symbol('*>',ivy_logic.RelationSort([self.sort,sort]))) add_impl(' {\n') add_impl(' z3::func_decl pto = g.ctx.function("{}",g.sort("{}"),g.sort("{}"),g.ctx.bool_sort());\n'.format(pto,self.sort.name,sort.name)) add_impl(' z3::expr Y = g.ctx.constant("Y",g.sort("{}"));\n'.format(sort.name)) add_impl(' conj = conj && forall(Y,!pto(v,Y));\n') add_impl(' }\n') add_impl( """ return conj; } template <> void __randomize<CLASSNAME>( gen &g, const z3::expr &apply_expr) { std::ostringstream os; os << "__SORTNAME__tmp" << CLASSNAME::temp_counter++; std::string temp = os.str(); z3::sort range = apply_expr.get_sort(); z3::expr disj = g.ctx.bool_val(false); """.replace('CLASSNAME',self.short_name()).replace('SORTNAME',self.sort.name)) add_impl('int tag = rand() % {};\n'.format(len(self.variants))) for idx,var in enumerate(self.variants): sort,ctype = var pto = ivy_solver.solver_name(ivy_logic.Symbol('*>',ivy_logic.RelationSort([self.sort,sort]))) add_impl(' if (tag == {}) {{\n'.format(idx)) add_impl(' z3::func_decl pto = g.ctx.function("{}",g.sort("{}"),g.sort("{}"),g.ctx.bool_sort());\n'.format(pto,self.sort.name,sort.name)) add_impl(' z3::expr X = g.ctx.constant(temp.c_str(),g.sort("{}"));\n'.format(sort.name)) add_impl(' z3::expr pred = pto(apply_expr,X);\n') add_impl(' g.add_alit(pred);\n') add_impl(' __randomize<{}>(g,X);\n'.format(ctype)) add_impl(' }\n') add_impl( """ } #endif """.replace('CLASSNAME',self.short_name()))
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 apply_match_func(match, func): sorts = func_sorts(func) sorts = [match.get(s, s) for s in sorts] return il.Symbol(func.name, sorts[0] if len(sorts) == 1 else il.FunctionSort(*sorts))
def lt_pred(sort): sym = ivy_logic.Symbol('<', sort) sig = sym.sort.to_z3() return z3.Function(solver_name(sym), *sig)
def map_fmla(lineno, fmla, pol): """ Add all of the subterms of `fmla` to the stratification graph. """ global universally_quantified_variables global macro_var_map global macro_dep_map global macro_map global macro_val_map global strat_map global arcs if il.is_binder(fmla): return map_fmla(lineno, fmla.body, pol) if il.is_variable(fmla): if fmla in universally_quantified_variables: if fmla not in strat_map: res = UFNode() strat_map[fmla] = res return strat_map[fmla], set() node, vs = macro_var_map.get(fmla, None), macro_dep_map.get(fmla, set()) return node, vs reses = [ map_fmla(lineno, f, il.polar(fmla, pos, pol)) for pos, f in enumerate(fmla.args) ] nodes, uvs = iu.unzip_pairs(reses) all_uvs = iu.union_of_list(uvs) all_uvs.update(n for n in nodes if n is not None) if il.is_eq(fmla): if not il.is_interpreted_sort(fmla.args[0].sort): S_sigma = strat_map[il.Symbol('=', fmla.args[0])] for x, uv in zip(nodes, uvs): if x is not None: unify(x, S_sigma) arcs.extend((v, S_sigma, fmla, lineno) for v in uv) else: check_interpreted(fmla, nodes, uvs, lineno, pol) return None, all_uvs if il.is_ite(fmla): # S_sigma = strat_map[il.Symbol('=',fmla.args[1])] # for x,uv in zip(nodes[1:],uvs[1:]): # if x is not None: # unify(x,S_sigma) # arcs.extend((v,S_sigma,fmla,lineno) for v in uv) # TODO: treat ite as pseudo-macro: does this work? if nodes[1] and nodes[2]: unify(*nodes[1:]) return nodes[1] or nodes[2], all_uvs if il.is_app(fmla): func = fmla.rep if not il.is_interpreted_symbol(func): if func in macro_value_map: return macro_value_map[func] if func in macro_map: defn, lf = macro_map[func] res = map_fmla(lf.lineno, defn.rhs(), None) macro_value_map[func] = res return res for idx, node in enumerate(nodes): anode = strat_map[(func, idx)] if node is not None: unify(anode, node) arcs.extend((v, anode, fmla, lineno) for v in uvs[idx]) else: check_interpreted(fmla, nodes, uvs, lineno, pol) return None, all_uvs return None, all_uvs
def from_z3_numeral(z3term, sort): name = str(z3term) if not (name[0].isdigit() or name[0] == '"' or name[0] == '-'): print "unexpected numeral from Z3 model: {}".format(name) return ivy_logic.Symbol(name, sort)