def type(self, typedef): # print "typedef {!r}".format(typedef) self.domain.sort_order.append(typedef.name) if isinstance(typedef, ivy_ast.GhostTypeDef): self.domain.ghost_sorts.add(typedef.name) if isinstance(typedef.value, ivy_ast.StructSort): sort = ivy_logic.ConstantSort(typedef.name) self.domain.sig.sorts[typedef.name] = sort # handle empty struct if typedef.name not in self.domain.sort_destructors: self.domain.sort_destructors[typedef.name] = [] for a in typedef.value.args: p = a.clone([ivy_ast.Variable('V:dstr', sort.name)] + a.args) p.sort = a.sort with ASTContext(typedef): with ASTContext(a): self.destructor(p) return with ASTContext(typedef.value): sort = typedef.value.cmpl(typedef.name) self.domain.sig.sorts[typedef.name] = sort for c in sort.defines(): # register the type's constructors sym = Symbol(c, sort) self.domain.functions[sym] = 0 self.domain.sig.symbols[c] = sym self.domain.sig.constructors.add(sym)
def sortify_with_inference(ast): # print "compiling : {}".format(ast) with top_sort_as_default(): res = ast.compile() with ASTContext(ast): res = sort_infer(res) return res
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 compile_call(self): assert top_context ctx = ExprContext(lineno=self.lineno) name = self.args[0].rep if name not in top_context.actions: raise iu.IvyError(self, "call to unknown action: {}".format(name)) with ctx: args = [a.cmpl() for a in self.args[0].args] params, returns = top_context.actions[name] if len(returns) != len(self.args) - 1: raise iu.IvyError( self, "wrong number of output parameters (got {}, expecting {})".format( len(self.args) - 1, len(returns))) if len(params) != len(args): raise iu.IvyError( self, "wrong number of input parameters (got {}, expecting {})".format( len(args), len(params))) with ASTContext(self): mas = [sort_infer(a, cmpl_sort(p.sort)) for a, p in zip(args, params)] # print self.args res = CallAction(*([ivy_ast.Atom(name, mas)] + [a.cmpl() for a in self.args[1:]])) res.lineno = self.lineno ctx.code.append(res) res = ctx.extract() # print "compiled call action: {}".format(res) return res
def concept(self, c): rel = c.args[0] with ASTContext(c): add_symbol(rel.relname, get_relation_sort(self.domain.sig, rel.args, c.args[1])) c = sortify_with_inference(c) self.domain.concept_spaces.append((c.args[0], c.args[1]))
def compile_assign(self): code = [] local_syms = [] with ExprContext(code, local_syms): if isinstance(self.args[0], ivy_ast.Tuple): args = [sortify_with_inference(a) for a in self.args] if not isinstance(args[1], ivy_ast.Tuple) or len( args[0].args) != len(args[1].args): raise IvyError(self, "wrong number of values in assignment") for lhs, rhs in zip(args[0].args, args[1].args): code.append(AssignAction(lhs, rhs)) else: with top_sort_as_default(): args = [a.compile() for a in self.args] if isinstance(args[1], ivy_ast.Tuple): raise IvyError(self, "wrong number of values in assignment") with ASTContext(self): teq = sort_infer(Equals(*args)) args = list(teq.args) code.append(AssignAction(*args)) for c in code: c.lineno = self.lineno if len(code) == 1: return code[0] res = LocalAction(*(local_syms + [Sequence(*code)])) res.lineno = self.lineno return res
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 progress(self, df): rel = df.args[0] with ASTContext(rel): sym = add_symbol( rel.relname, get_relation_sort(self.domain.sig, rel.args, df.args[1])) df = sortify_with_inference(df) self.domain.progress.append(df)
def __call__(self, ivy): for decl in ivy.decls: with ASTContext(decl): n = decl.name() # print "decl: {} : {}".format(n,decl.lineno if hasattr(decl,'lineno') else None) if n == 'assert': n = '_assert' # reserved in python! if hasattr(self, n): for x in decl.args: getattr(self, n)(x)
def derived(self, df): try: rel = df.args[0] with ASTContext(rel): sym = add_symbol( rel.relname, get_relation_sort(self.domain.sig, rel.args, df.args[1])) df = sortify_with_inference(df) self.domain.all_relations.append((sym, len(rel.args))) self.domain.relations[sym] = len(rel.args) self.domain.concepts.append(df) self.domain.updates.append(DerivedUpdate(df)) except ValueError: raise IvyError(df, "definition of derived relation must be a cube")
def compile_local(self): sig = ivy_logic.sig.copy() with sig: ls = self.args[0:-1] if len(ls) == 1 and isinstance(ls[0], AssignAction): v = ls[0] lhs = v.args[0] rhs = v.args[1] # temporarily rename lhs symbol in case it clashes with an existing symbol # tmp_lhs = lhs.prefix('__var_tmp:') tmp_lhs = lhs code = [] local_syms = [] with ExprContext(code, local_syms): with alpha_sort_as_default(): sym = compile_const(tmp_lhs, sig) ctmp_lhs = tmp_lhs.compile() crhs = rhs.compile() with ASTContext(self): teq = sort_infer(Equals(ctmp_lhs, crhs)) clhs, crhs = list(teq.args) # clhs = clhs.drop_prefix('__var_tmp:') asgn = v.clone([clhs, crhs]) ivy_logic.remove_symbol(sym) if clhs.rep.name in sig.symbols: del sig.symbols[clhs.rep.name] # shadow the existing symbol ivy_logic.add_symbol(clhs.rep.name, clhs.rep.sort) body = sortify(self.args[-1]) lines = body.args if isinstance(body, Sequence) else [body] body = Sequence(*([asgn] + lines)) code.append(LocalAction(clhs.rep, body)) for c in code: c.lineno = self.lineno if len(code) == 1: return code[0] res = LocalAction(*(local_syms + [Sequence(*code)])) res.lineno = self.lineno return res cls = [compile_const(v, sig) for v in ls] body = sortify(self.args[-1]) res = LocalAction(*(cls + [body])) res.lineno = self.lineno return res
def compile_action_def(a, sig): sig = sig.copy() if not hasattr(a.args[1], 'lineno'): print a assert hasattr(a.args[1], 'lineno') with sig: with ASTContext(a.args[1]): params = a.args[0].args pformals = [v.to_const('prm:') for v in params] if params: subst = dict((x.rep, y) for x, y in zip(params, pformals)) a = ivy_ast.substitute_ast(a, subst) assert hasattr(a.args[1], 'lineno') # a = ivy_ast.subst_prefix_atoms_ast(a,subst,None,None) # print "after: %s" % (a) # convert object paramaters to arguments (object-orientation!) formals = [ compile_const(v, sig) for v in pformals + a.formal_params ] returns = [compile_const(v, sig) for v in a.formal_returns] # print returns res = sortify(a.args[1]) assert hasattr(res, 'lineno'), res for suba in res.iter_subactions(): if isinstance(suba, CallAction): if any( lu.used_variables_ast(a) for a in suba.args[0].args): iu.dbg('a.args[0]') iu.dbg('a.formal_params') iu.dbg('suba.lineno') iu.dbg('suba') raise iu.IvyError(suba, "call may not have free variables") res.formal_params = formals res.formal_returns = returns res.label = a.args[0].relname return res
def _assert(self, a): with ASTContext(a): self.mod.assertions.append( type(a)(a.args[0], sortify_with_inference(a.args[1])))
def thing(self): with ASTContext(self): return self.cmpl()
def relation(self, rel): with ASTContext(rel): sym = add_symbol(rel.relname, get_relation_sort(self.domain.sig, rel.args)) self.domain.all_relations.append((sym, len(rel.args))) self.domain.relations[sym] = len(rel.args)
def compile_const(v, sig): with ASTContext(v): rng = find_sort(v.sort) if hasattr( v, 'sort') else ivy_logic.default_sort() return add_symbol(v.rep, get_function_sort(sig, v.args, rng))
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 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))
def scenario(self, scen): for (s, lineno) in scen.places(): with ASTContext(scen): sym = add_symbol(s, ivy_logic.RelationSort([])) self.domain.all_relations.append((sym, 0)) self.domain.relations[sym] = 0