public override void ComputeFreeVariables(Set freeVars) { //Contract.Requires(freeVars != null); foreach (var v in Dummies) { Contract.Assert(v != null); Contract.Assert(!freeVars[v]); } Body.ComputeFreeVariables(freeVars); for (var a = Attributes; a != null; a = a.Next) { foreach (var o in a.Params) { var e = o as Expr; if (e != null) { e.ComputeFreeVariables(freeVars); } } } foreach (var v in Dummies) { freeVars.AddRange(v.TypedIdent.Type.FreeVariables); } freeVars.RemoveRange(Dummies); foreach (var e in Rhss) { e.ComputeFreeVariables(freeVars); } }
public override void ComputeFreeVariables(Set /*Variable*/ freeVars) { //Contract.Requires(freeVars != null); foreach (Variable /*!*/ v in Dummies) { Contract.Assert(v != null); Contract.Assert(!freeVars[v]); } Body.ComputeFreeVariables(freeVars); foreach (Variable /*!*/ v in Dummies) { Contract.Assert(v != null); foreach (TypeVariable /*!*/ w in v.TypedIdent.Type.FreeVariables) { Contract.Assert(w != null); freeVars.Add(w); } } foreach (Variable /*!*/ v in Dummies) { Contract.Assert(v != null); freeVars.Remove(v); } foreach (TypeVariable /*!*/ v in TypeParameters) { Contract.Assert(v != null); freeVars.Remove(v); } }
/// <summary> /// Add to "freeVars" the free variables in the triggering expressions. /// </summary> public void ComputeFreeVariables(Set /*Variable*/ freeVars) { Contract.Requires(freeVars != null); foreach (Expr /*!*/ e in this.Tr) { Contract.Assert(e != null); e.ComputeFreeVariables(freeVars); } }
public override Expr VisitOldExpr(OldExpr node) { Set freeVars = new Set(); node.Expr.ComputeFreeVariables(freeVars); foreach (var v in freeVars) { // Note, "v" is either a Variable or a TypeVariable if (v is Variable) { FreeOldVars.Add((Variable)v); } } return node; // don't visit subexpressions, since ComputeFreeVariables has already gone through those }
public override void ComputeFreeVariables(Set /*Variable*/ freeVars) { //Contract.Requires(freeVars != null); foreach (Variable/*!*/ v in Dummies) { Contract.Assert(v != null); Contract.Assert(!freeVars[v]); } Body.ComputeFreeVariables(freeVars); foreach (Variable/*!*/ v in Dummies) { Contract.Assert(v != null); foreach (TypeVariable/*!*/ w in v.TypedIdent.Type.FreeVariables) { Contract.Assert(w != null); freeVars.Add(w); } } foreach (Variable/*!*/ v in Dummies) { Contract.Assert(v != null); freeVars.Remove(v); } foreach (TypeVariable/*!*/ v in TypeParameters) { Contract.Assert(v != null); freeVars.Remove(v); } }
public static void ComputeBinderFreeVariables(List <TypeVariable> typeParameters, List <Variable> dummies, Expr body, QKeyValue attributes, Set freeVars) { Contract.Requires(dummies != null); Contract.Requires(body != null); foreach (var v in dummies) { Contract.Assert(v != null); Contract.Assert(!freeVars[v]); } body.ComputeFreeVariables(freeVars); for (var a = attributes; a != null; a = a.Next) { foreach (var o in a.Params) { var e = o as Expr; if (e != null) { e.ComputeFreeVariables(freeVars); } } } foreach (var v in dummies) { freeVars.AddRange(v.TypedIdent.Type.FreeVariables); } freeVars.RemoveRange(dummies); freeVars.RemoveRange(typeParameters); }
public override void ComputeFreeVariables(Set freeVars) { //Contract.Requires(freeVars != null); ComputeBinderFreeVariables(TypeParameters, Dummies, Body, Attributes, freeVars); }
/// <summary> /// Add to "freeVars" the free variables in the triggering expressions. /// </summary> public void ComputeFreeVariables(Set /*Variable*/ freeVars) { Contract.Requires(freeVars != null); foreach (Expr/*!*/ e in this.Tr) { Contract.Assert(e != null); e.ComputeFreeVariables(freeVars); } }
public static void ComputeBinderFreeVariables(List<TypeVariable> typeParameters, List<Variable> dummies, Expr body, QKeyValue attributes, Set freeVars) { Contract.Requires(dummies != null); Contract.Requires(body != null); foreach (var v in dummies) { Contract.Assert(v != null); Contract.Assert(!freeVars[v]); } body.ComputeFreeVariables(freeVars); for (var a = attributes; a != null; a = a.Next) { foreach (var o in a.Params) { var e = o as Expr; if (e != null) { e.ComputeFreeVariables(freeVars); } } } foreach (var v in dummies) { freeVars.AddRange(v.TypedIdent.Type.FreeVariables); } freeVars.RemoveRange(dummies); freeVars.RemoveRange(typeParameters); }
public override Expr VisitLambdaExpr(LambdaExpr lambda) { var baseResult = base.VisitLambdaExpr(lambda); lambda = baseResult as LambdaExpr; if (lambda == null) { return baseResult; // apparently, the base visitor already turned the lambda into something else } // We start by getting rid of any use of "old" inside the lambda. This is done as follows. // For each variable "g" occurring inside lambda as "old(... g ...)", create a new name "og". // Replace each old occurrence of "g" with "og", removing the enclosing "old" wrappers. var oldFinder = new OldFinder(); oldFinder.Visit(lambda); var oldSubst = new Dictionary<Variable, Expr>(); // g -> g0 var callOldMapping = new Dictionary<Variable, Expr>(); // g0 -> old(g) foreach (var v in oldFinder.FreeOldVars) { var g = v as GlobalVariable; if (g != null) { var g0 = new GlobalVariable(g.tok, new TypedIdent(g.tok, g.TypedIdent.Name + "@old", g.TypedIdent.Type)); oldSubst.Add(g, new IdentifierExpr(g0.tok, g0)); callOldMapping.Add(g0, new OldExpr(g0.tok, new IdentifierExpr(g.tok, g))); } } var lambdaBody = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromHashtable(new Dictionary<Variable,Expr>()), Substituter.SubstitutionFromHashtable(oldSubst), lambda.Body); var lambdaAttrs = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromHashtable(oldSubst), lambda.Attributes); if (0 < CommandLineOptions.Clo.VerifySnapshots && QKeyValue.FindStringAttribute(lambdaAttrs, "checksum") == null) { // Attach a dummy checksum to avoid issues in the dependency analysis. var checksumAttr = new QKeyValue(lambda.tok, "checksum", new List<object> { "stable" }, null); if (lambdaAttrs == null) { lambdaAttrs = checksumAttr; } else { lambdaAttrs.AddLast(checksumAttr); } } // this is ugly, the output will depend on hashing order var subst = new Dictionary<Variable, Expr>(); var substFnAttrs = new Dictionary<Variable, Expr>(); var formals = new List<Variable>(); var callArgs = new List<Expr>(); var axCallArgs = new List<Expr>(); var dummies = new List<Variable>(lambda.Dummies); var freeTypeVars = new List<TypeVariable>(); var fnTypeVarActuals = new List<Type/*!*/>(); var freshTypeVars = new List<TypeVariable>(); // these are only used in the lambda@n function's definition // compute the free variables of the lambda expression, but with lambdaBody instead of lambda.Body Set freeVars = new Set(); BinderExpr.ComputeBinderFreeVariables(lambda.TypeParameters, lambda.Dummies, lambdaBody, lambdaAttrs, freeVars); foreach (object o in freeVars) { // 'o' is either a Variable or a TypeVariable. if (o is Variable) { var v = o as Variable; var ti = new TypedIdent(v.TypedIdent.tok, v.TypedIdent.Name, v.TypedIdent.Type); var f = new Formal(v.tok, ti, true); formals.Add(f); substFnAttrs.Add(v, new IdentifierExpr(f.tok, f)); var b = new BoundVariable(v.tok, ti); dummies.Add(b); if (callOldMapping.ContainsKey(v)) { callArgs.Add(callOldMapping[v]); } else { callArgs.Add(new IdentifierExpr(v.tok, v)); } Expr id = new IdentifierExpr(b.tok, b); subst.Add(v, id); axCallArgs.Add(id); } else { var tv = (TypeVariable)o; freeTypeVars.Add(tv); fnTypeVarActuals.Add(tv); freshTypeVars.Add(new TypeVariable(tv.tok, tv.Name)); } } var sw = new System.IO.StringWriter(); var wr = new TokenTextWriter(sw, true); lambda.Emit(wr); string lam_str = sw.ToString(); FunctionCall fcall; IToken tok = lambda.tok; Formal res = new Formal(tok, new TypedIdent(tok, TypedIdent.NoName, cce.NonNull(lambda.Type)), false); if (liftedLambdas.TryGetValue(lambda, out fcall)) { if (CommandLineOptions.Clo.TraceVerify) { Console.WriteLine("Old lambda: {0}", lam_str); } } else { if (CommandLineOptions.Clo.TraceVerify) { Console.WriteLine("New lambda: {0}", lam_str); } Function fn = new Function(tok, FreshLambdaFunctionName(), freshTypeVars, formals, res, "auto-generated lambda function", Substituter.Apply(Substituter.SubstitutionFromHashtable(substFnAttrs), lambdaAttrs)); fcall = new FunctionCall(new IdentifierExpr(tok, fn.Name)); fcall.Func = fn; // resolve here liftedLambdas[lambda] = fcall; List<Expr/*!*/> selectArgs = new List<Expr/*!*/>(); foreach (Variable/*!*/ v in lambda.Dummies) { Contract.Assert(v != null); selectArgs.Add(new IdentifierExpr(v.tok, v)); } NAryExpr axcall = new NAryExpr(tok, fcall, axCallArgs); axcall.Type = res.TypedIdent.Type; axcall.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); NAryExpr select = Expr.Select(axcall, selectArgs); select.Type = lambdaBody.Type; List<Type/*!*/> selectTypeParamActuals = new List<Type/*!*/>(); List<TypeVariable> forallTypeVariables = new List<TypeVariable>(); foreach (TypeVariable/*!*/ tp in lambda.TypeParameters) { Contract.Assert(tp != null); selectTypeParamActuals.Add(tp); forallTypeVariables.Add(tp); } forallTypeVariables.AddRange(freeTypeVars); select.TypeParameters = SimpleTypeParamInstantiation.From(lambda.TypeParameters, selectTypeParamActuals); Expr bb = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaBody); NAryExpr body = Expr.Eq(select, bb); body.Type = Type.Bool; body.TypeParameters = SimpleTypeParamInstantiation.EMPTY; Trigger trig = new Trigger(select.tok, true, new List<Expr> { select }); lambdaFunctions.Add(fn); lambdaAxioms.Add(new ForallExpr(tok, forallTypeVariables, dummies, Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaAttrs), trig, body)); } NAryExpr call = new NAryExpr(tok, fcall, callArgs); call.Type = res.TypedIdent.Type; call.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); return call; }
void CreateProceduresForLoops(Implementation impl, Graph<Block/*!*/>/*!*/ g, List<Implementation/*!*/>/*!*/ loopImpls, Dictionary<string, Dictionary<string, Block>> fullMap) { Contract.Requires(impl != null); Contract.Requires(cce.NonNullElements(loopImpls)); // Enumerate the headers // for each header h: // create implementation p_h with // inputs = inputs, outputs, and locals of impl // outputs = outputs and locals of impl // locals = empty set // add call o := p_h(i) at the beginning of the header block // break the back edges whose target is h // Enumerate the headers again to create the bodies of p_h // for each header h: // compute the loop corresponding to h // make copies of all blocks in the loop for h // delete all target edges that do not go to a block in the loop // create a new entry block and a new return block // add edges from entry block to the loop header and the return block // add calls o := p_h(i) at the end of the blocks that are sources of back edges foreach (Block block in impl.Blocks) { AddToFullMap(fullMap, impl.Name, block.Label, block); } bool detLoopExtract = CommandLineOptions.Clo.DeterministicExtractLoops; Dictionary<Block/*!*/, List<Variable>/*!*/>/*!*/ loopHeaderToInputs = new Dictionary<Block/*!*/, List<Variable>/*!*/>(); Dictionary<Block/*!*/, List<Variable>/*!*/>/*!*/ loopHeaderToOutputs = new Dictionary<Block/*!*/, List<Variable>/*!*/>(); Dictionary<Block/*!*/, Dictionary<Variable, Expr>/*!*/>/*!*/ loopHeaderToSubstMap = new Dictionary<Block/*!*/, Dictionary<Variable, Expr>/*!*/>(); Dictionary<Block/*!*/, LoopProcedure/*!*/>/*!*/ loopHeaderToLoopProc = new Dictionary<Block/*!*/, LoopProcedure/*!*/>(); Dictionary<Block/*!*/, CallCmd/*!*/>/*!*/ loopHeaderToCallCmd1 = new Dictionary<Block/*!*/, CallCmd/*!*/>(); Dictionary<Block, CallCmd> loopHeaderToCallCmd2 = new Dictionary<Block, CallCmd>(); Dictionary<Block, AssignCmd> loopHeaderToAssignCmd = new Dictionary<Block, AssignCmd>(); foreach (Block/*!*/ header in g.Headers) { Contract.Assert(header != null); Contract.Assert(header != null); List<Variable> inputs = new List<Variable>(); List<Variable> outputs = new List<Variable>(); List<Expr> callInputs1 = new List<Expr>(); List<IdentifierExpr> callOutputs1 = new List<IdentifierExpr>(); List<Expr> callInputs2 = new List<Expr>(); List<IdentifierExpr> callOutputs2 = new List<IdentifierExpr>(); List<AssignLhs> lhss = new List<AssignLhs>(); List<Expr> rhss = new List<Expr>(); Dictionary<Variable, Expr> substMap = new Dictionary<Variable, Expr>(); // Variable -> IdentifierExpr List<Variable>/*!*/ targets = new List<Variable>(); HashSet<Variable> footprint = new HashSet<Variable>(); foreach (Block/*!*/ b in g.BackEdgeNodes(header)) { Contract.Assert(b != null); foreach (Block/*!*/ block in g.NaturalLoops(header, b)) { Contract.Assert(block != null); foreach (Cmd/*!*/ cmd in block.Cmds) { Contract.Assert(cmd != null); cmd.AddAssignedVariables(targets); VariableCollector c = new VariableCollector(); c.Visit(cmd); footprint.UnionWith(c.usedVars); } } } List<IdentifierExpr>/*!*/ globalMods = new List<IdentifierExpr>(); Set targetSet = new Set(); foreach (Variable/*!*/ v in targets) { Contract.Assert(v != null); if (targetSet.Contains(v)) continue; targetSet.Add(v); if (v is GlobalVariable) globalMods.Add(new IdentifierExpr(Token.NoToken, v)); } foreach (Variable v in impl.InParams) { Contract.Assert(v != null); if (!footprint.Contains(v)) continue; callInputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true); inputs.Add(f); callInputs2.Add(new IdentifierExpr(Token.NoToken, f)); substMap[v] = new IdentifierExpr(Token.NoToken, f); } foreach (Variable v in impl.OutParams) { Contract.Assert(v != null); if (!footprint.Contains(v)) continue; callInputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f1 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true); inputs.Add(f1); if (targetSet.Contains(v)) { callOutputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f2 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false); outputs.Add(f2); callInputs2.Add(new IdentifierExpr(Token.NoToken, f2)); callOutputs2.Add(new IdentifierExpr(Token.NoToken, f2)); lhss.Add(new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, f2))); rhss.Add(new IdentifierExpr(Token.NoToken, f1)); substMap[v] = new IdentifierExpr(Token.NoToken, f2); } else { callInputs2.Add(new IdentifierExpr(Token.NoToken, f1)); substMap[v] = new IdentifierExpr(Token.NoToken, f1); } } foreach (Variable v in impl.LocVars) { Contract.Assert(v != null); if (!footprint.Contains(v)) continue; callInputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f1 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "in_" + v.Name, v.TypedIdent.Type), true); inputs.Add(f1); if (targetSet.Contains(v)) { callOutputs1.Add(new IdentifierExpr(Token.NoToken, v)); Formal f2 = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "out_" + v.Name, v.TypedIdent.Type), false); outputs.Add(f2); callInputs2.Add(new IdentifierExpr(Token.NoToken, f2)); callOutputs2.Add(new IdentifierExpr(Token.NoToken, f2)); lhss.Add(new SimpleAssignLhs(Token.NoToken, new IdentifierExpr(Token.NoToken, f2))); rhss.Add(new IdentifierExpr(Token.NoToken, f1)); substMap[v] = new IdentifierExpr(Token.NoToken, f2); } else { callInputs2.Add(new IdentifierExpr(Token.NoToken, f1)); substMap[v] = new IdentifierExpr(Token.NoToken, f1); } } loopHeaderToInputs[header] = inputs; loopHeaderToOutputs[header] = outputs; loopHeaderToSubstMap[header] = substMap; LoopProcedure loopProc = new LoopProcedure(impl, header, inputs, outputs, globalMods); loopHeaderToLoopProc[header] = loopProc; CallCmd callCmd1 = new CallCmd(Token.NoToken, loopProc.Name, callInputs1, callOutputs1); callCmd1.Proc = loopProc; loopHeaderToCallCmd1[header] = callCmd1; CallCmd callCmd2 = new CallCmd(Token.NoToken, loopProc.Name, callInputs2, callOutputs2); callCmd2.Proc = loopProc; loopHeaderToCallCmd2[header] = callCmd2; Debug.Assert(lhss.Count == rhss.Count); if (lhss.Count > 0) { AssignCmd assignCmd = new AssignCmd(Token.NoToken, lhss, rhss); loopHeaderToAssignCmd[header] = assignCmd; } } // Keep track of the new blocks created: maps a header node to the // header_last block that was created because of splitting header. Dictionary<Block, Block> newBlocksCreated = new Dictionary<Block, Block>(); bool headRecursion = false; // testing an option to put recursive call before loop body IEnumerable<Block> sortedHeaders = g.SortHeadersByDominance(); foreach (Block/*!*/ header in sortedHeaders) { Contract.Assert(header != null); LoopProcedure loopProc = loopHeaderToLoopProc[header]; Dictionary<Block, Block> blockMap = new Dictionary<Block, Block>(); HashSet<string> dummyBlocks = new HashSet<string>(); CodeCopier codeCopier = new CodeCopier(loopHeaderToSubstMap[header]); // fix me List<Variable> inputs = loopHeaderToInputs[header]; List<Variable> outputs = loopHeaderToOutputs[header]; int si_unique_loc = 1; // Added by AL: to distinguish the back edges foreach (Block/*!*/ source in g.BackEdgeNodes(header)) { Contract.Assert(source != null); foreach (Block/*!*/ block in g.NaturalLoops(header, source)) { Contract.Assert(block != null); if (blockMap.ContainsKey(block)) continue; Block newBlock = new Block(); newBlock.Label = block.Label; if (headRecursion && block == header) { CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone(); addUniqueCallAttr(si_unique_loc, callCmd); si_unique_loc++; newBlock.Cmds.Add(callCmd); // add the recursive call at head of loop var rest = codeCopier.CopyCmdSeq(block.Cmds); newBlock.Cmds.AddRange(rest); } else newBlock.Cmds = codeCopier.CopyCmdSeq(block.Cmds); blockMap[block] = newBlock; if (newBlocksCreated.ContainsKey(block)) { Block newBlock2 = new Block(); newBlock2.Label = newBlocksCreated[block].Label; newBlock2.Cmds = codeCopier.CopyCmdSeq(newBlocksCreated[block].Cmds); blockMap[newBlocksCreated[block]] = newBlock2; } //for detLoopExtract, need the immediate successors even outside the loop if (detLoopExtract) { GotoCmd auxGotoCmd = block.TransferCmd as GotoCmd; Contract.Assert(auxGotoCmd != null && auxGotoCmd.labelNames != null && auxGotoCmd.labelTargets != null && auxGotoCmd.labelTargets.Count >= 1); foreach(var bl in auxGotoCmd.labelTargets) { bool found = false; foreach(var n in g.NaturalLoops(header, source)) { //very expensive, can we do a contains? if (bl == n) { //clarify: is this the right comparison? found = true; break; } } if (!found) { Block auxNewBlock = new Block(); auxNewBlock.Label = ((Block)bl).Label; auxNewBlock.Cmds = codeCopier.CopyCmdSeq(((Block)bl).Cmds); //add restoration code for such blocks if (loopHeaderToAssignCmd.ContainsKey(header)) { AssignCmd assignCmd = loopHeaderToAssignCmd[header]; auxNewBlock.Cmds.Add(assignCmd); } List<AssignLhs> lhsg = new List<AssignLhs>(); List<IdentifierExpr>/*!*/ globalsMods = loopHeaderToLoopProc[header].Modifies; foreach (IdentifierExpr gl in globalsMods) lhsg.Add(new SimpleAssignLhs(Token.NoToken, gl)); List<Expr> rhsg = new List<Expr>(); foreach (IdentifierExpr gl in globalsMods) rhsg.Add(new OldExpr(Token.NoToken, gl)); if (lhsg.Count != 0) { AssignCmd globalAssignCmd = new AssignCmd(Token.NoToken, lhsg, rhsg); auxNewBlock.Cmds.Add(globalAssignCmd); } blockMap[(Block)bl] = auxNewBlock; } } } } List<Cmd> cmdSeq; if (headRecursion) cmdSeq = new List<Cmd>(); else { CallCmd callCmd = (CallCmd)(loopHeaderToCallCmd2[header]).Clone(); addUniqueCallAttr(si_unique_loc, callCmd); si_unique_loc++; cmdSeq = new List<Cmd> { callCmd }; } Block/*!*/ block1 = new Block(Token.NoToken, source.Label + "_dummy", new List<Cmd>{ new AssumeCmd(Token.NoToken, Expr.False) }, new ReturnCmd(Token.NoToken)); Block/*!*/ block2 = new Block(Token.NoToken, block1.Label, cmdSeq, new ReturnCmd(Token.NoToken)); impl.Blocks.Add(block1); dummyBlocks.Add(block1.Label); GotoCmd gotoCmd = source.TransferCmd as GotoCmd; Contract.Assert(gotoCmd != null && gotoCmd.labelNames != null && gotoCmd.labelTargets != null && gotoCmd.labelTargets.Count >= 1); List<String>/*!*/ newLabels = new List<String>(); List<Block>/*!*/ newTargets = new List<Block>(); for (int i = 0; i < gotoCmd.labelTargets.Count; i++) { if (gotoCmd.labelTargets[i] == header) continue; newTargets.Add(gotoCmd.labelTargets[i]); newLabels.Add(gotoCmd.labelNames[i]); } newTargets.Add(block1); newLabels.Add(block1.Label); gotoCmd.labelNames = newLabels; gotoCmd.labelTargets = newTargets; blockMap[block1] = block2; } List<Block/*!*/>/*!*/ blocks = new List<Block/*!*/>(); Block exit = new Block(Token.NoToken, "exit", new List<Cmd>(), new ReturnCmd(Token.NoToken)); GotoCmd cmd = new GotoCmd(Token.NoToken, new List<String> { cce.NonNull(blockMap[header]).Label, exit.Label }, new List<Block> { blockMap[header], exit }); if (detLoopExtract) //cutting the non-determinism cmd = new GotoCmd(Token.NoToken, new List<String> { cce.NonNull(blockMap[header]).Label }, new List<Block> { blockMap[header] }); Block entry; List<Cmd> initCmds = new List<Cmd>(); if (loopHeaderToAssignCmd.ContainsKey(header)) { AssignCmd assignCmd = loopHeaderToAssignCmd[header]; initCmds.Add(assignCmd); } entry = new Block(Token.NoToken, "entry", initCmds, cmd); blocks.Add(entry); foreach (Block/*!*/ block in blockMap.Keys) { Contract.Assert(block != null); Block/*!*/ newBlock = cce.NonNull(blockMap[block]); GotoCmd gotoCmd = block.TransferCmd as GotoCmd; if (gotoCmd == null) { newBlock.TransferCmd = new ReturnCmd(Token.NoToken); } else { Contract.Assume(gotoCmd.labelNames != null && gotoCmd.labelTargets != null); List<String> newLabels = new List<String>(); List<Block> newTargets = new List<Block>(); for (int i = 0; i < gotoCmd.labelTargets.Count; i++) { Block target = gotoCmd.labelTargets[i]; if (blockMap.ContainsKey(target)) { newLabels.Add(gotoCmd.labelNames[i]); newTargets.Add(blockMap[target]); } } if (newTargets.Count == 0) { if (!detLoopExtract) newBlock.Cmds.Add(new AssumeCmd(Token.NoToken, Expr.False)); newBlock.TransferCmd = new ReturnCmd(Token.NoToken); } else { newBlock.TransferCmd = new GotoCmd(Token.NoToken, newLabels, newTargets); } } blocks.Add(newBlock); } blocks.Add(exit); Implementation loopImpl = new Implementation(Token.NoToken, loopProc.Name, new List<TypeVariable>(), inputs, outputs, new List<Variable>(), blocks); loopImpl.Proc = loopProc; loopImpls.Add(loopImpl); // Make a (shallow) copy of the header before splitting it Block origHeader = new Block(header.tok, header.Label, header.Cmds, header.TransferCmd); // Finally, add call to the loop in the containing procedure string lastIterBlockName = header.Label + "_last"; Block lastIterBlock = new Block(Token.NoToken, lastIterBlockName, header.Cmds, header.TransferCmd); newBlocksCreated[header] = lastIterBlock; header.Cmds = new List<Cmd> { loopHeaderToCallCmd1[header] }; header.TransferCmd = new GotoCmd(Token.NoToken, new List<String> { lastIterBlockName }, new List<Block> { lastIterBlock }); impl.Blocks.Add(lastIterBlock); blockMap[origHeader] = blockMap[header]; blockMap.Remove(header); Contract.Assert(fullMap[impl.Name][header.Label] == header); fullMap[impl.Name][header.Label] = origHeader; foreach (Block block in blockMap.Keys) { // Don't add dummy blocks to the map if (dummyBlocks.Contains(blockMap[block].Label)) continue; // Following two statements are for nested loops: compose map if (!fullMap[impl.Name].ContainsKey(block.Label)) continue; var target = fullMap[impl.Name][block.Label]; AddToFullMap(fullMap, loopProc.Name, blockMap[block].Label, target); } fullMap[impl.Name].Remove(header.Label); fullMap[impl.Name][lastIterBlockName] = origHeader; } }
public override Expr VisitLambdaExpr(LambdaExpr lambda) { var baseResult = base.VisitLambdaExpr(lambda); lambda = baseResult as LambdaExpr; if (lambda == null) { return baseResult; // apparently, the base visitor already turned the lambda into something else } // We start by getting rid of any use of "old" inside the lambda. This is done as follows. // For each variable "g" occurring inside lambda as "old(... g ...)", create a new name "og". // Replace each old occurrence of "g" with "og", removing the enclosing "old" wrappers. var oldFinder = new OldFinder(); oldFinder.Visit(lambda); var oldSubst = new Dictionary<Variable, Expr>(); // g -> g0 var callOldMapping = new Dictionary<Variable, Expr>(); // g0 -> old(g) foreach (var v in oldFinder.FreeOldVars) { var g = v as GlobalVariable; if (g != null) { var g0 = new GlobalVariable(g.tok, new TypedIdent(g.tok, g.TypedIdent.Name + "@old", g.TypedIdent.Type)); oldSubst.Add(g, new IdentifierExpr(g0.tok, g0)); callOldMapping.Add(g0, new OldExpr(g0.tok, new IdentifierExpr(g.tok, g))); } } var lambdaBody = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromHashtable(new Dictionary<Variable,Expr>()), Substituter.SubstitutionFromHashtable(oldSubst), lambda.Body); var lambdaAttrs = Substituter.ApplyReplacingOldExprs( Substituter.SubstitutionFromHashtable(new Dictionary<Variable, Expr>()), Substituter.SubstitutionFromHashtable(oldSubst), lambda.Attributes); if (0 < CommandLineOptions.Clo.VerifySnapshots && QKeyValue.FindStringAttribute(lambdaAttrs, "checksum") == null) { // Attach a dummy checksum to avoid issues in the dependency analysis. var checksumAttr = new QKeyValue(lambda.tok, "checksum", new List<object> { "lambda expression" }, null); if (lambdaAttrs == null) { lambdaAttrs = checksumAttr; } else { lambdaAttrs.AddLast(checksumAttr); } } // this is ugly, the output will depend on hashing order var subst = new Dictionary<Variable, Expr>(); var substFnAttrs = new Dictionary<Variable, Expr>(); var formals = new List<Variable>(); var callArgs = new List<Expr>(); var axCallArgs = new List<Expr>(); var dummies = new List<Variable>(lambda.Dummies); var freeTypeVars = new List<TypeVariable>(); var fnTypeVarActuals = new List<Type/*!*/>(); var freshTypeVars = new List<TypeVariable>(); // these are only used in the lambda@n function's definition // compute the free variables of the lambda expression, but with lambdaBody instead of lambda.Body Set freeVars = new Set(); BinderExpr.ComputeBinderFreeVariables(lambda.TypeParameters, lambda.Dummies, lambdaBody, lambdaAttrs, freeVars); foreach (object o in freeVars) { // 'o' is either a Variable or a TypeVariable. if (o is Variable) { var v = o as Variable; var ti = new TypedIdent(v.TypedIdent.tok, v.TypedIdent.Name, v.TypedIdent.Type); var f = new Formal(v.tok, ti, true); formals.Add(f); substFnAttrs.Add(v, new IdentifierExpr(f.tok, f)); var b = new BoundVariable(v.tok, ti); dummies.Add(b); if (callOldMapping.ContainsKey(v)) { callArgs.Add(callOldMapping[v]); } else { callArgs.Add(new IdentifierExpr(v.tok, v)); } Expr id = new IdentifierExpr(b.tok, b); subst.Add(v, id); axCallArgs.Add(id); } else { var tv = (TypeVariable)o; freeTypeVars.Add(tv); fnTypeVarActuals.Add(tv); freshTypeVars.Add(new TypeVariable(tv.tok, tv.Name)); } } var sw = new System.IO.StringWriter(); var wr = new TokenTextWriter(sw, true); lambda.Emit(wr); string lam_str = sw.ToString(); FunctionCall fcall; IToken tok = lambda.tok; Formal res = new Formal(tok, new TypedIdent(tok, TypedIdent.NoName, cce.NonNull(lambda.Type)), false); if (liftedLambdas.TryGetValue(lambda, out fcall)) { if (CommandLineOptions.Clo.TraceVerify) { Console.WriteLine("Old lambda: {0}", lam_str); } } else { if (CommandLineOptions.Clo.TraceVerify) { Console.WriteLine("New lambda: {0}", lam_str); } Function fn = new Function(tok, FreshLambdaFunctionName(), freshTypeVars, formals, res, "auto-generated lambda function", Substituter.Apply(Substituter.SubstitutionFromHashtable(substFnAttrs), lambdaAttrs)); fn.OriginalLambdaExprAsString = lam_str; fcall = new FunctionCall(new IdentifierExpr(tok, fn.Name)); fcall.Func = fn; // resolve here liftedLambdas[lambda] = fcall; List<Expr/*!*/> selectArgs = new List<Expr/*!*/>(); foreach (Variable/*!*/ v in lambda.Dummies) { Contract.Assert(v != null); selectArgs.Add(new IdentifierExpr(v.tok, v)); } NAryExpr axcall = new NAryExpr(tok, fcall, axCallArgs); axcall.Type = res.TypedIdent.Type; axcall.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); NAryExpr select = Expr.Select(axcall, selectArgs); select.Type = lambdaBody.Type; List<Type/*!*/> selectTypeParamActuals = new List<Type/*!*/>(); List<TypeVariable> forallTypeVariables = new List<TypeVariable>(); foreach (TypeVariable/*!*/ tp in lambda.TypeParameters) { Contract.Assert(tp != null); selectTypeParamActuals.Add(tp); forallTypeVariables.Add(tp); } forallTypeVariables.AddRange(freeTypeVars); select.TypeParameters = SimpleTypeParamInstantiation.From(lambda.TypeParameters, selectTypeParamActuals); Expr bb = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaBody); NAryExpr body = Expr.Eq(select, bb); body.Type = Type.Bool; body.TypeParameters = SimpleTypeParamInstantiation.EMPTY; Trigger trig = new Trigger(select.tok, true, new List<Expr> { select }); lambdaFunctions.Add(fn); lambdaAxioms.Add(new ForallExpr(tok, forallTypeVariables, dummies, Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambdaAttrs), trig, body)); } NAryExpr call = new NAryExpr(tok, fcall, callArgs); call.Type = res.TypedIdent.Type; call.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); return call; }
public override Absy Visit(Absy node) { //Contract.Requires(node != null); Contract.Ensures(Contract.Result<Absy>() != null); node = base.Visit(node); LambdaExpr lambda = node as LambdaExpr; if (lambda != null) { IToken/*!*/ tok = lambda.tok; Contract.Assert(tok != null); Set freeVars = new Set(); lambda.ComputeFreeVariables(freeVars); // this is ugly, the output will depend on hashing order Dictionary<Variable, Expr> subst = new Dictionary<Variable, Expr>(); List<Variable> formals = new List<Variable>(); List<Expr> callArgs = new List<Expr>(); List<Expr> axCallArgs = new List<Expr>(); List<Variable> dummies = new List<Variable>(lambda.Dummies); List<TypeVariable> freeTypeVars = new List<TypeVariable>(); List<Type/*!*/> fnTypeVarActuals = new List<Type/*!*/>(); List<TypeVariable> freshTypeVars = new List<TypeVariable>(); // these are only used in the lambda@n function's definition foreach (object o in freeVars) { // 'o' is either a Variable or a TypeVariable. Since the lambda desugaring happens only // at the outermost level of a program (where there are no mutable variables) and, for // procedure bodies, after the statements have been passified (when mutable variables have // been replaced by immutable incarnations), we are interested only in BoundVar's and // TypeVariable's. BoundVariable v = o as BoundVariable; if (v != null) { TypedIdent ti = new TypedIdent(v.TypedIdent.tok, v.TypedIdent.Name, v.TypedIdent.Type); Formal f = new Formal(v.tok, ti, true); formals.Add(f); BoundVariable b = new BoundVariable(v.tok, ti); dummies.Add(b); callArgs.Add(new IdentifierExpr(v.tok, v)); Expr/*!*/ id = new IdentifierExpr(f.tok, b); Contract.Assert(id != null); subst.Add(v, id); axCallArgs.Add(id); } else if (o is TypeVariable) { TypeVariable tv = (TypeVariable)o; freeTypeVars.Add(tv); fnTypeVarActuals.Add(tv); freshTypeVars.Add(new TypeVariable(tv.tok, tv.Name)); } } Formal res = new Formal(tok, new TypedIdent(tok, TypedIdent.NoName, cce.NonNull(lambda.Type)), false); Function fn = new Function(tok, "lambda@" + lambdaid++, freshTypeVars, formals, res, "auto-generated lambda function", lambda.Attributes); lambdaFunctions.Add(fn); FunctionCall fcall = new FunctionCall(new IdentifierExpr(tok, fn.Name)); fcall.Func = fn; // resolve here List<Expr/*!*/> selectArgs = new List<Expr/*!*/>(); foreach (Variable/*!*/ v in lambda.Dummies) { Contract.Assert(v != null); selectArgs.Add(new IdentifierExpr(v.tok, v)); } NAryExpr axcall = new NAryExpr(tok, fcall, axCallArgs); axcall.Type = res.TypedIdent.Type; axcall.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); NAryExpr select = Expr.Select(axcall, selectArgs); select.Type = lambda.Body.Type; List<Type/*!*/> selectTypeParamActuals = new List<Type/*!*/>(); List<TypeVariable> forallTypeVariables = new List<TypeVariable>(); foreach (TypeVariable/*!*/ tp in lambda.TypeParameters) { Contract.Assert(tp != null); selectTypeParamActuals.Add(tp); forallTypeVariables.Add(tp); } forallTypeVariables.AddRange(freeTypeVars); select.TypeParameters = SimpleTypeParamInstantiation.From(lambda.TypeParameters, selectTypeParamActuals); Expr bb = Substituter.Apply(Substituter.SubstitutionFromHashtable(subst), lambda.Body); NAryExpr body = Expr.Eq(select, bb); body.Type = Type.Bool; body.TypeParameters = SimpleTypeParamInstantiation.EMPTY; Trigger trig = new Trigger(select.tok, true, new List<Expr> { select }); lambdaAxioms.Add(new ForallExpr(tok, forallTypeVariables, dummies, lambda.Attributes, trig, body)); NAryExpr call = new NAryExpr(tok, fcall, callArgs); call.Type = res.TypedIdent.Type; call.TypeParameters = SimpleTypeParamInstantiation.From(freeTypeVars, fnTypeVarActuals); return call; } return node; }