/// <param name="module">The module into which the duplicate IR will be grafted.</param> /// <param name="type">The type into which the duplicate Member will be grafted. Ignored if entire type, or larger unit is duplicated.</param> public Duplicator(Module/*!*/ module, TypeNode type) { this.TargetModule = module; this.TargetType = this.OriginalTargetType = type; this.DuplicateFor = new TrivialHashtable(); this.TypesToBeDuplicated = new TrivialHashtable(); //^ base(); }
private void CopyMissingMembers() { Contract.Ensures(this.duplicatedMembers != null); this.duplicatedMembers = new TrivialHashtable(this.toBeDuplicatedMembers.Count * 2); foreach (var missing in this.toBeDuplicatedMembers) { Contract.Assume(missing.Value != null); Contract.Assume(missing.Key != null); InstanceInitializer ctor = missing.Key as InstanceInitializer; if (ctor != null && ctor.ParameterCount == 0) { continue; } var targetType = missing.Value; Trace("COPYOOB: copying {0} to {1}", missing.Key.FullName, targetType.FullName); this.Duplicator.TargetType = targetType; var dup = (Member)this.Duplicator.Visit(missing.Key); targetType.Members.Add(dup); duplicatedMembers[missing.Key.UniqueKey] = missing; } }
public virtual AttributeNode GetClosestMatch(AttributeNode/*!*/ nd1, AttributeList/*!*/ list1, AttributeList list2, int list1pos, ref int list2start, TrivialHashtable/*!*/ matchedNodes, out Differences closestDifferences, out int list2pos) { closestDifferences = null; list2pos = -1; if (list2 == null) return null; if (nd1 == null || list1 == null || matchedNodes == null || list1pos < 0 || list1pos >= list1.Count || list2start < 0 || list2start >= list2.Count) { Debug.Assert(false); return null; } AttributeNode closest = null; Differences winnerSoFar = null; for (int j = list2start, m = list2.Count; j < m; j++){ AttributeNode nd2 = list2[j]; if (list2start == j) list2start++; if (nd2 == null) continue; if (matchedNodes[nd2.UniqueKey] != null) continue; Differences diff = this.GetDifferences(nd1, nd2); if (diff == null){Debug.Assert(false); continue;} if (diff.Similarity <= 0.5){ //Not a good enough match if (list2start == j+1) list2start--; //The next call to GetClosestMatch will start looking at list2start, so this node will be considered then continue; //ignore it for the rest of this call } if (winnerSoFar != null && winnerSoFar.Similarity >= diff.Similarity) continue; winnerSoFar = closestDifferences = diff; closest = nd2; list2pos = j; if (diff.NumberOfDifferences == 0) return closest; //Perfect match, no need to look for other matches } if (closest != null){ //^ assert winnerSoFar != null; //closest is closer to nd1 than any other node in list2, but this is no good if some other node in list1 has a better claim on closest for (int i = list1pos+1, n = list1.Count; i < n; i++){ AttributeNode nd1alt = list1[i]; if (nd1alt == null) continue; if (matchedNodes[nd1alt.UniqueKey] != null) continue; Differences diff = this.GetDifferences(nd1alt, closest); if (diff == null){Debug.Assert(false); continue;} if (diff.Similarity <= winnerSoFar.Similarity) continue; //nd1alt has a better claim on closest. See if it wants closest. Differences diff2; int j, k = list2start; AttributeNode nd2alt = this.GetClosestMatch(nd1alt, list1, list2, i, ref k, matchedNodes, out diff2, out j); if (nd2alt != closest){ Debug.Assert(nd2alt != null && diff2 != null && diff2.Similarity >= diff.Similarity); continue; //nd1alt prefers nd2alt to closest, so closest is still available } //nd1alt wants closest, take it out of the running matchedNodes[closest.UniqueKey] = nd1alt; //Now that closest is out of the running, try again k = list2start; AttributeNode newClosest = this.GetClosestMatch(nd1, list1, list2, i, ref k, matchedNodes, out winnerSoFar, out list2pos); //put closest back in the running so that the next call to this routine will pick it up matchedNodes[closest.UniqueKey] = closest; closest = newClosest; break; } } closestDifferences = winnerSoFar; return closest; }
public virtual SwitchCase VisitSwitchCase(SwitchCase switchCase, Class scope, TrivialHashtable targetFor, IdentifierList labelList) { if (switchCase == null) { return(null); } this.VisitBlock(switchCase.Body, scope, targetFor, labelList); return(switchCase); }
/// <summary> /// Walks the statement list of the given block gathering information from declarations for use by forward references. Does not recurse into nested blocks. /// </summary> /// <param name="block">The block whose declarations are to be processed</param> /// <param name="scope">Maps identifiers to Metadata nodes (e.g. Fields).</param> /// <param name="targetFor">Maps labels (Identifiers) to the corresponding labeled blocks (single statements are promoted to blocks for this purpose).</param> /// <param name="labelList">A list of all the labels encountered by Declarer.</param> public virtual void VisitBlock(Block block, Class scope, TrivialHashtable targetFor, IdentifierList labelList){ if (block == null) return; this.scope = scope; this.targetFor = targetFor; this.labelList = labelList; StatementList statements = block.Statements; if (statements == null) return; for (int i = 0, n = statements.Count; i < n; i++) statements[i] = (Statement)this.Visit(statements[i]); }
public MemberReferenceFinder(TrivialHashtable membersToFind, bool omitMethodBodies) { if (membersToFind == null) { Debug.Assert(false); membersToFind = new TrivialHashtable(); } this.MembersToFind = membersToFind; this.AllReferencesAreConfinedToMethodBodies = true; this.insideMethodBody = false; this.omitMethodBodies = omitMethodBodies; }
public Normalizer(TypeSystem typeSystem){ this.typeSystem = typeSystem; this.exitTargets = new StatementList(); this.continueTargets = new StatementList(); this.currentTryStatements = new Stack(); this.exceptionBlockFor = new TrivialHashtable(); this.visitedCompleteTypes = new TrivialHashtable(); this.EndIfLabel = new TrivialHashtable(); this.foreachLength = 7; this.WrapToBlockExpression = true; this.useGenerics = TargetPlatform.UseGenerics; }
public Checker(ErrorHandler errorHandler, TypeSystem typeSystem, TrivialHashtable scopeFor, TrivialHashtable ambiguousTypes, TrivialHashtable referencedLabels) : base(errorHandler) { this.typeSystem = typeSystem; this.Errors = errorHandler == null ? null : errorHandler.Errors; this.scopeFor = scopeFor; this.ambiguousTypes = ambiguousTypes; this.referencedLabels = referencedLabels; this.MayNotReferenceThisFromFieldInitializer = true; this.allowedExceptions = new TypeNodeList(); this.useGenerics = TargetPlatform.UseGenerics; this.AllowPropertiesIndexersAsRef = true; }
public AbbreviationDuplicator(Method sourceMethod, Method targetMethod, ContractNodes contractNodes, Method abbreviation, Expression targetObject, ExpressionList actuals) : base(targetMethod.DeclaringType.DeclaringModule, sourceMethod, targetMethod, contractNodes, false) { this.targetObject = targetObject; this.abbreviation = abbreviation; this.actuals = actuals; this.localsInActuals = new TrivialHashtable(); PopulateLocalsInActuals(); }
public override Statement VisitLabeledStatement(LabeledStatement lStatement){ if (lStatement == null) return null; this.labelList.Add(lStatement.Label); lStatement.Scope = this.scope as BlockScope; if (this.localLabels == null) this.localLabels = new TrivialHashtable(); if (this.localLabels[lStatement.Label.UniqueIdKey] == null){ this.localLabels[lStatement.Label.UniqueIdKey] = lStatement; this.targetFor[lStatement.Label.UniqueIdKey] = lStatement; }else this.HandleError(lStatement.Label, Error.LabelIdentiferAlreadyInUse, lStatement.Label.ToString()); lStatement.Statement = (Statement)this.Visit(lStatement.Statement); return lStatement; }
/// <summary> /// Walks the statement list of the given block gathering information from declarations for use by forward references. Does not recurse into nested blocks. /// </summary> /// <param name="block">The block whose declarations are to be processed</param> /// <param name="scope">Maps identifiers to Metadata nodes (e.g. Fields).</param> /// <param name="targetFor">Maps labels (Identifiers) to the corresponding labeled blocks (single statements are promoted to blocks for this purpose).</param> /// <param name="labelList">A list of all the labels encountered by Declarer.</param> public virtual void VisitBlock(Block block, Class scope, TrivialHashtable targetFor, IdentifierList labelList) { if (block == null) { return; } this.scope = scope; this.targetFor = targetFor; this.labelList = labelList; StatementList statements = block.Statements; if (statements == null) { return; } for (int i = 0, n = statements.Count; i < n; i++) { statements[i] = (Statement)this.Visit(statements[i]); } }
public Looker(Scope scope, ErrorHandler errorHandler, TrivialHashtable scopeFor, TypeSystem typeSystem, TrivialHashtable ambiguousTypes, TrivialHashtable referencedLabels) : base(errorHandler){ //TODO: verify that crucial system types have either been imported or defined by the Parser this.scope = scope; this.AddToAllScopes(this.scope); this.scopeFor = scopeFor; this.ambiguousTypes = ambiguousTypes; this.referencedLabels = referencedLabels; this.alreadyReported = new TrivialHashtable(); this.hasExplicitBaseClass = new TrivialHashtable(); this.typesToKeepUninstantiated = new TrivialHashtable(); this.UsedNamespaces = new UsedNamespaceList(); this.targetFor = new TrivialHashtable(); this.labelList = new IdentifierList(); this.AbstractSealedUsedAsType = Error.NotAType; Debug.Assert(typeSystem != null); this.typeSystem = typeSystem; this.useGenerics = TargetPlatform.UseGenerics; this.inMethodParameter = false; this.inEventContext = false; }
public Expression DecompileBooleanExpression(BlockExpression be) { if (be == null) { return(null); } TypeReconstructorAndExpressionSimplifier tr = new TypeReconstructorAndExpressionSimplifier(); be = tr.VisitBlockExpression(be) as BlockExpression; if (be == null) { return(null); } Block b = be.Block; #region Make sure the block expression has the right shape foreach (Statement s in b.Statements) { Block b_prime = s as Block; Debug.Assert(b_prime != null); Debug.Assert(HelperMethods.IsBasicBlock(b_prime)); } #endregion Block firstBlock = (Block)b.Statements[0]; block2Index = new TrivialHashtable(b.Statements.Count); blocks = new BlockList(b.Statements.Count); for (int i = 0, n = b.Statements.Count; i < n; i++) { block2Index[b.Statements[i].UniqueKey] = i; blocks.Add(b.Statements[i] as Block); } Expression e = DecompileBooleanExpression(firstBlock); // BUGBUG: this isn't a good place to do this because then it gets done for all contracts, // not just postconditions!! Plus, we could just leave Result in the contracts and let the // BPL translation recognize it. //ReplaceResult repResult = new ReplaceResult(this.localToUseForResult, this.contractNodes.ResultTemplate, // this.contractNodes.ParameterTemplate); //e = repResult.VisitExpression(e); return(e); }
/// <summary> /// Walks the supplied System.CodeDom.CodeCompileUnit and produces a corresponding CompilationUnit. /// Enters declarations into the supplied Module and errors into the supplied ErrorNodeList. /// Calls back to the supplied compiler to resolve assembly references and to create appropriate documents for code snippets. /// </summary> /// <param name="compiler">Called upon to resolve assembly references and to create Documents for snippets.</param> /// <param name="compilationUnit">The root of the CodeDOM tree to be translated into an IR CompileUnit.</param> /// <param name="targetModule">The module or assembly to which the compilation unit will be compiled.</param> /// <param name="errorNodes">Errors in the CodeDOM tree that are found during translation are added to this list.</param> /// <returns></returns> public CompilationUnit Translate(Compiler compiler, CodeCompileUnit compilationUnit, Module targetModule, ErrorNodeList errorNodes){ Debug.Assert(compiler != null); Debug.Assert(compilationUnit != null); Debug.Assert(targetModule != null); Debug.Assert(errorNodes != null); this.compiler = compiler; this.errorNodes = errorNodes; this.targetModule = targetModule; CodeSnippetCompileUnit cscu = compilationUnit as CodeSnippetCompileUnit; CompilationUnit cunit = cscu != null ? new CompilationUnitSnippet() : new CompilationUnit(); this.Translate(compilationUnit.AssemblyCustomAttributes, targetModule.Attributes); StringCollection references = compilationUnit.ReferencedAssemblies; if (references != null && references.Count > 0){ AssemblyReferenceList arefs = targetModule.AssemblyReferences; TrivialHashtable alreadyReferencedAssemblies = new TrivialHashtable(); for (int i = 0, n = arefs.Count; i < n; i++) alreadyReferencedAssemblies[arefs[i].Assembly.UniqueKey] = this; foreach (string rAssemblyName in references) compiler.AddAssemblyReferenceToModule(null, targetModule, rAssemblyName, null, errorNodes, alreadyReferencedAssemblies, false); } Namespace defaultNamespace = new Namespace(Identifier.Empty, Identifier.Empty, null, null, new NamespaceList(), null); NamespaceList nspaceList = defaultNamespace.NestedNamespaces; CodeNamespaceCollection nspaces = compilationUnit.Namespaces; if (nspaces != null) foreach (CodeNamespace cns in nspaces) nspaceList.Add(this.Translate(cns)); if (cscu == null) return cunit; Document doc = null; if (cscu.LinePragma == null) doc = compiler.CreateDocument(targetModule.Name, 1, cscu.Value); else{ doc = compiler.CreateDocument(cscu.LinePragma.FileName, cscu.LinePragma.LineNumber, cscu.Value); cunit.Name = Identifier.For(cscu.LinePragma.FileName); } cunit.SourceContext = new SourceContext(doc); defaultNamespace.SourceContext = cunit.SourceContext; return cunit; }
public override Statement VisitLabeledStatement(LabeledStatement lStatement) { if (lStatement == null) { return(null); } this.labelList.Add(lStatement.Label); lStatement.Scope = this.scope as BlockScope; if (this.localLabels == null) { this.localLabels = new TrivialHashtable(); } if (this.localLabels[lStatement.Label.UniqueIdKey] == null) { this.localLabels[lStatement.Label.UniqueIdKey] = lStatement; this.targetFor[lStatement.Label.UniqueIdKey] = lStatement; } else { this.HandleError(lStatement.Label, Error.LabelIdentiferAlreadyInUse, lStatement.Label.ToString()); } lStatement.Statement = (Statement)this.Visit(lStatement.Statement); return(lStatement); }
public virtual Differences VisitTypeNodeList(TypeNodeList list1, TypeNodeList list2, out TypeNodeList changes, out TypeNodeList deletions, out TypeNodeList insertions){ changes = list1 == null ? null : list1.Clone(); deletions = list1 == null ? null : list1.Clone(); insertions = list1 == null ? new TypeNodeList() : list1.Clone(); //^ assert insertions != null; Differences differences = new Differences(); //Compare definitions that have matching key attributes TrivialHashtable matchingPosFor = new TrivialHashtable(); TrivialHashtable matchedNodes = new TrivialHashtable(); for (int j = 0, n = list2 == null ? 0 : list2.Count; j < n; j++){ //^ assert list2 != null; TypeNode nd2 = list2[j]; if (nd2 == null || nd2.Name == null) continue; string fullName = nd2.FullName; if (fullName == null) continue; matchingPosFor[Identifier.For(fullName).UniqueIdKey] = j; insertions.Add(null); } for (int i = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){ //^ assert list1 != null && changes != null && deletions != null; TypeNode nd1 = list1[i]; if (nd1 == null || nd1.Name == null) continue; string fullName = nd1.FullName; if (fullName == null) continue; object pos = matchingPosFor[Identifier.For(fullName).UniqueIdKey]; if (!(pos is int)) continue; //^ assert pos != null; //^ assume list2 != null; //since there was entry int matchingPosFor int j = (int)pos; TypeNode nd2 = list2[j]; //^ assume nd2 != null; //nd1 and nd2 have the same key attributes and are therefore treated as the same entity matchedNodes[nd1.UniqueKey] = nd1; matchedNodes[nd2.UniqueKey] = nd2; //nd1 and nd2 may still be different, though, so find out how different Differences diff = this.VisitTypeNode(nd1, nd2); if (diff == null){Debug.Assert(false); continue;} if (diff.NumberOfDifferences != 0){ changes[i] = diff.Changes as TypeNode; deletions[i] = diff.Deletions as TypeNode; insertions[i] = diff.Insertions as TypeNode; insertions[n+j] = nd1; //Records the position of nd2 in list2 in case the change involved a permutation //Debug.Assert(diff.Changes == changes[i] && diff.Deletions == deletions[i] && diff.Insertions == insertions[i]); differences.NumberOfDifferences += diff.NumberOfDifferences; differences.NumberOfSimilarities += diff.NumberOfSimilarities; if (nd1.DeclaringModule == this.OriginalModule || (nd1.DeclaringType != null && nd1.DeclaringType.DeclaringModule == this.OriginalModule)){ if (this.MembersThatHaveChanged == null) this.MembersThatHaveChanged = new MemberList(); this.MembersThatHaveChanged.Add(nd1); } continue; } changes[i] = null; deletions[i] = null; insertions[i] = null; insertions[n+j] = nd1; //Records the position of nd2 in list2 in case the change involved a permutation } //Find deletions for (int i = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){ //^ assert list1 != null && changes != null && deletions != null; TypeNode nd1 = list1[i]; if (nd1 == null) continue; if (matchedNodes[nd1.UniqueKey] != null) continue; changes[i] = null; deletions[i] = nd1; insertions[i] = null; differences.NumberOfDifferences += 1; if (nd1.DeclaringModule == this.OriginalModule || (nd1.DeclaringType != null && nd1.DeclaringType.DeclaringModule == this.OriginalModule)){ if (this.MembersThatHaveChanged == null) this.MembersThatHaveChanged = new MemberList(); this.MembersThatHaveChanged.Add(nd1); } } //Find insertions for (int j = 0, n = list1 == null ? 0 : list1.Count, m = list2 == null ? 0 : list2.Count; j < m; j++){ //^ assert list2 != null; TypeNode nd2 = list2[j]; if (nd2 == null) continue; if (matchedNodes[nd2.UniqueKey] != null) continue; insertions[n+j] = nd2; //Records nd2 as an insertion into list1, along with its position in list2 differences.NumberOfDifferences += 1; //REVIEW: put the size of the tree here? } if (differences.NumberOfDifferences == 0){ changes = null; deletions = null; insertions = null; } return differences; }
/// <summary> /// Gets a difference object representing the differences between node1 and node2. Caches the result and returns it for subsequent calls. /// I.e. this is a caching factory method for Differences instances. Calls GetNewDifferences to construct new instances when needed. /// </summary> public virtual Differences GetDifferences(Node/*!*/ node1, Node node2) { if (node1 == null || node2 == null) return new Differences(node1, node2); if (this.differencesMapFor == null) this.differencesMapFor = new TrivialHashtable(); TrivialHashtable map = this.differencesMapFor[node1.UniqueKey] as TrivialHashtable; if (map == null) this.differencesMapFor[node1.UniqueKey] = map = new TrivialHashtable(); Differences differences = map[node2.UniqueKey] as Differences; if (differences == null){ map[node2.UniqueKey] = differences = this.Visit(node1, node2); if (differences != null && differences.NumberOfDifferences > 0 && differences.Changes == null) differences.Changes = node2; } return differences; }
internal Scoper(TrivialHashtable scopeFor) : base(scopeFor) { }
public virtual Differences VisitAssemblyReferenceList(AssemblyReferenceList list1, AssemblyReferenceList list2, out AssemblyReferenceList changes, out AssemblyReferenceList deletions, out AssemblyReferenceList insertions){ changes = list1 == null ? null : list1.Clone(); deletions = list1 == null ? null : list1.Clone(); insertions = list1 == null ? new AssemblyReferenceList() : list1.Clone(); //^ assert insertions != null; Differences differences = new Differences(); //Compare references that have matching assembly names TrivialHashtable matchingPosFor = new TrivialHashtable(); TrivialHashtable matchedNodes = new TrivialHashtable(); for (int j = 0, n = list2 == null ? 0 : list2.Count; j < n; j++){ //^ assert list2 != null; AssemblyReference nd2 = list2[j]; if (nd2 == null || nd2.Name == null) continue; matchingPosFor[Identifier.For(nd2.Name).UniqueIdKey] = j; insertions.Add(null); } for (int i = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){ //^ assert list1 != null && changes != null && deletions != null; AssemblyReference nd1 = list1[i]; if (nd1 == null || nd1.Name == null) continue; object pos = matchingPosFor[Identifier.For(nd1.Name).UniqueIdKey]; if (!(pos is int)) continue; //^ assert pos != null; //^ assume list2 != null; //since there was entry int matchingPosFor int j = (int)pos; AssemblyReference nd2 = list2[j]; //^ assume nd2 != null; //nd1 and nd2 define the same alias name and are therefore treated as the same entity matchedNodes[nd1.UniqueKey] = nd1; matchedNodes[nd2.UniqueKey] = nd2; //nd1 and nd2 may still be different, though, so find out how different Differences diff = this.VisitAssemblyReference(nd1, nd2); if (diff == null){Debug.Assert(false); continue;} if (diff.NumberOfDifferences != 0){ changes[i] = diff.Changes as AssemblyReference; deletions[i] = diff.Deletions as AssemblyReference; insertions[i] = diff.Insertions as AssemblyReference; insertions[n+j] = nd1; //Records the position of nd2 in list2 in case the change involved a permutation Debug.Assert(diff.Changes == changes[i] && diff.Deletions == deletions[i] && diff.Insertions == insertions[i]); differences.NumberOfDifferences += diff.NumberOfDifferences; differences.NumberOfSimilarities += diff.NumberOfSimilarities; continue; } changes[i] = null; deletions[i] = null; insertions[i] = null; insertions[n+j] = nd1; //Records the position of nd2 in list2 in case the change involved a permutation } //Find deletions for (int i = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){ //^ assert list1 != null && changes != null && deletions != null; AssemblyReference nd1 = list1[i]; if (nd1 == null) continue; if (matchedNodes[nd1.UniqueKey] != null) continue; changes[i] = null; deletions[i] = nd1; insertions[i] = null; differences.NumberOfDifferences += 1; } //Find insertions for (int j = 0, n = list1 == null ? 0 : list1.Count, m = list2 == null ? 0 : list2.Count; j < m; j++){ //^ assert list2 != null; AssemblyReference nd2 = list2[j]; if (nd2 == null) continue; if (matchedNodes[nd2.UniqueKey] != null) continue; insertions[n+j] = nd2; //Records nd2 as an insertion into list1, along with its position in list2 differences.NumberOfDifferences += 1; } if (differences.NumberOfDifferences == 0){ changes = null; deletions = null; insertions = null; } return differences; }
public virtual AttributeNode VisitAttributeNode(AttributeNode attribute, Node target) { if (attribute == null || target == null) return null; attribute.Constructor = this.VisitAttributeConstructor(attribute, target); ExpressionList expressions = attribute.Expressions = this.VisitExpressionList(attribute.Expressions); MemberBinding mb = attribute.Constructor as MemberBinding; if (mb == null || mb.BoundMember == null) { Debug.Assert(attribute.Constructor == null); return null; } //Check arguments for validity TypeNode attributeType = mb.BoundMember.DeclaringType; if (attributeType == null) return null; InstanceInitializer ctor = (InstanceInitializer)mb.BoundMember; ParameterList pars = ctor.Parameters; ExpressionList positionalArgs = new ExpressionList(); TrivialHashtable alreadySeenNames = new TrivialHashtable(); for (int i = 0, n = expressions == null ? 0 : expressions.Count; i < n; i++) { Expression e = expressions[i]; this.TypeInVariableContext(e as Literal); NamedArgument narg = e as NamedArgument; if (narg == null) { positionalArgs.Add(e); expressions[i] = null; continue; } if (narg.Name == null) { expressions[i] = null; continue; } if (alreadySeenNames[narg.Name.UniqueIdKey] != null) { this.HandleError(narg.Name, Error.DuplicateNamedAttributeArgument, narg.Name.ToString()); expressions[i] = null; continue; } alreadySeenNames[narg.Name.UniqueIdKey] = narg.Name; Member mem = null; TypeNode aType = attributeType; while (aType != null) { MemberList members = this.GetTypeView(aType).GetMembersNamed(narg.Name); for (int j = 0, m = members == null ? 0 : members.Count; j < m; j++) { mem = members[j]; if (mem == null) continue; switch (mem.NodeType) { case NodeType.Field: if (!mem.IsPublic) goto error; Field f = (Field)mem; if (f.IsInitOnly || f.IsLiteral || f.IsStatic) goto error; if (!this.IsValidTypeForCustomAttributeParameter(f.Type)) { this.HandleError(narg, Error.BadNamedAttributeArgumentType, this.GetMemberSignature(f)); this.HandleRelatedError(f); return null; } this.CheckForObsolesence(narg, f); narg.IsCustomAttributeProperty = false; e = this.typeSystem.ImplicitCoercion(narg.Value, narg.Type = f.Type, this.TypeViewer); if (!this.IsValidTypeForCustomAttributeArgument(e, narg.Value)) return null; if (e is BinaryExpression && e.NodeType == NodeType.Box) { narg.ValueIsBoxed = true; e = ((BinaryExpression)e).Operand1; } narg.Value = e; goto doneWithArg; case NodeType.Property: if (!mem.IsPublic) goto error; Property p = (Property)mem; if (!this.IsValidTypeForCustomAttributeParameter(p.Type)) { this.HandleError(narg, Error.BadNamedAttributeArgumentType, this.GetMemberSignature(p)); this.HandleRelatedError(p); return null; } if (p.Setter == null || p.Getter == null || p.IsStatic || !p.Setter.IsPublic || !p.Getter.IsPublic) goto error; this.CheckForObsolesence(narg, p); narg.IsCustomAttributeProperty = true; e = this.typeSystem.ImplicitCoercion(narg.Value, narg.Type = p.Type, this.TypeViewer); if (!this.IsValidTypeForCustomAttributeArgument(e, narg.Value)) return null; if (e is BinaryExpression && e.NodeType == NodeType.Box) { narg.ValueIsBoxed = true; e = ((BinaryExpression)e).Operand1; } narg.Value = e; goto doneWithArg; } } aType = aType.BaseType; } error: if (mem != null) { this.HandleError(narg, Error.BadNamedAttributeArgument, narg.Name.ToString()); this.HandleRelatedError(mem); } else this.HandleError(narg, Error.NoSuchMember, this.GetTypeName(attributeType), narg.Name.ToString()); doneWithArg: ; } ExpressionList exprs = positionalArgs.Clone(); this.CoerceArguments(pars, ref positionalArgs, true, ctor.CallingConvention); attribute.Expressions = positionalArgs; for (int i = 0, n = positionalArgs == null ? 0 : positionalArgs.Count; i < n; i++) { Expression e = positionalArgs[i]; if (e == null) continue; if (!this.IsValidTypeForCustomAttributeArgument(e, exprs[i])) return null; if (e is BinaryExpression && e.NodeType == NodeType.Box) e = ((BinaryExpression)e).Operand1; positionalArgs[i] = e; } for (int i = 0, n = expressions == null ? 0 : expressions.Count; i < n; i++) { Expression e = expressions[i]; if (e == null) continue; positionalArgs.Add(e); } attribute.Expressions = positionalArgs; //Now call specific visitors to deal with any pseudo custom attributes that describe metadata settings for target switch (target.NodeType) { case NodeType.Assembly: return this.VisitAssemblyAttribute(attribute, (AssemblyNode)target); case NodeType.Field: return this.VisitFieldAttribute(attribute, (Field)target); case NodeType.InstanceInitializer: case NodeType.StaticInitializer: case NodeType.Method: return this.VisitMethodAttribute(attribute, (Method)target); case NodeType.Property: return this.VisitPropertyAttribute(attribute, (Property)target); case NodeType.Parameter: return this.VisitParameterAttribute(attribute, (Parameter)target); default: TypeNode t = target as TypeNode; if (t != null) return this.VisitTypeAttribute(attribute, t); break; } return attribute; }
public Looker(Scope scope, Cci.ErrorHandler errorHandler, TrivialHashtable scopeFor) : this(scope, errorHandler, scopeFor, null, null) { this.alreadyReported[StandardIds.Var.UniqueIdKey] = true; }
public virtual Method InferMethodTemplateArgumentsAndReturnTemplateInstance(Method method, ParameterList delegateParameters){ if (method == null || method.Parameters == null || method.Parameters.Count == 0 || method.TemplateParameters == null || method.TemplateParameters.Count == 0){Debug.Assert(false); return method;} if (delegateParameters == null) return method; int numParams = delegateParameters.Count; if (numParams == 0 || numParams != method.Parameters.Count){Debug.Assert(false); return method;} TrivialHashtable inferredTypeFor = new TrivialHashtable(); for (int i = 0; i < numParams; i++){ Parameter dpar = delegateParameters[i]; if (dpar == null || dpar.Type == null) continue; Parameter mpar = method.Parameters[i]; if (mpar == null) continue; if (!this.InferMethodTemplateArguments(dpar.Type, null, mpar.Type, inferredTypeFor)) return method; } int numTypeArgs = method.TemplateParameters.Count; TypeNodeList typeArguments = new TypeNodeList(numTypeArgs); for (int i = 0; i < numTypeArgs; i++){ TypeNode templPar = method.TemplateParameters[i]; if (templPar == null) return method; TypeNode templArg = inferredTypeFor[templPar.UniqueKey] as TypeNode; if (templArg == null) return method; typeArguments.Add(templArg); } return method.GetTemplateInstance(this.currentType, typeArguments); }
public override Property VisitProperty(Property property) { property = base.VisitProperty(property); if (property == null) return null; property.Attributes = this.VisitAttributeList(property.Attributes, property); if (property.Name != null && property.Name.UniqueIdKey == StandardIds.Item.UniqueIdKey && property.Parameters != null && property.Parameters.Count > 0) { if (this.indexerNames == null) this.indexerNames = new TrivialHashtable(); Identifier previousName = (Identifier)this.indexerNames[this.currentType.UniqueKey]; if (previousName == null) this.indexerNames[this.currentType.UniqueKey] = StandardIds.Item; else if (previousName.UniqueIdKey != property.Name.UniqueIdKey) { this.HandleError(property.Name, Error.InconsistantIndexerNames); Identifier id = new Identifier(previousName.ToString()); id.SourceContext = property.Name.SourceContext; property.Name = id; } } if (property.Type == SystemTypes.Void) this.HandleError(property.Name, Error.PropertyCantHaveVoidType, this.GetMemberSignature(property)); else if (this.IsLessAccessible(property.Type, property)) { Error e = Error.PropertyTypeLessAccessibleThanProperty; if (property.Parameters != null && property.Parameters.Count > 0) e = Error.PropertyTypeLessAccessibleThanIndexedProperty; this.HandleError(property.Name, e, this.GetTypeName(property.Type), this.GetMemberSignature(property)); this.HandleRelatedError(property.Type); } this.CheckParameterTypeAccessibility(property.Parameters, property); if (property.Getter == null && property.Setter == null) { this.HandleError(property.Name, Error.PropertyWithNoAccessors, this.GetMemberSignature(property)); return null; } TypeNodeList implementedTypes = property.ImplementedTypes; for (int i = 0, n = implementedTypes == null ? 0 : implementedTypes.Count; i < n; i++) { TypeNode t = implementedTypes[i]; if (t == null) continue; MemberList tmems = this.GetTypeView(t).GetMembersNamed(property.Name); Property p = null; for (int j = 0, m = tmems == null ? 0 : tmems.Count; j < m; j++) { p = tmems[j] as Property; if (p == null) continue; if (p.Type != property.Type) { p = null; continue; } if (!p.ParametersMatch(property.Parameters)) { p = null; continue; } break; } if (p == null) { this.HandleError(property.Name, Error.InterfaceMemberNotFound, this.GetMemberSignature(property), this.GetTypeName(t)); this.HandleRelatedError(t); } else { if (p.Getter == null) { if (property.Getter != null) { this.HandleError(property.Getter.Name, Error.ExplicitPropertyAddingAccessor, this.GetMethodSignature(property.Getter), this.GetMemberSignature(p)); this.HandleRelatedError(p); } } else { if (property.Getter == null) { this.HandleError(property.Name, Error.ExplicitPropertyMissingAccessor, this.GetMemberSignature(property), this.GetMethodSignature(p.Getter)); this.HandleRelatedError(p.Getter); } } if (p.Setter == null) { if (property.Setter != null) { this.HandleError(property.Setter.Name, Error.ExplicitPropertyAddingAccessor, this.GetMethodSignature(property.Setter), this.GetMemberSignature(p)); this.HandleRelatedError(p); } } else { if (property.Setter == null) { this.HandleError(property.Name, Error.ExplicitPropertyMissingAccessor, this.GetMemberSignature(property), this.GetMethodSignature(p.Setter)); this.HandleRelatedError(p.Setter); } } } } return property; }
public override Method VisitMethod(Method method){ if (method == null) return null; if (method.IsNormalized) return method; if (method.Scope != null) method.Scope.ThisTypeInstance = this.currentTypeInstance; method.Attributes = this.VisitAttributeList(method.Attributes); method.ReturnAttributes = this.VisitAttributeList(method.ReturnAttributes); method.SecurityAttributes = this.VisitSecurityAttributeList(method.SecurityAttributes); Method savedCurrentMethod = this.currentMethod; this.currentMethod = method; method.ReturnType = this.VisitTypeReference(method.ReturnType); TypeNodeList implementedTypes = method.ImplementedTypes = this.VisitTypeReferenceList(method.ImplementedTypes); method.Parameters = this.VisitParameterList(method.Parameters); method.TemplateArguments = this.VisitTypeReferenceList(method.TemplateArguments); method.TemplateParameters = this.VisitTypeParameterList(method.TemplateParameters); method.Contract = this.VisitMethodContract(method.Contract); method = this.CheckMethodProperties(method); if (method == null) { this.currentMethod = savedCurrentMethod; return method; } method.Body = this.VisitBlock(method.Body); StreamTypeExpression stExpr = method.ReturnType as StreamTypeExpression; TypeUnionExpression tuExpr = stExpr != null ? (TypeUnionExpression)stExpr.ElementType : (method.ReturnType as TypeUnionExpression); if (tuExpr != null){ TypeNodeList types = new TypeNodeList(); TrivialHashtable alreadyPresent = new TrivialHashtable(); //REVIEW: this seems redundant for (int i = 0, m = tuExpr.Types == null ? 0 : tuExpr.Types.Count; i < m; i++){ TypeNode t = tuExpr.Types[i]; if (t == null) continue; if (alreadyPresent[t.UniqueKey] != null) continue; types.Add(t); alreadyPresent[t.UniqueKey] = t; } if (types.Count == 1) method.ReturnType = types[0]; else method.ReturnType = TypeUnion.For(types, this.currentType); } if (stExpr != null) method.ReturnType = SystemTypes.GenericIEnumerable.GetTemplateInstance(this.currentType, method.ReturnType); int n = implementedTypes == null ? 0 : implementedTypes.Count; MethodList implementedInterfaceMethods = method.ImplementedInterfaceMethods = n == 0 ? null : new MethodList(n); for (int i = 0; i < n; i++){ Interface iface = implementedTypes[i] as Interface; Method meth = null; if (iface != null){ MemberList members = this.GetTypeView(iface).GetMembersNamed(method.Name); for (int j = 0, m = members.Count; j < m; j++){ Method im = members[j] as Method; if (im == null) continue; if (im.ReturnType == null || !im.ReturnType.IsStructurallyEquivalentTo(method.ReturnType)) continue; if (!im.ParametersMatchStructurally(method.Parameters)) continue; meth = im; break; } } implementedInterfaceMethods.Add(meth); } this.currentMethod = savedCurrentMethod; return method; }
public virtual Method InferMethodTemplateArgumentsAndReturnTemplateInstance(Method method, ExpressionList arguments, bool allowPartialInference, TypeNode paramArrayElemType){ if (method == null || method.Parameters == null || method.Parameters.Count == 0 || method.TemplateParameters == null || method.TemplateParameters.Count == 0){Debug.Assert(false); return method;} if (arguments == null) return method; int numArgs = arguments.Count; int numPars = method.Parameters.Count; if (numArgs == 0 || (numArgs != numPars && paramArrayElemType == null && (!allowPartialInference || numArgs > numPars))){ Debug.Assert(false); return method; } TrivialHashtable inferredTypeFor = new TrivialHashtable(); for (int i = 0; i < numArgs; i++){ Expression arg = arguments[i]; if (arg == null) continue; TypeNode argType = TypeNode.StripModifiers(arg.Type); if (arg is Literal && argType == SystemTypes.Object && ((Literal)arg).Value == null) continue; if (arg is AnonymousNestedFunction) continue; Parameter par = method.Parameters[i]; if (par == null) continue; TypeNode parType = TypeNode.StripModifiers(par.Type); Reference reft = argType as Reference; if (reft != null && !(arg is UnaryExpression)) argType = reft.ElementType; if (i == numPars - 1 && paramArrayElemType != null) if (!(argType is ArrayType && parType is ArrayType)) parType = paramArrayElemType; if (!this.InferMethodTemplateArguments(argType, arg as MemberBinding, parType, inferredTypeFor)) return method; if (i == numPars-1) break; } int numTypeArgs = method.TemplateParameters.Count; TypeNodeList typeArguments = new TypeNodeList(numTypeArgs); for (int i = 0; i < numTypeArgs; i++){ TypeNode templPar = method.TemplateParameters[i]; if (templPar == null) return method; TypeNode templArg = inferredTypeFor[templPar.UniqueKey] as TypeNode; if (templArg == null && !allowPartialInference) return method; if (templArg == null) templArg = templPar; typeArguments.Add(templArg); } return method.GetTemplateInstance(this.currentType, typeArguments); }
public override Method VisitMethod(Method method){ // body might not have been materialized, so make sure we do that first! Block body = method.Body; if (method == null) return null; BlockSorter blockSorter = new BlockSorter(); BlockList sortedBlocks = blockSorter.SortedBlocks; this.SucessorBlock = blockSorter.SuccessorBlock; this.StackLocalsAtEntry = new TrivialHashtable(); this.localsStack = new LocalsStack(); ExceptionHandlerList ehandlers = method.ExceptionHandlers; for (int i = 0, n = ehandlers == null ? 0 : ehandlers.Count; i < n; i++){ ExceptionHandler ehandler = ehandlers[i]; if (ehandler == null) continue; Block handlerStart = ehandler.HandlerStartBlock; if (handlerStart == null) continue; LocalsStack lstack = new LocalsStack(); this.StackLocalsAtEntry[handlerStart.UniqueKey] = lstack; if (ehandler.HandlerType == NodeType.Catch) { lstack.exceptionHandlerType = CoreSystemTypes.Object; if (ehandler.FilterType != null) lstack.exceptionHandlerType = ehandler.FilterType; } else if (ehandler.HandlerType == NodeType.Filter) { lstack.exceptionHandlerType = CoreSystemTypes.Object; if (ehandler.FilterExpression != null) { lstack = new LocalsStack(); lstack.exceptionHandlerType = CoreSystemTypes.Object; this.StackLocalsAtEntry[ehandler.FilterExpression.UniqueKey] = lstack; } } } blockSorter.VisitMethodBody(body); for (int i = 0, n = sortedBlocks.Count; i < n; i++) { Block b = sortedBlocks[i]; if (b == null) { Debug.Assert(false); continue; } this.VisitBlock(b); } return method; }
public MemberReferenceFinder(TrivialHashtable membersToFind, bool omitMethodBodies){ if (membersToFind == null){Debug.Assert(false); membersToFind = new TrivialHashtable();} this.MembersToFind = membersToFind; this.AllReferencesAreConfinedToMethodBodies = true; this.insideMethodBody = false; this.omitMethodBodies = omitMethodBodies; }
public void ResetPragmaWarnInformation() { this.PragmaWarnInformation = null; }
public PreDAStatus(TrivialHashtable created, TrivialHashtable committed, Hashtable oktable, Hashtable nonDelayArrayTable) { this.createdButNotCommitted = created; this.committed = committed; this.okTable = oktable; this.nonDelayArrayTable = nonDelayArrayTable; }
/// <summary> /// We pass the argument expression in case we are dealing with an implicit delegate construction /// </summary> /// <param name="argExpr">This is the actual argument expression</param> public virtual bool InferMethodTemplateArguments(TypeNode argType, MemberBinding argExpr, TypeNode parType, TrivialHashtable inferredTypeFor){ if (argType == null || parType == null) return false; if (inferredTypeFor == null){Debug.Assert(false); return false;} TypeNode modifiedArgType = argType; TypeNode modifiedParType = parType; argType = TypeNode.StripModifiers(argType); parType = TypeNode.StripModifiers(parType); if (parType is MethodTypeParameter || parType is MethodClassParameter){ TypeNode prevInference = inferredTypeFor[parType.UniqueKey] as TypeNode; if (prevInference != null) { if (!prevInference.IsStructurallyEquivalentTo(modifiedArgType)) { if (!TypeNode.StripModifiers(prevInference).IsStructurallyEquivalentTo(argType)) return false; if (!this.typeSystem.ImplicitCoercionFromTo(argType, prevInference)) return false; } } else inferredTypeFor[parType.UniqueKey] = modifiedArgType; return true; } ArrayType pArrT = parType as ArrayType; ArrayType aArrT = argType as ArrayType; if (pArrT != null){ if (aArrT == null || aArrT.Rank != pArrT.Rank) return false; //TODO: param arrays return this.InferMethodTemplateArguments(aArrT.ElementType, null, pArrT.ElementType, inferredTypeFor); } Reference pRefT = parType as Reference; Reference aRefT = argType as Reference; if (pRefT != null) { if (aRefT == null) return false; return this.InferMethodTemplateArguments(aRefT.ElementType, null, pRefT.ElementType, inferredTypeFor); } if (parType.IsStructural && argType.IsStructural){ TypeNodeList parElemTypes = parType.StructuralElementTypes; TypeNodeList argElemTypes = argType.StructuralElementTypes; int n = parElemTypes == null ? 0 : parElemTypes.Count; int m = argElemTypes == null ? 0 : argElemTypes.Count; if (parType.Template != null && argType.Template != null && parType.Template == argType.Template) { for (int i = 0; i < n; i++) { TypeNode peType = parElemTypes[i]; if (peType == null) return false; TypeNode aeType = argElemTypes[i]; if (aeType == null) return false; if (!this.InferMethodTemplateArguments(aeType, null, peType, inferredTypeFor)) return false; } if (parType.DeclaringType == null) return true; if (argType == parType) return true; if (argType.DeclaringType != null && parType.DeclaringType != null && this.InferMethodTemplateArguments(argType.DeclaringType, null, parType.DeclaringType, inferredTypeFor)) { if (argType.Template != null) argType = argType.Template; if (parType.Template != null) parType = parType.Template; return argType.Name != null && parType.Name != null && argType.Name.UniqueIdKey == parType.Name.UniqueIdKey; } return true; } else { for (int i = 0, c = argType.Interfaces == null ? 0 : argType.Interfaces.Count; i < c; i++) { Interface aintf = argType.Interfaces[i]; if (aintf == null) return false; if (this.InferMethodTemplateArguments(aintf, null, parType, inferredTypeFor)) return true; } Class cl = argType as Class; if (cl != null) return this.InferMethodTemplateArguments(cl.BaseClass, null, parType, inferredTypeFor); } } if (argType == parType) return true; if (argType.DeclaringType != null && parType.DeclaringType != null && this.InferMethodTemplateArguments(argType.DeclaringType, null, parType.DeclaringType, inferredTypeFor)) return argType.Name != null && parType.Name != null && argType.Name.UniqueIdKey == parType.Name.UniqueIdKey; if (argExpr != null && argType == SystemTypes.Delegate) { DelegateNode parDelegate = parType as DelegateNode; Method meth = argExpr.BoundMember as Method; if (meth != null && parDelegate != null) { // match up parameters and results int numArgs1 = meth.Parameters == null ? 0 : meth.Parameters.Count; int numArgs2 = parDelegate.Parameters == null ? 0 : parDelegate.Parameters.Count; if (numArgs1 == numArgs2) { for (int j = 0; j < numArgs1; j++) { if (!InferMethodTemplateArguments(meth.Parameters[j].Type, null, parDelegate.Parameters[j].Type, inferredTypeFor)) return false; } // do result type return InferMethodTemplateArguments(meth.ReturnType, null, parDelegate.ReturnType, inferredTypeFor); } } } return this.typeSystem.ImplicitCoercionFromTo(argType, parType); }
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); } }
public FindLocalsInActuals(TrivialHashtable target) { this.localsFound = target; }
public virtual AttributeList VisitAttributeList(AttributeList attributes, Node target) { if (attributes == null) return null; TypeNode targetType = target as TypeNode; TrivialHashtable alreadyPresent = null; for (int i = 0, n = attributes.Count; i < n; i++) { AttributeNode attr = attributes[i]; if (attr == null) continue; if (!attr.AllowMultiple) { TypeNode attrType = attr.Type; if (attrType == null) continue; if (alreadyPresent == null) alreadyPresent = new TrivialHashtable(); else if (alreadyPresent[attrType.UniqueKey] != null) { if (attr.Constructor.SourceContext.Document != null) { Error e = Error.None; AttributeTargets attrTarget = attr.Target; for (int j = 0; j < i; j++) { AttributeNode a = attributes[j]; if (a == null) a = alreadyPresent[attrType.UniqueKey] as AttributeNode; if (a == null) continue; if (a.Type == attr.Type && a.Target == attrTarget) { e = Error.DuplicateAttribute; break; } } if (e != Error.None) this.HandleError(attr.Constructor, e, attr.Constructor.SourceContext.SourceText); } attributes[i] = null; continue; } alreadyPresent[attrType.UniqueKey] = attr; } attributes[i] = this.VisitAttributeNode(attributes[i], target); } return attributes; }
public void SetPragmaWarnInformation(TrivialHashtable pragmaWarnInformation) { this.PragmaWarnInformation = pragmaWarnInformation; }
public override TypeNode VisitTypeNode(TypeNode typeNode) { if (typeNode == null) return null; TypeNode savedCurrentType = this.currentType; if (typeNode.IsNormalized) { this.currentType = this.typeSystem.currentType = typeNode; this.VisitMemberList(typeNode.Members); this.currentType = this.typeSystem.currentType = savedCurrentType; return typeNode; } if (typeNode.Template == this.currentType && typeNode.IsNotFullySpecialized) return typeNode; if (typeNode.PartiallyDefines != null) { if (this.visitedCompleteTypes == null) this.visitedCompleteTypes = new TrivialHashtable(); if (this.visitedCompleteTypes[typeNode.PartiallyDefines.UniqueKey] == null) { this.VisitTypeNode(typeNode.PartiallyDefines); this.visitedCompleteTypes[typeNode.PartiallyDefines.UniqueKey] = typeNode; } return typeNode; } typeNode.Attributes = this.VisitAttributeList(typeNode.Attributes); //Flatten interface list InterfaceList interfaces = this.GetTypeView(typeNode).Interfaces; for (int i = 0, n = interfaces == null ? 0 : interfaces.Count; i < n; i++) { Interface iface = interfaces[i]; if (iface == null || iface is TypeParameter) continue; if (this.GetTypeView(iface).IsAssignableTo(typeNode)) { this.HandleError(typeNode.Name, Error.CycleInInterfaceInheritance, this.GetTypeName(iface), this.GetTypeName(typeNode)); if (iface != typeNode) this.HandleRelatedError(iface); for (int j = i; j < n-1; j++) interfaces[j] = interfaces[j+1]; interfaces.Count = n-1; continue; } if (typeNode.NodeType == NodeType.Interface) { if (this.IsLessAccessible(iface, typeNode)) { this.HandleError(typeNode.Name, Error.BaseInterfaceLessAccessible, this.GetTypeName(iface), this.GetTypeName(typeNode)); this.HandleRelatedError(iface); } } InterfaceList inheritedInterfaces = this.GetTypeView(iface).Interfaces; int m = inheritedInterfaces == null ? 0 : inheritedInterfaces.Count; for (int j = 0; j < m; j++) { Interface iiface = inheritedInterfaces[j]; if (iiface == null) continue; bool mustAddInterface = true; for (int k = 0; k < n; k++) { if (interfaces[k] == iiface) { mustAddInterface = false; break; } } if (mustAddInterface) { interfaces.Add(iiface); n++; } } } typeNode.Attributes = this.VisitAttributeList(typeNode.Attributes, typeNode); this.currentType = this.typeSystem.currentType = typeNode; this.CheckHidingAndOverriding(typeNode); #region Deal with modelfields that are inherited from implemented interfaces. if (typeNode is Class) { StringCollection implementedModelfields = new StringCollection(); //contains the names of modelfields implemented so far foreach (Interface implInterface in typeNode.Interfaces) { if (implInterface == null) continue; //Why is Interfaces initialized to a List with a single null element? Means this check is essential. if (implInterface.Contract != null) { foreach (ModelfieldContract mfCToImplement in implInterface.Contract.ModelfieldContracts) { #region implement mfCToImplement in typeNode String fieldnameToImplement = mfCToImplement.Modelfield.Name.Name; if (implementedModelfields.Contains(fieldnameToImplement)) { this.HandleError(typeNode, Error.GenericError, "Class " + typeNode.Name.Name + " cannot implement two interfaces that both define a model field " + fieldnameToImplement); continue; //ignore this contract //Disallowed to prevent the unexpected modification of a modelfield in one interface by changing a modelfield in another interface. } else { implementedModelfields.Add(fieldnameToImplement); ModelfieldContract mfCThatImplements = null; //represents the contract that will implement mfCToImplement Member implementingMember = null; #region if typeNode or a superclass already defines a member named fieldNameToImplement, store it in implementingMember. for (TypeNode classWithField = typeNode; classWithField != null && implementingMember == null; classWithField = classWithField.BaseType) { MemberList members = this.GetTypeView(classWithField).GetMembersNamed(mfCToImplement.Modelfield.Name); foreach (Member m in members) { if (m.Name.Name == fieldnameToImplement) { implementingMember = m; break; //implementing member found; stop looking } } } #endregion #region if there is an implentingMember: if it is a modelfield in typeNode, then store its contract in mfCThatImplements, else complain if (implementingMember != null && implementingMember.DeclaringType != typeNode) { this.HandleError(typeNode, Error.GenericError, "Class " + typeNode.Name.Name + " does not define a model field " + fieldnameToImplement + " that implements " + mfCToImplement.Modelfield.FullName + " and hides " + implementingMember.FullName); this.HandleRelatedError(mfCToImplement.Modelfield); this.HandleRelatedError(implementingMember); //TODO: suppress error typeNode does not implement implInterface.fieldnameToImplement.get continue; //ignore this contract //Disallowed to prevent the unexpected modification of a superclass member by changing a modelfield in an interface/the unexpected hiding of a superclass member by a modelfield in an interface. } if (implementingMember != null && !(implementingMember is Field && (implementingMember as Field).IsModelfield)) { this.HandleError(typeNode, Error.GenericError, "Class " + typeNode.Name.Name + " cannot implement " + mfCToImplement.Modelfield.FullName + " as it contains a non-modelfield member of that name"); this.HandleRelatedError(mfCToImplement.Modelfield); this.HandleRelatedError(implementingMember); //TODO: suppress error typeNode does not implement implInterface.fieldnameToImplement.get continue; //ignore this contract } if (implementingMember != null) { //typeNode defines a modelfield (i.e., implementingMember) that can implement mfCToImplement Debug.Assert(typeNode.Contract != null); //a class that defines a modelfield must have a modelfieldcontract that applies to it. foreach (ModelfieldContract mfC in typeNode.Contract.ModelfieldContracts) if (mfC.Modelfield == implementingMember) { mfCThatImplements = mfC; break; } Debug.Assert(mfCThatImplements != null); } #endregion #region if there is no implementingMember: add a new modelfield + contract to typeNode and store contract in mfCThatImplements //TODO: Unfortunately, qualified identifiers have already been resolved: currently references to the modelfield will produce an error. if (implementingMember == null) { Identifier mfIdent = new Identifier(mfCToImplement.Modelfield.Name.Name); mfCThatImplements = new ModelfieldContract(typeNode, new AttributeList(), mfCToImplement.ModelfieldType, mfIdent, typeNode.SourceContext); Field mf = (mfCThatImplements.Modelfield as Field); mf.SourceContext = mfCToImplement.SourceContext; //the modelfield does not appear in the code but implements mfCToImplement. typeNode.Members.Add(mf); if (typeNode.Contract == null) typeNode.Contract = new TypeContract(typeNode); typeNode.Contract.ModelfieldContracts.Add(mfCThatImplements); } #endregion #region Implement the property and property getter that represent mfCToImplement, let getter return mfCThatImplements.Modelfield //assert typeNode.Contract.ModelfieldContracts.Contains(mfCThatImplements); //create Property: // public <mfCThatImplements.ModelfieldType> <mfCThatImplements.Modelfield.Name> // ensures result == <mfCThatImplements.Modelfield>; // { [Confined] get { return <mfCThatImplements.Modelfield>; } } // Note that getter needs to be confined because it inherits NoDefaultContract MemberBinding thisMf = new MemberBinding(new This(typeNode), mfCThatImplements.Modelfield); Statement ret = new Return(thisMf); Method getter = new Method(typeNode, new AttributeList(), (mfCToImplement.Modelfield as Property).Getter.Name, new ParameterList(), mfCThatImplements.ModelfieldType, new Block(new StatementList(ret))); getter.Flags = MethodFlags.Public; getter.CallingConvention = CallingConventionFlags.HasThis; if (getter.Contract == null) { getter.Contract = new MethodContract(getter); } Expression resultOfGet = new ReturnValue(getter.ReturnType, mfCToImplement.SourceContext); BinaryExpression b = new BinaryExpression(resultOfGet, thisMf, NodeType.Eq, mfCToImplement.SourceContext); b.Type = SystemTypes.Boolean; //Give getter Confined (as it has NoDefaultContract) // That means make it [Pure][Reads(Reads.Owned)] InstanceInitializer pCtor = SystemTypes.PureAttribute.GetConstructor(); if (pCtor != null) getter.Attributes.Add(new AttributeNode(new MemberBinding(null, pCtor), null, AttributeTargets.Method)); InstanceInitializer rCtor = SystemTypes.ReadsAttribute.GetConstructor(); // can use nullary ctor since default is confined if (rCtor != null) getter.Attributes.Add(new AttributeNode(new MemberBinding(null, rCtor), null, AttributeTargets.Method)); getter.Contract.Ensures.Add(new EnsuresNormal(b)); Identifier implPropName = new Identifier(mfCToImplement.Modelfield.FullName, mfCToImplement.SourceContext); //use full name as typeNode might define modelfield with this name itself. Property implementingProperty = new Property(typeNode, new AttributeList(), PropertyFlags.None, implPropName, getter, null); typeNode.Members.Add(implementingProperty); typeNode.Members.Add(getter); #endregion #region Copy the info from mfCToImplement to typeNode's mfCThatImplements foreach (Expression satClause in mfCToImplement.SatisfiesList) mfCThatImplements.SatisfiesList.Add(satClause); //Don't copy the explicit witness from the implemented contract: can likely infer a better one. #endregion } #endregion } } } } #endregion //needs to happen after CheckHidingAndOverriding, but before CheckAbstractMethods. this.CheckAbstractMethods(typeNode); //TODO: suppress duplicate errors generated by template instances this.CheckCircularDependency(typeNode); this.CheckForDuplicateDeclarations(typeNode); // must do this *after* CheckForDuplicateDeclarations this.CheckForInterfaceImplementationsOfOutOfBandContractedMethods(typeNode); this.CheckOperatorOverloads(typeNode); if (typeNode is Class && typeNode.IsSealed) this.CheckForNewFamilyOrVirtualMembers(typeNode); this.VisitTemplateInstanceTypes(typeNode); this.CheckContractInheritance(typeNode); TypeNode result = base.VisitTypeNode(typeNode); #region infer and serialize witnesses where needed (for modelfields and pure methods). ALSO infers postconditions. if (this.currentOptions != null && !this.currentOptions.DisablePublicContractsMetadata && !this.currentOptions.DisableInternalContractsMetadata) { //Note that this code could move to the boogie end, except that we need a runtime witness for modelfields. //We need to show that the contract of a modelfield mf is consistent in order to use the associated axioms. //An inferred witness is a guess at an expression e that will satisfy the contract, i.e., //an expression e such that for each satisfies clause p, p[e/mf] holds. Checking this witness is left to Boogie. if (typeNode.Contract != null) { foreach (ModelfieldContract mfC in typeNode.Contract.ModelfieldContracts) { if (mfC.ModelfieldType == null) continue; //signals error, but will be reported elsewhere Expression satisfies = null; foreach (Expression sat in mfC.SatisfiesList) { //construct a single expression to take advantage of the fact that multiple clauses act as an && if (sat == null) continue; if (satisfies == null) satisfies = sat; else satisfies = new BinaryExpression(sat, satisfies, NodeType.LogicalAnd, SystemTypes.Boolean); } WUCs witnesses = Checker.GetWitnesses(satisfies, mfC.Modelfield, mfC.ModelfieldType); this.SerializeWUCs(witnesses, mfC); //also serializes explicitly specified witnesses. if (mfC.Witness == null) { //we need to set a witness as runtime witness (do this afterwards as it will be serialized otherwise) //But as we have only one runtime witness, we can't guarantuee that we pick the right one. For now, just hope for the best. if (witnesses.RuntimeWitness != null) mfC.Witness = witnesses.RuntimeWitness; else mfC.Witness = this.GetInferredWitness(mfC); //this calculates a runtime witness } } } foreach (Member m in typeNode.Members) { Method method = m as Method; if (method == null || method.ReturnType == null) continue; if (!method.IsPure && !method.IsConfined && !method.IsStateIndependent) continue; if (method.CciKind != CciMemberKind.Regular) continue; //no need to check consistency of methodology method contracts if (method.ReturnType == SystemTypes.Void) continue; //no witness needed for void #region infer potential method contract witnesses and add them as WitnessAttributes //A pure method can be used in specifications and assert statements. //Therefore, we need to show that the contract of a pure method is consistent in order to use purity axioms. //An inferred witness is a guess at an expression e that will satisfy all postconditions, i.e., //an expression e such that for each postcondition p, p[e/result] holds. Checking this witness is left to Boogie. Expression postcondition = null; if (method.Contract != null) { foreach (Ensures ens in method.Contract.Ensures) { if (ens.PostCondition != null) { if (postcondition == null) postcondition = ens.PostCondition; else postcondition = new BinaryExpression(ens.PostCondition, postcondition, NodeType.LogicalAnd, SystemTypes.Boolean); } } } WUCs witnesses = Checker.GetWitnesses(postcondition, null, method.ReturnType); #region find witnesses in method code and infer postconditions if (method.Body != null && method.Body.Statements != null) { WitnessFromCodeFinderVisitor codeWitnessFinder = new WitnessFromCodeFinderVisitor(); if (!method.IsVirtual && //don't infer postcondition: the absence might be intentional, to give overriding method more freedom (method.Contract == null || method.Contract.Ensures.Count == 0)) //don't infer post if user specified a postcondition { //look for inferred postconditions codeWitnessFinder.methodToInferPostFrom = method; } codeWitnessFinder.VisitStatementList(method.Body.Statements); if (method.ReturnType != SystemTypes.Boolean && method.ReturnType.NodeType != NodeType.EnumNode) //check if all possible witnesses have already been added, finder was only run to infer postconditions foreach (Expression witness in codeWitnessFinder.Witnesses) witnesses.Exact.Add(new WitnessUnderConstruction(witness, null, 0)); } #endregion this.SerializeWUCs(witnesses, method); #endregion } } #endregion // do this here so the serialized contracts reflect any modifications made during Checker // serialized contracts should be pre-Normalized ASTs, *but* they should not reflect // any contract inheritance that has happened. // Note that this (possibly) adds things to the Attributes of the typeNode // Those attribute nodes will not be checked as part of Checker this.SerializeContracts(typeNode); this.currentType = this.typeSystem.currentType = savedCurrentType; return result; }
public Looker(Scope scope, Cci.ErrorHandler errorHandler, TrivialHashtable scopeFor, TrivialHashtable ambiguousTypes, TrivialHashtable referencedLabels) : base(scope, errorHandler, scopeFor, new TypeSystem(new ErrorHandler(errorHandler.Errors)), ambiguousTypes, referencedLabels) { this.alreadyReported[StandardIds.Var.UniqueIdKey] = true; }
public virtual void CheckForDuplicateDeclarations(TypeNode type) { if (type == null) return; MemberList members = type.Members; // just check the members syntactically in this type or extension if (members == null) return; bool partialType = type.PartiallyDefines != null; if (partialType) type = type.PartiallyDefines; TrivialHashtable firstDeclaration = new TrivialHashtable(); for (int i = 0, n = members.Count; i < n; i++) { Member mem = members[i]; if (mem == null) continue; Identifier name = mem.Name; if (name == null) continue; if (partialType) { //Do not check injected constructors for duplication InstanceInitializer ctor = mem as InstanceInitializer; if (ctor != null && ctor.HasCompilerGeneratedSignature && (ctor.Parameters == null || ctor.Parameters.Count == 0)) { continue; } StaticInitializer cctor = mem as StaticInitializer; if (cctor != null && cctor.HasCompilerGeneratedSignature) continue; } int key = name.UniqueIdKey; object fmem = firstDeclaration[key]; if (fmem == null) { firstDeclaration[key] = mem; // check this type's member against all like-named members everywhere else: MemberList potentialDups = this.GetTypeView(type).GetMembersNamed(name); if (name.UniqueIdKey == StandardIds.opImplicit.UniqueIdKey) { MemberList explicits = this.GetTypeView(type).GetMembersNamed(StandardIds.opExplicit); int k = explicits == null ? 0 : explicits.Count; if (k > 0) { potentialDups = potentialDups.Clone(); for (int j = 0; j < k; j++) potentialDups.Add(explicits[j]); } } this.CheckForDuplicateDeclarations(mem, potentialDups); } } }
static Checker() { OperatorName = new TrivialHashtable(); OperatorName[StandardIds.opAddition.UniqueIdKey] = "operator +"; OperatorName[StandardIds.opBitwiseAnd.UniqueIdKey] = "operator &"; OperatorName[StandardIds.opBitwiseOr.UniqueIdKey] = "operator |"; OperatorName[StandardIds.opDecrement.UniqueIdKey] = "operator --"; OperatorName[StandardIds.opDivision.UniqueIdKey] = "operator /"; OperatorName[StandardIds.opEquality.UniqueIdKey] = "operator =="; OperatorName[StandardIds.opExclusiveOr.UniqueIdKey] = "operator ^"; OperatorName[StandardIds.opExplicit.UniqueIdKey] = "explicit operator"; OperatorName[StandardIds.opFalse.UniqueIdKey] = "operator false"; OperatorName[StandardIds.opGreaterThan.UniqueIdKey] = "operator >"; OperatorName[StandardIds.opGreaterThanOrEqual.UniqueIdKey] = "operator >="; OperatorName[StandardIds.opImplicit.UniqueIdKey] = "implicit operator"; OperatorName[StandardIds.opIncrement.UniqueIdKey] = "operator ++"; OperatorName[StandardIds.opInequality.UniqueIdKey] = "operator !="; OperatorName[StandardIds.opLeftShift.UniqueIdKey] = "operator <<"; OperatorName[StandardIds.opLessThan.UniqueIdKey] = "operator <"; OperatorName[StandardIds.opLessThanOrEqual.UniqueIdKey] = "operator <="; OperatorName[StandardIds.opLogicalNot.UniqueIdKey] = "operator !"; OperatorName[StandardIds.opModulus.UniqueIdKey] = "operator %"; OperatorName[StandardIds.opMultiply.UniqueIdKey] = "operator *"; OperatorName[StandardIds.opOnesComplement.UniqueIdKey] = "operator ~"; OperatorName[StandardIds.opRightShift.UniqueIdKey] = "operator >>"; OperatorName[StandardIds.opSubtraction.UniqueIdKey] = "operator -"; OperatorName[StandardIds.opTrue.UniqueIdKey] = "operator true"; OperatorName[StandardIds.opUnaryNegation.UniqueIdKey] = "operator -"; OperatorName[StandardIds.opUnaryPlus.UniqueIdKey] = "operator +"; }
public override void CompileParseTree(Compilation compilation, ErrorNodeList errorNodes) { if (compilation == null) { Debug.Assert(false, "wrong compilation"); return; } CONTEXT.useComputeMath = ((ZonnonCompilerParameters)compilation.CompilerParameters).UseComputeMath; // Before the actual back-end compilation takes place, // we perform the Zonnon-tree to CCI-tree conversion. // Notice that we do that for the overall tree (i.e., for all sources) // and store the resulting CCI tree to CompilationUnits[0], // but do not spread subtrees to corresponding CompilationUnits. ERROR.errCount = 0; Parser.ConvertTree(compilation.CompilationUnits[0]); bool mainCompilationFailed = ERROR.errCount > 0; // ERROR.EndOfMessages(); // Module symbolTable = compilation.TargetModule; // compilation.GlobalScope = this.GetGlobalScope(symbolTable); ZonnonCompilerParameters options = compilation.CompilerParameters as ZonnonCompilerParameters; if (options == null) { options = new ZonnonCompilerParameters(); } // Walk IR looking up names #if DEBUG if (options.Debug) { System.Console.Write("Scoper is working..."); } #endif ErrorHandler eh = new ErrorHandler(errorNodes); TrivialHashtable ambiguousTypes = new TrivialHashtable(); TrivialHashtable referencedLabels = new TrivialHashtable(); TrivialHashtable scopeFor = new TrivialHashtable(); TypeSystem typeSystem = new TypeSystem(eh); Scoper scoper = new Scoper(scopeFor); scoper.VisitCompilation(compilation); #if DEBUG if (options.Debug) { System.Console.WriteLine("Done."); System.Console.Write("Looker is working... "); } #endif Looker looker = new Looker(compilation.GlobalScope, eh, scopeFor, typeSystem, ambiguousTypes, referencedLabels); looker.VisitCompilation(compilation); // Walk IR inferring types and resolving overloads if (!mainCompilationFailed) // Resolve only if no errors { Resolver resolver = new Resolver(eh, typeSystem); resolver.VisitCompilation(compilation); // Walk IR checking for semantic errors and repairing it so that it the next walk will work Checker checker = new Checker(eh, typeSystem, ambiguousTypes, referencedLabels); checker.VisitCompilation(compilation); // Walk IR reducing it to nodes that have predefined mappings to MD+IL Normalizer normalizer = new Normalizer(typeSystem); normalizer.VisitCompilation(compilation); Analyzer analyzer = new Analyzer(typeSystem, compilation); analyzer.VisitCompilation(compilation); } #if DEBUG if (options.Debug) { System.Console.WriteLine("Done."); } #endif }
public virtual AttributeNode VisitPropertyAttribute(AttributeNode attr, Property property) { if (attr == null || property == null) return null; ExpressionList args = attr.Expressions; MemberBinding mb = attr.Constructor as MemberBinding; if (mb == null || mb.BoundMember == null) return null; if (mb.BoundMember.DeclaringType == SystemTypes.IndexerNameAttribute) { if (property.OverridesBaseClassMember) this.HandleError(attr, Error.IndexerNameAttributeOnOverride); else if (property.ImplementedTypes != null && property.ImplementedTypes.Count > 0) this.HandleError(attr, Error.AttributeOnBadTarget, "IndexerName", "non interface implementation property"); if (args == null || args.Count < 1) { Debug.Assert(false); return null; } Literal lit = args[0] as Literal; if (lit == null) return null; string indexerName = lit.Value as string; if (indexerName == null) { this.HandleError(args[0], Error.InvalidAttributeArgument, "IndexerName"); return null; } if (!this.IsValidIdentifier(indexerName)) { this.HandleError(args[0], Error.IndexerNameNotIdentifier); return null; } Identifier id = new Identifier(indexerName); if (this.indexerNames == null) this.indexerNames = new TrivialHashtable(); Identifier previousName = (Identifier)this.indexerNames[this.currentType.UniqueKey]; if (previousName == null) this.indexerNames[this.currentType.UniqueKey] = id; else if (previousName.UniqueIdKey != id.UniqueIdKey) { this.HandleError(args[0], Error.InconsistantIndexerNames); id = new Identifier(previousName.ToString()); } id.SourceContext = property.Name.SourceContext; property.Name = id; if (property.Getter != null && property.Getter.Name != null) { id = new Identifier("get_" + indexerName); id.SourceContext = property.Getter.Name.SourceContext; property.Getter.Name = id; } if (property.Setter != null && property.Setter.Name != null) { id = new Identifier("set_" + indexerName); id.SourceContext = property.Setter.Name.SourceContext; property.Setter.Name = id; } attr.IsPseudoAttribute = true; return attr; } return attr; }
public SubstituteParameters(TrivialHashtable map, List <Parameter> parameters) { this.map = map; this.parameters = parameters; }
/// <summary> /// This method checks all of the methods in a class or structure to make sure that /// if the method implements an interface method (either explicitly or implicitly), /// then the contract inheritance rules are not violated. /// /// It also introduces the default expose block around the body of whichever methods /// should get the default. /// </summary> /// <param name="type">The type that will have all of its methods checked.</param> public virtual void CheckContractInheritance(TypeNode type) { if (type == null || type is Interface) return; InterfaceList ifaces = this.GetTypeView(type).Interfaces; for (int i = 0, n = ifaces == null ? 0 : ifaces.Count; i < n; i++) { Interface iface = ifaces[i]; if (iface == null) continue; TrivialHashtable processedContracts = new TrivialHashtable(); MemberList members = this.GetTypeView(iface).Members; for (int j = 0, m = members == null ? 0 : members.Count; j < m; j++) { Method meth = members[j] as Method; if (meth == null) continue; processedContracts[meth.UniqueKey] = meth; Method impl = this.GetTypeView(type).GetImplementingMethod(meth, false); //Look only in type and get explicit implementation if (impl == null || impl.ImplementedInterfaceMethods == null || impl.ImplementedInterfaceMethods.Count == 0) impl = this.GetTypeView(type).GetImplementingMethod(meth, true); //No explicit interface method was found, look again, this time looking only at public methods, but including base types if (impl == null) continue; // If this is an error, then it will get caught in other methods in Checker. if (impl.Contract != null && impl.Contract.OriginalDeclaringMethod != null) { if (processedContracts[impl.Contract.OriginalDeclaringMethod.UniqueKey] != null) continue; } bool ifaceHasThrows = false; bool overriddenMethodHasThrows = false; for (int ensuresIndex = 0, ensuresLength = meth.Contract == null || meth.Contract.Ensures == null ? 0 : meth.Contract.Ensures.Count; ensuresIndex < ensuresLength; ensuresIndex++) { EnsuresExceptional e = meth.Contract.Ensures[ensuresIndex] as EnsuresExceptional; if (e != null) { ifaceHasThrows = true; break; } } for (int ensuresIndex = 0, ensuresLength = impl.OverriddenMethod == null || impl.OverriddenMethod.Contract == null || impl.OverriddenMethod.Contract.Ensures == null ? 0 : impl.OverriddenMethod.Contract.Ensures.Count; ensuresIndex < ensuresLength; ensuresIndex++) { EnsuresExceptional e = impl.OverriddenMethod.Contract.Ensures[ensuresIndex] as EnsuresExceptional; if (e != null) { overriddenMethodHasThrows = true; break; } } if (impl.OverriddenMethod != null) { if (ifaceHasThrows || overriddenMethodHasThrows) { this.HandleError(type.Name, Error.ContractInheritanceRulesViolated, this.GetMethodSignature(meth), this.GetMethodSignature(impl)); continue; } } bool ok = true; if (impl.DeclaringType != type) { // Then the implementation for the interface method has been inherited. Figure out if // there are any contract inheritance violations. ok |= this.CheckContractRules(meth, impl, type); } } } // MB - 01/06/2005 - commented out, but leave here because at some point we may want to introduce // the defaults here again. They are currently introduced in Normalizer. // #region Introduce Specsharp-specific defaults for each method // // REVIEW: Other types besides classes? // // MB: 04 January 2005: Change default expose around body to a default precondition of this.IsConsistent // if (this.GetTypeView(type).IsAssignableTo(SystemTypes.IGuardedObject) && type.NodeType == NodeType.Class // && type.GetAttribute(SystemTypes.NoDefaultActivityAttribute) == null){ // MemberList members = this.Members; // just check the members syntactically in this type or extension // for (int i = 0, n = members == null ? 0 : members.Length; i < n; i++){ // Method m = members[i] as Method; // if (m == null) continue; // if (m.IsAbstract || m.IsStatic) continue; // if (m.HasCompilerGeneratedSignature) continue; // if (m.NodeType == NodeType.InstanceInitializer || m.NodeType == NodeType.StaticInitializer) // continue; // if (m.Body == null || m.Body.Statements == null || !(m.Body.Statements.Length > 0)) // continue; // if (m.GetAttribute(SystemTypes.NoDefaultActivityAttribute) != null) // continue; // if (m.Contract == null){ // m.Contract = new MethodContract(); // } // if (m.Contract.Requires == null){ // m.Contract.Requires = new RequiresList(1); // } // m.Contract.Requires.Add(new RequiresPlain( // new MethodCall(new MemberBinding(new This(type),SystemTypes.IGuardedObject_IsConsistent.Getter),new ExpressionList(),NodeType.Callvirt,SystemTypes.Boolean) // )); // } // } // #endregion Introduce Specsharp-specific defaults for each method return; }
public virtual Differences VisitUsedNamespaceList(UsedNamespaceList list1, UsedNamespaceList list2, out UsedNamespaceList changes, out UsedNamespaceList deletions, out UsedNamespaceList insertions){ changes = list1 == null ? null : list1.Clone(); deletions = list1 == null ? null : list1.Clone(); insertions = list1 == null ? new UsedNamespaceList() : list1.Clone(); //^ assert insertions != null; Differences differences = new Differences(); for (int j = 0, n = list2 == null ? 0 : list2.Count; j < n; j++){ //^ assert list2 != null; UsedNamespace nd2 = list2[j]; if (nd2 == null) continue; insertions.Add(null); } TrivialHashtable savedDifferencesMapFor = this.differencesMapFor; this.differencesMapFor = null; TrivialHashtable matchedNodes = new TrivialHashtable(); for (int i = 0, k = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){ //^ assert list1 != null && changes != null && deletions != null; UsedNamespace nd1 = list1[i]; if (nd1 == null) continue; Differences diff; int j; UsedNamespace nd2 = this.GetClosestMatch(nd1, list1, list2, i, ref k, matchedNodes, out diff, out j); if (nd2 == null || diff == null){Debug.Assert(nd2 == null && diff == null); continue;} matchedNodes[nd1.UniqueKey] = nd1; matchedNodes[nd2.UniqueKey] = nd2; changes[i] = diff.Changes as UsedNamespace; deletions[i] = diff.Deletions as UsedNamespace; insertions[i] = diff.Insertions as UsedNamespace; insertions[n+j] = nd1; //Records the position of nd2 in list2 in case the change involved a permutation Debug.Assert(diff.Changes == changes[i] && diff.Deletions == deletions[i] && diff.Insertions == insertions[i]); differences.NumberOfDifferences += diff.NumberOfDifferences; differences.NumberOfSimilarities += diff.NumberOfSimilarities; } //Find deletions for (int i = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){ //^ assert list1 != null && changes != null && deletions != null; UsedNamespace nd1 = list1[i]; if (nd1 == null) continue; if (matchedNodes[nd1.UniqueKey] != null) continue; changes[i] = null; deletions[i] = nd1; insertions[i] = null; differences.NumberOfDifferences += 1; } //Find insertions for (int j = 0, n = list1 == null ? 0 : list1.Count, m = list2 == null ? 0 : list2.Count; j < m; j++){ //^ assert list2 != null; UsedNamespace nd2 = list2[j]; if (nd2 == null) continue; if (matchedNodes[nd2.UniqueKey] != null) continue; insertions[n+j] = nd2; //Records nd2 as an insertion into list1, along with its position in list2 differences.NumberOfDifferences += 1; //REVIEW: put the size of the tree here? } if (differences.NumberOfDifferences == 0){ changes = null; deletions = null; insertions = null; } this.differencesMapFor = savedDifferencesMapFor; return differences; }
public override MethodContract VisitMethodContract(MethodContract contract) { if (contract == null) return null; // don't visit contract.DeclaringMethod // don't visit contract.OverriddenMethods bool savedInsideMethodContract = this.insideMethodContract; bool savedUnsafe = this.typeSystem.insideUnsafeCode; this.insideMethodContract = true; Yield savedYield = this.yieldNode; Method method = contract.DeclaringMethod; insidePureContract = method.IsPure || method.IsConfined || method.IsStateIndependent; if (method != null) { this.typeSystem.insideUnsafeCode = method.IsUnsafe; if (contract.Ensures != null && contract.Ensures.Count > 0) { TrivialHashtable /*TypeNode*/ throwsSet = new TrivialHashtable(); for (int i = 0, n = contract.Ensures.Count; i < n; i++) { EnsuresExceptional e = contract.Ensures[i] as EnsuresExceptional; if (e == null) continue; if (e.Inherited) continue; if (e.Type == null) continue; if (!this.GetTypeView(e.Type).IsAssignableTo(SystemTypes.ICheckedException)) { this.HandleError(e, Error.UncheckedExceptionInThrowsClause, this.GetTypeName(method.DeclaringType) + "." + method.Name.ToString()); contract.Ensures[i] = null; } if (throwsSet[e.Type.UniqueKey] != null) { this.HandleError(method, Error.DuplicateThrowsType, this.GetTypeName(method.DeclaringType) + "." + method.Name.ToString()); contract.Ensures[i] = null; } else { throwsSet[e.Type.UniqueKey] = e.Type; } } } contract.Requires = this.VisitRequiresList(contract.Requires); InstanceInitializer ctor = this.currentMethod as InstanceInitializer; bool savedMayReferenceThisAndBase = this.MayReferenceThisAndBase; if (ctor != null) { // method contracts are visited as part of visiting the methods to which they // are attached. So their ability to reference "this" is usually the same as // the method's ability. But the postcondition of a ctor can mention instance // variables. this.MayReferenceThisAndBase = true; } bool savedInsideEnsures = this.insideEnsures; this.insideEnsures = true; contract.Ensures = this.VisitEnsuresList(contract.Ensures); this.insideEnsures = savedInsideEnsures; this.MayReferenceThisAndBase = savedMayReferenceThisAndBase; bool savedInsideModifies = this.insideModifies; this.insideModifies = true; contract.Modifies = this.VisitExpressionList(contract.Modifies); this.insideModifies = savedInsideModifies; //if (method.IsVirtual) { // // use FindNearest..., can't rely on method.OverriddenMethod since it might not be set further up the chain // Method overridden = method.DeclaringType.FindNearestOverriddenMethod(method); // if (overridden != null) { // this.CheckEnsuresListsCompatibility(overridden, method); // } // for (int i = 0, n = method.ImplementedInterfaceMethods == null ? 0 : method.ImplementedInterfaceMethods.Count; i < n; i++) { // Method ifaceMethod = method.ImplementedInterfaceMethods[i]; // this.CheckEnsuresListsCompatibility(ifaceMethod, method); // } // for (int i = 0, n = method.ImplicitlyImplementedInterfaceMethods == null ? 0 : method.ImplicitlyImplementedInterfaceMethods.Count; i < n; i++) { // Method ifaceMethod = method.ImplicitlyImplementedInterfaceMethods[i]; // this.CheckEnsuresListsCompatibility(ifaceMethod, method); // } //} } this.insideMethodContract = savedInsideMethodContract; this.typeSystem.insideUnsafeCode = savedUnsafe; this.yieldNode = savedYield; return contract; }
public virtual Differences GetMemberDifferences(Member member1, Member member2) { if (member1 == null || member2 == null) return new Differences(member1, member2); if (this.memberDifferencesMapFor == null) this.memberDifferencesMapFor = new TrivialHashtable(); TrivialHashtable map = this.memberDifferencesMapFor[member1.UniqueKey] as TrivialHashtable; if (map == null) this.memberDifferencesMapFor[member1.UniqueKey] = map = new TrivialHashtable(); Differences differences = map[member2.UniqueKey] as Differences; if (differences == null){ map[member2.UniqueKey] = differences = new Differences(member1, member2); if (member1 == member2) differences.NumberOfSimilarities++; } return differences; }
public override Namespace VisitNamespace(Namespace nspace) { nspace = base.VisitNamespace(nspace); if (nspace == null) return null; TypeNodeList types = nspace.Types; UsedNamespaceList usedNspaces = nspace.UsedNamespaces; if (usedNspaces != null) { TrivialHashtable alreadyUsedNamespaces = new TrivialHashtable(); for (int i = 0, n = usedNspaces.Count; i < n; i++) { UsedNamespace uns = usedNspaces[i]; if (uns == null || uns.Namespace == null) continue; if (alreadyUsedNamespaces[uns.Namespace.UniqueIdKey] != null) this.HandleError(uns.Namespace, Error.DuplicateUsedNamespace, uns.Namespace.ToString()); alreadyUsedNamespaces[uns.Namespace.UniqueIdKey] = uns; this.VisitUsedNamespace(usedNspaces[i]); } } AliasDefinitionList aliasDefinitions = nspace.AliasDefinitions; if (aliasDefinitions != null) { TrivialHashtable alreadyUsedAliases = new TrivialHashtable(); for (int i = 0, n = aliasDefinitions == null ? 0 : aliasDefinitions.Count; i < n; i++) { AliasDefinition aliasDef = aliasDefinitions[i]; if (aliasDef == null) continue; AliasDefinition dup = (AliasDefinition)alreadyUsedAliases[aliasDef.Alias.UniqueIdKey]; if (dup == null) alreadyUsedAliases[aliasDef.Alias.UniqueIdKey] = aliasDef; else { this.HandleError(aliasDef.Alias, Error.DuplicateAliasDefinition, nspace.Name.ToString(), aliasDef.Alias.ToString()); this.HandleError(dup.Alias, Error.RelatedErrorLocation); continue; } if (aliasDef.ConflictingType != null) { string nsName = nspace.Name == null || nspace.Name == Identifier.Empty ? "<global namespace>" : nspace.Name.ToString(); this.HandleError(aliasDef.Alias, Error.ConflictBetweenAliasAndType, nsName, aliasDef.Alias.ToString()); this.HandleRelatedError(aliasDef.ConflictingType); } } } return nspace; }
public override Method VisitMethod(Method method) { // body might not have been materialized, so make sure we do that first! Block body = method.Body; if (method == null) { return(null); } BlockSorter blockSorter = new BlockSorter(); BlockList sortedBlocks = blockSorter.SortedBlocks; this.SucessorBlock = blockSorter.SuccessorBlock; this.StackLocalsAtEntry = new TrivialHashtable(); this.localsStack = new LocalsStack(); ExceptionHandlerList ehandlers = method.ExceptionHandlers; for (int i = 0, n = ehandlers == null ? 0 : ehandlers.Count; i < n; i++) { ExceptionHandler ehandler = ehandlers[i]; if (ehandler == null) { continue; } Block handlerStart = ehandler.HandlerStartBlock; if (handlerStart == null) { continue; } LocalsStack lstack = new LocalsStack(); this.StackLocalsAtEntry[handlerStart.UniqueKey] = lstack; if (ehandler.HandlerType == NodeType.Catch) { lstack.exceptionHandlerType = CoreSystemTypes.Object; if (ehandler.FilterType != null) { lstack.exceptionHandlerType = ehandler.FilterType; } } else if (ehandler.HandlerType == NodeType.Filter) { lstack.exceptionHandlerType = CoreSystemTypes.Object; if (ehandler.FilterExpression != null) { lstack = new LocalsStack(); lstack.exceptionHandlerType = CoreSystemTypes.Object; this.StackLocalsAtEntry[ehandler.FilterExpression.UniqueKey] = lstack; } } } blockSorter.VisitMethodBody(body); for (int i = 0, n = sortedBlocks.Count; i < n; i++) { Block b = sortedBlocks[i]; if (b == null) { Debug.Assert(false); continue; } this.VisitBlock(b); } return(method); }
public Scoper(TrivialHashtable scopeFor) { this.ScopeFor = scopeFor; }