private void IdentifyClass(ClassDecl classDecl) { _allMethods[classDecl.Module].Add(classDecl, new List<Method>()); foreach (var member in classDecl.Members) if (member is Method) { _allMethods[classDecl.Module][classDecl].Add((Method) member); _allRemovableTypes.AddMember(member); } }
public override AstNode VisitClassDecl(ClassDecl ast) { if (ast.BaseClass.TypeName != null) { //resolve base class var baseTypeName = ast.BaseClass.TypeName.Content; if (!m_types.Contains(baseTypeName)) { m_errorManager.AddError(c_SE_TypeNameMissing, ast.BaseClass.TypeName.Span, baseTypeName); //leave ast.BaseClass.Type empty } else { var type = m_types[baseTypeName] as CodeClassType; Debug.Assert(type != null); if (type.IsStatic) { m_errorManager.AddError(c_SE_StaticBaseType, ast.BaseClass.TypeName.Span, baseTypeName); } ast.BaseClass.Type = type; (ast.Type as CodeClassType).BaseType = type; } } //resolve member decl types //fields foreach (var field in ast.Fields) { field.FieldInfo = new Field() { DeclaringType = ast.Type }; Visit(field); } //methods foreach (var method in ast.Methods) { method.MethodInfo = new Method() { DeclaringType = ast.Type }; Visit(method); } return ast; }
public override AstNode VisitClassDecl(ClassDecl ast) { var name = ast.Name.Value; if (m_types.Contains(name)) { m_errorManager.AddError(c_SE_TypeNameDuplicates, ast.Name.Span, name); return ast; } var classType = new CodeClassType() { Name = name }; m_types.Add(classType); ast.Type = classType; return ast; }
private void FindRemovableTypesInMethod(Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { if (method.Body == null) { return; } var block = method.Body; foreach (var statement in block.Body) { FindRemovableTypesInStatement(statement, block, method, wildCardParent, classDecl); } }
internal TypeValue(ClassDecl declaration) { QualifiedName = declaration.QualifiedName; Declaration = declaration; }
private void CheckClassesAreRefinements(ClassDecl nw, ClassDecl d) { if (nw.TypeArgs.Count != d.TypeArgs.Count) { reporter.Error(MessageSource.RefinementTransformer, nw, "a refining class ({0}) must have the same number of type parameters", nw.Name); } else { var map = new Dictionary<string, MemberDecl>(); foreach (var mem in nw.Members) { map.Add(mem.Name, mem); } foreach (var m in d.Members) { MemberDecl newMem; if (map.TryGetValue(m.Name, out newMem)) { if (m.HasStaticKeyword != newMem.HasStaticKeyword) { reporter.Error(MessageSource.RefinementTransformer, newMem, "member {0} must {1}", m.Name, m.HasStaticKeyword ? "be static" : "not be static"); } if (m is Field) { if (newMem is Field) { var newField = (Field)newMem; if (!ResolvedTypesAreTheSame(newField.Type, ((Field)m).Type)) reporter.Error(MessageSource.RefinementTransformer, newMem, "field must be refined by a field with the same type (got {0}, expected {1})", newField.Type, ((Field)m).Type); if (m.IsGhost || !newField.IsGhost) reporter.Error(MessageSource.RefinementTransformer, newField, "a field re-declaration ({0}) must be to ghostify the field", newField.Name, nw.Name); } else { reporter.Error(MessageSource.RefinementTransformer, newMem, "a field declaration ({1}) must be replaced by a field in the refinement base (not {0})", newMem.Name, nw.Name); } } else if (m is Method) { if (newMem is Method) { CheckMethodsAreRefinements((Method)newMem, (Method)m); } else { reporter.Error(MessageSource.RefinementTransformer, newMem, "method must be refined by a method"); } } else if (m is Function) { if (newMem is Function) { CheckFunctionsAreRefinements((Function)newMem, (Function)m); } else { reporter.Error(MessageSource.RefinementTransformer, newMem, "{0} must be refined by a {0}", m.WhatKind); } } } else { reporter.Error(MessageSource.RefinementTransformer, nw is DefaultClassDecl ? nw.Module.tok : nw.tok, "refining {0} must have member {1}", nw is DefaultClassDecl ? "module" : "class", m.Name); } } } }
private void CompileMethod(ClassDecl c, Method m) { Contract.Assert(c != null); Contract.Assert(m != null); Contract.Assert(m.Body != null); VarTracker.Clear(); if (m.TypeArgs.Count != 0) { // Template expansion isn't supported j.WriteComment("BUGBUG: Type args not supported: omitting method " + m.FullCompileName); return; } if (IsUnsupportedMethod(m.Name, m.Outs, m.Ins)) { return; } using (WriteArray()) { j.WriteValue(KremlinAst.DFunction); using (WriteArray()) { // of (CallingConvention.t option * flag list * typ * lident * binder list * expr) WriteDefaultCallingConvention(); using (WriteArray()) { // empty flag list } WriteMethodReturnType(m.Outs); // typ WriteLident(m); // lident using (WriteArray()) { // start of binder list WriteFormals(m.Ins); } using (WriteArray()) { j.WriteValue(KremlinAst.ESequence); using (WriteArray()) { List<Formal> Outs = new List<Formal>(m.Outs); if (!(m is Constructor)) { WriteEPushFrame(); } foreach (Formal p in Outs) { // bugbug: this now needs to be hoisted out and made recursive if (!p.IsGhost) { // ELet v in { Stmt j.WriteStartArray(); j.WriteValue(KremlinAst.ELet); j.WriteStartArray(); WriteBinder(p, p.Name, true); // lident WriteDefaultValue(p.Type); // = default VarTracker.Push(p); // "in" is the contents that follow j.WriteStartArray(); j.WriteValue(KremlinAst.ESequence); j.WriteStartArray(); WriteEUnit(); } } if (m.IsTailRecursive) { // Note that Dafny conservatively flags functions as possibly-tail-recursive. This does not acutally // indicate the function is tail recursive, or even recursive. j.WriteComment("WARNING: IsTailRecursive not supported but the method may not recurse"); // bugbug: implement } Contract.Assert(enclosingMethod == null); enclosingMethod = m; TrStmtList(m.Body.Body); Contract.Assert(enclosingMethod == m); enclosingMethod = null; if (!(m is Constructor)) { WriteEPopFrame(); } if (m.Outs.Count != 0) { var ReturnValue = m.Outs[0]; WriteEBound(ReturnValue); } Outs.Reverse(); foreach (var l in Outs) { VarTracker.Pop(l); j.WriteEndArray(); // Closing out the expr list in the ESequence j.WriteEndArray(); // Closing out the array aboce ESequence j.WriteEndArray(); // Closing out the list of binder * expr * expr j.WriteEndArray(); // Closing out the array above ELet } } } } } }
public override void Visit(ClassDecl classDeclaration) { VisitTopLevelDeclarationWithMembers(classDeclaration, () => base.Visit(classDeclaration)); }
private void FindRemovableTypesInIfStmt(IfStmt ifstmt, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { FindRemovableTypesInStatement(ifstmt.Thn, ifstmt, method, wildCardParent, classDecl); FindRemovableTypesInStatement(ifstmt.Els, ifstmt, method, wildCardParent, classDecl); }
/// <summary> /// Tries to get class and return in second parameter. /// </summary> /// <param name="className">Class name</param> /// <param name="declaration">out parameter with result</param> /// <returns>true if class exists</returns> public bool TryGetClass(QualifiedName className, out ClassDecl declaration) { return(nativeObjects.TryGetValue(className, out declaration)); }
private void FindRemovableTypesInStatement(Statement statement, Statement parent, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { if (statement is AssertStmt) FindRemovableTypesInAssertStmt((AssertStmt) statement, parent, method); else if (statement is BlockStmt) FindRemovableTypesInBlockStmt((BlockStmt) statement, method, wildCardParent, classDecl); else if (statement is IfStmt) FindRemovableTypesInIfStmt((IfStmt) statement, method, wildCardParent, classDecl); else if (statement is LoopStmt) FindRemovableTypesInLoopStmt((LoopStmt) statement, method, wildCardParent, classDecl); else if (statement is MatchStmt) FindRemovableTypesInMatchStmt((MatchStmt) statement, method, wildCardParent, classDecl); else if (statement is ForallStmt) FindRemovableTypesInForallStmt((ForallStmt) statement, method, wildCardParent, classDecl); else if (statement is CalcStmt) FindRemovableTypesInCalcStmt((CalcStmt) statement, parent, method, wildCardParent, classDecl); else if (statement is UpdateStmt) FindRemovableTypesInUpdateStmt((UpdateStmt) statement, parent, method, classDecl); }
private void FindRemovableTypesInCalcStmt(CalcStmt calc, Statement parent, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { Wrap<Statement> calcWrap = null; if (parent is BlockStmt) calcWrap = new Wrap<Statement>(calc, ((BlockStmt)parent).Body); else if (parent is MatchStmt) { var matchStmt = (MatchStmt) parent; foreach (var matchCase in matchStmt.Cases) { if (!matchCase.Body.Contains(calc)) continue; calcWrap = new Wrap<Statement>(calc, matchCase.Body); break; } if (calcWrap == null) throw new Exception("Calc not found!"); } else { throw new Exception("Calc not found!"); } _allRemovableTypes.AddCalc(calcWrap, method); foreach (var hint in calc.Hints) { FindRemovableTypesInStatement(hint, calc, method, wildCardParent, classDecl); // This will check the inside of the hint - it will ID anything that can be shortened inside it. } }
public ASTDiff(ClassDecl src, ClassDecl tgt, bool exploreExpr = true) { this.src = new ASTClassNode(src, null, exploreExpr); this.tgt = new ASTClassNode(tgt, null, exploreExpr); }
private void FindRemovableTypesInMethod(Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { if (method.Body == null) return; var block = method.Body; foreach (var statement in block.Body) FindRemovableTypesInStatement(statement, block, method, wildCardParent, classDecl); }
public ASTClassNode(ClassDecl Class, ASTNode parent, bool exploreExpr = true) : base(parent) { this.Class = Class; this.exploreExpr = exploreExpr; initHeight(); }
static SymbolDecl[] ParseSymbolInternal(string[] tokens, ref int index) { if (CppParser.Token(tokens, ref index, "public") || CppParser.Token(tokens, ref index, "protected") || CppParser.Token(tokens, ref index, "private")) { index--; return(null); } TemplateDecl templateDecl = null; if (CppParser.Token(tokens, ref index, "template")) { templateDecl = new TemplateDecl { TypeParameters = new List <TypeParameterDecl>(), Specialization = new List <TypeDecl>(), }; CppParser.EnsureToken(tokens, ref index, "<"); if (!CppParser.Token(tokens, ref index, ">")) { while (true) { string token = null; CppParser.SkipUntilInTemplate(tokens, ref index, out token, ",", ">", "="); index -= 2; templateDecl.TypeParameters.Add(new TypeParameterDecl { Name = CppParser.EnsureId(tokens, ref index), }); index++; if (token == "=") { CppParser.SkipUntilInTemplate(tokens, ref index, out token, ",", ">"); } if (token == ">") { break; } } } } if (CppParser.Token(tokens, ref index, "friend")) { int oldIndex = index - 1; string token = null; CppParser.SkipUntil(tokens, ref index, out token, ";", "{"); if (token == ";") { return(null); } else { index = oldIndex; tokens[index] = "static"; } } if (CppParser.Token(tokens, ref index, "namespace")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } var decl = new NamespaceDecl(); decl.Name = CppParser.EnsureId(tokens, ref index); CppParser.EnsureToken(tokens, ref index, "{"); ParseSymbols(tokens, ref index, decl); CppParser.EnsureToken(tokens, ref index, "}"); return(new SymbolDecl[] { decl }); } else if (CppParser.Token(tokens, ref index, "using")) { if (CppParser.Token(tokens, ref index, "namespace")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } var decl = new UsingNamespaceDecl(); decl.Path = new List <string>(); decl.Path.Add(CppParser.EnsureId(tokens, ref index)); while (!CppParser.Token(tokens, ref index, ";")) { CppParser.EnsureToken(tokens, ref index, ":"); CppParser.EnsureToken(tokens, ref index, ":"); decl.Path.Add(CppParser.EnsureId(tokens, ref index)); } return(new SymbolDecl[] { decl }); } else { string name = null; if (CppParser.Id(tokens, ref index, out name)) { if (templateDecl != null) { if (CppParser.Token(tokens, ref index, "<")) { while (true) { templateDecl.Specialization.Add(CppTypeParser.EnsureTypeWithoutNameInTemplate(tokens, ref index)); if (CppParser.Token(tokens, ref index, ">")) { break; } CppParser.EnsureToken(tokens, ref index, ","); } } } if (CppParser.Token(tokens, ref index, "=")) { SymbolDecl decl = new TypedefDecl { Name = name, Type = CppTypeParser.EnsureTypeWithoutName(tokens, ref index), }; CppParser.EnsureToken(tokens, ref index, ";"); if (templateDecl != null) { templateDecl.Element = decl; decl = templateDecl; } return(new SymbolDecl[] { decl }); } } if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } CppParser.SkipUntil(tokens, ref index, ";"); } } else if (CppParser.Token(tokens, ref index, "typedef")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } string name = null; var type = CppTypeParser.EnsureTypeWithName(tokens, ref index, out name); CppParser.EnsureToken(tokens, ref index, ";"); var decl = new TypedefDecl(); decl.Name = name; decl.Type = type; return(new SymbolDecl[] { decl }); } else if (CppParser.Token(tokens, ref index, "enum")) { if (templateDecl != null) { throw new ArgumentException("Failed to parse."); } bool enumClass = CppParser.Token(tokens, ref index, "class"); string name = CppParser.EnsureId(tokens, ref index); if (CppParser.Token(tokens, ref index, ":")) { CppTypeParser.EnsureTypeWithoutName(tokens, ref index); } if (!CppParser.Token(tokens, ref index, ";")) { CppParser.EnsureToken(tokens, ref index, "{"); var decl = new EnumDecl { Name = name, EnumClass = enumClass, Children = new List <SymbolDecl>(), }; while (true) { if (CppParser.Token(tokens, ref index, "}")) { break; } string document = null; while (index < tokens.Length && tokens[index].Length >= 3 && tokens[index].StartsWith("///")) { var line = tokens[index]; if (document == null) { document = ""; } document += line.StartsWith("/// ") || line.StartsWith("///\t") ? line.Substring(4) : line.Substring(3); document += "\r\n"; index++; } decl.Children.Add(new EnumItemDecl { Name = CppParser.EnsureId(tokens, ref index), Document = document, }); string token = null; CppParser.SkipUntil(tokens, ref index, out token, ",", "}"); if (token == "}") { break; } } if (CppParser.Id(tokens, ref index, out name)) { var varDecl = new VarDecl { Static = false, Name = name, Type = new RefTypeDecl { Name = decl.Name, }, }; CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl, varDecl }); } else { CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl }); } } } else if (CppParser.Token(tokens, ref index, "struct") || CppParser.Token(tokens, ref index, "class") || CppParser.Token(tokens, ref index, "union")) { if (CppParser.Token(tokens, ref index, "{")) { if (tokens[index - 2] == "class") { throw new ArgumentException("Failed to parse."); } var decl = new GroupedFieldDecl { Grouping = tokens[index - 2] == "struct" ? Grouping.Struct : Grouping.Union, }; ParseSymbols(tokens, ref index, decl); CppParser.EnsureToken(tokens, ref index, "}"); CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl }); } else { string name = CppParser.EnsureId(tokens, ref index); if (!CppParser.Token(tokens, ref index, ";")) { var classDecl = new ClassDecl { ClassType = tokens[index - 2] == "struct" ? ClassType.Struct : tokens[index - 2] == "class" ? ClassType.Class : ClassType.Union, BaseTypes = new List <BaseTypeDecl>(), Name = name, }; if (templateDecl != null) { if (CppParser.Token(tokens, ref index, "<")) { if (!CppParser.Token(tokens, ref index, ">")) { while (true) { int oldIndex = index; templateDecl.Specialization.Add(CppTypeParser.EnsureTypeWithoutNameInTemplate(tokens, ref index)); if (CppParser.Token(tokens, ref index, ">")) { break; } CppParser.EnsureToken(tokens, ref index, ","); } } } } CppParser.Token(tokens, ref index, "abstract"); if (CppParser.Token(tokens, ref index, ":")) { while (true) { Access access = classDecl.ClassType == ClassType.Class ? Access.Private : Access.Public; CppParser.Token(tokens, ref index, "virtual"); if (CppParser.Token(tokens, ref index, "private")) { access = Access.Private; } else if (CppParser.Token(tokens, ref index, "protected")) { access = Access.Protected; } else if (CppParser.Token(tokens, ref index, "public")) { access = Access.Public; } CppParser.Token(tokens, ref index, "virtual"); classDecl.BaseTypes.Add(new BaseTypeDecl { Access = access, Type = CppTypeParser.EnsureTypeWithoutName(tokens, ref index), }); if (!CppParser.Token(tokens, ref index, ",")) { break; } } } CppParser.EnsureToken(tokens, ref index, "{"); while (true) { if (CppParser.Token(tokens, ref index, "}")) { break; } Access access = classDecl.ClassType == ClassType.Class ? Access.Private : Access.Public; if (CppParser.Token(tokens, ref index, "private")) { access = Access.Private; CppParser.EnsureToken(tokens, ref index, ":"); } else if (CppParser.Token(tokens, ref index, "protected")) { access = Access.Protected; CppParser.EnsureToken(tokens, ref index, ":"); } else if (CppParser.Token(tokens, ref index, "public")) { access = Access.Public; CppParser.EnsureToken(tokens, ref index, ":"); } ParseSymbols(tokens, ref index, classDecl, access); } SymbolDecl decl = classDecl; if (templateDecl != null) { templateDecl.Element = decl; decl = templateDecl; } if (CppParser.Id(tokens, ref index, out name)) { var varDecl = new VarDecl { Static = false, Name = name, Type = new RefTypeDecl { Name = classDecl.Name, }, }; CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl, varDecl }); } else { CppParser.EnsureToken(tokens, ref index, ";"); return(new SymbolDecl[] { decl }); } } } } else if (!CppParser.Token(tokens, ref index, ";")) { Function function = Function.Function; { int oldIndex = index; string name = null; if (CppParser.Id(tokens, ref index, out name)) { if (CppParser.Token(tokens, ref index, "(")) { CppParser.SkipUntil(tokens, ref index, ")"); if (CppParser.Token(tokens, ref index, ";") || CppParser.Token(tokens, ref index, "=") || CppParser.Token(tokens, ref index, ":") || CppParser.Token(tokens, ref index, "{")) { function = Function.Constructor; } } index = oldIndex; } else if (CppParser.Token(tokens, ref index, "~")) { function = Function.Destructor; } } if (function == Function.Function) { Virtual virtualFunction = Virtual.Normal; CppParser.Token(tokens, ref index, "extern"); CppParser.Token(tokens, ref index, "mutable"); if (CppParser.Token(tokens, ref index, "virtual")) { virtualFunction = Virtual.Virtual; } else if (CppParser.Token(tokens, ref index, "static")) { virtualFunction = Virtual.Static; } CppParser.Token(tokens, ref index, "inline"); CppParser.Token(tokens, ref index, "__forceinline"); if (CppParser.Token(tokens, ref index, "operator")) { TypeDecl returnType = null; { int oldIndex = index; CppParser.SkipUntilInTemplate(tokens, ref index, "("); int modify = --index; tokens[modify] = "$"; index = oldIndex; returnType = CppTypeParser.EnsureTypeWithoutName(tokens, ref index); if (index != modify) { throw new ArgumentException("Failed to parse."); } tokens[modify] = "("; } var decl = new FuncDecl { Virtual = Virtual.Normal, Name = "operator", Function = function, }; TypeDecl functionType = null; Action <TypeDecl> continuation = null; CallingConvention callingConvention = CallingConvention.Default; CppTypeParser.ParseTypeContinueAfterName(tokens, ref index, ref callingConvention, out functionType, out continuation); continuation(returnType); decl.Type = functionType; if (!CppParser.Token(tokens, ref index, ";")) { CppParser.EnsureToken(tokens, ref index, "{"); CppParser.SkipUntil(tokens, ref index, "}"); } if (templateDecl != null) { templateDecl.Element = decl; return(new SymbolDecl[] { templateDecl }); } else { return(new SymbolDecl[] { decl }); } } else { string name = null; TypeDecl type = null; if (CppTypeParser.ParseType(tokens, ref index, out type, out name)) { if (name == null) { throw new ArgumentException("Failed to parse."); } if (type is FunctionTypeDecl) { if (CppParser.Token(tokens, ref index, "=")) { if (CppParser.Token(tokens, ref index, "0")) { virtualFunction = Virtual.Abstract; } else { CppParser.EnsureToken(tokens, ref index, "default", "delete"); } } var decl = new FuncDecl { Virtual = virtualFunction, Name = name, Type = type, Function = Function.Function, }; { var funcType = (FunctionTypeDecl)type; var returnType = funcType.ReturnType as RefTypeDecl; if (returnType != null && returnType.Name == "auto") { if (CppParser.Token(tokens, ref index, "-")) { CppParser.EnsureToken(tokens, ref index, ">"); TypeDecl newReturnType = CppTypeParser.EnsureTypeWithoutName(tokens, ref index); funcType.ReturnType = newReturnType; } } if (!CppParser.Token(tokens, ref index, ";")) { CppParser.EnsureToken(tokens, ref index, "{"); CppParser.SkipUntil(tokens, ref index, "}"); } } if (templateDecl != null) { templateDecl.Element = decl; return(new SymbolDecl[] { templateDecl }); } else { return(new SymbolDecl[] { decl }); } } else { if (virtualFunction != Virtual.Normal && virtualFunction != Virtual.Static) { throw new ArgumentException("Failed to parse."); } if (CppParser.Token(tokens, ref index, "=")) { CppParser.SkipUntil(tokens, ref index, ";"); } else if (CppParser.Token(tokens, ref index, "{")) { CppParser.SkipUntil(tokens, ref index, "}"); } else { CppParser.EnsureToken(tokens, ref index, ";"); } if (!(type is ClassMemberTypeDecl)) { var decl = new VarDecl { Static = virtualFunction == Virtual.Static, Name = name, Type = type, }; return(new SymbolDecl[] { decl }); } } } } } else { var decl = new FuncDecl { Virtual = Virtual.Normal, Name = (function == Function.Constructor ? "" : "~") + CppParser.EnsureId(tokens, ref index), Function = function, }; TypeDecl functionType = null; Action <TypeDecl> continuation = null; CallingConvention callingConvention = CallingConvention.Default; CppTypeParser.ParseTypeContinueAfterName(tokens, ref index, ref callingConvention, out functionType, out continuation); continuation(new RefTypeDecl { Name = "void" }); decl.Type = functionType; if (CppParser.Token(tokens, ref index, "=")) { CppParser.EnsureToken(tokens, ref index, "default", "delete"); } if (!CppParser.Token(tokens, ref index, ";")) { if (CppParser.Token(tokens, ref index, ":")) { do { CppTypeParser.EnsureMiniType(tokens, ref index); if (CppParser.Token(tokens, ref index, "(")) { CppParser.SkipUntil(tokens, ref index, ")"); } else if (CppParser.Token(tokens, ref index, "{")) { CppParser.SkipUntil(tokens, ref index, "}"); } else { throw new ArgumentException("Failed to parse."); } }while (CppParser.Token(tokens, ref index, ",")); } CppParser.EnsureToken(tokens, ref index, "{"); CppParser.SkipUntil(tokens, ref index, "}"); } if (templateDecl != null) { templateDecl.Element = decl; return(new SymbolDecl[] { templateDecl }); } else { return(new SymbolDecl[] { decl }); } } } return(null); }
protected override BlockTargetWriter CreateClass(TargetWriter wr, ClassDecl cl) { return(CreateInternalClass(wr, cl.CompileName)); }
private void FindRemovableTypesInCalcStmt(CalcStmt calc, Statement parent, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { Wrap <Statement> calcWrap = null; if (parent is BlockStmt) { calcWrap = new Wrap <Statement>(calc, ((BlockStmt)parent).Body); } else if (parent is MatchStmt) { var matchStmt = (MatchStmt)parent; foreach (var matchCase in matchStmt.Cases) { if (!matchCase.Body.Contains(calc)) { continue; } calcWrap = new Wrap <Statement>(calc, matchCase.Body); break; } if (calcWrap == null) { throw new Exception("Calc not found!"); } } else { throw new Exception("Calc not found!"); } _allRemovableTypes.AddCalc(calcWrap, method); foreach (var hint in calc.Hints) { FindRemovableTypesInStatement(hint, calc, method, wildCardParent, classDecl); // This will check the inside of the hint - it will ID anything that can be shortened inside it. } }
private void FindRemovableTypesInForallStmt(ForallStmt forall, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { FindRemovableTypesInStatement(forall.Body, forall, method, wildCardParent, classDecl); }
private void FindRemovableTypesInMatchStmt(MatchStmt match, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { foreach (var matchCase in match.Cases) { foreach (var stmt in matchCase.Body) { FindRemovableTypesInStatement(stmt, match, method, wildCardParent, classDecl); } } }
private void FindRemovableTypesInMatchStmt(MatchStmt match, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { foreach (var matchCase in match.Cases) foreach (var stmt in matchCase.Body) FindRemovableTypesInStatement(stmt, match, method, wildCardParent, classDecl); }
private void FindRemovableTypesInUpdateStmt(UpdateStmt updateStmt, List <Statement> parent, Method method, ClassDecl classDecl) { foreach (var expr in updateStmt.Rhss) { if (!IsAssignmentLemmaCall(expr, classDecl)) { continue; } _allRemovableTypes.AddLemmaCall(new Wrap <Statement>(updateStmt, parent), method); } }
private void FindRemovableTypesInLoopStmt(LoopStmt loopStmt, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { GetLoopInvariants(loopStmt, method); IdentifyRemovableDecreasesTypesInLoop(loopStmt, method, ref wildCardParent); if (!(loopStmt is WhileStmt)) return; var whileStmt = (WhileStmt) loopStmt; FindRemovableTypesInStatement(whileStmt.Body, loopStmt, method, wildCardParent, classDecl); }
bool WriteClassStruct(ClassDecl c, bool forCompanionClass) { Contract.Requires(c != null); // Don't write out a struct with no members, as it isn't valid C if (c.InheritedMembers.Count == 0) { bool HasNoMembers = true; foreach (MemberDecl member in c.Members) { if (member is Field) { var f = (Field)member; if (f.IsGhost || forCompanionClass) { // emit nothing } else { HasNoMembers = false; break; } } } if (HasNoMembers) { j.WriteComment("Not writing class struct " + c.FullCompileName + " as it has no non-ghost members"); return false; } } using (WriteArray()) { j.WriteValue(KremlinAst.DTypeFlat); // of (lident * (ident * (typ * bool)) list) using (WriteArray()) { WriteLident(c.FullName); using (WriteArray()) { // list foreach (var member in c.InheritedMembers) { Contract.Assert(!member.IsGhost && !member.IsStatic); // only non-ghost instance members should ever be added to .InheritedMembers j.WriteComment("Inherited member"); using (WriteArray()) { if (member is Field) { var f = (Field)member; using (WriteArray()) { // (ident * (typ * bool)) j.WriteValue(f.Name); using (WriteArray()) { WriteTypeName(f.Type); j.WriteValue(true); // mutable } } } } } foreach (MemberDecl member in c.Members) { if (member is Field) { var f = (Field)member; if (f.IsGhost || forCompanionClass) { // emit nothing } else if (c is TraitDecl) { WriteToken(member.tok); j.WriteComment("BUGBUG TraitDecl not supported: " + f.CompileName); // bugbug: implement } else { using (WriteArray()) { // (ident * (typ * bool)) j.WriteValue(f.Name); using (WriteArray()) { WriteTypeName(f.Type); j.WriteValue(true); } } } } } } } } return true; }
private void CompileMethod(ClassDecl c, int indent, Method m, TextWriter wr) { Indent(indent, wr); wr.Write("public {0}void @{1}", m.IsStatic ? "static " : "", m.CompileName); if (m.TypeArgs.Count != 0) { wr.Write("<{0}>", TypeParameters(m.TypeArgs)); } wr.Write("("); int nIns = WriteFormals("", m.Ins, wr); WriteFormals(nIns == 0 ? "" : ", ", m.Outs, wr); wr.WriteLine(")"); Indent(indent, wr); wr.WriteLine("{"); foreach (Formal p in m.Outs) { if (!p.IsGhost) { Indent(indent + IndentAmount, wr); wr.WriteLine("@{0} = {1};", p.CompileName, DefaultValue(p.Type, wr)); } } if (m.Body == null) { Error("Method {0} has no body", wr, m.FullName); } else { if (m.IsTailRecursive) { if (!m.IsStatic) { Indent(indent + IndentAmount, wr); wr.WriteLine("var _this = this;"); } Indent(indent, wr); wr.WriteLine("TAIL_CALL_START: ;"); } Contract.Assert(enclosingMethod == null); enclosingMethod = m; TrStmtList(m.Body.Body, indent, wr); Contract.Assert(enclosingMethod == m); enclosingMethod = null; } Indent(indent, wr); wr.WriteLine("}"); // allow the Main method to be an instance method if (IsMain(m) && (!m.IsStatic || m.CompileName != "Main")) { Indent(indent, wr); wr.WriteLine("public static void Main(string[] args) {"); if (!m.IsStatic) { Contract.Assert(m.EnclosingClass == c); Indent(indent + IndentAmount, wr); wr.Write("@{0} b = new @{0}", c.CompileName); if (c.TypeArgs.Count != 0) { // instantiate every parameter, it doesn't particularly matter how wr.Write("<"); string sep = ""; for (int i = 0; i < c.TypeArgs.Count; i++) { wr.Write("{0}int", sep); sep = ", "; } wr.Write(">"); } wr.WriteLine("();"); Indent(indent + IndentAmount, wr); wr.WriteLine("b.@{0}();", m.CompileName); } else { Indent(indent + IndentAmount, wr); wr.WriteLine("@{0}();", m.CompileName); } Indent(indent, wr); wr.WriteLine("}"); } }
private void FindRemovableTypesInBlockStmt(BlockStmt blockStmt, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { foreach (var stmt in blockStmt.Body) FindRemovableTypesInStatement(stmt, blockStmt, method, wildCardParent, classDecl); }
public void SetDefaultClass(ClassDecl c) { defaultClass = c; }
private void FindRemovableTypesInUpdateStmt(UpdateStmt updateStmt, List<Statement> parent, Method method, ClassDecl classDecl) { foreach (var expr in updateStmt.Rhss) { if (!IsAssignmentLemmaCall(expr, classDecl)) continue; _allRemovableTypes.AddLemmaCall(new Wrap<Statement>(updateStmt, parent), method); } }
void SymbolDecl.IVisitor.Visit(ClassDecl decl) { EntryDecl(decl); }
private void FindRemovableTypesInUpdateStmt(UpdateStmt updateStmt, Statement parent, Method method, ClassDecl classDecl) { if (parent is BlockStmt) { var blockStmt = (BlockStmt) parent; FindRemovableTypesInUpdateStmt(updateStmt, blockStmt.Body, method, classDecl); } else if (parent is MatchStmt) { var matchStmt = (MatchStmt) parent; foreach (var matchCase in matchStmt.Cases) { if (!matchCase.Body.Contains(updateStmt)) continue; FindRemovableTypesInUpdateStmt(updateStmt, matchCase.Body, method, classDecl); break; } } }
ClassDecl MergeClass(ClassDecl nw, ClassDecl prev) { CheckAgreement_TypeParameters(nw.tok, prev.TypeArgs, nw.TypeArgs, nw.Name, "class"); nw.Attributes = refinementCloner.MergeAttributes(prev.Attributes, nw.Attributes); // Create a simple name-to-member dictionary. Ignore any duplicates at this time. var declaredNames = new Dictionary<string, int>(); for (int i = 0; i < nw.Members.Count; i++) { var member = nw.Members[i]; if (!declaredNames.ContainsKey(member.Name)) { declaredNames.Add(member.Name, i); } if (prev.IsDefaultClass && refinedSigOpened.StaticMembers.ContainsKey(member.Name) && !RefinedSig.StaticMembers.ContainsKey(member.Name)) { reporter.Error(MessageSource.RefinementTransformer, member.tok, "Base module {0} imports {1} from an opened import, so it cannot be overridden. Give this declaration a unique name to disambiguate.", RefinedSig.ModuleDef.Name, member.Name); } } // Merge the declarations of prev into the declarations of m foreach (var member in prev.Members) { int index; if (!declaredNames.TryGetValue(member.Name, out index)) { var nwMember = refinementCloner.CloneMember(member); nwMember.RefinementBase = member; nw.Members.Add(nwMember); } else { var nwMember = nw.Members[index]; if (nwMember is Field) { if (member is Field && TypesAreSyntacticallyEqual(((Field)nwMember).Type, ((Field)member).Type)) { if (member.IsGhost || !nwMember.IsGhost) reporter.Error(MessageSource.RefinementTransformer, nwMember, "a field re-declaration ({0}) must be to ghostify the field", nwMember.Name, nw.Name); } else { reporter.Error(MessageSource.RefinementTransformer, nwMember, "a field declaration ({0}) in a refining class ({1}) must replace a field in the refinement base", nwMember.Name, nw.Name); } nwMember.RefinementBase = member; } else if (nwMember is Function) { var f = (Function)nwMember; bool isPredicate = f is Predicate; bool isIndPredicate = f is InductivePredicate; bool isCoPredicate = f is CoPredicate; if (!(member is Function) || (isPredicate && !(member is Predicate)) || (isIndPredicate && !(member is InductivePredicate)) || (isCoPredicate && !(member is CoPredicate)) || (f is TwoStatePredicate && !(member is TwoStatePredicate)) || (f is TwoStateFunction && (!(member is TwoStateFunction) || member is TwoStatePredicate))) { reporter.Error(MessageSource.RefinementTransformer, nwMember, "a {0} declaration ({1}) can only refine a {0}", f.WhatKind, nwMember.Name); } else if (f.IsProtected != ((Function)member).IsProtected) { reporter.Error(MessageSource.RefinementTransformer, f, "a {0} in a refinement module must be declared 'protected' if and only if the refined {0} is", f.WhatKind); } else { var prevFunction = (Function)member; if (f.Req.Count != 0) { reporter.Error(MessageSource.RefinementTransformer, f.Req[0].tok, "a refining {0} is not allowed to add preconditions", f.WhatKind); } if (f.Reads.Count != 0) { reporter.Error(MessageSource.RefinementTransformer, f.Reads[0].E.tok, "a refining {0} is not allowed to extend the reads clause", f.WhatKind); } if (f.Decreases.Expressions.Count != 0) { reporter.Error(MessageSource.RefinementTransformer, f.Decreases.Expressions[0].tok, "decreases clause on refining {0} not supported", f.WhatKind); } if (prevFunction.HasStaticKeyword != f.HasStaticKeyword) { reporter.Error(MessageSource.RefinementTransformer, f, "a function in a refining module cannot be changed from static to non-static or vice versa: {0}", f.Name); } if (!prevFunction.IsGhost && f.IsGhost) { reporter.Error(MessageSource.RefinementTransformer, f, "a function method cannot be changed into a (ghost) function in a refining module: {0}", f.Name); } else if (prevFunction.IsGhost && !f.IsGhost && prevFunction.Body != null) { reporter.Error(MessageSource.RefinementTransformer, f, "a function can be changed into a function method in a refining module only if the function has not yet been given a body: {0}", f.Name); } if (f.SignatureIsOmitted) { Contract.Assert(f.TypeArgs.Count == 0); Contract.Assert(f.Formals.Count == 0); reporter.Info(MessageSource.RefinementTransformer, f.SignatureEllipsis, Printer.FunctionSignatureToString(prevFunction)); } else { CheckAgreement_TypeParameters(f.tok, prevFunction.TypeArgs, f.TypeArgs, f.Name, "function"); CheckAgreement_Parameters(f.tok, prevFunction.Formals, f.Formals, f.Name, "function", "parameter"); if (!TypesAreSyntacticallyEqual(prevFunction.ResultType, f.ResultType)) { reporter.Error(MessageSource.RefinementTransformer, f, "the result type of function '{0}' ({1}) differs from the result type of the corresponding function in the module it refines ({2})", f.Name, f.ResultType, prevFunction.ResultType); } } Expression moreBody = null; Expression replacementBody = null; if (prevFunction.Body == null) { replacementBody = f.Body; } else if (f.Body != null) { if (isPredicate && f.IsProtected) { moreBody = f.Body; } else if (isPredicate) { reporter.Error(MessageSource.RefinementTransformer, nwMember, "a refining predicate is not allowed to extend/change the body unless it is declared 'protected'"); } else { reporter.Error(MessageSource.RefinementTransformer, nwMember, "a refining function is not allowed to extend/change the body"); } } var newF = CloneFunction(f.tok, prevFunction, f.IsGhost, f.Ens, moreBody, replacementBody, prevFunction.Body == null, f.Attributes); newF.RefinementBase = member; nw.Members[index] = newF; } } else { var m = (Method)nwMember; if (!(member is Method)) { reporter.Error(MessageSource.RefinementTransformer, nwMember, "a method declaration ({0}) can only refine a method", nwMember.Name); } else { var prevMethod = (Method)member; if (m.Req.Count != 0) { reporter.Error(MessageSource.RefinementTransformer, m.Req[0].E.tok, "a refining method is not allowed to add preconditions"); } if (m.Mod.Expressions.Count != 0) { reporter.Error(MessageSource.RefinementTransformer, m.Mod.Expressions[0].E.tok, "a refining method is not allowed to extend the modifies clause"); } // If the previous method was not specified with "decreases *", then the new method is not allowed to provide any "decreases" clause. // Any "decreases *" clause is not inherited, so if the previous method was specified with "decreases *", then the new method needs // to either redeclare "decreases *", provided a termination-checking "decreases" clause, or give no "decreases" clause and thus // get a default "decreases" loop. Specification<Expression> decreases; if (m.Decreases.Expressions.Count == 0) { // inherited whatever the previous loop used decreases = refinementCloner.CloneSpecExpr(prevMethod.Decreases); } else { if (!Contract.Exists(prevMethod.Decreases.Expressions, e => e is WildcardExpr)) { // If the previous loop was not specified with "decreases *", then the new loop is not allowed to provide any "decreases" clause. reporter.Error(MessageSource.RefinementTransformer, m.Decreases.Expressions[0].tok, "decreases clause on refining method not supported, unless the refined method was specified with 'decreases *'"); } decreases = m.Decreases; } if (prevMethod.HasStaticKeyword != m.HasStaticKeyword) { reporter.Error(MessageSource.RefinementTransformer, m, "a method in a refining module cannot be changed from static to non-static or vice versa: {0}", m.Name); } if (prevMethod.IsGhost && !m.IsGhost) { reporter.Error(MessageSource.RefinementTransformer, m, "a method cannot be changed into a ghost method in a refining module: {0}", m.Name); } else if (!prevMethod.IsGhost && m.IsGhost) { reporter.Error(MessageSource.RefinementTransformer, m, "a ghost method cannot be changed into a non-ghost method in a refining module: {0}", m.Name); } if (m.SignatureIsOmitted) { Contract.Assert(m.TypeArgs.Count == 0); Contract.Assert(m.Ins.Count == 0); Contract.Assert(m.Outs.Count == 0); reporter.Info(MessageSource.RefinementTransformer, m.SignatureEllipsis, Printer.MethodSignatureToString(prevMethod)); } else { CheckAgreement_TypeParameters(m.tok, prevMethod.TypeArgs, m.TypeArgs, m.Name, "method"); CheckAgreement_Parameters(m.tok, prevMethod.Ins, m.Ins, m.Name, "method", "in-parameter"); CheckAgreement_Parameters(m.tok, prevMethod.Outs, m.Outs, m.Name, "method", "out-parameter"); } currentMethod = m; var replacementBody = m.BodyForRefinement; if (replacementBody != null) { if (prevMethod.BodyForRefinement == null) { // cool } else { replacementBody = MergeBlockStmt(replacementBody, prevMethod.BodyForRefinement); } } var newM = CloneMethod(prevMethod, m.Ens, decreases, replacementBody, prevMethod.BodyForRefinement == null, m.Attributes); newM.RefinementBase = member; nw.Members[index] = newM; } } } } return nw; }
private bool IsAssignmentLemmaCall(AssignmentRhs expr, ClassDecl classDecl) { var exprRhs = expr as ExprRhs; if (exprRhs == null) return false; if (!(exprRhs.Expr is ApplySuffix)) return false; return IsCallToGhost((ApplySuffix) exprRhs.Expr, classDecl); }
private void FindRemovableTypesInStatement(Statement statement, Statement parent, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { if (statement is AssertStmt) { FindRemovableTypesInAssertStmt((AssertStmt)statement, parent, method); } else if (statement is BlockStmt) { FindRemovableTypesInBlockStmt((BlockStmt)statement, method, wildCardParent, classDecl); } else if (statement is IfStmt) { FindRemovableTypesInIfStmt((IfStmt)statement, method, wildCardParent, classDecl); } else if (statement is LoopStmt) { FindRemovableTypesInLoopStmt((LoopStmt)statement, method, wildCardParent, classDecl); } else if (statement is MatchStmt) { FindRemovableTypesInMatchStmt((MatchStmt)statement, method, wildCardParent, classDecl); } else if (statement is ForallStmt) { FindRemovableTypesInForallStmt((ForallStmt)statement, method, wildCardParent, classDecl); } else if (statement is CalcStmt) { FindRemovableTypesInCalcStmt((CalcStmt)statement, parent, method, wildCardParent, classDecl); } else if (statement is UpdateStmt) { FindRemovableTypesInUpdateStmt((UpdateStmt)statement, parent, method, classDecl); } }
private bool IsCallToGhost(SuffixExpr expr, ClassDecl classDecl) { var name = ""; var nameSeg = expr.Lhs as NameSegment; if (nameSeg != null) name = nameSeg.Name; // Look through all the methods within the current scope and return whether it is ghost or not return (from method in _allMethods[classDecl.Module][classDecl] where method.Name == name select method.IsGhost).FirstOrDefault(); }
public override void Visit(ClassDecl o) { }
private void FindRemovableTypesInLoopStmt(LoopStmt loopStmt, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { GetLoopInvariants(loopStmt, method); IdentifyRemovableDecreasesTypesInLoop(loopStmt, method, ref wildCardParent); if (!(loopStmt is WhileStmt)) { return; } var whileStmt = (WhileStmt)loopStmt; FindRemovableTypesInStatement(whileStmt.Body, loopStmt, method, wildCardParent, classDecl); }
void ClassDecl(ModuleDefinition/*!*/ module, out ClassDecl/*!*/ c) { Contract.Requires(module != null); Contract.Ensures(Contract.ValueAtReturn(out c) != null); IToken/*!*/ id; Type trait = null; List<Type>/*!*/ traits = new List<Type>(); Attributes attrs = null; List<TypeParameter/*!*/> typeArgs = new List<TypeParameter/*!*/>(); List<MemberDecl/*!*/> members = new List<MemberDecl/*!*/>(); IToken bodyStart; while (!(la.kind == 0 || la.kind == 70)) {SynErr(141); Get();} Expect(70); while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); if (la.kind == 52) { GenericParameters(typeArgs); } if (la.kind == 71) { Get(); Type(out trait); traits.Add(trait); while (la.kind == 22) { Get(); Type(out trait); traits.Add(trait); } } Expect(46); bodyStart = t; while (StartOf(2)) { ClassMemberDecl(members, true, false, false); } Expect(47); c = new ClassDecl(id, id.val, module, typeArgs, members, attrs, traits); c.BodyStartTok = bodyStart; c.BodyEndTok = t; }
private void FindRemovableTypesInBlockStmt(BlockStmt blockStmt, Method method, WildCardDecreases wildCardParent, ClassDecl classDecl) { foreach (var stmt in blockStmt.Body) { FindRemovableTypesInStatement(stmt, blockStmt, method, wildCardParent, classDecl); } }
public virtual void Visit(ClassDecl classDecl) { }
private void FindRemovableTypesInUpdateStmt(UpdateStmt updateStmt, Statement parent, Method method, ClassDecl classDecl) { if (parent is BlockStmt) { var blockStmt = (BlockStmt)parent; FindRemovableTypesInUpdateStmt(updateStmt, blockStmt.Body, method, classDecl); } else if (parent is MatchStmt) { var matchStmt = (MatchStmt)parent; foreach (var matchCase in matchStmt.Cases) { if (!matchCase.Body.Contains(updateStmt)) { continue; } FindRemovableTypesInUpdateStmt(updateStmt, matchCase.Body, method, classDecl); break; } } }
public void Compile() { Util.Assert(!isPrinting); string name = FunName(DafnySpec.SimpleName(typeApply.AppName())); string fullName = FunName(DafnySpec.SimpleName(typeApply.AppFullName())); bool isAxiom = Attributes.Contains(function.Attributes, "axiom"); bool isPrivate = Attributes.Contains(function.Attributes, "private"); bool hidden = Attributes.Contains(function.Attributes, "opaque"); bool isHeap = DafnySpec.IsHeapFunction(function); List <string> heapParams = isHeap ? new List <string> { "$absMem:[int][int]int" } : new List <string>(); List <string> heapArgs = isHeap ? new List <string> { "$absMem" } : new List <string>(); var formals = function.Formals; var reads = function.Reads.Where(e => e.Field != null).ToList().ConvertAll(e => new Formal(e.tok, e.FieldName, e.Field.Type, true, e.Field.IsGhost)); formals = reads.Concat(formals).ToList(); if (hidden && formals.Count == 0) { formals = new List <Formal> { new Formal(function.tok, "___dummy", Type.Bool, true, true) }; } if (hidden && !function.Name.EndsWith("_FULL")) { ClassDecl cls = (ClassDecl)function.EnclosingClass; Function full = (Function)cls.Members.Find(m => m.Name == "#" + function.Name + "_FULL"); dafnySpec.Compile_Function(full, typeApply.typeArgs); } bool isFull = hidden && function.Name.EndsWith("_FULL"); string unfullName = isFull ? name.Substring(0, name.Length - "__FULL".Length) .Replace("#", "").Replace("____HASH", "") : null; string argsNoRec = String.Join(", ", heapArgs.Concat(formals.Select(f => GhostVar(f.Name)))); List <RtlExp> reqsNoRec = minVerify ? new List <RtlExp>() : function.Req.ConvertAll(e => GhostExpression(e, true)); List <RtlExp> enssNoRec = minVerify ? new List <RtlExp>() : function.Ens.ConvertAll(e => GhostExpression(e, true)); AddTypeWellFormed(reqsNoRec, formals); AddTypeWellFormed(enssNoRec, name + "(" + argsNoRec + ")", function.IsGhost, function.ResultType); if (function.Body != null && !minVerify) { recFunName = name; stmtExprEnabled = true; GhostExpression(function.Body); function.IsRecursive = recCalls.Count != 0; stmtExprEnabled = false; stmts = new List <RtlStmt>(); recCalls = new List <List <RtlExp> >(); recFunName = null; } if (function.IsRecursive) { recFunName = name; } stmts = new List <RtlStmt>(); stmtExprEnabled = true; var bodyDecls = PushForall(); RtlExp body = (function.Body == null || minVerify) ? null : GhostExpression(function.Body); List <RtlStmt> bodyStmts = stmts; PopForall(); stmtExprEnabled = false; stmts = new List <RtlStmt>(); string parms = String.Join(", ", heapParams.Concat( formals.Select(f => GhostVar(f.Name) + ":" + TypeString(AppType(f.Type))))); string args = String.Join(", ", heapArgs.Concat( formals.Select(f => GhostVar(f.Name)))); string sep = (heapArgs.Count + formals.Count != 0) ? ", " : ""; string ret = TypeString(AppType(function.ResultType)); string recName = "rec_" + name; string decreases = null; List <RtlExp> reqs = minVerify ? new List <RtlExp>() : function.Req.ConvertAll(e => GhostExpression(e, true)); List <RtlExp> enss = minVerify ? new List <RtlExp>() : function.Ens.ConvertAll(e => GhostExpression(e, true)); AddTypeWellFormed(reqs, formals); AddTypeWellFormed(enss, name + "(" + args + ")", function.IsGhost, function.ResultType); string reqConjunct = "(true" + String.Concat(reqs.Select(e => " && (" + e + ")")) + ")"; string ensConjunct = "(true" + String.Concat(enss.Select(e => " && (" + e + ")")) + ")"; Util.Assert(!isPrinting); if (function.IsRecursive && function.Body != null && !minVerify) { decreases = DecreasesExp(function); } List <RtlExp> enssRec = null; if (function.IsRecursive && (!hidden || isFull) && body != null && !minVerify) { enssRec = function.Ens.ConvertAll(e => GhostExpression(e, true)); } isPrinting = true; var fiWriter = isPrivate ? writer : iwriter; if (function.IsRecursive && function.Body != null && !minVerify) { iwriter.WriteLine("function decreases0_" + name + "(" + parms + "):int { " + decreases + " }"); iwriter.WriteLine("function decreases_" + name + "(" + parms + "):int { if decreases0_" + name + "(" + args + ") < 0 then 0 else 1 + decreases0_" + name + "(" + args + ") }"); iwriter.WriteLine("function " + recName + "(__decreases:int, __unroll:int" + sep + parms + "):" + ret + ";"); fiWriter.WriteLine("function implementation{" + FunName("unroll") + "(__unroll), " + recName + "(__decreases, __unroll" + sep + args + ")} " + recName + "(__decreases:int, __unroll:int" + sep + parms + "):" + ret); fiWriter.WriteLine("{"); fiWriter.WriteLine(" " + body.ToString()); fiWriter.WriteLine("}"); } iwriter.WriteLine("function " + name + "(" + parms + "):" + ret + ";"); if (hidden && !isFull && !minVerify) { iwriter.WriteLine("function unhide_" + name + "(" + parms + "):bool { true }"); fiWriter.WriteLine("function implementation{unhide_" + name + "(" + args + ")} " + name + "(" + parms + "):" + ret); fiWriter.WriteLine("{"); fiWriter.WriteLine(" " + fullName + "(" + args + ")"); fiWriter.WriteLine("}"); iwriter.WriteLine("atomic ghost procedure " + GhostProcName("reveal__" + DafnySpec.SimpleName(typeApply.AppName())) + "();"); string forall = "forall " + parms + "::" + name + "(" + args + ") == " + fullName + "(" + args + ")"; iwriter.WriteLine(" ensures (" + forall + ");"); writer.WriteLine("implementation " + GhostProcName("reveal__" + DafnySpec.SimpleName(typeApply.AppName())) + "()"); writer.WriteLine("{"); writer.WriteLine(" " + forall); writer.WriteLine(" {"); writer.WriteLine(" assert unhide_" + name + "(" + args + ");"); writer.WriteLine(" }"); writer.WriteLine("}"); } if (body != null && (!hidden || isFull)) { fiWriter.WriteLine("function implementation{" + name + "(" + args + ")" + "} " + name + "(" + parms + "):" + ret); fiWriter.WriteLine("{"); if (function.IsRecursive) { fiWriter.WriteLine(" " + recName + "(decreases_" + name + "(" + args + "), 0" + sep + args + ")"); } else { fiWriter.WriteLine(" " + body.ToString()); } fiWriter.WriteLine("}"); } if (function.IsRecursive && (!hidden || isFull) && body != null && !minVerify) { AddTypeWellFormed(enssRec, recName + "(__decreases, __unroll" + sep + args + ")", function.IsGhost, function.ResultType); string ensRecConjunct = "(true" + String.Concat(enssRec.Select(e => " && (" + e + ")")) + ")"; iwriter.WriteLine("atomic ghost procedure lemma_unroll2_" + recName + "(__decreases:int, __unroll:int, __unroll2:int" + sep + parms + ");"); iwriter.WriteLine(" requires __decreases == decreases_" + name + "(" + args + ");"); iwriter.WriteLine(" ensures " + reqConjunct + " ==> " + ensRecConjunct + " && " + recName + "(__decreases, __unroll" + sep + args + ") == " + recName + "(__decreases, __unroll2" + sep + args + ");"); writer.WriteLine("implementation lemma_unroll2_" + recName + "(__decreases:int, __unroll:int, __unroll2:int" + sep + parms + ")"); writer.WriteLine("{"); writer.WriteLine(" " + bodyDecls); writer.WriteLine(" assert fun_unroll(__unroll) && fun_unroll(__unroll2);"); dafnySpec.WriteLemmas(writer, this, visibleModules, function.Attributes); writer.WriteLine(" if (" + reqConjunct + ")"); writer.WriteLine(" {"); bodyStmts.ForEach(s => writer.WriteLine(" " + s)); writer.WriteLine(" }"); foreach (List <RtlExp> recArgs in recCalls) { string rec_args = String.Join(", ", recArgs); string rec_decrease = "decreases_" + name + "(" + rec_args + ")"; writer.WriteLine(" if (0 <= " + rec_decrease + " && " + rec_decrease + " < __decreases)"); writer.WriteLine(" {"); writer.WriteLine(" call lemma_unroll2_" + recName + "(" + rec_decrease + ", __unroll + 1, __unroll2 + 1" + sep + rec_args + ");"); writer.WriteLine(" }"); } writer.WriteLine("}"); string unroll_args = "decreases_" + name + "(" + args + "), __unroll"; string unroll_args0 = "decreases_" + name + "(" + args + "), 0"; string unroll = recName + "(" + unroll_args + sep + args + ")"; string unroll0 = recName + "(" + unroll_args0 + sep + args + ")"; var lwriter = isPrivate ? writer : iwriter; string recForall = "forall __unroll:int" + sep + parms + "::" + "{fun_unroll(__unroll), " + unroll + "} " + reqConjunct + " ==> fun_unroll(__unroll) ==> " + unroll + " == " + body; lwriter.WriteLine("atomic ghost procedure lemma_unroll_" + recName + "();"); lwriter.WriteLine(" ensures (" + recForall + ");"); writer.WriteLine("implementation lemma_unroll_" + recName + "()"); writer.WriteLine("{"); dafnySpec.WriteLemmas(writer, this, visibleModules, function.Attributes); writer.WriteLine(" " + recForall); writer.WriteLine(" {"); writer.WriteLine(" " + bodyDecls); writer.WriteLine(" if (" + reqConjunct + ")"); writer.WriteLine(" {"); bodyStmts.ForEach(s => writer.WriteLine(" " + s)); writer.WriteLine(" }"); writer.WriteLine(" }"); writer.WriteLine("}"); dafnySpec.AddLemma(new LemmaCall((isPrivate ? "private##" : "") + moduleName, visibleElementType, "call lemma_unroll_" + recName + "();", false)); Func <string, string> forall = s => "forall __unroll:int" + sep + parms + "::" + "{" + s + unroll + "} " + "{fun_unroll__all(__unroll), " + unroll + "} " + reqConjunct + " ==> " + unroll + " == " + name + "(" + args + ") && " + ensConjunct; iwriter.WriteLine("atomic ghost procedure lemma_unroll_" + name + "();"); iwriter.WriteLine(" ensures (" + forall(unroll0 + ", ") + ");"); writer.WriteLine("implementation lemma_unroll_" + name + "()"); writer.WriteLine("{"); dafnySpec.WriteLemmas(writer, this, visibleModules, function.Attributes); writer.WriteLine(" " + forall("")); writer.WriteLine(" {"); writer.WriteLine(" call lemma_unroll2_" + recName + "(" + unroll_args + ", 0" + sep + args + ");"); writer.WriteLine(" if (" + reqConjunct + ")"); writer.WriteLine(" {"); enss.ForEach(e => writer.WriteLine(" assert " + e + ";")); writer.WriteLine(" }"); writer.WriteLine(" }"); writer.WriteLine("}"); dafnySpec.AddLemma(new LemmaCall(moduleName, visibleElementType, "call lemma_unroll_" + name + "();", false)); } else if (enssNoRec.Count > 0 && !minVerify) { string reqConjunctNoRec = "(true" + String.Concat(reqsNoRec.Select(e => " && (" + e + ")")) + ")"; string ensConjunctNoRec = "(true" + String.Concat(enssNoRec.Select(e => " && (" + e + ")")) + ")"; iwriter.WriteLine("function trigger_" + name + "(" + parms + "):bool { true }"); iwriter.WriteLine("atomic ghost procedure lemma_fun_ensures_" + name + "();"); string forallNoRec = "forall " + parms + "::{" + name + "(" + argsNoRec + ")}" + (isFull ? ("{" + unfullName + "(" + argsNoRec + ")}") : "") + "{trigger_" + name + "(" + argsNoRec + ")}" + "trigger_" + name + "(" + argsNoRec + ") ==> " + reqConjunctNoRec + " ==> " + ensConjunctNoRec; iwriter.WriteLine(" ensures (" + forallNoRec + ");"); if (body != null || hidden || isAxiom) { writer.WriteLine("implementation lemma_fun_ensures_" + name + "()"); writer.WriteLine("{"); dafnySpec.WriteLemmas(writer, this, visibleModules, function.Attributes); writer.WriteLine(" " + forallNoRec); writer.WriteLine(" {"); writer.WriteLine(" " + bodyDecls); writer.WriteLine(" if (" + reqConjunct + ")"); writer.WriteLine(" {"); if (isAxiom) { writer.WriteLine(" // dummy lemma body for axiom"); } else { bodyStmts.ForEach(s => writer.WriteLine(" " + s)); } writer.WriteLine(" }"); if (hidden && !isFull) { writer.WriteLine(" assert unhide_" + name + "(" + argsNoRec + ");"); } if (hidden && isFull) { writer.WriteLine(" assert unhide_" + unfullName + "(" + argsNoRec + ");"); } writer.WriteLine(" if (" + reqConjunct + ")"); writer.WriteLine(" {"); enssNoRec.ForEach(e => writer.WriteLine(" assert " + e + ";")); writer.WriteLine(" }"); writer.WriteLine(" }"); writer.WriteLine("}"); } dafnySpec.AddLemma(new LemmaCall(moduleName, visibleElementType, "call lemma_fun_ensures_" + name + "();", false)); } isPrinting = false; }
public void PrintClass(ClassDecl c, int indent, string fileBeingPrinted) { Contract.Requires(c != null); Indent(indent); PrintClassMethodHelper((c is TraitDecl) ? "trait" : "class", c.Attributes, c.Name, c.TypeArgs); string sep = " extends "; foreach (var trait in c.TraitsTyp) { wr.Write(sep); PrintType(trait); sep = ", "; } if (c.Members.Count == 0) { wr.WriteLine(" { }"); } else { wr.WriteLine(" {"); PrintMembers(c.Members, indent + IndentAmount, fileBeingPrinted); Indent(indent); wr.WriteLine("}"); } }
private void FindRemovableTypesInClass(ClassDecl classDecl) { foreach (var member in classDecl.Members) { FindRemovableTypesInMember(member, classDecl); } }
public override AstNode VisitClassDecl(ClassDecl ast) { m_currentType = GetClrType(ast.Type) as TypeBuilder; foreach (var method in ast.Methods) { Visit(method); } GetClrCtor(ast.Type); m_currentType.CreateType(); return ast; }
private void FindRemovableTypesInMember(MemberDecl member, ClassDecl classDecl) { if (member is Tactic) return; WildCardDecreases wildCardParent = null; // The parent of the current wildCard we are tracking FindDecreasesTypesInMember(member, ref wildCardParent); var method = member as Method; if (method != null) FindRemovableTypesInMethod(method, wildCardParent, classDecl); }
void CompileClassMembers(ClassDecl c) { Contract.Requires(c != null); // For C#, Dafny generates a C# class containing base members, class // fields, methods, and functions all together. // // For Kremlin, a class will generate a struct (a Kremlin DTypeFlat) // followed by functions (Kremlin DFunction), with explicit "this" // parameters. bool forCompanionClass = false; // bugbug: implement // Generate the DTypeFlat struct representing the class if (!WriteClassStruct(c, forCompanionClass)) { // No class struct was written because it has no non-ghost members foreach (var member in c.InheritedMembers) { Contract.Assert(!member.IsGhost && !member.IsStatic); // only non-ghost instance members should ever be added to .InheritedMembers } bool HasNoMembers = true; foreach (MemberDecl member in c.Members) { if (!(member is Field) && !member.IsGhost) { HasNoMembers = false; break; } } if (HasNoMembers) { // Skip the class if it is entirely ghost return; } } UserDefinedType thisType = UserDefinedType.FromTopLevelDecl(c.tok, c); foreach (var member in c.InheritedMembers) { Contract.Assert(!member.IsGhost && !member.IsStatic); // only non-ghost instance members should ever be added to .InheritedMembers using (WriteArray()) { if (member is Field) { // Do nothing - WriteClassStruct already handled this case } else if (member is Function) { var f = (Function)member; Contract.Assert(f.Body != null); WriteToken(member.tok); j.WriteComment("BUGBUG Function unsupported: " + f.CompileName); // bugbug: implement } else if (member is Method) { var method = (Method)member; Contract.Assert(method.Body != null); WriteToken(member.tok); j.WriteComment("BUGBUG Method unsupported: " + method.CompileName); // bugbug: implement } else { Contract.Assert(false); // unexpected member } } } foreach (MemberDecl member in c.Members) { if (member is Field) { // Do nothing - WriteClassStruct already handled this case } else if (member is Function) { var f = (Function)member; if (f.Body == null && !(c is TraitDecl && !f.IsStatic)) { // A (ghost or non-ghost) function must always have a body, except if it's an instance function in a trait. if (forCompanionClass /* || Attributes.Contains(f.Attributes, "axiom") */) { // suppress error message (in the case of "forCompanionClass", the non-forCompanionClass call will produce the error message) } else { // The C# backend ignores functions that are axioms. But for // the Spartan scenario, treat these as extern functions. WriteToken(member.tok); CompileExternalFunction(f); } } else if (f.IsGhost) { // nothing to compile, but we do check for assumes if (f.Body == null) { Contract.Assert(c is TraitDecl && !f.IsStatic); } else { var v = new CheckHasNoAssumes_VisitorJ(this, j); v.Visit(f.Body); } } else if (c is TraitDecl && !forCompanionClass) { // include it, unless it's static if (!f.IsStatic) { WriteToken(member.tok); j.WriteComment("BUGBUG TraitDecl in function is unsupported: " + f.FullName); // bugbug: implement } } else if (forCompanionClass && !f.IsStatic) { // companion classes only has static members } else { WriteToken(member.tok); enclosingThis = (f.IsStatic) ? null : new BoundVar(c.tok, ThisName, thisType); CompileFunction(f); enclosingThis = null; } } else if (member is Method) { var m = (Method)member; if (m.Body == null && !(c is TraitDecl && !m.IsStatic)) { // A (ghost or non-ghost) method must always have a body, except if it's an instance method in a trait. if (forCompanionClass /* || Attributes.Contains(m.Attributes, "axiom") */ ) { // suppress error message (in the case of "forCompanionClass", the non-forCompanionClass call will produce the error message) } else { // The C# backend ignores functions that are axioms. But for // the Spartan scenario, treat these as extern functions. WriteToken(member.tok); CompileExternalMethod(c, m); } } else if (m.IsGhost) { // nothing to compile, but we do check for assumes if (m.Body == null) { Contract.Assert(c is TraitDecl && !m.IsStatic); } else { var v = new CheckHasNoAssumes_VisitorJ(this, j); v.Visit(m.Body); } } else if (c is TraitDecl && !forCompanionClass) { // include it, unless it's static if (!m.IsStatic) { j.WriteComment("BUGBUG TraitDecl not supported: " + m.CompileName); // bugbug: implement } } else if (forCompanionClass && !m.IsStatic) { // companion classes only has static members } else { WriteToken(member.tok); enclosingThis = (m.IsStatic) ? null : new BoundVar(c.tok, ThisName, thisType); CompileMethod(c, m); enclosingThis = null; } } else { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected member } } }
public override void PreVisit(ClassDecl classDecl) { this.FunctionScope = new SymbolTable(); this.ClassInstanceScope = this.GlobalScope.Get(classDecl.ClassName, Classification.Class).Link; }
// Compile a method with no body private void CompileExternalMethod(ClassDecl c, Method m) { Contract.Assert(c != null); Contract.Assert(m != null); Contract.Assert(m.Body == null); if (m.TypeArgs.Count != 0) { // Template expansion isn't supported j.WriteComment("BUGBUG: Type args not supported: omitting method " + m.FullCompileName); return; } List<Tuple<Type, string>> typeList = new List<Tuple<Type, string>>(); if (enclosingThis != null) { typeList.Add(Tuple.Create(enclosingThis.Type, ThisName)); } foreach (Formal p in m.Ins) { if (!p.IsGhost) { typeList.Add(Tuple.Create(p.Type, p.Name)); } } bool HasAnOut = false; foreach (Formal p in m.Outs) { if (!p.IsGhost) { typeList.Add(Tuple.Create(p.Type, p.Name)); HasAnOut = true; } } if (!HasAnOut) { typeList.Add(new Tuple<Type, string>(null, "")); } WriteExternal(m, typeList); }
void ClassDecl(DeclModifierData dmodClass, ModuleDefinition/*!*/ module, out ClassDecl/*!*/ c) { Contract.Requires(module != null); Contract.Ensures(Contract.ValueAtReturn(out c) != null); IToken/*!*/ id; Type trait = null; List<Type>/*!*/ traits = new List<Type>(); Attributes attrs = null; List<TypeParameter/*!*/> typeArgs = new List<TypeParameter/*!*/>(); List<MemberDecl/*!*/> members = new List<MemberDecl/*!*/>(); IToken bodyStart; CheckDeclModifiers(dmodClass, "Classes", AllowedDeclModifiers.Extern); DeclModifierData dmod; while (!(la.kind == 0 || la.kind == 80)) {SynErr(155); Get();} Expect(80); while (la.kind == 46) { Attribute(ref attrs); } NoUSIdent(out id); EncodeExternAsAttribute(dmodClass, ref attrs, id, /* needAxiom */ false); if (la.kind == 52) { GenericParameters(typeArgs); } if (la.kind == 78) { Get(); Type(out trait); traits.Add(trait); while (la.kind == 22) { Get(); Type(out trait); traits.Add(trait); } } Expect(46); bodyStart = t; while (StartOf(4)) { dmod = new DeclModifierData(); while (StartOf(2)) { DeclModifier(ref dmod); } ClassMemberDecl(dmod, members, true, false, false); } Expect(47); c = new ClassDecl(id, id.val, module, typeArgs, members, attrs, traits); c.BodyStartTok = bodyStart; c.BodyEndTok = t; }
void CompileClassMembers(ClassDecl c, bool forCompanionClass, int indent, TextWriter wr) { Contract.Requires(c != null); Contract.Requires(!forCompanionClass || c is TraitDecl); Contract.Requires(0 <= indent); foreach (var member in c.InheritedMembers) { Contract.Assert(!member.IsGhost && !member.IsStatic); // only non-ghost instance members should ever be added to .InheritedMembers if (member is Field) { var f = (Field)member; // every field is inherited Indent(indent, wr); wr.WriteLine("public {0} @_{1};", TypeName(f.Type, wr), f.CompileName); wr.Write("public {0} @{1}", TypeName(f.Type, wr), f.CompileName); wr.WriteLine(" {"); wr.WriteLine(" get { "); wr.Write("return this.@_{0};", f.CompileName); wr.WriteLine("}"); wr.WriteLine(" set { "); wr.WriteLine("this.@_{0} = value;", f.CompileName); wr.WriteLine("}"); wr.WriteLine("}"); } else if (member is Function) { var f = (Function)member; Contract.Assert(f.Body != null); CompileFunction(indent, f, wr); } else if (member is Method) { var method = (Method)member; Contract.Assert(method.Body != null); CompileMethod(c, indent, method, wr); } else { Contract.Assert(false); // unexpected member } } foreach (MemberDecl member in c.Members) { if (member is Field) { var f = (Field)member; if (f.IsGhost || forCompanionClass) { // emit nothing } else if (c is TraitDecl) { Indent(indent, wr); wr.Write("{0} @{1}", TypeName(f.Type, wr), f.CompileName); wr.WriteLine(" { get; set; }"); } else { Indent(indent, wr); wr.WriteLine("public {0} @{1} = {2};", TypeName(f.Type, wr), f.CompileName, DefaultValue(f.Type, wr)); } } else if (member is Function) { var f = (Function)member; if (f.Body == null && !(c is TraitDecl && !f.IsStatic)) { // A (ghost or non-ghost) function must always have a body, except if it's an instance function in a trait. if (forCompanionClass || Attributes.Contains(f.Attributes, "axiom")) { // suppress error message (in the case of "forCompanionClass", the non-forCompanionClass call will produce the error message) } else { Error("Function {0} has no body", wr, f.FullName); } } else if (f.IsGhost) { // nothing to compile, but we do check for assumes if (f.Body == null) { Contract.Assert(c is TraitDecl && !f.IsStatic); } else { var v = new CheckHasNoAssumes_Visitor(this, wr); v.Visit(f.Body); } } else if (c is TraitDecl && !forCompanionClass) { // include it, unless it's static if (!f.IsStatic) { Indent(indent, wr); wr.Write("{0} @{1}", TypeName(f.ResultType, wr), f.CompileName); wr.Write("("); WriteFormals("", f.Formals, wr); wr.WriteLine(");"); } } else if (forCompanionClass && !f.IsStatic) { // companion classes only has static members } else { CompileFunction(indent, f, wr); } } else if (member is Method) { var m = (Method)member; if (m.Body == null && !(c is TraitDecl && !m.IsStatic)) { // A (ghost or non-ghost) method must always have a body, except if it's an instance method in a trait. if (forCompanionClass || Attributes.Contains(m.Attributes, "axiom")) { // suppress error message (in the case of "forCompanionClass", the non-forCompanionClass call will produce the error message) } else { Error("Method {0} has no body", wr, m.FullName); } } else if (m.IsGhost) { // nothing to compile, but we do check for assumes if (m.Body == null) { Contract.Assert(c is TraitDecl && !m.IsStatic); } else { var v = new CheckHasNoAssumes_Visitor(this, wr); v.Visit(m.Body); } } else if (c is TraitDecl && !forCompanionClass) { // include it, unless it's static if (!m.IsStatic) { Indent(indent, wr); wr.Write("void @{0}", m.CompileName); wr.Write("("); int nIns = WriteFormals("", m.Ins, wr); WriteFormals(nIns == 0 ? "" : ", ", m.Outs, wr); wr.WriteLine(");"); } } else if (forCompanionClass && !m.IsStatic) { // companion classes only has static members } else { CompileMethod(c, indent, m, wr); } } else { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected member } } }
public override void Leave(ClassDecl o) { JumpUpInScope(); SetClass(null); }
public override AstNode VisitClassDecl(ClassDecl ast) { m_currentType = ast.Type as CodeClassType; foreach (var method in ast.Methods) { Visit(method); } return ast; }
public virtual AstNode VisitClassDecl(ClassDecl ast) { return(ast); }