public override Expression VisitMethodCall(MethodCall call) { MemberBinding mb = call.Callee as MemberBinding; if (mb == null) { return(call); } Method calledMethod = mb.BoundMember as Method; if (calledMethod == null) { return(call); } Method template = calledMethod.Template; if (contractNodes.IsOldMethod(template)) { OldExpression oe = new OldExpression(ExtractOldExpression(call)); oe.Type = call.Type; return(oe); } if (contractNodes.IsValueAtReturnMethod(template)) { return(new AddressDereference(call.Operands[0], calledMethod.TemplateArguments[0], call.SourceContext)); } if (contractNodes.IsResultMethod(template)) { // check if we are in an Task returning method if (this.declaringMethod != null && this.declaringMethod.ReturnType != null) { var rt = this.declaringMethod.ReturnType; var templ = rt.Template; if (templ != null && templ.Name.Name == "Task`1" && rt.TemplateArguments != null && rt.TemplateArguments.Count == 1) { var targ = rt.TemplateArguments[0]; if (calledMethod.TemplateArguments[0] == targ) { // use of ReturnValue<T>() instead of ReturnValue<Task<T>>().Result var retExp = new ReturnValue(rt, call.SourceContext); var resultProp = rt.GetProperty(Identifier.For("Result")); if (resultProp != null && resultProp.Getter != null) { return(new MethodCall(new MemberBinding(retExp, resultProp.Getter), new ExpressionList())); } } } } return(new ReturnValue(calledMethod.ReturnType, call.SourceContext)); } return(base.VisitMethodCall(call)); }
/// <summary> /// Performs a bunch of transformations that the basic Extractor doesn't seem to do: /// - Turns calls to Old contract method into OldExpressions /// - Turns references to "result" into ResultExpressions /// - /// </summary> public override Expression VisitMethodCall(MethodCall call) { MemberBinding mb = call.Callee as MemberBinding; if (mb == null) { return(call); } Method calledMethod = mb.BoundMember as Method; if (calledMethod == null) { return(call); } Method template = calledMethod.Template; if (contractNodes.IsOldMethod(template)) { Expression result = base.VisitMethodCall(call); call = result as MethodCall; if (call == null) { return(result); } result = new OldExpression(call.Operands[0]); result.Type = call.Type; return(result); } if (contractNodes.IsValueAtReturnMethod(template)) { return(new AddressDereference(call.Operands[0], calledMethod.TemplateArguments[0], call.SourceContext)); } if (calledMethod.Parameters != null) { if (calledMethod.Parameters.Count == 0) { if (contractNodes.IsResultMethod(template)) { return(new ReturnValue(calledMethod.ReturnType, call.SourceContext)); } } else if (insideInvariant && contractNodes.IsInvariantMethod(calledMethod)) { Expression condition = call.Operands[0]; condition.SourceContext = call.SourceContext; return(VisitExpression(condition)); } } return(base.VisitMethodCall(call)); }
private Local GetLocalForOldExpression(OldExpression oldExpression) { Contract.Requires(oldExpression != null); string localName = BestGuessForLocalName(oldExpression); return(new Local(Identifier.For("Contract.Old(" + localName + ")"), oldExpression.Type)); }
public override Expression VisitParameter(Parameter parameter) { if (parameter == null) return null; var oe = new OldExpression(parameter); oe.Type = parameter.Type; return oe; }
public override Expression VisitOldExpression(OldExpression oldExpression) { //Debug.Assert(false, "old was not substituted"); TypeNode returnType = oldExpression.Type; if (returnType.IsValueType) return new Literal(0, returnType); return new Literal(null, returnType); }
public override Expression VisitOldExpression(OldExpression oldExpression) { //Debug.Assert(false, "old was not substituted"); TypeNode returnType = oldExpression.Type; if (returnType.IsValueType) { return(new Literal(0, returnType)); } return(new Literal(null, returnType)); }
public override Expression VisitMethodCall(MethodCall call) { MemberBinding mb = call.Callee as MemberBinding; if (mb == null) return call; Method calledMethod = mb.BoundMember as Method; if (calledMethod == null) return call; Method template = calledMethod.Template; if (contractNodes.IsOldMethod(template)) { OldExpression oe = new OldExpression(ExtractOldExpression(call)); oe.Type = call.Type; return oe; } if (contractNodes.IsValueAtReturnMethod(template)) { return new AddressDereference(call.Operands[0], calledMethod.TemplateArguments[0], call.SourceContext); } if (contractNodes.IsResultMethod(template)) { // check if we are in an Task returning method if (this.declaringMethod != null && this.declaringMethod.ReturnType != null) { var rt = this.declaringMethod.ReturnType; var templ = rt.Template; if (templ != null && templ.Name.Name == "Task`1" && rt.TemplateArguments != null && rt.TemplateArguments.Count == 1) { var targ = rt.TemplateArguments[0]; if (calledMethod.TemplateArguments[0] == targ) { // use of ReturnValue<T>() instead of ReturnValue<Task<T>>().Result var retExp = new ReturnValue(rt, call.SourceContext); var resultProp = rt.GetProperty(Identifier.For("Result")); if (resultProp != null && resultProp.Getter != null) { return new MethodCall(new MemberBinding(retExp, resultProp.Getter), new ExpressionList()); } } } } return new ReturnValue(calledMethod.ReturnType, call.SourceContext); } return base.VisitMethodCall(call); }
public override Expression VisitParameter(Parameter parameter) { if (parameter == null) { return(null); } var oe = new OldExpression(parameter); oe.Type = parameter.Type; return(oe); }
/// <summary> /// Checks for errors before applying a rule. /// </summary> /// <param name="node">The node instance to check.</param> /// <param name="dataList">Optional data collected during inspection of sources.</param> /// <param name="data">Private data to give to Apply() upon return.</param> /// <returns>True if an error occured.</returns> public override bool CheckConsistency(IOldExpression node, IDictionary <ISourceTemplate, object> dataList, out object data) { data = null; bool Success = true; Success &= OldExpression.ResolveCompilerReferences(node, ErrorList, out ResolvedExpression ResolvedExpression); if (Success) { data = ResolvedExpression; } return(Success); }
public override Expression VisitOldExpression(OldExpression oldExpression) { if (oldExpression == null || oldExpression.expression == null) { return(null); } if (this._string == null) { this._string = new StringBuilder(); } this._string.Append("\\old("); this.VisitExpression(oldExpression.expression); this._string.Append(")"); return(oldExpression); }
private string BestGuessForLocalName(OldExpression oldExpression) { Contract.Requires(oldExpression != null); MemberBinding mb = oldExpression.expression as MemberBinding; if (mb != null) { return(mb.BoundMember.Name.Name); } MethodCall mc = oldExpression.expression as MethodCall; if (mc != null) { mb = mc.Callee as MemberBinding; if (mb != null) { Method calledMethod = mb.BoundMember as Method; if (calledMethod != null && calledMethod.IsPropertyGetter) { Property prop = calledMethod.DeclaringMember as Property; if (prop != null) { return(prop.Name.Name); } return(mb.BoundMember.Name.Name); } return(mb.BoundMember.Name.Name); } } Parameter p = oldExpression.expression as Parameter; if (p != null) { return(p.Name.Name); } // Didn't find something good to use for the name, so just make it unique. var x = this.counter.ToString(); this.counter++; return(x); }
private string BestGuessForLocalName(OldExpression oldExpression) { Contract.Requires(oldExpression != null); MemberBinding mb = oldExpression.expression as MemberBinding; if (mb != null) { return mb.BoundMember.Name.Name; } MethodCall mc = oldExpression.expression as MethodCall; if (mc != null) { mb = mc.Callee as MemberBinding; if (mb != null) { Method calledMethod = mb.BoundMember as Method; if (calledMethod != null && calledMethod.IsPropertyGetter) { Property prop = calledMethod.DeclaringMember as Property; if (prop != null) return prop.Name.Name; else return mb.BoundMember.Name.Name; } else { return mb.BoundMember.Name.Name; } } } Parameter p = oldExpression.expression as Parameter; if (p != null) { return p.Name.Name; } // Didn't find something good to use for the name, so just make it unique. var x = this.counter.ToString(); this.counter++; return x; }
public override Expression VisitOldExpression(OldExpression oldExpression) { // no point descending down into any old expressions return oldExpression; }
public override Expression VisitOldExpression(OldExpression oldExpression) { if (this.topLevelClosureClass != null) { #region In Closure ==> Create a field // Since we're within a closure, we can't create a local to hold the value of the old expression // but instead have to create a field for it. That field can be a member of the top-level // closure class since nothing mentioned in the old expression (except possibly for the // bound variables of enclosing quantifications) should be anything captured from // an inner anonymous delegate. // BUT, first we have to know if the old expression depends on any of the bound // variables of the closures in which it is located. If not, then we can implement // it as a scalar and just generate the assignment "closure_class.field := e" for // "Old(e)" to take a snapshot of e's value in the prestate. If it does depend on // any of the bound variables, then we need to generate a set of for-loops that // compute the indices and values of e for each tuple of indices so it can be retrieved // (given the indices) in the post-state. CollectBoundVariables cbv = new CollectBoundVariables(this.stackOfBoundVariables); cbv.VisitExpression(oldExpression.expression); SubstituteClosureClassWithinOldExpressions subst = new SubstituteClosureClassWithinOldExpressions(this.closureLocals); Expression e = subst.VisitExpression(oldExpression.expression); if (cbv.FoundVariables.Count == 0) { #region Use a scalar for the old variable Local closureLocal; if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal)) { Contract.Assume(false, "can't find closure local!"); } #region Define a scalar var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass); Field f = new Field(clTemplate, null, FieldFlags.CompilerControlled | FieldFlags.Public, Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr. oldExpression.Type, null); clTemplate.Members.Add(f); // now produce properly instantiated field f = (Field)Rewriter.GetMemberInstanceReference(f, this.topLevelClosureClass); #endregion #region Generate code to store value in prestate this.prestateValuesOfOldExpressions.Statements.Add(new AssignmentStatement(new MemberBinding(closureLocal, f), e)); #endregion #region Return expression to be used in poststate // Return an expression that will evaluate in the poststate to the value of the old // expression in the prestate. This will be this.up.f where "up" is the field C# // generated to point to the instance of the top-level closure class. if (this.PointerToTopLevelClosureClass == null) { // then the old expression occurs in the top-level closure class. Just return "this.f" // where "this" refers to the top-level closure class. return new MemberBinding(new This(this.currentClosureClass), f); } else { return new MemberBinding( new MemberBinding(new This(this.currentClosureClass), this.PointerToTopLevelClosureClass), f); } #endregion #endregion } else { // the Old expression *does* depend upon at least one of the bound variable // in a ForAll or Exists expression #region Use an indexed variable for the old variable TypeNode oldVariableTypeDomain; #region Decide if domain is one-dimensional or not bool oneDimensional = cbv.FoundVariables.Count == 1 && cbv.FoundVariables[0].Type.IsValueType; if (oneDimensional) { // a one-dimensional old-expression can use the index variable directly oldVariableTypeDomain = cbv.FoundVariables[0].Type; } else { oldVariableTypeDomain = SystemTypes.GenericList.GetTemplateInstance(this.module, SystemTypes.Int32); } #endregion TypeNode oldVariableTypeRange = oldExpression.Type; TypeNode oldVariableType = SystemTypes.GenericDictionary.GetTemplateInstance(this.module, oldVariableTypeDomain, oldVariableTypeRange); Local closureLocal; if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal)) { Contract.Assume(false, "can't find closure local"); } #region Define an indexed variable var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass); Field f = new Field(clTemplate, null, FieldFlags.CompilerControlled | FieldFlags.Assembly, // can't be private or protected because it needs to be accessed from inner (closure) classes that don't inherit from the class this field is added to. Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr. oldVariableType, null); clTemplate.Members.Add(f); // instantiate f f = (Field)Rewriter.GetMemberInstanceReference(f, closureLocal.Type); #endregion #region Generate code to initialize the indexed variable Statement init = new AssignmentStatement( new MemberBinding(closureLocal, f), new Construct(new MemberBinding(null, oldVariableType.GetConstructor()), null)); this.prestateValuesOfOldExpressions.Statements.Add(init); #endregion #region Generate code to store values in prestate #region Create assignment: this.closure.f[i,j,k,...] = e; Method setItem = oldVariableType.GetMethod(Identifier.For("set_Item"), oldVariableTypeDomain, oldVariableTypeRange); Expression index; if (oneDimensional) { index = cbv.FoundVariables[0]; } else { //InstanceInitializer ctor = // ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1)); //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList( index = Literal.Null; } MethodCall mc = new MethodCall(new MemberBinding(new MemberBinding(closureLocal, f), setItem), new ExpressionList(index, e)); Statement stat = new ExpressionStatement(mc); #endregion List<Local> locals = new List<Local>(this.stackOfBoundVariables.Count); TrivialHashtable paramMap = new TrivialHashtable(); #region Generate a local for each bound variable to use in for-loop foreach (Variable v in this.stackOfBoundVariables) { Local l = new Local(Identifier.Empty, v.Type); paramMap[v.UniqueKey] = l; locals.Add(l); } #endregion #region Substitute locals for bound variables in old expression *AND* in inner loop bounds SubstituteParameters sps = new SubstituteParameters(paramMap, this.stackOfBoundVariables); sps.Visit(stat); #endregion #region Create nested for-loops around assignment // keep track of when the first variable is used (from innermost to outermost) // as soon as the first one is needed because the old expression depends on it, // then keep all enclosing loops. It would be possible to keep only those where // the necessary loops have loop bounds that depend on an enclosing loop, but I // haven't calculated that, so just keep them all. For instance, if the old expression // depends on j and the loops are "for i,0,n" and inside that "for j,0,i", then need // both loops. If the inner loop bounds were 0 and n, then wouldn't need the outer // loop. bool usedAVariable = false; for (int i = this.stackOfBoundVariables.Count - 1; 0 <= i; i--) { if (!usedAVariable && !cbv.FoundVariables.Contains(this.stackOfBoundVariables[i])) continue; usedAVariable = true; Expression lowerBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression( this.stackOfMethods[i].Operands[0]); lowerBound = subst.VisitExpression(lowerBound); lowerBound = sps.VisitExpression(lowerBound); Expression upperBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression( this.stackOfMethods[i].Operands[1]); upperBound = subst.VisitExpression(upperBound); upperBound = sps.VisitExpression(upperBound); stat = RewriteHelper.GenerateForLoop(locals[i], lowerBound, upperBound, stat); } #endregion this.prestateValuesOfOldExpressions.Statements.Add(stat); #endregion #region Return expression to be used in poststate Method getItem = oldVariableType.GetMethod(Identifier.For("get_Item"), oldVariableTypeDomain); if (oneDimensional) { index = cbv.FoundReferences[0]; } else { //InstanceInitializer ctor = // ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1)); //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList( index = Literal.Null; } // Return an expression that will evaluate in the poststate to the value of the old // expression in the prestate. This will be this.up.f[i,j,k,...] where "up" is the field C# // generated to point to the instance of the top-level closure class. MemberBinding thisDotF; if (this.PointerToTopLevelClosureClass == null) { // then the old expression occurs in the top-level closure class. Just return "this.f" // where "this" refers to the top-level closure class. Contract.Assume(f != null); thisDotF = new MemberBinding(new This(clTemplate), HelperMethods.Unspecialize(f)); } else { thisDotF = new MemberBinding( new MemberBinding(new This(clTemplate), this.PointerToTopLevelClosureClass), f); } return new MethodCall(new MemberBinding(thisDotF, getItem), new ExpressionList(index)); #endregion #endregion } #endregion } else { #region Not in closure ==> Create a local variable Local l = GetLocalForOldExpression(oldExpression); #region Make sure local can be seen in the debugger (for the entire method, unfortunately) if (currentMethod.LocalList == null) { currentMethod.LocalList = new LocalList(); } currentMethod.LocalList.Add(l); currentMethod.Body.HasLocals = true; #endregion this.prestateValuesOfOldExpressions.Statements.Add( new AssignmentStatement(l, oldExpression.expression)); // Return an expression that will evaluate in the poststate to the value of the old // expression in the prestate. When we're not in a closure, this is just the local // itself. return l; #endregion } }
public EventingVisitor(Action<OldExpression> visitOldExpression) { VisitedOldExpression += visitOldExpression; } public event Action<OldExpression> VisitedOldExpression; public override Expression VisitOldExpression(OldExpression oldExpression) { if (VisitedOldExpression != null) VisitedOldExpression(oldExpression); return base.VisitOldExpression(oldExpression); }
public virtual void VisitOldExpression(OldExpression oldExpression) { if (oldExpression == null) return; this.VisitExpression(oldExpression.expression); }
private static string oldExpression2str(OldExpression oe) { StringBuilder sb = new StringBuilder(); sb.Append(oldExpression2str(oe.NodeType)); sb.Append("("); sb.Append(expression2str(oe.expression)); sb.Append(")"); return sb.ToString(); }
public override Expression VisitOldExpression(OldExpression oldExpression) { if (this.topLevelClosureClass != null) { // In Closure ==> Create a field // Since we're within a closure, we can't create a local to hold the value of the old expression // but instead have to create a field for it. That field can be a member of the top-level // closure class since nothing mentioned in the old expression (except possibly for the // bound variables of enclosing quantifications) should be anything captured from // an inner anonymous delegate. // BUT, first we have to know if the old expression depends on any of the bound // variables of the closures in which it is located. If not, then we can implement // it as a scalar and just generate the assignment "closure_class.field := e" for // "Old(e)" to take a snapshot of e's value in the prestate. If it does depend on // any of the bound variables, then we need to generate a set of for-loops that // compute the indices and values of e for each tuple of indices so it can be retrieved // (given the indices) in the post-state. CollectBoundVariables cbv = new CollectBoundVariables(this.stackOfBoundVariables); cbv.VisitExpression(oldExpression.expression); SubstituteClosureClassWithinOldExpressions subst = new SubstituteClosureClassWithinOldExpressions(this.closureLocals); Expression e = subst.VisitExpression(oldExpression.expression); if (cbv.FoundVariables.Count == 0) { // Use a scalar for the old variable Local closureLocal; if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal)) { Contract.Assume(false, "can't find closure local!"); } // Define a scalar var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass); Field f = new Field(clTemplate, null, FieldFlags.CompilerControlled | FieldFlags.Public, Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr. oldExpression.Type, null); clTemplate.Members.Add(f); // now produce properly instantiated field f = (Field)Rewriter.GetMemberInstanceReference(f, this.topLevelClosureClass); // Generate code to store value in prestate this.prestateValuesOfOldExpressions.Statements.Add( new AssignmentStatement(new MemberBinding(closureLocal, f), e)); // Return expression to be used in poststate // Return an expression that will evaluate in the poststate to the value of the old // expression in the prestate. This will be this.up.f where "up" is the field C# // generated to point to the instance of the top-level closure class. if (this.PointerToTopLevelClosureClass == null) { // then the old expression occurs in the top-level closure class. Just return "this.f" // where "this" refers to the top-level closure class. return(new MemberBinding(new This(this.currentClosureClass), f)); } else { return(new MemberBinding( new MemberBinding(new This(this.currentClosureClass), this.PointerToTopLevelClosureClass), f)); } } else { // the Old expression *does* depend upon at least one of the bound variable // in a ForAll or Exists expression // Use an indexed variable for the old variable TypeNode oldVariableTypeDomain; // Decide if domain is one-dimensional or not bool oneDimensional = cbv.FoundVariables.Count == 1 && cbv.FoundVariables[0].Type.IsValueType; if (oneDimensional) { // a one-dimensional old-expression can use the index variable directly oldVariableTypeDomain = cbv.FoundVariables[0].Type; } else { oldVariableTypeDomain = SystemTypes.GenericList.GetTemplateInstance(this.module, SystemTypes.Int32); } TypeNode oldVariableTypeRange = oldExpression.Type; TypeNode oldVariableType = SystemTypes.GenericDictionary.GetTemplateInstance(this.module, oldVariableTypeDomain, oldVariableTypeRange); Local closureLocal; if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal)) { Contract.Assume(false, "can't find closure local"); } // Define an indexed variable var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass); Field f = new Field(clTemplate, null, FieldFlags.CompilerControlled | FieldFlags.Assembly, // can't be private or protected because it needs to be accessed from inner (closure) classes that don't inherit from the class this field is added to. Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr. oldVariableType, null); clTemplate.Members.Add(f); // instantiate f f = (Field)Rewriter.GetMemberInstanceReference(f, closureLocal.Type); // Generate code to initialize the indexed variable Statement init = new AssignmentStatement( new MemberBinding(closureLocal, f), new Construct(new MemberBinding(null, oldVariableType.GetConstructor()), null)); this.prestateValuesOfOldExpressions.Statements.Add(init); // Generate code to store values in prestate // Create assignment: this.closure.f[i,j,k,...] = e; Method setItem = oldVariableType.GetMethod(Identifier.For("set_Item"), oldVariableTypeDomain, oldVariableTypeRange); Expression index; if (oneDimensional) { index = cbv.FoundVariables[0]; } else { //InstanceInitializer ctor = // ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1)); //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList( index = Literal.Null; } MethodCall mc = new MethodCall(new MemberBinding(new MemberBinding(closureLocal, f), setItem), new ExpressionList(index, e)); Statement stat = new ExpressionStatement(mc); List <Local> locals = new List <Local>(this.stackOfBoundVariables.Count); TrivialHashtable paramMap = new TrivialHashtable(); // Generate a local for each bound variable to use in for-loop foreach (Variable v in this.stackOfBoundVariables) { Local l = new Local(Identifier.Empty, v.Type); paramMap[v.UniqueKey] = l; locals.Add(l); } // Substitute locals for bound variables in old expression *AND* in inner loop bounds SubstituteParameters sps = new SubstituteParameters(paramMap, this.stackOfBoundVariables); sps.Visit(stat); // Create nested for-loops around assignment // keep track of when the first variable is used (from innermost to outermost) // as soon as the first one is needed because the old expression depends on it, // then keep all enclosing loops. It would be possible to keep only those where // the necessary loops have loop bounds that depend on an enclosing loop, but I // haven't calculated that, so just keep them all. For instance, if the old expression // depends on j and the loops are "for i,0,n" and inside that "for j,0,i", then need // both loops. If the inner loop bounds were 0 and n, then wouldn't need the outer // loop. bool usedAVariable = false; for (int i = this.stackOfBoundVariables.Count - 1; 0 <= i; i--) { if (!usedAVariable && !cbv.FoundVariables.Contains(this.stackOfBoundVariables[i])) { continue; } usedAVariable = true; Expression lowerBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression( this.stackOfMethods[i].Operands[0]); lowerBound = subst.VisitExpression(lowerBound); lowerBound = sps.VisitExpression(lowerBound); Expression upperBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression( this.stackOfMethods[i].Operands[1]); upperBound = subst.VisitExpression(upperBound); upperBound = sps.VisitExpression(upperBound); stat = RewriteHelper.GenerateForLoop(locals[i], lowerBound, upperBound, stat); } this.prestateValuesOfOldExpressions.Statements.Add(stat); // Return expression to be used in poststate Method getItem = oldVariableType.GetMethod(Identifier.For("get_Item"), oldVariableTypeDomain); if (oneDimensional) { index = cbv.FoundReferences[0]; } else { //InstanceInitializer ctor = // ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1)); //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList( index = Literal.Null; } // Return an expression that will evaluate in the poststate to the value of the old // expression in the prestate. This will be this.up.f[i,j,k,...] where "up" is the field C# // generated to point to the instance of the top-level closure class. MemberBinding thisDotF; if (this.PointerToTopLevelClosureClass == null) { // then the old expression occurs in the top-level closure class. Just return "this.f" // where "this" refers to the top-level closure class. Contract.Assume(f != null); thisDotF = new MemberBinding(new This(clTemplate), HelperMethods.Unspecialize(f)); } else { thisDotF = new MemberBinding( new MemberBinding(new This(clTemplate), this.PointerToTopLevelClosureClass), f); } return(new MethodCall(new MemberBinding(thisDotF, getItem), new ExpressionList(index))); } } else { // Not in closure ==> Create a local variable Local l = GetLocalForOldExpression(oldExpression); // Make sure local can be seen in the debugger (for the entire method, unfortunately) if (currentMethod.LocalList == null) { currentMethod.LocalList = new LocalList(); } currentMethod.LocalList.Add(l); currentMethod.Body.HasLocals = true; this.prestateValuesOfOldExpressions.Statements.Add(new AssignmentStatement(l, oldExpression.expression)); // Return an expression that will evaluate in the poststate to the value of the old // expression in the prestate. When we're not in a closure, this is just the local // itself. return(l); } }
private Local GetLocalForOldExpression(OldExpression oldExpression) { Contract.Requires(oldExpression != null); string localName = BestGuessForLocalName(oldExpression); return new Local(Identifier.For("Contract.Old(" + localName + ")"), oldExpression.Type); }
public override Expression VisitOldExpression(OldExpression old){ if (old == null) return null; old.expression = this.VisitExpression(old.expression); if (old.expression == null) return null; old.Type = old.expression.Type; return old; }
public override void VisitOldExpression(OldExpression oldExpression) { this.errorHandler(new Error(1023, "OldValue() can be used only in Ensures.", lastSC)); }
public override Expression VisitOldExpression(OldExpression oldExpression) { // no point descending down into any old expressions return(oldExpression); }
// TODO: allow arr[i][x][j], where i,j are quantified variables, and x is not // TODO: multidimensional array... public override Expression VisitIndexer(Indexer indexer) { //^ assert this.dependents.Contains(indexer) bool operandsDependentOnQuantifiedVar = false; foreach (Expression e1 in indexer.Operands) { if (this.dependents.ContainsKey(e1)) { operandsDependentOnQuantifiedVar = true; break; } } bool objectDependentOnQuantifiedVar = this.dependents.ContainsKey(indexer.Object); if (operandsDependentOnQuantifiedVar) { this.currentIndexLevel ++; Expression newArr = this.VisitExpression(indexer.Object); OldExpression olde = newArr as OldExpression; if (olde == null && !objectDependentOnQuantifiedVar) { // If this is an array expression that does not depend on any of the quantified vars // create an old expression olde = new OldExpression(newArr); } if (olde != null) { olde.ShallowCopyUptoDimension = this.currentIndexLevel; indexer.Object = olde; } else { indexer.Object = newArr; } this.currentIndexLevel --; indexer.Operands = this.VisitExpressionList(indexer.Operands); return indexer; } return base.VisitIndexer(indexer); }
private Expression ParseIndexerCallOrSelector(Expression expression, TokenSet followers){ TokenSet followersOrContinuers = followers|Token.LeftBracket|Token.LeftParenthesis|Token.Dot; for(;;){ switch (this.currentToken){ case Token.LeftBracket: SourceContext lbCtx = this.scanner.CurrentSourceContext; this.GetNextToken(); if (this.insideModifiesClause && this.currentToken == Token.Multiply){ // Handle code such as // // modifies myArray[*]; // // which means that the method may modify all elements of myArray. int savedStartPos = this.scanner.startPos; int savedEndPos = this.scanner.endPos; this.GetNextToken(); if (this.currentToken == Token.RightBracket){ SourceContext sctxt = this.scanner.CurrentSourceContext; sctxt.StartPos = lbCtx.StartPos; this.GetNextToken(); return new ModifiesArrayClause(expression, sctxt); } this.scanner.startPos = savedStartPos; this.scanner.endPos = savedEndPos; } int endCol; ExpressionList indices = this.ParseIndexList(followersOrContinuers, lbCtx, out endCol); Indexer indexer = new Indexer(expression, indices); indexer.SourceContext = expression.SourceContext; indexer.SourceContext.EndPos = endCol; indexer.ArgumentListIsIncomplete = this.scanner.GetChar(endCol-1) != ']'; expression = indexer; break; case Token.LessThan: SourceContext ltCtx = this.scanner.CurrentSourceContext; ScannerState ss = this.scanner.state; int arity; TypeNodeList typeArguments = this.ParseTypeArguments(true, false, followers|Token.LeftParenthesis, out endCol, out arity); if (typeArguments == null || (typeArguments.Count > 1 && Parser.TypeArgumentListNonFollower[this.currentToken])) { this.scanner.endPos = ltCtx.StartPos; this.scanner.state = ss; this.currentToken = Token.None; this.GetNextToken(); return expression; } TemplateInstance instance = new TemplateInstance(expression, typeArguments); instance.TypeArgumentExpressions = typeArguments == null ? null : typeArguments.Clone(); instance.SourceContext = expression.SourceContext; instance.SourceContext.EndPos = endCol; expression = instance; break; case Token.LeftParenthesis: SourceContext lpCtx = this.scanner.CurrentSourceContext; this.GetNextToken(); ExpressionList arguments = this.ParseArgumentList(followersOrContinuers, lpCtx, out endCol); if (expression == null) return null; if (expression is Identifier && arguments.Count == 1 && ((Identifier)expression).Name == "old" && InEnsuresContext){ OldExpression old = new OldExpression(arguments[0]); typeArguments = null; old.SourceContext = expression.SourceContext; old.SourceContext.EndPos = endCol; expression = old; break; } if (expression is TemplateInstance) ((TemplateInstance)expression).IsMethodTemplate = true; MethodCall mcall = new MethodCall(expression, arguments); typeArguments = null; mcall.GiveErrorIfSpecialNameMethod = true; mcall.SourceContext = expression.SourceContext; mcall.SourceContext.EndPos = endCol; mcall.ArgumentListIsIncomplete = this.scanner.GetChar(endCol-1) != ')'; expression = mcall; break; case Token.LeftBrace: if (this.compatibilityOn || this.scanner.TokenIsFirstAfterLineBreak) goto default; Expression quant = this.ParseComprehension(followers); if (quant == null) { break; } Block argBlock = new Block(new StatementList(new ExpressionStatement(quant)),quant.SourceContext, this.insideCheckedBlock, this.insideUncheckedBlock, this.inUnsafeCode); argBlock.IsUnsafe = this.inUnsafeCode; argBlock.SourceContext = quant.SourceContext; ExpressionList arguments2 = new ExpressionList(new AnonymousNestedFunction(new ParameterList(0), argBlock, quant.SourceContext)); MethodCall mcall2 = new MethodCall(expression, arguments2); typeArguments = null; mcall2.GiveErrorIfSpecialNameMethod = true; mcall2.SourceContext = expression.SourceContext; mcall2.SourceContext.EndPos = this.scanner.endPos; expression = mcall2; break; case Token.Dot: expression = this.ParseQualifiedIdentifier(expression, followersOrContinuers); break; case Token.RealLiteral: string tokStr = this.scanner.GetTokenSource(); if (this.insideModifiesClause && tokStr == ".0") { // this case is here only for parsing ".0" while parsing a modifies clause // e.g., "modifies this.0;" this.GetNextToken(); // eat the ".0" return new ModifiesNothingClause(expression, this.scanner.CurrentSourceContext); } else { return expression; } case Token.Arrow: if (!this.allowUnsafeCode){ this.HandleError(Error.IllegalUnsafe); this.allowUnsafeCode = true; } this.currentToken = Token.Dot; AddressDereference ad = new AddressDereference(); ad.Address = expression; ad.ExplicitOperator = AddressDereference.ExplicitOp.Arrow; ad.SourceContext = expression.SourceContext; expression = this.ParseQualifiedIdentifier(ad, followersOrContinuers); break; default: return expression; } } }
public override Expression VisitOldExpression(OldExpression oldExp) { Expression/*?*/ transformedExpression = oldExp; if (this.toplevelOldExpression == null) { this.toplevelOldExpression = oldExp; this.collectSubExpsDependentOnQuantifiedVars(oldExp); transformedExpression = this.markOldSubExps(oldExp); } if (transformedExpression != oldExp) { // if we are not at the toplevel, or the transformed top level is not the old expression, // which means the old operator has been pushed down using the distribution law. Expression result = this.VisitExpression(transformedExpression); if (this.toplevelOldExpression == oldExp) { // leave top level old expression this.toplevelOldExpression = null; this.subExpsDependentOnQuantifiedVars = null; } return result; } else { OldExpression oldExpression = transformedExpression as OldExpression; //^ assert oldExpression != null; TypeNode t = oldExpression.Type; Reference rt = t as Reference; Expression e = oldExpression.expression; if (rt != null) { e = new AddressDereference(e, rt.ElementType, e.SourceContext); } string oldName = e.SourceContext.SourceText != null && e.SourceContext.SourceText.Length > 0 ? "old(" + e.SourceContext.SourceText + ")" : "$SSold" + e.UniqueKey; Local l = new Local(Identifier.For(oldName), e.Type); #region Add local to method's local list so it gets the right debug scope // Since the scope of the "old" local is the entire method body, it suffices // to add it to the method's local list. Because of how that is processed in Writer, // that means the local's scope will be the entire method body. if (this.currentMethod.LocalList == null) { this.currentMethod.LocalList = new LocalList(); } this.currentMethod.LocalList.Add(l); #endregion // normalize the old expression itself e = this.VisitExpression(e); Statement a = this.initializeOldExp(l, e, oldExpression.ShallowCopyUptoDimension); this.currentContractPrelude.Statements.Add(a); this.currentContractPrelude.HasLocals = true; if (this.toplevelOldExpression == oldExpression) { this.toplevelOldExpression = null; this.subExpsDependentOnQuantifiedVars = null; } if (rt != null) return new UnaryExpression(l, NodeType.AddressOf, t, e.SourceContext); else return l; } }
void Factor(Expression target, out Expression e) { e = null; Member m; ExpressionList es; Expression p; Expression p1; Expression p2; TypeNode t1; /*Identifier blockVarId;*/ MemberBinding mb; switch (la.kind) { case 2: case 3: case 4: case 70: case 71: case 72: case 73: case 74: case 75: { Literal(out e); break; } case 27: case 30: case 55: { Local(out p); e = p; break; } case 1: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 25: case 26: case 28: case 35: { MemberRef(out m); Debug.Assert(m != null); e = new MemberBinding(target,m); if (la.kind == 49) { ArgExprs(out es); Method meth = (Method)m; if ( ! meth.IsVirtual){ e = new MethodCall(e, es, NodeType.Call); }else{ e = new MethodCall(e, es, NodeType.Callvirt); /*dangerous*/ } e.Type = meth.ReturnType; } break; } case 54: { BlockVar(out mb); Debug.Assert(target == null); e = mb; Debug.Assert(e != null); // block variable not found break; } case 5: { Get(); Expect(38); Expect(22); Expr(out e); OldExpression oe = new OldExpression(e); oe.Type = e.Type; e = oe; Expect(24); break; } case 22: { Get(); Expr(out e); Expect(24); break; } case 39: { Get(); Expect(22); Expr(out p); Expect(23); PType(out t1); Expect(24); e = new BinaryExpression(p,new Literal(t1,SystemTypes.Type),NodeType.ExplicitCoercion); e.Type = t1; break; } case 40: { Get(); Expect(22); Expr(out p); Expect(23); PType(out t1); Expect(24); e = new BinaryExpression(p,new Literal(t1,SystemTypes.Type),NodeType.Is); e.Type = SystemTypes.Boolean; break; } case 41: { Get(); Expect(22); Expr(out p); Expect(23); PType(out t1); Expect(24); e = new BinaryExpression(p,new Literal(t1,SystemTypes.Type),NodeType.Castclass); e.Type = t1; break; } case 42: { Get(); Expect(22); PType(out t1); Expect(24); e = new UnaryExpression(new Literal(t1, SystemTypes.Type), NodeType.Typeof, OptionalModifier.For(SystemTypes.NonNullType, SystemTypes.Type)); break; } case 43: { Get(); Expect(22); Expr(out p); Expect(23); Expr(out p1); Expect(23); Expr(out p2); Expect(23); PType(out t1); Expect(24); e = new TernaryExpression(p,p1,p2,NodeType.Conditional,t1); break; } case 44: { Get(); Expect(22); Expr(out p); Expect(23); PType(out t1); Expect(24); e = new BinaryExpression(p,new MemberBinding(null,t1),NodeType.Box); e.Type = SystemTypes.Object; break; } case 45: { Get(); Expect(22); Expr(out p); Expect(23); PType(out t1); Expect(24); e = new BinaryExpression(p,new MemberBinding(null,t1),NodeType.Unbox); e.Type = t1.GetReferenceType(); break; } case 46: { Get(); Expect(22); Expr(out p); Expect(24); e = new UnaryExpression(p, NodeType.RefAddress, p.Type); break; } case 57: case 58: case 59: case 60: case 61: case 62: case 63: case 64: { Quantifier(out e); break; } case 65: { TrueComprehension(out e); break; } case 47: { Get(); if (la.kind == 48 || la.kind == 51 || la.kind == 52) { if (la.kind == 48) { Get(); Expect(22); PType(out t1); Expect(24); Expect(49); Expr(out p); Expect(50); TypeNode newType = p.Type.GetReferenceType(); e = new UnaryExpression(p,NodeType.AddressOf,newType); } else if (la.kind == 51) { Get(); Expect(49); Expr(out p); Expect(50); Reference r = (Reference) p.Type; if (r != null) e = new AddressDereference(p,r.ElementType); else e = new AddressDereference(p, SystemTypes.UInt8); } else { TypeNode tt1 = null, tt2 = null, tt3 = null; Get(); Expect(22); PType(out tt1); Expect(23); PType(out tt2); Expect(24); Expect(49); Expr(out p); Expect(23); PType(out tt3); Expect(50); e = new BinaryExpression(p, new Literal(tt3, SystemTypes.Type), NodeType.Isinst); e.Type = tt3; } } else if (la.kind == 53) { TypeNode tt1 = null, tt2 = null, tt3 = null; Get(); Expect(22); PType(out tt1); Expect(23); PType(out tt2); Expect(24); Expect(49); Expr(out p); Expect(23); PType(out tt3); Expect(50); e = new BinaryExpression(p, new Literal(tt3, SystemTypes.Type), NodeType.Isinst); e.Type = tt3; } else if (StartOf(2)) { OperatorNode(out p); e = p; } else SynErr(111); break; } default: SynErr(112); break; } }
public virtual Expression VisitOldExpression(OldExpression oldExpression1, OldExpression oldExpression2) { if (oldExpression1 == null) return null; if (oldExpression2 == null) oldExpression1.expression = this.VisitExpression(oldExpression1.expression, null); else oldExpression1.expression = this.VisitExpression(oldExpression1.expression, oldExpression2.expression); return oldExpression1; }
public override Expression VisitOldExpression(OldExpression oldExpression) { if (oldExpression == null) return null; if (insidePureContract && insideEnsures) this.HandleError(oldExpression, Error.OldExprInPureEnsures); return base.VisitOldExpression(oldExpression); }
public override Expression VisitOldExpression(OldExpression oldExpression) { if (oldExpression == null) return null; return base.VisitOldExpression((OldExpression)oldExpression.Clone()); }
public virtual Expression VisitOldExpression (OldExpression oldExpression) { if (oldExpression == null) return null; oldExpression.expression = this.VisitExpression(oldExpression.expression); return oldExpression; }
public override Expression VisitOldExpression(OldExpression oldExpression) { if (oldExpression == null || oldExpression.expression == null) return null; if (this._string == null){ this._string = new StringBuilder(); } this._string.Append("\\old("); this.VisitExpression(oldExpression.expression); this._string.Append(")"); return oldExpression; }
public override void VisitOldExpression(OldExpression oldExpression) { if (oldExpression == null) return; // Make sure the argument to Old() isn't just a literal. if (oldExpression.expression is Literal) this.HandleError(1000, "Literal expression in Old expression."); base.VisitOldExpression(oldExpression); }
/// <summary> /// Performs a bunch of transformations that the basic Extractor doesn't seem to do: /// - Turns calls to Old contract method into OldExpressions /// - Turns references to "result" into ResultExpressions /// - /// </summary> public override Expression VisitMethodCall(MethodCall call) { MemberBinding mb = call.Callee as MemberBinding; if (mb == null) return call; Method calledMethod = mb.BoundMember as Method; if (calledMethod == null) return call; Method template = calledMethod.Template; if (contractNodes.IsOldMethod(template)) { Expression result = base.VisitMethodCall(call); call = result as MethodCall; if (call == null) return result; result = new OldExpression(call.Operands[0]); result.Type = call.Type; return result; } if (contractNodes.IsValueAtReturnMethod(template)) { return new AddressDereference(call.Operands[0], calledMethod.TemplateArguments[0], call.SourceContext); } if (calledMethod.Parameters != null) { if (calledMethod.Parameters.Count == 0) { if (contractNodes.IsResultMethod(template)) { return new ReturnValue(calledMethod.ReturnType, call.SourceContext); } } else if (insideInvariant && contractNodes.IsInvariantMethod(calledMethod)) { Expression condition = call.Operands[0]; condition.SourceContext = call.SourceContext; return VisitExpression(condition); } } return base.VisitMethodCall(call); }