diff options
author | Unknown <aleks@aleks-PC> | 2012-05-06 09:46:45 -0400 |
---|---|---|
committer | Unknown <aleks@aleks-PC> | 2012-05-06 09:46:45 -0400 |
commit | bda15df6576f848c6c53ea6edfdd6812dfece091 (patch) | |
tree | 3c6f5eaa6829c61f71eb5d17e1fe8946aff831cb | |
parent | e6bcb0f21b6cc153a37d4040392f614c279131af (diff) | |
parent | 1096701ea6ac332655167e3e849a0df6a7de7b97 (diff) |
Merge
40 files changed, 4154 insertions, 1509 deletions
diff --git a/Dafny/Compiler.cs b/Dafny/Compiler.cs index caf3df24..fcbfeac5 100644 --- a/Dafny/Compiler.cs +++ b/Dafny/Compiler.cs @@ -67,6 +67,10 @@ namespace Microsoft.Dafny { CompileBuiltIns(program.BuiltIns);
foreach (ModuleDecl m in program.Modules) {
+ if (m.IsGhost) {
+ // the purpose of a ghost module is to skip compilation
+ continue;
+ }
int indent = 0;
if (!m.IsDefaultModule) {
wr.WriteLine("namespace @{0} {{", m.Name);
@@ -78,7 +82,7 @@ namespace Microsoft.Dafny { var at = (ArbitraryTypeDecl)d;
Error("Arbitrary type ('{0}') cannot be compiled", at.Name);
} else if (d is DatatypeDecl) {
- DatatypeDecl dt = (DatatypeDecl)d;
+ var dt = (DatatypeDecl)d;
Indent(indent);
wr.Write("public abstract class Base_{0}", dt.Name);
if (dt.TypeArgs.Count != 0) {
@@ -182,7 +186,35 @@ namespace Microsoft.Dafny { }
void CompileDatatypeConstructors(DatatypeDecl dt, int indent)
- {Contract.Requires(dt != null);
+ {
+ Contract.Requires(dt != null);
+
+ string typeParams = dt.TypeArgs.Count == 0 ? "" : string.Format("<{0}>", TypeParameters(dt.TypeArgs));
+ if (dt is CoDatatypeDecl) {
+ // public class Dt__Lazy<T> : Base_Dt<T> {
+ // public delegate Base_Dt<T> Computer();
+ // public delegate Computer ComputerComputer();
+ // Computer c;
+ // public Dt__Lazy(Computer c) { this.c = c; }
+ // public Base_Dt<T> Get() { return c(); }
+ // }
+ Indent(indent);
+ wr.WriteLine("public class {0}__Lazy{1} : Base_{0}{1} {{", dt.Name, typeParams);
+ int ind = indent + IndentAmount;
+ Indent(ind);
+ wr.WriteLine("public delegate Base_{0}{1} Computer();", dt.Name, typeParams);
+ Indent(ind);
+ wr.WriteLine("public delegate Computer ComputerComputer();");
+ Indent(ind);
+ wr.WriteLine("Computer c;");
+ Indent(ind);
+ wr.WriteLine("public {0}__Lazy(Computer c) {{ this.c = c; }}", dt.Name);
+ Indent(ind);
+ wr.WriteLine("public Base_{0}{1} Get() {{ return c(); }}", dt.Name, typeParams);
+ Indent(indent);
+ wr.WriteLine("}");
+ }
+
foreach (DatatypeCtor ctor in dt.Ctors) {
// class Dt_Ctor<T,U> : Base_Dt<T> {
// Fields;
@@ -196,17 +228,13 @@ namespace Microsoft.Dafny { // public override int GetHashCode() {
// return base.GetHashCode(); // surely this can be improved
// }
+ // public override string ToString() { // only for inductive datatypes
+ // // ...
+ // }
// }
Indent(indent);
- wr.Write("public class {0}", DtCtorName(ctor));
- if (dt.TypeArgs.Count != 0) {
- wr.Write("<{0}>", TypeParameters(dt.TypeArgs));
- }
- wr.Write(" : Base_{0}", dt.Name);
- if (dt.TypeArgs.Count != 0) {
- wr.Write("<{0}>", TypeParameters(dt.TypeArgs));
- }
- wr.WriteLine(" {");
+ wr.Write("public class {0}", DtCtorName(ctor, dt.TypeArgs));
+ wr.WriteLine(" : Base_{0}{1} {{", dt.Name, typeParams);
int ind = indent + IndentAmount;
int i = 0;
@@ -235,10 +263,7 @@ namespace Microsoft.Dafny { // Equals method
Indent(ind); wr.WriteLine("public override bool Equals(object other) {");
Indent(ind + IndentAmount);
- wr.Write("var oth = other as {0}", DtCtorName(ctor));
- if (dt.TypeArgs.Count != 0) {
- wr.Write("<{0}>", TypeParameters(dt.TypeArgs));
- }
+ wr.Write("var oth = other as {0}", DtCtorName(ctor, dt.TypeArgs));
wr.WriteLine(";");
Indent(ind + IndentAmount);
wr.Write("return oth != null");
@@ -262,6 +287,27 @@ namespace Microsoft.Dafny { Indent(ind + IndentAmount); wr.WriteLine("return base.GetHashCode(); // surely this can be improved");
Indent(ind); wr.WriteLine("}");
+ if (dt is IndDatatypeDecl) {
+ Indent(ind); wr.WriteLine("public override string ToString() {");
+ Indent(ind + IndentAmount); wr.WriteLine("string s = \"{0}\";", ctor.FullName.Substring(1)/*skip the #*/);
+ if (ctor.Formals.Count != 0) {
+ Indent(ind + IndentAmount); wr.WriteLine("s += \"(\";");
+ i = 0;
+ foreach (var arg in ctor.Formals) {
+ if (!arg.IsGhost) {
+ if (i != 0) {
+ Indent(ind + IndentAmount); wr.WriteLine("s += \", \";");
+ }
+ Indent(ind + IndentAmount); wr.WriteLine("s += @{0}.ToString();", FormalName(arg, i));
+ i++;
+ }
+ }
+ Indent(ind + IndentAmount); wr.WriteLine("s += \")\";");
+ }
+ Indent(ind + IndentAmount); wr.WriteLine("return s;");
+ Indent(ind); wr.WriteLine("}");
+ }
+
Indent(indent); wr.WriteLine("}");
}
}
@@ -272,16 +318,30 @@ namespace Microsoft.Dafny { // public struct Dt<T> {
// Base_Dt<T> d;
// public Base_Dt<T> _D {
- // get { if (d == null) { d = Default; } return d; }
+ // get {
+ // if (d == null) {
+ // d = Default;
+ // } else if (d is Dt__Lazy<T>) { // co-datatypes only
+ // d = ((Dt__Lazy<T>)d).Get(); // co-datatypes only
+ // }
+ // return d;
+ // }
// }
// public Dt(Base_Dt<T> d) { this.d = d; }
+ // static Base_Dt<T> theDefault;
// public static Base_Dt<T> Default {
- // get { return ...; }
+ // get {
+ // if (theDefault == null) {
+ // theDefault = ...;
+ // }
+ // return theDefault;
+ // }
// }
// public override bool Equals(object other) {
// return other is Dt<T> && _D.Equals(((Dt<T>)other)._D);
// }
// public override int GetHashCode() { return _D.GetHashCode(); }
+ // public override string ToString() { return _D.ToString(); } // only for inductive datatypes
//
// public bool _Ctor0 { get { return _D is Dt_Ctor0; } }
// ...
@@ -306,30 +366,62 @@ namespace Microsoft.Dafny { Indent(ind);
wr.WriteLine("public Base_{0} _D {{", DtT);
Indent(ind + IndentAmount);
- wr.WriteLine("get { if (d == null) { d = Default; } return d; }");
+ wr.WriteLine("get {");
+ Indent(ind + 2 * IndentAmount);
+ wr.WriteLine("if (d == null) {");
+ Indent(ind + 3 * IndentAmount);
+ wr.WriteLine("d = Default;");
+ if (dt is CoDatatypeDecl) {
+ string typeParams = dt.TypeArgs.Count == 0 ? "" : string.Format("<{0}>", TypeParameters(dt.TypeArgs));
+ Indent(ind + 2 * IndentAmount);
+ wr.WriteLine("}} else if (d is {0}__Lazy{1}) {{", dt.Name, typeParams);
+ Indent(ind + 3 * IndentAmount);
+ wr.WriteLine("d = (({0}__Lazy{1})d).Get();", dt.Name, typeParams);
+ }
+ Indent(ind + 2 * IndentAmount); wr.WriteLine("}");
+ Indent(ind + 2 * IndentAmount); wr.WriteLine("return d;");
+ Indent(ind + IndentAmount); wr.WriteLine("}");
Indent(ind); wr.WriteLine("}");
Indent(ind);
wr.WriteLine("public @{0}(Base_{1} d) {{ this.d = d; }}", dt.Name, DtT);
Indent(ind);
+ wr.WriteLine("static Base_{0} theDefault;", DtT);
+
+ Indent(ind);
wr.WriteLine("public static Base_{0} Default {{", DtT);
Indent(ind + IndentAmount);
- wr.Write("get { return ");
- wr.Write("new {0}", DtCtorName(cce.NonNull(dt.DefaultCtor)));
- if (dt.TypeArgs.Count != 0) {
- wr.Write("<{0}>", TypeParameters(dt.TypeArgs));
+ wr.WriteLine("get {");
+ Indent(ind + 2 * IndentAmount);
+ wr.WriteLine("if (theDefault == null) {");
+ Indent(ind + 3 * IndentAmount);
+ wr.Write("theDefault = ");
+
+ DatatypeCtor defaultCtor;
+ if (dt is IndDatatypeDecl) {
+ defaultCtor = ((IndDatatypeDecl)dt).DefaultCtor;
+ } else {
+ defaultCtor = ((CoDatatypeDecl)dt).Ctors[0]; // pick any one of them
}
+ wr.Write("new {0}", DtCtorName(defaultCtor, dt.TypeArgs));
wr.Write("(");
string sep = "";
- foreach (Formal f in dt.DefaultCtor.Formals) {
+ foreach (Formal f in defaultCtor.Formals) {
if (!f.IsGhost) {
wr.Write("{0}{1}", sep, DefaultValue(f.Type));
sep = ", ";
}
}
wr.Write(")");
- wr.WriteLine("; }");
+
+ wr.WriteLine(";");
+ Indent(ind + 2 * IndentAmount);
+ wr.WriteLine("}");
+ Indent(ind + 2 * IndentAmount);
+ wr.WriteLine("return theDefault;");
+ Indent(ind + IndentAmount); wr.WriteLine("}");
+
Indent(ind); wr.WriteLine("}");
Indent(ind); wr.WriteLine("public override bool Equals(object other) {");
@@ -339,6 +431,10 @@ namespace Microsoft.Dafny { Indent(ind);
wr.WriteLine("public override int GetHashCode() { return _D.GetHashCode(); }");
+ if (dt is IndDatatypeDecl) {
+ Indent(ind);
+ wr.WriteLine("public override string ToString() { return _D.ToString(); }");
+ }
// query properties
foreach (var ctor in dt.Ctors) {
@@ -386,11 +482,34 @@ namespace Microsoft.Dafny { }
string DtCtorName(DatatypeCtor ctor) {
- Contract.Requires(ctor != null);Contract.Ensures(Contract.Result<string>() != null);
+ Contract.Requires(ctor != null);
+ Contract.Ensures(Contract.Result<string>() != null);
return cce.NonNull(ctor.EnclosingDatatype).Name + "_" + ctor.Name;
}
+ string DtCtorName(DatatypeCtor ctor, List<TypeParameter> typeParams) {
+ Contract.Requires(ctor != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ var s = DtCtorName(ctor);
+ if (typeParams != null && typeParams.Count != 0) {
+ s += "<" + TypeParameters(typeParams) + ">";
+ }
+ return s;
+ }
+
+ string DtCtorName(DatatypeCtor ctor, List<Type> typeArgs) {
+ Contract.Requires(ctor != null);
+ Contract.Ensures(Contract.Result<string>() != null);
+
+ var s = DtCtorName(ctor);
+ if (typeArgs != null && typeArgs.Count != 0) {
+ s += "<" + TypeNames(typeArgs) + ">";
+ }
+ return s;
+ }
+
public bool HasMain(Program program) {
foreach (var module in program.Modules) {
foreach (var decl in module.TopLevelDecls) {
@@ -500,7 +619,7 @@ namespace Microsoft.Dafny { if (body is MatchExpr) {
MatchExpr me = (MatchExpr)body;
// Type source = e;
- // if (source._D is Dt_Ctor0) {
+ // if (source._Ctor0) {
// FormalType f0 = ((Dt_Ctor0)source._D).a0;
// ...
// return Body0;
@@ -524,8 +643,9 @@ namespace Microsoft.Dafny { wr.WriteLine("throw new System.Exception();");
} else {
int i = 0;
+ var sourceType = (UserDefinedType)me.Source.Type;
foreach (MatchCaseExpr mc in me.Cases) {
- MatchCasePrelude(source, cce.NonNull(mc.Ctor), mc.Arguments, i, me.Cases.Count, indent + IndentAmount);
+ MatchCasePrelude(source, sourceType, cce.NonNull(mc.Ctor), mc.Arguments, i, me.Cases.Count, indent + IndentAmount);
CompileReturnBody(mc.Body, indent + IndentAmount);
i++;
}
@@ -599,7 +719,7 @@ namespace Microsoft.Dafny { return name + "]";
} else if (type is UserDefinedType) {
UserDefinedType udt = (UserDefinedType)type;
- string s = "@" + udt.Name;
+ string s = "@" + udt.FullName;
if (udt.TypeArgs.Count != 0) {
if (Contract.Exists(udt.TypeArgs, argType =>argType is ObjectType)) {
Error("compilation does not support type 'object' as a type parameter; consider introducing a ghost");
@@ -685,7 +805,7 @@ namespace Microsoft.Dafny { if (udt.TypeArgs.Count != 0) {
s += "<" + TypeNames(udt.TypeArgs) + ">";
}
- return string.Format("new {0}({0}.Default)", s);
+ return string.Format("new {0}()", s);
} else if (type.IsTypeParameter) {
UserDefinedType udt = (UserDefinedType)type;
return "default(@" + udt.Name + ")";
@@ -706,40 +826,11 @@ namespace Microsoft.Dafny { Contract.Requires(stmt != null);
if (stmt is AssumeStmt) {
Error("an assume statement cannot be compiled (line {0})", stmt.Tok.line);
- } else if (stmt is BlockStmt) {
- foreach (Statement s in ((BlockStmt)stmt).Body) {
- CheckHasNoAssumes(s);
- }
- } else if (stmt is IfStmt) {
- IfStmt s = (IfStmt)stmt;
- CheckHasNoAssumes(s.Thn);
- if (s.Els != null) {
- CheckHasNoAssumes(s.Els);
- }
- } else if (stmt is AlternativeStmt) {
- foreach (var alternative in ((AlternativeStmt)stmt).Alternatives) {
- foreach (Statement s in alternative.Body) {
- CheckHasNoAssumes(s);
- }
- }
- } else if (stmt is WhileStmt) {
- WhileStmt s = (WhileStmt)stmt;
- CheckHasNoAssumes(s.Body);
- } else if (stmt is AlternativeLoopStmt) {
- foreach (var alternative in ((AlternativeLoopStmt)stmt).Alternatives) {
- foreach (Statement s in alternative.Body) {
- CheckHasNoAssumes(s);
- }
- }
- } else if (stmt is ParallelStmt) {
- var s = (ParallelStmt)stmt;
- CheckHasNoAssumes(s.Body);
- } else if (stmt is MatchStmt) {
- MatchStmt s = (MatchStmt)stmt;
- foreach (MatchCaseStmt mc in s.Cases) {
- foreach (Statement bs in mc.Body) {
- CheckHasNoAssumes(bs);
- }
+ } else if (stmt is AssignSuchThatStmt) {
+ Error("an assign-such-that statement cannot be compiled (line {0})", stmt.Tok.line);
+ } else {
+ foreach (var ss in stmt.SubStatements) {
+ CheckHasNoAssumes(ss);
}
}
}
@@ -1100,7 +1191,7 @@ namespace Microsoft.Dafny { } else if (stmt is MatchStmt) {
MatchStmt s = (MatchStmt)stmt;
// Type source = e;
- // if (source._D is Dt_Ctor0) {
+ // if (source._Ctor0) {
// FormalType f0 = ((Dt_Ctor0)source._D).a0;
// ...
// Body0;
@@ -1110,6 +1201,8 @@ namespace Microsoft.Dafny { // ...
// }
if (s.Cases.Count != 0) {
+ var sourceType = (UserDefinedType)s.Source.Type;
+
SpillLetVariableDecls(s.Source, indent);
string source = "_source" + tmpVarCount;
tmpVarCount++;
@@ -1120,7 +1213,7 @@ namespace Microsoft.Dafny { int i = 0;
foreach (MatchCaseStmt mc in s.Cases) {
- MatchCasePrelude(source, cce.NonNull(mc.Ctor), mc.Arguments, i, s.Cases.Count, indent);
+ MatchCasePrelude(source, sourceType, cce.NonNull(mc.Ctor), mc.Arguments, i, s.Cases.Count, indent);
TrStmtList(mc.Body, indent);
i++;
}
@@ -1216,7 +1309,7 @@ namespace Microsoft.Dafny { } else {
if (rhs is ExprRhs) {
SpillLetVariableDecls(((ExprRhs)rhs).Expr, indent);
- } else if (tRhs != null) {
+ } else if (tRhs != null && tRhs.ArrayDimensions != null) {
foreach (Expression dim in tRhs.ArrayDimensions) {
SpillLetVariableDecls(dim, indent);
}
@@ -1369,11 +1462,12 @@ namespace Microsoft.Dafny { }
}
- void MatchCasePrelude(string source, DatatypeCtor ctor, List<BoundVar/*!*/>/*!*/ arguments, int caseIndex, int caseCount, int indent) {
+ void MatchCasePrelude(string source, UserDefinedType sourceType, DatatypeCtor ctor, List<BoundVar/*!*/>/*!*/ arguments, int caseIndex, int caseCount, int indent) {
Contract.Requires(source != null);
+ Contract.Requires(sourceType != null);
Contract.Requires(ctor != null);
Contract.Requires(cce.NonNullElements(arguments));
- // if (source._D is Dt_Ctor0) {
+ // if (source._Ctor0) {
// FormalType f0 = ((Dt_Ctor0)source._D).a0;
// ...
Indent(indent);
@@ -1381,7 +1475,7 @@ namespace Microsoft.Dafny { if (caseIndex == caseCount - 1) {
wr.Write("true");
} else {
- wr.Write("{0}._D is {1}", source, DtCtorName(ctor));
+ wr.Write("{0}._{1}", source, ctor.Name);
}
wr.WriteLine(") {");
@@ -1393,7 +1487,7 @@ namespace Microsoft.Dafny { // FormalType f0 = ((Dt_Ctor0)source._D).a0;
Indent(indent + IndentAmount);
wr.WriteLine("{0} @{1} = (({2}){3}._D).@{4};",
- TypeName(bv.Type), bv.Name, DtCtorName(ctor), source, FormalName(arg, k));
+ TypeName(bv.Type), bv.Name, DtCtorName(ctor, sourceType.TypeArgs), source, FormalName(arg, k));
k++;
}
}
@@ -1561,42 +1655,80 @@ namespace Microsoft.Dafny { } else if (expr is FunctionCallExpr) {
FunctionCallExpr e = (FunctionCallExpr)expr;
- Function f = cce.NonNull(e.Function);
- if (f.IsStatic) {
- wr.Write(TypeName(cce.NonNull(e.Receiver.Type)));
- } else {
- TrParenExpr(e.Receiver);
- }
- wr.Write(".@{0}", f.Name);
- wr.Write("(");
- string sep = "";
- for (int i = 0; i < e.Args.Count; i++) {
- if (!e.Function.Formals[i].IsGhost) {
- wr.Write(sep);
- TrExpr(e.Args[i]);
- sep = ", ";
- }
- }
- wr.Write(")");
+ CompileFunctionCallExpr(e, wr, TrExpr);
} else if (expr is DatatypeValue) {
DatatypeValue dtv = (DatatypeValue)expr;
Contract.Assert(dtv.Ctor != null); // since dtv has been successfully resolved
- wr.Write("new {0}(new {1}", dtv.DatatypeName, DtCtorName(dtv.Ctor));
- if (dtv.InferredTypeArgs.Count != 0) {
- wr.Write("<{0}>", TypeNames(dtv.InferredTypeArgs));
- }
- wr.Write("(");
- string sep = "";
- for (int i = 0; i < dtv.Arguments.Count; i++) {
- Formal formal = dtv.Ctor.Formals[i];
- if (!formal.IsGhost) {
- wr.Write(sep);
- TrExpr(dtv.Arguments[i]);
- sep = ", ";
+ var typeParams = dtv.InferredTypeArgs.Count == 0 ? "" : string.Format("<{0}>", TypeNames(dtv.InferredTypeArgs));
+
+ wr.Write("new {0}{1}(", dtv.DatatypeName, typeParams);
+ if (!dtv.IsCoCall) {
+ // For an ordinary constructor (that is, one that does not guard any co-recursive calls), generate:
+ // new Dt_Cons<T>( args )
+ wr.Write("new {0}(", DtCtorName(dtv.Ctor, dtv.InferredTypeArgs));
+ string sep = "";
+ for (int i = 0; i < dtv.Arguments.Count; i++) {
+ Formal formal = dtv.Ctor.Formals[i];
+ if (!formal.IsGhost) {
+ wr.Write(sep);
+ TrExpr(dtv.Arguments[i]);
+ sep = ", ";
+ }
+ }
+ wr.Write(")");
+ } else {
+ // In the case of a co-recursive call, generate:
+ // new Dt__Lazy<T>( new Dt__Lazy<T>.ComputerComputer( LAMBDA )() )
+ // where LAMBDA is:
+ // () => { var someLocals = eagerlyEvaluatedArguments;
+ // return () => { return Dt_Cons<T>( ...args...using someLocals and including function calls to be evaluated lazily... ); };
+ // }
+ wr.Write("new {0}__Lazy{1}", dtv.DatatypeName, typeParams);
+ wr.Write("(new {0}__Lazy{1}.ComputerComputer(() => {{ ", dtv.DatatypeName, typeParams);
+
+ // locals
+ string args = "";
+ string sep = "";
+ for (int i = 0; i < dtv.Arguments.Count; i++) {
+ Formal formal = dtv.Ctor.Formals[i];
+ if (!formal.IsGhost) {
+ Expression actual = dtv.Arguments[i].Resolved;
+ string arg;
+ var fce = actual as FunctionCallExpr;
+ if (fce == null || fce.CoCall != FunctionCallExpr.CoCallResolution.Yes) {
+ string varName = "_ac" + tmpVarCount;
+ tmpVarCount++;
+ arg = varName;
+
+ wr.Write("var {0} = ", varName);
+ TrExpr(actual);
+ wr.Write("; ");
+ } else {
+ var sw = new StringWriter();
+ CompileFunctionCallExpr(fce, sw, (exp) => {
+ string varName = "_ac" + tmpVarCount;
+ tmpVarCount++;
+ sw.Write(varName);
+
+ wr.Write("var {0} = ", varName);
+ TrExpr(exp);
+ wr.Write("; ");
+
+ });
+ arg = sw.ToString();
+ }
+ args += sep + arg;
+ sep = ", ";
+ }
}
+
+ wr.Write("return () => { return ");
+
+ wr.Write("new {0}({1}", DtCtorName(dtv.Ctor, dtv.InferredTypeArgs), args);
+ wr.Write("); }; })())");
}
- wr.Write("))");
+ wr.Write(")");
} else if (expr is OldExpr) {
Contract.Assert(false); throw new cce.UnreachableException(); // 'old' is always a ghost (right?)
@@ -1917,5 +2049,29 @@ namespace Microsoft.Dafny { Contract.Assert(false); throw new cce.UnreachableException(); // unexpected expression
}
}
+
+ delegate void FCE_Arg_Translator(Expression e);
+
+ void CompileFunctionCallExpr(FunctionCallExpr e, TextWriter twr, FCE_Arg_Translator tr) {
+ Function f = cce.NonNull(e.Function);
+ if (f.IsStatic) {
+ twr.Write(TypeName(cce.NonNull(e.Receiver.Type)));
+ } else {
+ twr.Write("(");
+ tr(e.Receiver);
+ twr.Write(")");
+ }
+ twr.Write(".@{0}", f.Name);
+ twr.Write("(");
+ string sep = "";
+ for (int i = 0; i < e.Args.Count; i++) {
+ if (!e.Function.Formals[i].IsGhost) {
+ twr.Write(sep);
+ tr(e.Args[i]);
+ sep = ", ";
+ }
+ }
+ twr.Write(")");
+ }
}
}
diff --git a/Dafny/Dafny.atg b/Dafny/Dafny.atg index 5b9689b4..1390d5ca 100644 --- a/Dafny/Dafny.atg +++ b/Dafny/Dafny.atg @@ -148,27 +148,35 @@ Dafny defaultModule = new DefaultModuleDecl();
}
IToken idRefined;
+ bool isGhost;
.)
- { "module" (. attrs = null; idRefined = null; theImports = new List<string/*!*/>();
- namedModuleDefaultClassMembers = new List<MemberDecl>();
- .)
- { Attribute<ref attrs> }
- Ident<out id> (. defaultModule.ImportNames.Add(id.val); .)
- [ "refines" Ident<out idRefined> ]
- [ "imports" Idents<theImports> ] (. module = new ModuleDecl(id, id.val, idRefined == null ? null : idRefined.val, theImports, attrs); .)
- "{" (. module.BodyStartTok = t; .)
- { ClassDecl<module, out c> (. module.TopLevelDecls.Add(c); .)
- | DatatypeDecl<module, out dt> (. module.TopLevelDecls.Add(dt); .)
- | ArbitraryTypeDecl<module, out at>(. module.TopLevelDecls.Add(at); .)
- | ClassMemberDecl<namedModuleDefaultClassMembers, false>
- }
- "}" (. module.BodyEndTok = t;
- module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers));
- theModules.Add(module); .)
- | ClassDecl<defaultModule, out c> (. defaultModule.TopLevelDecls.Add(c); .)
- | DatatypeDecl<defaultModule, out dt> (. defaultModule.TopLevelDecls.Add(dt); .)
- | ArbitraryTypeDecl<defaultModule, out at> (. defaultModule.TopLevelDecls.Add(at); .)
- | ClassMemberDecl<membersDefaultClass, false>
+ { (. isGhost = false; .)
+ [ "ghost" (. isGhost = true; .) ]
+
+ ( "module" (. attrs = null; idRefined = null; theImports = new List<string/*!*/>();
+ namedModuleDefaultClassMembers = new List<MemberDecl>();
+ .)
+ { Attribute<ref attrs> }
+ Ident<out id> (. defaultModule.ImportNames.Add(id.val); .)
+ [ "refines" Ident<out idRefined> ]
+ [ "imports" Idents<theImports> ] (. module = new ModuleDecl(id, id.val, isGhost, idRefined == null ? null : idRefined.val, theImports, attrs); .)
+ "{" (. module.BodyStartTok = t; .)
+ { ClassDecl<module, out c> (. module.TopLevelDecls.Add(c); .)
+ | DatatypeDecl<module, out dt> (. module.TopLevelDecls.Add(dt); .)
+ | ArbitraryTypeDecl<module, out at>(. module.TopLevelDecls.Add(at); .)
+ | ClassMemberDecl<namedModuleDefaultClassMembers, false, false>
+ }
+ "}" (. module.BodyEndTok = t;
+ module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers));
+ theModules.Add(module); .)
+ | (. if (isGhost) { SemErr(t, "a class is not allowed to be declared as 'ghost'"); } .)
+ ClassDecl<defaultModule, out c> (. defaultModule.TopLevelDecls.Add(c); .)
+ | (. if (isGhost) { SemErr(t, "a datatype/codatatype is not allowed to be declared as 'ghost'"); } .)
+ DatatypeDecl<defaultModule, out dt> (. defaultModule.TopLevelDecls.Add(dt); .)
+ | (. if (isGhost) { SemErr(t, "a type is not allowed to be declared as 'ghost'"); } .)
+ ArbitraryTypeDecl<defaultModule, out at> (. defaultModule.TopLevelDecls.Add(at); .)
+ | ClassMemberDecl<membersDefaultClass, isGhost, false>
+ )
}
(. if (defaultModuleCreatedHere) {
defaultModule.TopLevelDecls.Add(new DefaultClassDecl(defaultModule, membersDefaultClass));
@@ -201,7 +209,7 @@ ClassDecl<ModuleDecl/*!*/ module, out ClassDecl/*!*/ c> Ident<out id>
[ GenericParameters<typeArgs> ]
"{" (. bodyStart = t; .)
- { ClassMemberDecl<members, true>
+ { ClassMemberDecl<members, false, true>
}
"}"
(. c = new ClassDecl(id, id.val, module, typeArgs, members, attrs);
@@ -209,11 +217,12 @@ ClassDecl<ModuleDecl/*!*/ module, out ClassDecl/*!*/ c> c.BodyEndTok = t;
.)
.
-ClassMemberDecl<.List<MemberDecl/*!*/>/*!*/ mm, bool allowConstructors.>
+ClassMemberDecl<.List<MemberDecl/*!*/>/*!*/ mm, bool isAlreadyGhost, bool allowConstructors.>
= (. Contract.Requires(cce.NonNullElements(mm));
Method/*!*/ m;
Function/*!*/ f;
MemberModifiers mmod = new MemberModifiers();
+ mmod.IsGhost = isAlreadyGhost;
.)
{ "ghost" (. mmod.IsGhost = true; .)
| "static" (. mmod.IsStatic = true; .)
@@ -232,9 +241,12 @@ DatatypeDecl<ModuleDecl/*!*/ module, out DatatypeDecl/*!*/ dt> List<TypeParameter/*!*/> typeArgs = new List<TypeParameter/*!*/>();
List<DatatypeCtor/*!*/> ctors = new List<DatatypeCtor/*!*/>();
IToken bodyStart = Token.NoToken; // dummy assignment
+ bool co = false;
.)
SYNC
- "datatype"
+ ( "datatype"
+ | "codatatype" (. co = true; .)
+ )
{ Attribute<ref attrs> }
Ident<out id>
[ GenericParameters<typeArgs> ]
@@ -242,7 +254,11 @@ DatatypeDecl<ModuleDecl/*!*/ module, out DatatypeDecl/*!*/ dt> DatatypeMemberDecl<ctors>
{ "|" DatatypeMemberDecl<ctors> }
SYNC ";"
- (. dt = new DatatypeDecl(id, id.val, module, typeArgs, ctors, attrs);
+ (. if (co) {
+ dt = new CoDatatypeDecl(id, id.val, module, typeArgs, ctors, attrs);
+ } else {
+ dt = new IndDatatypeDecl(id, id.val, module, typeArgs, ctors, attrs);
+ }
dt.BodyStartTok = bodyStart;
dt.BodyEndTok = t;
.)
@@ -365,8 +381,9 @@ MethodDecl<MemberModifiers mmod, bool allowConstructor, out Method/*!*/ m> List<Expression/*!*/> dec = new List<Expression/*!*/>();
Attributes decAttrs = null;
Attributes modAttrs = null;
- Statement/*!*/ bb; BlockStmt body = null;
+ BlockStmt body = null;
bool isConstructor = false;
+ bool signatureOmitted = false;
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
.)
@@ -391,18 +408,24 @@ MethodDecl<MemberModifiers mmod, bool allowConstructor, out Method/*!*/ m> .)
{ Attribute<ref attrs> }
Ident<out id>
- [ GenericParameters<typeArgs> ]
- Formals<true, !mmod.IsGhost, ins, out openParen>
- [ "returns" (. if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); } .)
- Formals<false, !mmod.IsGhost, outs, out openParen>
- ]
+ (
+ [ GenericParameters<typeArgs> ]
+ Formals<true, !mmod.IsGhost, ins, out openParen>
+ [ "returns" (. if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); } .)
+ Formals<false, !mmod.IsGhost, outs, out openParen>
+ ]
+ | "..." (. signatureOmitted = true; openParen = Token.NoToken; .)
+ )
{ MethodSpec<req, mod, ens, dec, ref decAttrs, ref modAttrs> }
- [ BlockStmt<out bb, out bodyStart, out bodyEnd> (. body = (BlockStmt)bb; .)
+ [ BlockStmt<out body, out bodyStart, out bodyEnd>
]
- (. if (isConstructor)
- m = new Constructor(id, id.val, typeArgs, ins, req, new Specification<FrameExpression>(mod, modAttrs), ens, new Specification<Expression>(dec, decAttrs), body, attrs);
- else
- m = new Method(id, id.val, mmod.IsStatic, mmod.IsGhost, typeArgs, ins, outs, req, new Specification<FrameExpression>(mod, modAttrs), ens, new Specification<Expression>(dec, decAttrs), body, attrs);
+ (. if (isConstructor) {
+ m = new Constructor(id, id.val, typeArgs, ins,
+ req, new Specification<FrameExpression>(mod, modAttrs), ens, new Specification<Expression>(dec, decAttrs), body, attrs, signatureOmitted);
+ } else {
+ m = new Method(id, id.val, mmod.IsStatic, mmod.IsGhost, typeArgs, ins, outs,
+ req, new Specification<FrameExpression>(mod, modAttrs), ens, new Specification<Expression>(dec, decAttrs), body, attrs, signatureOmitted);
+ }
m.BodyStartTok = bodyStart;
m.BodyEndTok = bodyEnd;
.)
@@ -519,12 +542,13 @@ FunctionDecl<MemberModifiers mmod, out Function/*!*/ f> List<Expression/*!*/> ens = new List<Expression/*!*/>();
List<FrameExpression/*!*/> reads = new List<FrameExpression/*!*/>();
List<Expression/*!*/> decreases = new List<Expression/*!*/>();
- Expression/*!*/ bb; Expression body = null;
+ Expression body = null;
bool isPredicate = false;
bool isFunctionMethod = false;
IToken openParen = null;
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
+ bool signatureOmitted = false;
.)
/* ----- function ----- */
( "function"
@@ -534,10 +558,14 @@ FunctionDecl<MemberModifiers mmod, out Function/*!*/ f> .)
{ Attribute<ref attrs> }
Ident<out id>
- [ GenericParameters<typeArgs> ]
- Formals<true, isFunctionMethod, formals, out openParen>
- ":"
- Type<out returnType>
+ (
+ [ GenericParameters<typeArgs> ]
+ Formals<true, isFunctionMethod, formals, out openParen>
+ ":"
+ Type<out returnType>
+ | "..." (. signatureOmitted = true;
+ openParen = Token.NoToken; .)
+ )
/* ----- predicate ----- */
| "predicate" (. isPredicate = true; .)
@@ -547,20 +575,26 @@ FunctionDecl<MemberModifiers mmod, out Function/*!*/ f> .)
{ Attribute<ref attrs> }
Ident<out id>
- [ GenericParameters<typeArgs> ]
- [ Formals<true, isFunctionMethod, formals, out openParen>
- [ ":" (. SemErr(t, "predicates do not have an explicitly declared return type; it is always bool"); .)
+ (
+ [ GenericParameters<typeArgs> ]
+ [ Formals<true, isFunctionMethod, formals, out openParen>
+ [ ":" (. SemErr(t, "predicates do not have an explicitly declared return type; it is always bool"); .)
+ ]
]
- ]
+ | "..." (. signatureOmitted = true;
+ openParen = Token.NoToken; .)
+ )
)
{ FunctionSpec<reqs, reads, ens, decreases> }
- [ FunctionBody<out bb, out bodyStart, out bodyEnd> (. body = bb; .)
+ [ FunctionBody<out body, out bodyStart, out bodyEnd>
]
(. if (isPredicate) {
- f = new Predicate(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals, reqs, reads, ens, new Specification<Expression>(decreases, null), body, false, attrs);
+ f = new Predicate(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals,
+ reqs, reads, ens, new Specification<Expression>(decreases, null), body, false, attrs, signatureOmitted);
} else {
- f = new Function(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals, returnType, reqs, reads, ens, new Specification<Expression>(decreases, null), body, attrs);
+ f = new Function(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals, returnType,
+ reqs, reads, ens, new Specification<Expression>(decreases, null), body, attrs, signatureOmitted);
}
f.BodyStartTok = bodyStart;
f.BodyEndTok = bodyEnd;
@@ -616,7 +650,7 @@ FunctionBody<out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd> "}" (. bodyEnd = t; .)
.
/*------------------------------------------------------------------------*/
-BlockStmt<out Statement/*!*/ block, out IToken bodyStart, out IToken bodyEnd>
+BlockStmt<out BlockStmt/*!*/ block, out IToken bodyStart, out IToken bodyEnd>
= (. Contract.Ensures(Contract.ValueAtReturn(out block) != null);
List<Statement/*!*/> body = new List<Statement/*!*/>();
.)
@@ -634,12 +668,12 @@ Stmt<.List<Statement/*!*/>/*!*/ ss.> OneStmt<out Statement/*!*/ s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; IToken/*!*/ id; string label = null;
s = dummyStmt; /* to please the compiler */
+ BlockStmt bs;
IToken bodyStart, bodyEnd;
int breakCount;
.)
- /* This list does not contain BlockStmt, see comment above in Stmt production. */
SYNC
- ( BlockStmt<out s, out bodyStart, out bodyEnd>
+ ( BlockStmt<out bs, out bodyStart, out bodyEnd> (. s = bs; .)
| AssertStmt<out s>
| AssumeStmt<out s>
| PrintStmt<out s>
@@ -660,6 +694,8 @@ OneStmt<out Statement/*!*/ s> SYNC
";" (. s = label != null ? new BreakStmt(x, label) : new BreakStmt(x, breakCount); .)
| ReturnStmt<out s>
+ | "..." (. s = new SkeletonStatement(t); .)
+ ";"
)
.
ReturnStmt<out Statement/*!*/ s>
@@ -683,21 +719,30 @@ UpdateStmt<out Statement/*!*/ s> Expression lhs0;
IToken x;
Attributes attrs = null;
+ Expression suchThat = null;
.)
Lhs<out e> (. x = e.tok; .)
- ( { IF(IsAttribute()) Attribute<ref attrs> }
+ ( { Attribute<ref attrs> }
";" (. rhss.Add(new ExprRhs(e, attrs)); .)
| (. lhss.Add(e); lhs0 = e; .)
{ "," Lhs<out e> (. lhss.Add(e); .)
}
- ":=" (. x = t; .)
- Rhs<out r, lhs0> (. rhss.Add(r); .)
- { "," Rhs<out r, lhs0> (. rhss.Add(r); .)
- }
+ ( ":=" (. x = t; .)
+ Rhs<out r, lhs0> (. rhss.Add(r); .)
+ { "," Rhs<out r, lhs0> (. rhss.Add(r); .)
+ }
+ | ":|" (. x = t; .)
+ Expression<out suchThat>
+ )
";"
| ":" (. SemErr(t, "invalid statement (did you forget the 'label' keyword?)"); .)
)
- (. s = new UpdateStmt(x, lhss, rhss); .)
+ (. if (suchThat != null) {
+ s = new AssignSuchThatStmt(x, lhss, suchThat);
+ } else {
+ s = new UpdateStmt(x, lhss, rhss);
+ }
+ .)
.
Rhs<out AssignmentRhs r, Expression receiverForInitCall>
= (. IToken/*!*/ x, newToken; Expression/*!*/ e;
@@ -733,7 +778,7 @@ Rhs<out AssignmentRhs r, Expression receiverForInitCall> | "*" (. r = new HavocRhs(t); .)
| Expression<out e> (. r = new ExprRhs(e); .)
)
- { IF(IsAttribute()) Attribute<ref attrs> } (. r.Attributes = attrs; .)
+ { Attribute<ref attrs> } (. r.Attributes = attrs; .)
.
VarDeclStatement<.out Statement/*!*/ s.>
= (. IToken x = null, assignTok = null; bool isGhost = false;
@@ -741,6 +786,7 @@ VarDeclStatement<.out Statement/*!*/ s.> AssignmentRhs r; IdentifierExpr lhs0;
List<VarDecl> lhss = new List<VarDecl>();
List<AssignmentRhs> rhss = new List<AssignmentRhs>();
+ Expression suchThat = null;
.)
[ "ghost" (. isGhost = true; x = t; .)
]
@@ -756,10 +802,18 @@ VarDeclStatement<.out Statement/*!*/ s.> Rhs<out r, lhs0> (. rhss.Add(r); .)
{ "," Rhs<out r, lhs0> (. rhss.Add(r); .)
}
+ | ":|" (. assignTok = t; .)
+ Expression<out suchThat>
]
";"
- (. UpdateStmt update;
- if (rhss.Count == 0) {
+ (. ConcreteUpdateStatement update;
+ if (suchThat != null) {
+ var ies = new List<Expression>();
+ foreach (var lhs in lhss) {
+ ies.Add(new IdentifierExpr(lhs.Tok, lhs.Name));
+ }
+ update = new AssignSuchThatStmt(assignTok, ies, suchThat);
+ } else if (rhss.Count == 0) {
update = null;
} else {
var ies = new List<Expression>();
@@ -773,8 +827,9 @@ VarDeclStatement<.out Statement/*!*/ s.> .
IfStmt<out Statement/*!*/ ifStmt>
= (. Contract.Ensures(Contract.ValueAtReturn(out ifStmt) != null); IToken/*!*/ x;
- Expression guard;
- Statement/*!*/ thn;
+ Expression guard = null; bool guardOmitted = false;
+ BlockStmt/*!*/ thn;
+ BlockStmt/*!*/ bs;
Statement/*!*/ s;
Statement els = null;
IToken bodyStart, bodyEnd;
@@ -783,14 +838,21 @@ IfStmt<out Statement/*!*/ ifStmt> .)
"if" (. x = t; .)
(
- Guard<out guard>
+ ( Guard<out guard>
+ | "..." (. guardOmitted = true; .)
+ )
BlockStmt<out thn, out bodyStart, out bodyEnd>
[ "else"
( IfStmt<out s> (. els = s; .)
- | BlockStmt<out s, out bodyStart, out bodyEnd> (. els = s; .)
+ | BlockStmt<out bs, out bodyStart, out bodyEnd> (. els = bs; .)
)
]
- (. ifStmt = new IfStmt(x, guard, thn, els); .)
+ (. if (guardOmitted) {
+ ifStmt = new SkeletonStatement(new IfStmt(x, guard, thn, els), true, false);
+ } else {
+ ifStmt = new IfStmt(x, guard, thn, els);
+ }
+ .)
|
AlternativeBlock<out alternatives>
(. ifStmt = new AlternativeStmt(x, alternatives); .)
@@ -814,23 +876,43 @@ AlternativeBlock<.out List<GuardedAlternative> alternatives.> .
WhileStmt<out Statement/*!*/ stmt>
= (. Contract.Ensures(Contract.ValueAtReturn(out stmt) != null); IToken/*!*/ x;
- Expression guard;
+ Expression guard = null; bool guardOmitted = false;
List<MaybeFreeExpression/*!*/> invariants = new List<MaybeFreeExpression/*!*/>();
List<Expression/*!*/> decreases = new List<Expression/*!*/>();
Attributes decAttrs = null;
Attributes modAttrs = null;
List<FrameExpression/*!*/> mod = null;
- Statement/*!*/ body;
- IToken bodyStart, bodyEnd;
+ BlockStmt/*!*/ body = null; bool bodyOmitted = false;
+ IToken bodyStart = null, bodyEnd = null;
List<GuardedAlternative> alternatives;
stmt = dummyStmt; // to please the compiler
.)
"while" (. x = t; .)
(
- Guard<out guard> (. Contract.Assume(guard == null || cce.Owner.None(guard)); .)
+ ( Guard<out guard> (. Contract.Assume(guard == null || cce.Owner.None(guard)); .)
+ | "..." (. guardOmitted = true; .)
+ )
LoopSpec<out invariants, out decreases, out mod, ref decAttrs, ref modAttrs>
- BlockStmt<out body, out bodyStart, out bodyEnd>
- (. stmt = new WhileStmt(x, guard, invariants, new Specification<Expression>(decreases, decAttrs), new Specification<FrameExpression>(mod, modAttrs), body); .)
+ ( BlockStmt<out body, out bodyStart, out bodyEnd>
+ | "..." (. bodyOmitted = true; .)
+ )
+ (.
+ if (guardOmitted || bodyOmitted) {
+ if (decreases.Count != 0) {
+ SemErr(decreases[0].tok, "'decreases' clauses are not allowed on refining loops");
+ }
+ if (mod != null) {
+ SemErr(mod[0].E.tok, "'modifies' clauses are not allowed on refining loops");
+ }
+ if (body == null) {
+ body = new BlockStmt(x, new List<Statement>());
+ }
+ stmt = new WhileStmt(x, guard, invariants, new Specification<Expression>(null, null), new Specification<FrameExpression>(null, null), body);
+ stmt = new SkeletonStatement(stmt, guardOmitted, bodyOmitted);
+ } else {
+ stmt = new WhileStmt(x, guard, invariants, new Specification<Expression>(decreases, decAttrs), new Specification<FrameExpression>(mod, modAttrs), body);
+ }
+ .)
|
LoopSpec<out invariants, out decreases, out mod, ref decAttrs, ref modAttrs>
AlternativeBlock<out alternatives>
@@ -846,12 +928,15 @@ LoopSpec<.out List<MaybeFreeExpression/*!*/> invariants, out List<Expression/*!* .)
{
Invariant<out invariant> SYNC ";" (. invariants.Add(invariant); .)
- | SYNC "decreases" { IF(IsAttribute()) Attribute<ref decAttrs> } DecreasesList<decreases, true> SYNC ";"
- | SYNC "modifies" { IF(IsAttribute()) Attribute<ref modAttrs> } (. mod = mod ?? new List<FrameExpression>(); .)
- [ FrameExpression<out fe> (. mod.Add(fe); .)
- { "," FrameExpression<out fe> (. mod.Add(fe); .)
- }
- ] SYNC ";"
+ | SYNC "decreases"
+ { IF(IsAttribute()) Attribute<ref decAttrs> }
+ DecreasesList<decreases, true> SYNC ";"
+ | SYNC "modifies"
+ { IF(IsAttribute()) Attribute<ref modAttrs> } (. mod = mod ?? new List<FrameExpression>(); .)
+ [ FrameExpression<out fe> (. mod.Add(fe); .)
+ { "," FrameExpression<out fe> (. mod.Add(fe); .)
+ }
+ ] SYNC ";"
}
.
Invariant<out MaybeFreeExpression/*!*/ invariant>
@@ -917,10 +1002,21 @@ CaseStatement<out MatchCaseStmt/*!*/ c> .
/*------------------------------------------------------------------------*/
AssertStmt<out Statement/*!*/ s>
-= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; Expression/*!*/ e; Attributes attrs = null; .)
+= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x;
+ Expression/*!*/ e = null; Attributes attrs = null;
+ .)
"assert" (. x = t; s = null;.)
- { IF(IsAttribute()) Attribute<ref attrs> } Expression<out e> (. s = new AssertStmt(x, e, attrs); .)
+ { IF(IsAttribute()) Attribute<ref attrs> }
+ ( Expression<out e>
+ | "..."
+ )
";"
+ (. if (e == null) {
+ s = new SkeletonStatement(new AssertStmt(x, new LiteralExpr(x, true), attrs), true, false);
+ } else {
+ s = new AssertStmt(x, e, attrs);
+ }
+ .)
.
AssumeStmt<out Statement/*!*/ s>
= (. Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; Expression/*!*/ e; .)
@@ -947,7 +1043,7 @@ ParallelStmt<out Statement/*!*/ s> var ens = new List<MaybeFreeExpression/*!*/>();
bool isFree;
Expression/*!*/ e;
- Statement/*!*/ block;
+ BlockStmt/*!*/ block;
IToken bodyStart, bodyEnd;
.)
"parallel" (. x = t; .)
diff --git a/Dafny/DafnyAst.cs b/Dafny/DafnyAst.cs index b410b37d..27f06518 100644 --- a/Dafny/DafnyAst.cs +++ b/Dafny/DafnyAst.cs @@ -32,7 +32,7 @@ namespace Microsoft.Dafny { public class BuiltIns
{
- public readonly ModuleDecl SystemModule = new ModuleDecl(Token.NoToken, "_System", null, new List<string>(), null);
+ public readonly ModuleDecl SystemModule = new ModuleDecl(Token.NoToken, "_System", false, null, new List<string>(), null);
Dictionary<int, ClassDecl/*!*/> arrayTypeDecls = new Dictionary<int, ClassDecl>();
public BuiltIns() {
@@ -101,7 +101,40 @@ namespace Microsoft.Dafny { Prev = prev;
}
- public class Argument {
+ public static bool Contains(Attributes attrs, string nm) {
+ Contract.Requires(nm != null);
+ for (; attrs != null; attrs = attrs.Prev) {
+ if (attrs.Name == nm) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /// <summary>
+ /// Returns true if "nm" is a specified attribute. If it is, then:
+ /// - if the attribute is {:nm true}, then value==true
+ /// - if the attribute is {:nm false}, then value==false
+ /// - if the attribute is anything else, then value returns as whatever it was passed in as.
+ /// </summary>
+ public static bool ContainsBool(Attributes attrs, string nm, ref bool value) {
+ Contract.Requires(nm != null);
+ for (; attrs != null; attrs = attrs.Prev) {
+ if (attrs.Name == nm) {
+ if (attrs.Args.Count == 1) {
+ var arg = attrs.Args[0].E as LiteralExpr;
+ if (arg != null && arg.Value is bool) {
+ value = (bool)arg.Value;
+ }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public class Argument
+ {
public readonly IToken Tok;
public readonly string S;
public readonly Expression E;
@@ -199,6 +232,21 @@ namespace Microsoft.Dafny { }
}
}
+ public bool IsIndDatatype {
+ get {
+ return AsIndDatatype != null;
+ }
+ }
+ public IndDatatypeDecl AsIndDatatype {
+ get {
+ UserDefinedType udt = this as UserDefinedType;
+ if (udt == null) {
+ return null;
+ } else {
+ return udt.ResolvedClass as IndDatatypeDecl;
+ }
+ }
+ }
public bool IsTypeParameter {
get {
UserDefinedType ct = this as UserDefinedType;
@@ -314,6 +362,16 @@ namespace Microsoft.Dafny { [Rep]
public readonly List<Type/*!*/>/*!*/ TypeArgs;
+ public string FullName {
+ get {
+ if (ResolvedClass != null && !ResolvedClass.Module.IsDefaultModule) {
+ return ResolvedClass.Module.Name + "." + Name;
+ } else {
+ return Name;
+ }
+ }
+ }
+
public TopLevelDecl ResolvedClass; // filled in by resolution, if Name denotes a class/datatype and TypeArgs match the type parameters of that class/datatype
public TypeParameter ResolvedParam; // filled in by resolution, if Name denotes an enclosing type parameter and TypeArgs is the empty list
@@ -610,6 +668,7 @@ namespace Microsoft.Dafny { public readonly List<TopLevelDecl/*!*/> TopLevelDecls = new List<TopLevelDecl/*!*/>(); // filled in by the parser; readonly after that
public readonly Graph<MemberDecl/*!*/> CallGraph = new Graph<MemberDecl/*!*/>(); // filled in during resolution
public int Height; // height in the topological sorting of modules; filled in during resolution
+ public readonly bool IsGhost;
[ContractInvariantMethod]
void ObjectInvariant() {
@@ -618,7 +677,7 @@ namespace Microsoft.Dafny { Contract.Invariant(CallGraph != null);
}
- public ModuleDecl(IToken tok, string name, string refinementBase, [Captured] List<string/*!*/>/*!*/ imports, Attributes attributes)
+ public ModuleDecl(IToken tok, string name, bool isGhost, string refinementBase, [Captured] List<string/*!*/>/*!*/ imports, Attributes attributes)
: base(tok, name, attributes) {
Contract.Requires(tok != null);
Contract.Requires(name != null);
@@ -631,6 +690,7 @@ namespace Microsoft.Dafny { ImportNames.Add(nm);
}
}
+ IsGhost = isGhost;
}
public virtual bool IsDefaultModule {
get {
@@ -640,7 +700,7 @@ namespace Microsoft.Dafny { }
public class DefaultModuleDecl : ModuleDecl {
- public DefaultModuleDecl() : base(Token.NoToken, "_default", null, new List<string/*!*/>(), null) {
+ public DefaultModuleDecl() : base(Token.NoToken, "_default", false, null, new List<string/*!*/>(), null) {
}
public override bool IsDefaultModule {
get {
@@ -729,7 +789,7 @@ namespace Microsoft.Dafny { }
}
- public class DatatypeDecl : TopLevelDecl {
+ public abstract class DatatypeDecl : TopLevelDecl {
public readonly List<DatatypeCtor/*!*/>/*!*/ Ctors;
[ContractInvariantMethod]
void ObjectInvariant() {
@@ -737,8 +797,6 @@ namespace Microsoft.Dafny { Contract.Invariant(1 <= Ctors.Count);
}
- public DatatypeCtor DefaultCtor; // set during resolution
-
public DatatypeDecl(IToken/*!*/ tok, string/*!*/ name, ModuleDecl/*!*/ module, List<TypeParameter/*!*/>/*!*/ typeArgs,
[Captured] List<DatatypeCtor/*!*/>/*!*/ ctors, Attributes attributes)
: base(tok, name, module, typeArgs, attributes) {
@@ -752,7 +810,39 @@ namespace Microsoft.Dafny { }
}
- public class DatatypeCtor : Declaration, TypeParameter.ParentType {
+ public class IndDatatypeDecl : DatatypeDecl
+ {
+ public DatatypeCtor DefaultCtor; // set during resolution
+ public bool[] TypeParametersUsedInConstructionByDefaultCtor; // set during resolution; has same length as
+
+ public IndDatatypeDecl(IToken/*!*/ tok, string/*!*/ name, ModuleDecl/*!*/ module, List<TypeParameter/*!*/>/*!*/ typeArgs,
+ [Captured] List<DatatypeCtor/*!*/>/*!*/ ctors, Attributes attributes)
+ : base(tok, name, module, typeArgs, ctors, attributes) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ Contract.Requires(module != null);
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Requires(cce.NonNullElements(ctors));
+ Contract.Requires(1 <= ctors.Count);
+ }
+ }
+
+ public class CoDatatypeDecl : DatatypeDecl
+ {
+ public CoDatatypeDecl(IToken/*!*/ tok, string/*!*/ name, ModuleDecl/*!*/ module, List<TypeParameter/*!*/>/*!*/ typeArgs,
+ [Captured] List<DatatypeCtor/*!*/>/*!*/ ctors, Attributes attributes)
+ : base(tok, name, module, typeArgs, ctors, attributes) {
+ Contract.Requires(tok != null);
+ Contract.Requires(name != null);
+ Contract.Requires(module != null);
+ Contract.Requires(cce.NonNullElements(typeArgs));
+ Contract.Requires(cce.NonNullElements(ctors));
+ Contract.Requires(1 <= ctors.Count);
+ }
+ }
+
+ public class DatatypeCtor : Declaration, TypeParameter.ParentType
+ {
public readonly List<Formal/*!*/>/*!*/ Formals;
[ContractInvariantMethod]
void ObjectInvariant() {
@@ -1055,7 +1145,8 @@ namespace Microsoft.Dafny { public readonly List<FrameExpression/*!*/>/*!*/ Reads;
public readonly List<Expression/*!*/>/*!*/ Ens;
public readonly Specification<Expression>/*!*/ Decreases;
- public readonly Expression Body; // an extended expression
+ public Expression Body; // an extended expression; Body is readonly after construction, except for any kind of rewrite that may take place around the time of resolution
+ public readonly bool SignatureIsOmitted; // is "false" for all Function objects that survive into resolution
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(cce.NonNullElements(TypeArgs));
@@ -1070,7 +1161,7 @@ namespace Microsoft.Dafny { public Function(IToken tok, string name, bool isStatic, bool isGhost, bool isUnlimited,
List<TypeParameter> typeArgs, IToken openParen, List<Formal> formals, Type resultType,
List<Expression> req, List<FrameExpression> reads, List<Expression> ens, Specification<Expression> decreases,
- Expression body, Attributes attributes)
+ Expression body, Attributes attributes, bool signatureOmitted)
: base(tok, name, isStatic, attributes) {
Contract.Requires(tok != null);
@@ -1093,6 +1184,7 @@ namespace Microsoft.Dafny { this.Ens = ens;
this.Decreases = decreases;
this.Body = body;
+ this.SignatureIsOmitted = signatureOmitted;
}
}
@@ -1102,8 +1194,8 @@ namespace Microsoft.Dafny { public Predicate(IToken tok, string name, bool isStatic, bool isGhost, bool isUnlimited,
List<TypeParameter> typeArgs, IToken openParen, List<Formal> formals,
List<Expression> req, List<FrameExpression> reads, List<Expression> ens, Specification<Expression> decreases,
- Expression body, bool bodyIsExtended, Attributes attributes)
- : base(tok, name, isStatic, isGhost, isUnlimited, typeArgs, openParen, formals, new BoolType(), req, reads, ens, decreases, body, attributes) {
+ Expression body, bool bodyIsExtended, Attributes attributes, bool signatureOmitted)
+ : base(tok, name, isStatic, isGhost, isUnlimited, typeArgs, openParen, formals, new BoolType(), req, reads, ens, decreases, body, attributes, signatureOmitted) {
Contract.Requires(!bodyIsExtended || body != null);
BodyIsExtended = bodyIsExtended;
}
@@ -1112,6 +1204,7 @@ namespace Microsoft.Dafny { public class Method : MemberDecl, TypeParameter.ParentType
{
public readonly bool IsGhost;
+ public readonly bool SignatureIsOmitted;
public readonly List<TypeParameter/*!*/>/*!*/ TypeArgs;
public readonly List<Formal/*!*/>/*!*/ Ins;
public readonly List<Formal/*!*/>/*!*/ Outs;
@@ -1119,7 +1212,7 @@ namespace Microsoft.Dafny { public readonly Specification<FrameExpression>/*!*/ Mod;
public readonly List<MaybeFreeExpression/*!*/>/*!*/ Ens;
public readonly Specification<Expression>/*!*/ Decreases;
- public readonly BlockStmt Body;
+ public BlockStmt Body; // Body is readonly after construction, except for any kind of rewrite that may take place around the time of resolution
[ContractInvariantMethod]
void ObjectInvariant() {
@@ -1140,7 +1233,7 @@ namespace Microsoft.Dafny { [Captured] List<MaybeFreeExpression/*!*/>/*!*/ ens,
[Captured] Specification<Expression>/*!*/ decreases,
[Captured] BlockStmt body,
- Attributes attributes)
+ Attributes attributes, bool signatureOmitted)
: base(tok, name, isStatic, attributes) {
Contract.Requires(tok != null);
Contract.Requires(name != null);
@@ -1160,6 +1253,7 @@ namespace Microsoft.Dafny { this.Ens = ens;
this.Decreases = decreases;
this.Body = body;
+ this.SignatureIsOmitted = signatureOmitted;
}
}
@@ -1172,8 +1266,8 @@ namespace Microsoft.Dafny { [Captured] List<MaybeFreeExpression/*!*/>/*!*/ ens,
[Captured] Specification<Expression>/*!*/ decreases,
[Captured] BlockStmt body,
- Attributes attributes)
- : base(tok, name, false, false, typeArgs, ins, new List<Formal>(), req, mod, ens, decreases, body, attributes) {
+ Attributes attributes, bool signatureOmitted)
+ : base(tok, name, false, false, typeArgs, ins, new List<Formal>(), req, mod, ens, decreases, body, attributes, signatureOmitted) {
Contract.Requires(tok != null);
Contract.Requires(name != null);
Contract.Requires(cce.NonNullElements(typeArgs));
@@ -1223,6 +1317,13 @@ namespace Microsoft.Dafny { Contract.Requires(tok != null);
this.Tok = tok;
}
+
+ /// <summary>
+ /// Returns the non-null substatements of the Statements.
+ /// </summary>
+ public virtual IEnumerable<Statement> SubStatements {
+ get { yield break; }
+ }
}
public class LabelNode
@@ -1497,18 +1598,22 @@ namespace Microsoft.Dafny { public ConcreteSyntaxStatement(IToken tok)
: base(tok) {
}
+
+ public override IEnumerable<Statement> SubStatements {
+ get { return ResolvedStatements; }
+ }
}
public class VarDeclStmt : ConcreteSyntaxStatement
{
public readonly List<VarDecl> Lhss;
- public readonly UpdateStmt Update;
+ public readonly ConcreteUpdateStatement Update;
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(cce.NonNullElements(Lhss));
}
- public VarDeclStmt(IToken tok, List<VarDecl> lhss, UpdateStmt update)
+ public VarDeclStmt(IToken tok, List<VarDecl> lhss, ConcreteUpdateStatement update)
: base(tok)
{
Contract.Requires(lhss != null);
@@ -1518,9 +1623,35 @@ namespace Microsoft.Dafny { }
}
- public class UpdateStmt : ConcreteSyntaxStatement
+ /// <summary>
+ /// Common superclass of UpdateStmt and AssignSuchThatStmt.
+ /// </summary>
+ public abstract class ConcreteUpdateStatement : ConcreteSyntaxStatement
{
public readonly List<Expression> Lhss;
+ public ConcreteUpdateStatement(IToken tok, List<Expression> lhss)
+ : base(tok) {
+ Contract.Requires(tok != null);
+ Contract.Requires(cce.NonNullElements(lhss));
+ Lhss = lhss;
+ }
+ }
+
+ public class AssignSuchThatStmt : ConcreteUpdateStatement
+ {
+ public readonly AssumeStmt Assume;
+ public AssignSuchThatStmt(IToken tok, List<Expression> lhss, Expression expr)
+ : base(tok, lhss) {
+ Contract.Requires(tok != null);
+ Contract.Requires(cce.NonNullElements(lhss));
+ Contract.Requires(lhss.Count != 0);
+ Contract.Requires(expr != null);
+ Assume = new AssumeStmt(tok, expr);
+ }
+ }
+
+ public class UpdateStmt : ConcreteUpdateStatement
+ {
public readonly List<AssignmentRhs> Rhss;
public readonly bool CanMutateKnownState;
[ContractInvariantMethod]
@@ -1529,24 +1660,22 @@ namespace Microsoft.Dafny { Contract.Invariant(cce.NonNullElements(Rhss));
}
public UpdateStmt(IToken tok, List<Expression> lhss, List<AssignmentRhs> rhss)
- : base(tok)
+ : base(tok, lhss)
{
Contract.Requires(tok != null);
Contract.Requires(cce.NonNullElements(lhss));
Contract.Requires(cce.NonNullElements(rhss));
Contract.Requires(lhss.Count != 0 || rhss.Count == 1);
- Lhss = lhss;
Rhss = rhss;
CanMutateKnownState = false;
}
public UpdateStmt(IToken tok, List<Expression> lhss, List<AssignmentRhs> rhss, bool mutate)
- : base(tok)
+ : base(tok, lhss)
{
Contract.Requires(tok != null);
Contract.Requires(cce.NonNullElements(lhss));
Contract.Requires(cce.NonNullElements(rhss));
Contract.Requires(lhss.Count != 0 || rhss.Count == 1);
- Lhss = lhss;
Rhss = rhss;
CanMutateKnownState = mutate;
}
@@ -1569,6 +1698,15 @@ namespace Microsoft.Dafny { this.Lhs = lhs;
this.Rhs = rhs;
}
+
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ var trhs = Rhs as TypeRhs;
+ if (trhs != null && trhs.InitCall != null) {
+ yield return trhs.InitCall;
+ }
+ }
+ }
}
public class VarDecl : Statement, IVariable {
@@ -1669,20 +1807,23 @@ namespace Microsoft.Dafny { Contract.Requires(tok != null);
Contract.Requires(cce.NonNullElements(body));
this.Body = body;
+ }
+ public override IEnumerable<Statement> SubStatements {
+ get { return Body; }
}
}
public class IfStmt : Statement {
public readonly Expression Guard;
- public readonly Statement Thn;
+ public readonly BlockStmt Thn;
public readonly Statement Els;
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(Thn != null);
Contract.Invariant(Els == null || Els is BlockStmt || Els is IfStmt);
}
- public IfStmt(IToken tok, Expression guard, Statement thn, Statement els)
+ public IfStmt(IToken tok, Expression guard, BlockStmt thn, Statement els)
: base(tok) {
Contract.Requires(tok != null);
Contract.Requires(thn != null);
@@ -1691,6 +1832,14 @@ namespace Microsoft.Dafny { this.Thn = thn;
this.Els = els;
}
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ yield return Thn;
+ if (Els != null) {
+ yield return Els;
+ }
+ }
+ }
}
public class GuardedAlternative
@@ -1728,6 +1877,15 @@ namespace Microsoft.Dafny { Contract.Requires(alternatives != null);
this.Alternatives = alternatives;
}
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ foreach (var alt in Alternatives) {
+ foreach (var s in alt.Body) {
+ yield return s;
+ }
+ }
+ }
+ }
}
public abstract class LoopStmt : Statement
@@ -1758,7 +1916,7 @@ namespace Microsoft.Dafny { public class WhileStmt : LoopStmt
{
public readonly Expression Guard;
- public readonly Statement/*!*/ Body;
+ public readonly BlockStmt/*!*/ Body;
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(Body != null);
@@ -1766,13 +1924,19 @@ namespace Microsoft.Dafny { public WhileStmt(IToken tok, Expression guard,
List<MaybeFreeExpression/*!*/>/*!*/ invariants, Specification<Expression>/*!*/ decreases, Specification<FrameExpression>/*!*/ mod,
- Statement/*!*/ body)
+ BlockStmt/*!*/ body)
: base(tok, invariants, decreases, mod) {
Contract.Requires(tok != null);
Contract.Requires(body != null);
this.Guard = guard;
this.Body = body;
}
+
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ yield return Body;
+ }
+ }
}
public class AlternativeLoopStmt : LoopStmt
@@ -1790,6 +1954,15 @@ namespace Microsoft.Dafny { Contract.Requires(alternatives != null);
this.Alternatives = alternatives;
}
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ foreach (var alt in Alternatives) {
+ foreach (var s in alt.Body) {
+ yield return s;
+ }
+ }
+ }
+ }
}
public class ParallelStmt : Statement
@@ -1865,6 +2038,12 @@ namespace Microsoft.Dafny { }
}
}
+
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ yield return Body;
+ }
+ }
}
public class MatchStmt : Statement
@@ -1887,7 +2066,16 @@ namespace Microsoft.Dafny { Contract.Requires(cce.NonNullElements(cases));
this.Source = source;
this.Cases = cases;
+ }
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ foreach (var kase in Cases) {
+ foreach (var s in kase.Body) {
+ yield return s;
+ }
+ }
+ }
}
}
@@ -1911,6 +2099,53 @@ namespace Microsoft.Dafny { }
}
+ /// <summary>
+ /// The class represents several possible scenarios:
+ /// * ...;
+ /// S == null
+ /// * assert ...
+ /// ConditionOmitted == true
+ /// * if ... { Stmt }
+ /// if ... { Stmt } else ElseStmt
+ /// ConditionOmitted == true
+ /// * while ... invariant J;
+ /// ConditionOmitted == true && BodyOmitted == true
+ /// * while ... invariant J; { Stmt }
+ /// ConditionOmitted == true && BodyOmitted == false
+ /// </summary>
+ public class SkeletonStatement : Statement
+ {
+ public readonly Statement S;
+ public readonly bool ConditionOmitted;
+ public readonly bool BodyOmitted;
+ public SkeletonStatement(IToken tok)
+ : base(tok)
+ {
+ Contract.Requires(tok != null);
+ }
+ public SkeletonStatement(Statement s, bool conditionOmitted, bool bodyOmitted)
+ : base(s.Tok)
+ {
+ Contract.Requires(s != null);
+ S = s;
+ ConditionOmitted = conditionOmitted;
+ BodyOmitted = bodyOmitted;
+ }
+ public override IEnumerable<Statement> SubStatements {
+ get {
+ // The SkeletonStatement is really a modification of its inner statement S. Therefore,
+ // we don't consider S to be a substatement. Instead, the substatements of S are the
+ // substatements of the SkeletonStatement. In the case the SkeletonStatement modifies
+ // S by omitting its body (which is true only for loops), there are no substatements.
+ if (!BodyOmitted) {
+ foreach (var s in S.SubStatements) {
+ yield return s;
+ }
+ }
+ }
+ }
+ }
+
// ------------------------------------------------------------------------------------------------------
public abstract class TokenWrapper : IToken
@@ -2093,6 +2328,7 @@ namespace Microsoft.Dafny { public readonly List<Expression/*!*/>/*!*/ Arguments;
public DatatypeCtor Ctor; // filled in by resolution
public List<Type/*!*/> InferredTypeArgs = new List<Type>(); // filled in by resolution
+ public bool IsCoCall; // filled in by resolution
[ContractInvariantMethod]
void ObjectInvariant() {
Contract.Invariant(DatatypeName != null);
@@ -2319,6 +2555,8 @@ namespace Microsoft.Dafny { public readonly Expression/*!*/ Receiver;
public readonly IToken OpenParen; // can be null if Args.Count == 0
public readonly List<Expression/*!*/>/*!*/ Args;
+ public enum CoCallResolution { No, Yes, NoBecauseFunctionHasSideEffects }
+ public CoCallResolution CoCall = CoCallResolution.No; // indicates whether or not the call is a co-recursive call; filled in by resolution
[ContractInvariantMethod]
void ObjectInvariant() {
@@ -2551,6 +2789,88 @@ namespace Microsoft.Dafny { }
public ResolvedOpcode ResolvedOp; // filled in by resolution
+ public static Opcode ResolvedOp2SyntacticOp(ResolvedOpcode rop) {
+ switch (rop) {
+ case ResolvedOpcode.Iff: return Opcode.Iff;
+ case ResolvedOpcode.Imp: return Opcode.Imp;
+ case ResolvedOpcode.And: return Opcode.And;
+ case ResolvedOpcode.Or: return Opcode.Or;
+
+ case ResolvedOpcode.EqCommon:
+ case ResolvedOpcode.SetEq:
+ case ResolvedOpcode.MultiSetEq:
+ case ResolvedOpcode.SeqEq:
+ return Opcode.Eq;
+
+ case ResolvedOpcode.NeqCommon:
+ case ResolvedOpcode.SetNeq:
+ case ResolvedOpcode.MultiSetNeq:
+ case ResolvedOpcode.SeqNeq:
+ return Opcode.Neq;
+
+ case ResolvedOpcode.Lt:
+ case ResolvedOpcode.ProperSubset:
+ case ResolvedOpcode.ProperMultiSuperset:
+ case ResolvedOpcode.ProperPrefix:
+ case ResolvedOpcode.RankLt:
+ return Opcode.Lt;
+
+ case ResolvedOpcode.Le:
+ case ResolvedOpcode.Subset:
+ case ResolvedOpcode.MultiSubset:
+ case ResolvedOpcode.Prefix:
+ return Opcode.Le;
+
+ case ResolvedOpcode.Ge:
+ case ResolvedOpcode.Superset:
+ case ResolvedOpcode.MultiSuperset:
+ return Opcode.Ge;
+
+ case ResolvedOpcode.Gt:
+ case ResolvedOpcode.ProperSuperset:
+ case ResolvedOpcode.ProperMultiSubset:
+ case ResolvedOpcode.RankGt:
+ return Opcode.Gt;
+
+ case ResolvedOpcode.Add:
+ case ResolvedOpcode.Union:
+ case ResolvedOpcode.MultiSetUnion:
+ case ResolvedOpcode.Concat:
+ return Opcode.Add;
+
+ case ResolvedOpcode.Sub:
+ case ResolvedOpcode.SetDifference:
+ case ResolvedOpcode.MultiSetDifference:
+ return Opcode.Sub;
+
+ case ResolvedOpcode.Mul:
+ case ResolvedOpcode.Intersection:
+ case ResolvedOpcode.MultiSetIntersection:
+ return Opcode.Mul;
+
+ case ResolvedOpcode.Div: return Opcode.Div;
+ case ResolvedOpcode.Mod: return Opcode.Mod;
+
+ case ResolvedOpcode.Disjoint:
+ case ResolvedOpcode.MultiSetDisjoint:
+ return Opcode.Disjoint;
+
+ case ResolvedOpcode.InSet:
+ case ResolvedOpcode.InMultiSet:
+ case ResolvedOpcode.InSeq:
+ return Opcode.In;
+
+ case ResolvedOpcode.NotInSet:
+ case ResolvedOpcode.NotInMultiSet:
+ case ResolvedOpcode.NotInSeq:
+ return Opcode.NotIn;
+
+ default:
+ Contract.Assert(false); // unexpected ResolvedOpcode
+ return Opcode.Add; // please compiler
+ }
+ }
+
public static string OpcodeString(Opcode op) {
Contract.Ensures(Contract.Result<string>() != null);
diff --git a/Dafny/DafnyPipeline.csproj b/Dafny/DafnyPipeline.csproj index 7264389b..cf2b51eb 100644 --- a/Dafny/DafnyPipeline.csproj +++ b/Dafny/DafnyPipeline.csproj @@ -158,6 +158,7 @@ <Compile Include="Printer.cs" />
<Compile Include="RefinementTransformer.cs" />
<Compile Include="Resolver.cs" />
+ <Compile Include="Rewriter.cs" />
<Compile Include="SccGraph.cs" />
<Compile Include="Translator.cs" />
<Compile Include="..\version.cs" />
diff --git a/Dafny/Parser.cs b/Dafny/Parser.cs index 18415db0..a063e26b 100644 --- a/Dafny/Parser.cs +++ b/Dafny/Parser.cs @@ -21,12 +21,12 @@ public class Parser { public const int _colon = 5;
public const int _lbrace = 6;
public const int _rbrace = 7;
- public const int maxT = 104;
+ public const int maxT = 107;
const bool T = true;
const bool x = false;
const int minErrDist = 2;
-
+
public Scanner/*!*/ scanner;
public Errors/*!*/ errors;
@@ -131,10 +131,10 @@ bool IsAttribute() { if (errDist >= minErrDist) errors.SemErr(t, msg);
errDist = 0;
}
-
- public void SemErr(IToken/*!*/ tok, string/*!*/ msg) {
- Contract.Requires(tok != null);
- Contract.Requires(msg != null);
+
+ public void SemErr(IToken/*!*/ tok, string/*!*/ msg) {
+ Contract.Requires(tok != null);
+ Contract.Requires(msg != null);
errors.SemErr(tok, msg);
}
@@ -147,15 +147,15 @@ bool IsAttribute() { la = t;
}
}
-
+
void Expect (int n) {
if (la.kind==n) Get(); else { SynErr(n); }
}
-
+
bool StartOf (int s) {
return set[s, la.kind];
}
-
+
void ExpectWeak (int n, int follow) {
if (la.kind == n) Get();
else {
@@ -179,7 +179,7 @@ bool IsAttribute() { }
}
-
+
void Dafny() {
ClassDecl/*!*/ c; DatatypeDecl/*!*/ dt; ArbitraryTypeDecl at;
Attributes attrs; IToken/*!*/ id; List<string/*!*/> theImports;
@@ -189,19 +189,25 @@ bool IsAttribute() { // to support multiple files, create a default module only if theModules doesn't already contain one
DefaultModuleDecl defaultModule = null;
foreach (ModuleDecl mdecl in theModules) {
- defaultModule = mdecl as DefaultModuleDecl;
- if (defaultModule != null) { break; }
+ defaultModule = mdecl as DefaultModuleDecl;
+ if (defaultModule != null) { break; }
}
bool defaultModuleCreatedHere = false;
if (defaultModule == null) {
- defaultModuleCreatedHere = true;
- defaultModule = new DefaultModuleDecl();
+ defaultModuleCreatedHere = true;
+ defaultModule = new DefaultModuleDecl();
}
IToken idRefined;
+ bool isGhost;
while (StartOf(1)) {
+ isGhost = false;
if (la.kind == 8) {
Get();
+ isGhost = true;
+ }
+ if (la.kind == 9) {
+ Get();
attrs = null; idRefined = null; theImports = new List<string/*!*/>();
namedModuleDefaultClassMembers = new List<MemberDecl>();
@@ -210,60 +216,63 @@ bool IsAttribute() { }
Ident(out id);
defaultModule.ImportNames.Add(id.val);
- if (la.kind == 9) {
+ if (la.kind == 10) {
Get();
Ident(out idRefined);
}
- if (la.kind == 10) {
+ if (la.kind == 11) {
Get();
Idents(theImports);
}
- module = new ModuleDecl(id, id.val, idRefined == null ? null : idRefined.val, theImports, attrs);
+ module = new ModuleDecl(id, id.val, isGhost, idRefined == null ? null : idRefined.val, theImports, attrs);
Expect(6);
module.BodyStartTok = t;
while (StartOf(2)) {
- if (la.kind == 11) {
+ if (la.kind == 12) {
ClassDecl(module, out c);
module.TopLevelDecls.Add(c);
- } else if (la.kind == 15) {
+ } else if (la.kind == 15 || la.kind == 16) {
DatatypeDecl(module, out dt);
module.TopLevelDecls.Add(dt);
- } else if (la.kind == 21) {
+ } else if (la.kind == 22) {
ArbitraryTypeDecl(module, out at);
module.TopLevelDecls.Add(at);
} else {
- ClassMemberDecl(namedModuleDefaultClassMembers, false);
+ ClassMemberDecl(namedModuleDefaultClassMembers, false, false);
}
}
Expect(7);
module.BodyEndTok = t;
module.TopLevelDecls.Add(new DefaultClassDecl(module, namedModuleDefaultClassMembers));
theModules.Add(module);
- } else if (la.kind == 11) {
+ } else if (la.kind == 12) {
+ if (isGhost) { SemErr(t, "a class is not allowed to be declared as 'ghost'"); }
ClassDecl(defaultModule, out c);
defaultModule.TopLevelDecls.Add(c);
- } else if (la.kind == 15) {
+ } else if (la.kind == 15 || la.kind == 16) {
+ if (isGhost) { SemErr(t, "a datatype/codatatype is not allowed to be declared as 'ghost'"); }
DatatypeDecl(defaultModule, out dt);
defaultModule.TopLevelDecls.Add(dt);
- } else if (la.kind == 21) {
+ } else if (la.kind == 22) {
+ if (isGhost) { SemErr(t, "a type is not allowed to be declared as 'ghost'"); }
ArbitraryTypeDecl(defaultModule, out at);
defaultModule.TopLevelDecls.Add(at);
- } else {
- ClassMemberDecl(membersDefaultClass, false);
- }
+ } else if (StartOf(3)) {
+ ClassMemberDecl(membersDefaultClass, isGhost, false);
+ } else SynErr(108);
}
if (defaultModuleCreatedHere) {
defaultModule.TopLevelDecls.Add(new DefaultClassDecl(defaultModule, membersDefaultClass));
theModules.Add(defaultModule);
} else {
- // find the default class in the default module, then append membersDefaultClass to its member list
- foreach (TopLevelDecl topleveldecl in defaultModule.TopLevelDecls) {
- DefaultClassDecl defaultClass = topleveldecl as DefaultClassDecl;
- if (defaultClass != null) {
- defaultClass.Members.AddRange(membersDefaultClass);
- break;
- }
- }
+ // find the default class in the default module, then append membersDefaultClass to its member list
+ foreach (TopLevelDecl topleveldecl in defaultModule.TopLevelDecls) {
+ DefaultClassDecl defaultClass = topleveldecl as DefaultClassDecl;
+ if (defaultClass != null) {
+ defaultClass.Members.AddRange(membersDefaultClass);
+ break;
+ }
+ }
}
Expect(0);
@@ -285,7 +294,7 @@ bool IsAttribute() { IToken/*!*/ id;
Ident(out id);
ids.Add(id.val);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
Ident(out id);
ids.Add(id.val);
@@ -301,19 +310,19 @@ bool IsAttribute() { List<MemberDecl/*!*/> members = new List<MemberDecl/*!*/>();
IToken bodyStart;
- while (!(la.kind == 0 || la.kind == 11)) {SynErr(105); Get();}
- Expect(11);
+ while (!(la.kind == 0 || la.kind == 12)) {SynErr(109); Get();}
+ Expect(12);
while (la.kind == 6) {
Attribute(ref attrs);
}
Ident(out id);
- if (la.kind == 22) {
+ if (la.kind == 23) {
GenericParameters(typeArgs);
}
Expect(6);
bodyStart = t;
while (StartOf(3)) {
- ClassMemberDecl(members, true);
+ ClassMemberDecl(members, false, true);
}
Expect(7);
c = new ClassDecl(id, id.val, module, typeArgs, members, attrs);
@@ -330,26 +339,36 @@ bool IsAttribute() { List<TypeParameter/*!*/> typeArgs = new List<TypeParameter/*!*/>();
List<DatatypeCtor/*!*/> ctors = new List<DatatypeCtor/*!*/>();
IToken bodyStart = Token.NoToken; // dummy assignment
+ bool co = false;
- while (!(la.kind == 0 || la.kind == 15)) {SynErr(106); Get();}
- Expect(15);
+ while (!(la.kind == 0 || la.kind == 15 || la.kind == 16)) {SynErr(110); Get();}
+ if (la.kind == 15) {
+ Get();
+ } else if (la.kind == 16) {
+ Get();
+ co = true;
+ } else SynErr(111);
while (la.kind == 6) {
Attribute(ref attrs);
}
Ident(out id);
- if (la.kind == 22) {
+ if (la.kind == 23) {
GenericParameters(typeArgs);
}
- Expect(16);
+ Expect(17);
bodyStart = t;
DatatypeMemberDecl(ctors);
- while (la.kind == 17) {
+ while (la.kind == 18) {
Get();
DatatypeMemberDecl(ctors);
}
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(107); Get();}
- Expect(18);
- dt = new DatatypeDecl(id, id.val, module, typeArgs, ctors, attrs);
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(112); Get();}
+ Expect(19);
+ if (co) {
+ dt = new CoDatatypeDecl(id, id.val, module, typeArgs, ctors, attrs);
+ } else {
+ dt = new IndDatatypeDecl(id, id.val, module, typeArgs, ctors, attrs);
+ }
dt.BodyStartTok = bodyStart;
dt.BodyEndTok = t;
@@ -359,24 +378,25 @@ bool IsAttribute() { IToken/*!*/ id;
Attributes attrs = null;
- Expect(21);
+ Expect(22);
while (la.kind == 6) {
Attribute(ref attrs);
}
Ident(out id);
at = new ArbitraryTypeDecl(id, id.val, module, attrs);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(108); Get();}
- Expect(18);
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(113); Get();}
+ Expect(19);
}
- void ClassMemberDecl(List<MemberDecl/*!*/>/*!*/ mm, bool allowConstructors) {
+ void ClassMemberDecl(List<MemberDecl/*!*/>/*!*/ mm, bool isAlreadyGhost, bool allowConstructors) {
Contract.Requires(cce.NonNullElements(mm));
Method/*!*/ m;
Function/*!*/ f;
MemberModifiers mmod = new MemberModifiers();
+ mmod.IsGhost = isAlreadyGhost;
- while (la.kind == 12 || la.kind == 13 || la.kind == 14) {
- if (la.kind == 12) {
+ while (la.kind == 8 || la.kind == 13 || la.kind == 14) {
+ if (la.kind == 8) {
Get();
mmod.IsGhost = true;
} else if (la.kind == 13) {
@@ -387,29 +407,29 @@ bool IsAttribute() { mmod.IsUnlimited = true;
}
}
- if (la.kind == 19) {
+ if (la.kind == 20) {
FieldDecl(mmod, mm);
- } else if (la.kind == 41 || la.kind == 42) {
+ } else if (la.kind == 43 || la.kind == 44) {
FunctionDecl(mmod, out f);
mm.Add(f);
- } else if (la.kind == 24 || la.kind == 25) {
+ } else if (la.kind == 25 || la.kind == 26) {
MethodDecl(mmod, allowConstructors, out m);
mm.Add(m);
- } else SynErr(109);
+ } else SynErr(114);
}
void GenericParameters(List<TypeParameter/*!*/>/*!*/ typeArgs) {
Contract.Requires(cce.NonNullElements(typeArgs));
IToken/*!*/ id;
- Expect(22);
+ Expect(23);
Ident(out id);
typeArgs.Add(new TypeParameter(id, id.val));
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
Ident(out id);
typeArgs.Add(new TypeParameter(id, id.val));
}
- Expect(23);
+ Expect(24);
}
void FieldDecl(MemberModifiers mmod, List<MemberDecl/*!*/>/*!*/ mm) {
@@ -417,8 +437,8 @@ bool IsAttribute() { Attributes attrs = null;
IToken/*!*/ id; Type/*!*/ ty;
- while (!(la.kind == 0 || la.kind == 19)) {SynErr(110); Get();}
- Expect(19);
+ while (!(la.kind == 0 || la.kind == 20)) {SynErr(115); Get();}
+ Expect(20);
if (mmod.IsUnlimited) { SemErr(t, "fields cannot be declared 'unlimited'"); }
if (mmod.IsStatic) { SemErr(t, "fields cannot be declared 'static'"); }
@@ -427,13 +447,13 @@ bool IsAttribute() { }
IdentType(out id, out ty);
mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs));
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
IdentType(out id, out ty);
mm.Add(new Field(id, id.val, mmod.IsGhost, ty, attrs));
}
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(111); Get();}
- Expect(18);
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(116); Get();}
+ Expect(19);
}
void FunctionDecl(MemberModifiers mmod, out Function/*!*/ f) {
@@ -447,16 +467,17 @@ bool IsAttribute() { List<Expression/*!*/> ens = new List<Expression/*!*/>();
List<FrameExpression/*!*/> reads = new List<FrameExpression/*!*/>();
List<Expression/*!*/> decreases = new List<Expression/*!*/>();
- Expression/*!*/ bb; Expression body = null;
+ Expression body = null;
bool isPredicate = false;
bool isFunctionMethod = false;
IToken openParen = null;
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
+ bool signatureOmitted = false;
- if (la.kind == 41) {
+ if (la.kind == 43) {
Get();
- if (la.kind == 24) {
+ if (la.kind == 25) {
Get();
isFunctionMethod = true;
}
@@ -466,16 +487,22 @@ bool IsAttribute() { Attribute(ref attrs);
}
Ident(out id);
- if (la.kind == 22) {
- GenericParameters(typeArgs);
- }
- Formals(true, isFunctionMethod, formals, out openParen);
- Expect(5);
- Type(out returnType);
- } else if (la.kind == 42) {
+ if (la.kind == 23 || la.kind == 34) {
+ if (la.kind == 23) {
+ GenericParameters(typeArgs);
+ }
+ Formals(true, isFunctionMethod, formals, out openParen);
+ Expect(5);
+ Type(out returnType);
+ } else if (la.kind == 28) {
+ Get();
+ signatureOmitted = true;
+ openParen = Token.NoToken;
+ } else SynErr(117);
+ } else if (la.kind == 44) {
Get();
isPredicate = true;
- if (la.kind == 24) {
+ if (la.kind == 25) {
Get();
isFunctionMethod = true;
}
@@ -485,28 +512,35 @@ bool IsAttribute() { Attribute(ref attrs);
}
Ident(out id);
- if (la.kind == 22) {
- GenericParameters(typeArgs);
- }
- if (la.kind == 32) {
- Formals(true, isFunctionMethod, formals, out openParen);
- if (la.kind == 5) {
- Get();
- SemErr(t, "predicates do not have an explicitly declared return type; it is always bool");
+ if (StartOf(4)) {
+ if (la.kind == 23) {
+ GenericParameters(typeArgs);
}
- }
- } else SynErr(112);
- while (StartOf(4)) {
+ if (la.kind == 34) {
+ Formals(true, isFunctionMethod, formals, out openParen);
+ if (la.kind == 5) {
+ Get();
+ SemErr(t, "predicates do not have an explicitly declared return type; it is always bool");
+ }
+ }
+ } else if (la.kind == 28) {
+ Get();
+ signatureOmitted = true;
+ openParen = Token.NoToken;
+ } else SynErr(118);
+ } else SynErr(119);
+ while (StartOf(5)) {
FunctionSpec(reqs, reads, ens, decreases);
}
if (la.kind == 6) {
- FunctionBody(out bb, out bodyStart, out bodyEnd);
- body = bb;
+ FunctionBody(out body, out bodyStart, out bodyEnd);
}
if (isPredicate) {
- f = new Predicate(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals, reqs, reads, ens, new Specification<Expression>(decreases, null), body, false, attrs);
+ f = new Predicate(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals,
+ reqs, reads, ens, new Specification<Expression>(decreases, null), body, false, attrs, signatureOmitted);
} else {
- f = new Function(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals, returnType, reqs, reads, ens, new Specification<Expression>(decreases, null), body, attrs);
+ f = new Function(id, id.val, mmod.IsStatic, !isFunctionMethod, mmod.IsUnlimited, typeArgs, openParen, formals, returnType,
+ reqs, reads, ens, new Specification<Expression>(decreases, null), body, attrs, signatureOmitted);
}
f.BodyStartTok = bodyStart;
f.BodyEndTok = bodyEnd;
@@ -527,57 +561,65 @@ bool IsAttribute() { List<Expression/*!*/> dec = new List<Expression/*!*/>();
Attributes decAttrs = null;
Attributes modAttrs = null;
- Statement/*!*/ bb; BlockStmt body = null;
+ BlockStmt body = null;
bool isConstructor = false;
+ bool signatureOmitted = false;
IToken bodyStart = Token.NoToken;
IToken bodyEnd = Token.NoToken;
- while (!(la.kind == 0 || la.kind == 24 || la.kind == 25)) {SynErr(113); Get();}
- if (la.kind == 24) {
+ while (!(la.kind == 0 || la.kind == 25 || la.kind == 26)) {SynErr(120); Get();}
+ if (la.kind == 25) {
Get();
- } else if (la.kind == 25) {
+ } else if (la.kind == 26) {
Get();
if (allowConstructor) {
isConstructor = true;
} else {
- SemErr(t, "constructors are only allowed in classes");
+ SemErr(t, "constructors are only allowed in classes");
}
- } else SynErr(114);
+ } else SynErr(121);
if (mmod.IsUnlimited) { SemErr(t, "methods cannot be declared 'unlimited'"); }
if (isConstructor) {
- if (mmod.IsGhost) {
- SemErr(t, "constructors cannot be declared 'ghost'");
- }
- if (mmod.IsStatic) {
- SemErr(t, "constructors cannot be declared 'static'");
- }
+ if (mmod.IsGhost) {
+ SemErr(t, "constructors cannot be declared 'ghost'");
+ }
+ if (mmod.IsStatic) {
+ SemErr(t, "constructors cannot be declared 'static'");
+ }
}
while (la.kind == 6) {
Attribute(ref attrs);
}
Ident(out id);
- if (la.kind == 22) {
- GenericParameters(typeArgs);
- }
- Formals(true, !mmod.IsGhost, ins, out openParen);
- if (la.kind == 26) {
+ if (la.kind == 23 || la.kind == 34) {
+ if (la.kind == 23) {
+ GenericParameters(typeArgs);
+ }
+ Formals(true, !mmod.IsGhost, ins, out openParen);
+ if (la.kind == 27) {
+ Get();
+ if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); }
+ Formals(false, !mmod.IsGhost, outs, out openParen);
+ }
+ } else if (la.kind == 28) {
Get();
- if (isConstructor) { SemErr(t, "constructors cannot have out-parameters"); }
- Formals(false, !mmod.IsGhost, outs, out openParen);
- }
- while (StartOf(5)) {
+ signatureOmitted = true; openParen = Token.NoToken;
+ } else SynErr(122);
+ while (StartOf(6)) {
MethodSpec(req, mod, ens, dec, ref decAttrs, ref modAttrs);
}
if (la.kind == 6) {
- BlockStmt(out bb, out bodyStart, out bodyEnd);
- body = (BlockStmt)bb;
+ BlockStmt(out body, out bodyStart, out bodyEnd);
+ }
+ if (isConstructor) {
+ m = new Constructor(id, id.val, typeArgs, ins,
+ req, new Specification<FrameExpression>(mod, modAttrs), ens, new Specification<Expression>(dec, decAttrs), body, attrs, signatureOmitted);
+ } else {
+ m = new Method(id, id.val, mmod.IsStatic, mmod.IsGhost, typeArgs, ins, outs,
+ req, new Specification<FrameExpression>(mod, modAttrs), ens, new Specification<Expression>(dec, decAttrs), body, attrs, signatureOmitted);
}
- if (isConstructor)
- m = new Constructor(id, id.val, typeArgs, ins, req, new Specification<FrameExpression>(mod, modAttrs), ens, new Specification<Expression>(dec, decAttrs), body, attrs);
- else
- m = new Method(id, id.val, mmod.IsStatic, mmod.IsGhost, typeArgs, ins, outs, req, new Specification<FrameExpression>(mod, modAttrs), ens, new Specification<Expression>(dec, decAttrs), body, attrs);
m.BodyStartTok = bodyStart;
m.BodyEndTok = bodyEnd;
@@ -593,7 +635,7 @@ bool IsAttribute() { Attribute(ref attrs);
}
Ident(out id);
- if (la.kind == 32) {
+ if (la.kind == 34) {
FormalsOptionalIds(formals);
}
ctors.Add(new DatatypeCtor(id, id.val, formals, attrs));
@@ -601,17 +643,17 @@ bool IsAttribute() { void FormalsOptionalIds(List<Formal/*!*/>/*!*/ formals) {
Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; string/*!*/ name; bool isGhost;
- Expect(32);
- if (StartOf(6)) {
+ Expect(34);
+ if (StartOf(7)) {
TypeIdentOptional(out id, out name, out ty, out isGhost);
formals.Add(new Formal(id, name, ty, true, isGhost));
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
TypeIdentOptional(out id, out name, out ty, out isGhost);
formals.Add(new Formal(id, name, ty, true, isGhost));
}
}
- Expect(33);
+ Expect(35);
}
void IdentType(out IToken/*!*/ id, out Type/*!*/ ty) {
@@ -625,7 +667,7 @@ bool IsAttribute() { Contract.Ensures(Contract.ValueAtReturn(out id)!=null);
Contract.Ensures(Contract.ValueAtReturn(out ty)!=null);
isGhost = false;
- if (la.kind == 12) {
+ if (la.kind == 8) {
Get();
if (allowGhostKeyword) { isGhost = true; } else { SemErr(t, "formal cannot be declared 'ghost' in this context"); }
}
@@ -666,7 +708,7 @@ bool IsAttribute() { Contract.Ensures(Contract.ValueAtReturn(out ty)!=null);
Contract.Ensures(Contract.ValueAtReturn(out identName)!=null);
string name = null; isGhost = false;
- if (la.kind == 12) {
+ if (la.kind == 8) {
Get();
isGhost = true;
}
@@ -675,9 +717,9 @@ bool IsAttribute() { Get();
UserDefinedType udt = ty as UserDefinedType;
if (udt != null && udt.TypeArgs.Count == 0) {
- name = udt.Name;
+ name = udt.Name;
} else {
- SemErr(id, "invalid formal-parameter name in datatype constructor");
+ SemErr(id, "invalid formal-parameter name in datatype constructor");
}
Type(out ty);
@@ -685,7 +727,7 @@ bool IsAttribute() { if (name != null) {
identName = name;
} else {
- identName = "#" + anonymousIds++;
+ identName = "#" + anonymousIds++;
}
}
@@ -695,22 +737,22 @@ bool IsAttribute() { List<Type/*!*/>/*!*/ gt;
switch (la.kind) {
- case 34: {
+ case 36: {
Get();
tok = t;
break;
}
- case 35: {
+ case 37: {
Get();
tok = t; ty = new NatType();
break;
}
- case 36: {
+ case 38: {
Get();
tok = t; ty = new IntType();
break;
}
- case 37: {
+ case 39: {
Get();
tok = t; gt = new List<Type/*!*/>();
GenericInstantiation(gt);
@@ -721,7 +763,7 @@ bool IsAttribute() { break;
}
- case 38: {
+ case 40: {
Get();
tok = t; gt = new List<Type/*!*/>();
GenericInstantiation(gt);
@@ -732,7 +774,7 @@ bool IsAttribute() { break;
}
- case 39: {
+ case 41: {
Get();
tok = t; gt = new List<Type/*!*/>();
GenericInstantiation(gt);
@@ -743,28 +785,28 @@ bool IsAttribute() { break;
}
- case 1: case 3: case 40: {
+ case 1: case 3: case 42: {
ReferenceType(out tok, out ty);
break;
}
- default: SynErr(115); break;
+ default: SynErr(123); break;
}
}
void Formals(bool incoming, bool allowGhostKeyword, List<Formal/*!*/>/*!*/ formals, out IToken openParen) {
Contract.Requires(cce.NonNullElements(formals)); IToken/*!*/ id; Type/*!*/ ty; bool isGhost;
- Expect(32);
+ Expect(34);
openParen = t;
- if (la.kind == 1 || la.kind == 12) {
+ if (la.kind == 1 || la.kind == 8) {
GIdentType(allowGhostKeyword, out id, out ty, out isGhost);
formals.Add(new Formal(id, id.val, ty, incoming, isGhost));
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
GIdentType(allowGhostKeyword, out id, out ty, out isGhost);
formals.Add(new Formal(id, id.val, ty, incoming, isGhost));
}
}
- Expect(33);
+ Expect(35);
}
void MethodSpec(List<MaybeFreeExpression/*!*/>/*!*/ req, List<FrameExpression/*!*/>/*!*/ mod, List<MaybeFreeExpression/*!*/>/*!*/ ens,
@@ -772,62 +814,62 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Contract.Requires(cce.NonNullElements(req)); Contract.Requires(cce.NonNullElements(mod)); Contract.Requires(cce.NonNullElements(ens)); Contract.Requires(cce.NonNullElements(decreases));
Expression/*!*/ e; FrameExpression/*!*/ fe; bool isFree = false; Attributes ensAttrs = null;
- while (!(StartOf(7))) {SynErr(116); Get();}
- if (la.kind == 27) {
+ while (!(StartOf(8))) {SynErr(124); Get();}
+ if (la.kind == 29) {
Get();
while (IsAttribute()) {
Attribute(ref modAttrs);
}
- if (StartOf(8)) {
+ if (StartOf(9)) {
FrameExpression(out fe);
mod.Add(fe);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
FrameExpression(out fe);
mod.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(117); Get();}
- Expect(18);
- } else if (la.kind == 28 || la.kind == 29 || la.kind == 30) {
- if (la.kind == 28) {
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(125); Get();}
+ Expect(19);
+ } else if (la.kind == 30 || la.kind == 31 || la.kind == 32) {
+ if (la.kind == 30) {
Get();
isFree = true;
}
- if (la.kind == 29) {
+ if (la.kind == 31) {
Get();
Expression(out e);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(118); Get();}
- Expect(18);
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(126); Get();}
+ Expect(19);
req.Add(new MaybeFreeExpression(e, isFree));
- } else if (la.kind == 30) {
+ } else if (la.kind == 32) {
Get();
while (IsAttribute()) {
Attribute(ref ensAttrs);
}
Expression(out e);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(119); Get();}
- Expect(18);
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(127); Get();}
+ Expect(19);
ens.Add(new MaybeFreeExpression(e, isFree, ensAttrs));
- } else SynErr(120);
- } else if (la.kind == 31) {
+ } else SynErr(128);
+ } else if (la.kind == 33) {
Get();
while (IsAttribute()) {
Attribute(ref decAttrs);
}
DecreasesList(decreases, false);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(121); Get();}
- Expect(18);
- } else SynErr(122);
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(129); Get();}
+ Expect(19);
+ } else SynErr(130);
}
- void BlockStmt(out Statement/*!*/ block, out IToken bodyStart, out IToken bodyEnd) {
+ void BlockStmt(out BlockStmt/*!*/ block, out IToken bodyStart, out IToken bodyEnd) {
Contract.Ensures(Contract.ValueAtReturn(out block) != null);
List<Statement/*!*/> body = new List<Statement/*!*/>();
Expect(6);
bodyStart = t;
- while (StartOf(9)) {
+ while (StartOf(10)) {
Stmt(body);
}
Expect(7);
@@ -838,7 +880,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void FrameExpression(out FrameExpression/*!*/ fe) {
Contract.Ensures(Contract.ValueAtReturn(out fe) != null); Expression/*!*/ e; IToken/*!*/ id; string fieldName = null;
Expression(out e);
- if (la.kind == 45) {
+ if (la.kind == 47) {
Get();
Ident(out id);
fieldName = id.val;
@@ -856,16 +898,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (!allowWildcard && e is WildcardExpr) {
SemErr(e.tok, "'decreases *' is only allowed on loops");
} else {
- decreases.Add(e);
+ decreases.Add(e);
}
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
PossiblyWildExpression(out e);
if (!allowWildcard && e is WildcardExpr) {
SemErr(e.tok, "'decreases *' is only allowed on loops");
} else {
- decreases.Add(e);
+ decreases.Add(e);
}
}
@@ -873,15 +915,15 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void GenericInstantiation(List<Type/*!*/>/*!*/ gt) {
Contract.Requires(cce.NonNullElements(gt)); Type/*!*/ ty;
- Expect(22);
+ Expect(23);
Type(out ty);
gt.Add(ty);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
Type(out ty);
gt.Add(ty);
}
- Expect(23);
+ Expect(24);
}
void ReferenceType(out IToken/*!*/ tok, out Type/*!*/ ty) {
@@ -889,7 +931,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo tok = Token.NoToken; ty = new BoolType(); /*keep compiler happy*/
List<Type/*!*/>/*!*/ gt;
- if (la.kind == 40) {
+ if (la.kind == 42) {
Get();
tok = t; ty = new ObjectType();
} else if (la.kind == 3) {
@@ -901,55 +943,55 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
int dims = 1;
if (tok.val.Length != 5) {
- dims = int.Parse(tok.val.Substring(5));
+ dims = int.Parse(tok.val.Substring(5));
}
ty = theBuiltIns.ArrayType(tok, dims, gt[0], true);
} else if (la.kind == 1) {
Ident(out tok);
gt = new List<Type/*!*/>();
- if (la.kind == 22) {
+ if (la.kind == 23) {
GenericInstantiation(gt);
}
ty = new UserDefinedType(tok, tok.val, gt);
- } else SynErr(123);
+ } else SynErr(131);
}
void FunctionSpec(List<Expression/*!*/>/*!*/ reqs, List<FrameExpression/*!*/>/*!*/ reads, List<Expression/*!*/>/*!*/ ens, List<Expression/*!*/>/*!*/ decreases) {
Contract.Requires(cce.NonNullElements(reqs)); Contract.Requires(cce.NonNullElements(reads)); Contract.Requires(cce.NonNullElements(decreases));
Expression/*!*/ e; FrameExpression/*!*/ fe;
- if (la.kind == 29) {
- while (!(la.kind == 0 || la.kind == 29)) {SynErr(124); Get();}
+ if (la.kind == 31) {
+ while (!(la.kind == 0 || la.kind == 31)) {SynErr(132); Get();}
Get();
Expression(out e);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(125); Get();}
- Expect(18);
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(133); Get();}
+ Expect(19);
reqs.Add(e);
- } else if (la.kind == 43) {
+ } else if (la.kind == 45) {
Get();
- if (StartOf(10)) {
+ if (StartOf(11)) {
PossiblyWildFrameExpression(out fe);
reads.Add(fe);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
PossiblyWildFrameExpression(out fe);
reads.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(126); Get();}
- Expect(18);
- } else if (la.kind == 30) {
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(134); Get();}
+ Expect(19);
+ } else if (la.kind == 32) {
Get();
Expression(out e);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(127); Get();}
- Expect(18);
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(135); Get();}
+ Expect(19);
ens.Add(e);
- } else if (la.kind == 31) {
+ } else if (la.kind == 33) {
Get();
DecreasesList(decreases, false);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(128); Get();}
- Expect(18);
- } else SynErr(129);
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(136); Get();}
+ Expect(19);
+ } else SynErr(137);
}
void FunctionBody(out Expression/*!*/ e, out IToken bodyStart, out IToken bodyEnd) {
@@ -963,23 +1005,23 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void PossiblyWildFrameExpression(out FrameExpression/*!*/ fe) {
Contract.Ensures(Contract.ValueAtReturn(out fe) != null); fe = dummyFrameExpr;
- if (la.kind == 44) {
+ if (la.kind == 46) {
Get();
fe = new FrameExpression(new WildcardExpr(t), null);
- } else if (StartOf(8)) {
+ } else if (StartOf(9)) {
FrameExpression(out fe);
- } else SynErr(130);
+ } else SynErr(138);
}
void PossiblyWildExpression(out Expression/*!*/ e) {
Contract.Ensures(Contract.ValueAtReturn(out e)!=null);
e = dummyExpr;
- if (la.kind == 44) {
+ if (la.kind == 46) {
Get();
e = new WildcardExpr(t);
- } else if (StartOf(8)) {
+ } else if (StartOf(9)) {
Expression(out e);
- } else SynErr(131);
+ } else SynErr(139);
}
void Stmt(List<Statement/*!*/>/*!*/ ss) {
@@ -992,52 +1034,54 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void OneStmt(out Statement/*!*/ s) {
Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; IToken/*!*/ id; string label = null;
s = dummyStmt; /* to please the compiler */
+ BlockStmt bs;
IToken bodyStart, bodyEnd;
int breakCount;
- while (!(StartOf(11))) {SynErr(132); Get();}
+ while (!(StartOf(12))) {SynErr(140); Get();}
switch (la.kind) {
case 6: {
- BlockStmt(out s, out bodyStart, out bodyEnd);
+ BlockStmt(out bs, out bodyStart, out bodyEnd);
+ s = bs;
break;
}
- case 62: {
+ case 65: {
AssertStmt(out s);
break;
}
- case 63: {
+ case 66: {
AssumeStmt(out s);
break;
}
- case 64: {
+ case 67: {
PrintStmt(out s);
break;
}
- case 1: case 2: case 17: case 32: case 89: case 90: case 91: case 92: case 93: case 94: case 95: {
+ case 1: case 2: case 18: case 34: case 92: case 93: case 94: case 95: case 96: case 97: case 98: {
UpdateStmt(out s);
break;
}
- case 12: case 19: {
+ case 8: case 20: {
VarDeclStatement(out s);
break;
}
- case 55: {
+ case 58: {
IfStmt(out s);
break;
}
- case 59: {
+ case 62: {
WhileStmt(out s);
break;
}
- case 61: {
+ case 64: {
MatchStmt(out s);
break;
}
- case 65: {
+ case 68: {
ParallelStmt(out s);
break;
}
- case 46: {
+ case 48: {
Get();
x = t;
Ident(out id);
@@ -1046,49 +1090,66 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo s.Labels = new LabelNode(x, id.val, s.Labels);
break;
}
- case 47: {
+ case 49: {
Get();
x = t; breakCount = 1; label = null;
if (la.kind == 1) {
Ident(out id);
label = id.val;
- } else if (la.kind == 18 || la.kind == 47) {
- while (la.kind == 47) {
+ } else if (la.kind == 19 || la.kind == 49) {
+ while (la.kind == 49) {
Get();
breakCount++;
}
- } else SynErr(133);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(134); Get();}
- Expect(18);
+ } else SynErr(141);
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(142); Get();}
+ Expect(19);
s = label != null ? new BreakStmt(x, label) : new BreakStmt(x, breakCount);
break;
}
- case 48: {
+ case 50: {
ReturnStmt(out s);
break;
}
- default: SynErr(135); break;
+ case 28: {
+ Get();
+ s = new SkeletonStatement(t);
+ Expect(19);
+ break;
+ }
+ default: SynErr(143); break;
}
}
void AssertStmt(out Statement/*!*/ s) {
- Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; Expression/*!*/ e; Attributes attrs = null;
- Expect(62);
+ Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x;
+ Expression/*!*/ e = null; Attributes attrs = null;
+
+ Expect(65);
x = t; s = null;
while (IsAttribute()) {
Attribute(ref attrs);
}
- Expression(out e);
- s = new AssertStmt(x, e, attrs);
- Expect(18);
+ if (StartOf(9)) {
+ Expression(out e);
+ } else if (la.kind == 28) {
+ Get();
+ } else SynErr(144);
+ Expect(19);
+ if (e == null) {
+ s = new SkeletonStatement(new AssertStmt(x, new LiteralExpr(x, true), attrs), true, false);
+ } else {
+ s = new AssertStmt(x, e, attrs);
+ }
+
}
void AssumeStmt(out Statement/*!*/ s) {
Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; Expression/*!*/ e;
- Expect(63);
+ Expect(66);
x = t;
Expression(out e);
- Expect(18);
+ Expect(19);
s = new AssumeStmt(x, e);
}
@@ -1096,16 +1157,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Contract.Ensures(Contract.ValueAtReturn(out s) != null); IToken/*!*/ x; Attributes.Argument/*!*/ arg;
List<Attributes.Argument/*!*/> args = new List<Attributes.Argument/*!*/>();
- Expect(64);
+ Expect(67);
x = t;
AttributeArg(out arg);
args.Add(arg);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
AttributeArg(out arg);
args.Add(arg);
}
- Expect(18);
+ Expect(19);
s = new PrintStmt(x, args);
}
@@ -1116,37 +1177,49 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expression lhs0;
IToken x;
Attributes attrs = null;
+ Expression suchThat = null;
Lhs(out e);
x = e.tok;
- if (la.kind == 6 || la.kind == 18) {
- while (IsAttribute()) {
+ if (la.kind == 6 || la.kind == 19) {
+ while (la.kind == 6) {
Attribute(ref attrs);
}
- Expect(18);
+ Expect(19);
rhss.Add(new ExprRhs(e, attrs));
- } else if (la.kind == 20 || la.kind == 49) {
+ } else if (la.kind == 21 || la.kind == 51 || la.kind == 52) {
lhss.Add(e); lhs0 = e;
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
Lhs(out e);
lhss.Add(e);
}
- Expect(49);
- x = t;
- Rhs(out r, lhs0);
- rhss.Add(r);
- while (la.kind == 20) {
+ if (la.kind == 51) {
Get();
+ x = t;
Rhs(out r, lhs0);
rhss.Add(r);
- }
- Expect(18);
+ while (la.kind == 21) {
+ Get();
+ Rhs(out r, lhs0);
+ rhss.Add(r);
+ }
+ } else if (la.kind == 52) {
+ Get();
+ x = t;
+ Expression(out suchThat);
+ } else SynErr(145);
+ Expect(19);
} else if (la.kind == 5) {
Get();
SemErr(t, "invalid statement (did you forget the 'label' keyword?)");
- } else SynErr(136);
- s = new UpdateStmt(x, lhss, rhss);
+ } else SynErr(146);
+ if (suchThat != null) {
+ s = new AssignSuchThatStmt(x, lhss, suchThat);
+ } else {
+ s = new UpdateStmt(x, lhss, rhss);
+ }
+
}
void VarDeclStatement(out Statement/*!*/ s) {
@@ -1155,44 +1228,57 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo AssignmentRhs r; IdentifierExpr lhs0;
List<VarDecl> lhss = new List<VarDecl>();
List<AssignmentRhs> rhss = new List<AssignmentRhs>();
+ Expression suchThat = null;
- if (la.kind == 12) {
+ if (la.kind == 8) {
Get();
isGhost = true; x = t;
}
- Expect(19);
+ Expect(20);
if (!isGhost) { x = t; }
LocalIdentTypeOptional(out d, isGhost);
lhss.Add(d);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
LocalIdentTypeOptional(out d, isGhost);
lhss.Add(d);
}
- if (la.kind == 49) {
- Get();
- assignTok = t;
- lhs0 = new IdentifierExpr(lhss[0].Tok, lhss[0].Name);
- lhs0.Var = lhss[0]; lhs0.Type = lhss[0].OptionalType; // resolve here
-
- Rhs(out r, lhs0);
- rhss.Add(r);
- while (la.kind == 20) {
+ if (la.kind == 51 || la.kind == 52) {
+ if (la.kind == 51) {
Get();
+ assignTok = t;
+ lhs0 = new IdentifierExpr(lhss[0].Tok, lhss[0].Name);
+ lhs0.Var = lhss[0]; lhs0.Type = lhss[0].OptionalType; // resolve here
+
Rhs(out r, lhs0);
rhss.Add(r);
+ while (la.kind == 21) {
+ Get();
+ Rhs(out r, lhs0);
+ rhss.Add(r);
+ }
+ } else {
+ Get();
+ assignTok = t;
+ Expression(out suchThat);
}
}
- Expect(18);
- UpdateStmt update;
- if (rhss.Count == 0) {
- update = null;
+ Expect(19);
+ ConcreteUpdateStatement update;
+ if (suchThat != null) {
+ var ies = new List<Expression>();
+ foreach (var lhs in lhss) {
+ ies.Add(new IdentifierExpr(lhs.Tok, lhs.Name));
+ }
+ update = new AssignSuchThatStmt(assignTok, ies, suchThat);
+ } else if (rhss.Count == 0) {
+ update = null;
} else {
- var ies = new List<Expression>();
- foreach (var lhs in lhss) {
- ies.Add(new AutoGhostIdentifierExpr(lhs.Tok, lhs.Name));
- }
- update = new UpdateStmt(assignTok, ies, rhss);
+ var ies = new List<Expression>();
+ foreach (var lhs in lhss) {
+ ies.Add(new AutoGhostIdentifierExpr(lhs.Tok, lhs.Name));
+ }
+ update = new UpdateStmt(assignTok, ies, rhss);
}
s = new VarDeclStmt(x, lhss, update);
@@ -1200,73 +1286,109 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void IfStmt(out Statement/*!*/ ifStmt) {
Contract.Ensures(Contract.ValueAtReturn(out ifStmt) != null); IToken/*!*/ x;
- Expression guard;
- Statement/*!*/ thn;
+ Expression guard = null; bool guardOmitted = false;
+ BlockStmt/*!*/ thn;
+ BlockStmt/*!*/ bs;
Statement/*!*/ s;
Statement els = null;
IToken bodyStart, bodyEnd;
List<GuardedAlternative> alternatives;
ifStmt = dummyStmt; // to please the compiler
- Expect(55);
+ Expect(58);
x = t;
- if (la.kind == 32) {
- Guard(out guard);
+ if (la.kind == 28 || la.kind == 34) {
+ if (la.kind == 34) {
+ Guard(out guard);
+ } else {
+ Get();
+ guardOmitted = true;
+ }
BlockStmt(out thn, out bodyStart, out bodyEnd);
- if (la.kind == 56) {
+ if (la.kind == 59) {
Get();
- if (la.kind == 55) {
+ if (la.kind == 58) {
IfStmt(out s);
els = s;
} else if (la.kind == 6) {
- BlockStmt(out s, out bodyStart, out bodyEnd);
- els = s;
- } else SynErr(137);
+ BlockStmt(out bs, out bodyStart, out bodyEnd);
+ els = bs;
+ } else SynErr(147);
+ }
+ if (guardOmitted) {
+ ifStmt = new SkeletonStatement(new IfStmt(x, guard, thn, els), true, false);
+ } else {
+ ifStmt = new IfStmt(x, guard, thn, els);
}
- ifStmt = new IfStmt(x, guard, thn, els);
+
} else if (la.kind == 6) {
AlternativeBlock(out alternatives);
ifStmt = new AlternativeStmt(x, alternatives);
- } else SynErr(138);
+ } else SynErr(148);
}
void WhileStmt(out Statement/*!*/ stmt) {
Contract.Ensures(Contract.ValueAtReturn(out stmt) != null); IToken/*!*/ x;
- Expression guard;
+ Expression guard = null; bool guardOmitted = false;
List<MaybeFreeExpression/*!*/> invariants = new List<MaybeFreeExpression/*!*/>();
List<Expression/*!*/> decreases = new List<Expression/*!*/>();
Attributes decAttrs = null;
Attributes modAttrs = null;
List<FrameExpression/*!*/> mod = null;
- Statement/*!*/ body;
- IToken bodyStart, bodyEnd;
+ BlockStmt/*!*/ body = null; bool bodyOmitted = false;
+ IToken bodyStart = null, bodyEnd = null;
List<GuardedAlternative> alternatives;
stmt = dummyStmt; // to please the compiler
- Expect(59);
+ Expect(62);
x = t;
- if (la.kind == 32) {
- Guard(out guard);
- Contract.Assume(guard == null || cce.Owner.None(guard));
+ if (la.kind == 28 || la.kind == 34) {
+ if (la.kind == 34) {
+ Guard(out guard);
+ Contract.Assume(guard == null || cce.Owner.None(guard));
+ } else {
+ Get();
+ guardOmitted = true;
+ }
LoopSpec(out invariants, out decreases, out mod, ref decAttrs, ref modAttrs);
- BlockStmt(out body, out bodyStart, out bodyEnd);
- stmt = new WhileStmt(x, guard, invariants, new Specification<Expression>(decreases, decAttrs), new Specification<FrameExpression>(mod, modAttrs), body);
- } else if (StartOf(12)) {
+ if (la.kind == 6) {
+ BlockStmt(out body, out bodyStart, out bodyEnd);
+ } else if (la.kind == 28) {
+ Get();
+ bodyOmitted = true;
+ } else SynErr(149);
+ if (guardOmitted || bodyOmitted) {
+ if (decreases.Count != 0) {
+ SemErr(decreases[0].tok, "'decreases' clauses are not allowed on refining loops");
+ }
+ if (mod != null) {
+ SemErr(mod[0].E.tok, "'modifies' clauses are not allowed on refining loops");
+ }
+ if (body == null) {
+ body = new BlockStmt(x, new List<Statement>());
+ }
+ stmt = new WhileStmt(x, guard, invariants, new Specification<Expression>(null, null), new Specification<FrameExpression>(null, null), body);
+ stmt = new SkeletonStatement(stmt, guardOmitted, bodyOmitted);
+ } else {
+ stmt = new WhileStmt(x, guard, invariants, new Specification<Expression>(decreases, decAttrs), new Specification<FrameExpression>(mod, modAttrs), body);
+ }
+
+ } else if (StartOf(13)) {
LoopSpec(out invariants, out decreases, out mod, ref decAttrs, ref modAttrs);
AlternativeBlock(out alternatives);
stmt = new AlternativeLoopStmt(x, invariants, new Specification<Expression>(decreases, decAttrs), new Specification<FrameExpression>(mod, modAttrs), alternatives);
- } else SynErr(139);
+ } else SynErr(150);
}
void MatchStmt(out Statement/*!*/ s) {
Contract.Ensures(Contract.ValueAtReturn(out s) != null);
Token x; Expression/*!*/ e; MatchCaseStmt/*!*/ c;
List<MatchCaseStmt/*!*/> cases = new List<MatchCaseStmt/*!*/>();
- Expect(61);
+ Expect(64);
x = t;
Expression(out e);
Expect(6);
- while (la.kind == 57) {
+ while (la.kind == 60) {
CaseStatement(out c);
cases.Add(c);
}
@@ -1283,12 +1405,12 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo var ens = new List<MaybeFreeExpression/*!*/>();
bool isFree;
Expression/*!*/ e;
- Statement/*!*/ block;
+ BlockStmt/*!*/ block;
IToken bodyStart, bodyEnd;
- Expect(65);
+ Expect(68);
x = t;
- Expect(32);
+ Expect(34);
if (la.kind == 1) {
List<BoundVar/*!*/> bvarsX; Attributes attrsX; Expression rangeX;
QuantifierDomain(out bvarsX, out attrsX, out rangeX);
@@ -1298,16 +1420,16 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (bvars == null) { bvars = new List<BoundVar>(); }
if (range == null) { range = new LiteralExpr(x, true); }
- Expect(33);
- while (la.kind == 28 || la.kind == 30) {
+ Expect(35);
+ while (la.kind == 30 || la.kind == 32) {
isFree = false;
- if (la.kind == 28) {
+ if (la.kind == 30) {
Get();
isFree = true;
}
- Expect(30);
+ Expect(32);
Expression(out e);
- Expect(18);
+ Expect(19);
ens.Add(new MaybeFreeExpression(e, isFree));
}
BlockStmt(out block, out bodyStart, out bodyEnd);
@@ -1319,18 +1441,18 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo List<AssignmentRhs> rhss = null;
AssignmentRhs r;
- Expect(48);
+ Expect(50);
returnTok = t;
- if (StartOf(13)) {
+ if (StartOf(14)) {
Rhs(out r, null);
rhss = new List<AssignmentRhs>(); rhss.Add(r);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
Rhs(out r, null);
rhss.Add(r);
}
}
- Expect(18);
+ Expect(19);
s = new ReturnStmt(returnTok, rhss);
}
@@ -1343,27 +1465,27 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo r = null; // to please compiler
Attributes attrs = null;
- if (la.kind == 50) {
+ if (la.kind == 53) {
Get();
newToken = t;
TypeAndToken(out x, out ty);
- if (la.kind == 51 || la.kind == 53) {
- if (la.kind == 51) {
+ if (la.kind == 54 || la.kind == 56) {
+ if (la.kind == 54) {
Get();
ee = new List<Expression>();
Expressions(ee);
- Expect(52);
+ Expect(55);
UserDefinedType tmp = theBuiltIns.ArrayType(x, ee.Count, new IntType(), true);
} else {
Get();
Ident(out x);
- Expect(32);
+ Expect(34);
args = new List<Expression/*!*/>();
- if (StartOf(8)) {
+ if (StartOf(9)) {
Expressions(args);
}
- Expect(33);
+ Expect(35);
initCall = new CallStmt(x, new List<Expression>(),
receiverForInitCall, x.val, args);
}
@@ -1371,22 +1493,22 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (ee != null) {
r = new TypeRhs(newToken, ty, ee);
} else {
- r = new TypeRhs(newToken, ty, initCall);
+ r = new TypeRhs(newToken, ty, initCall);
}
- } else if (la.kind == 54) {
+ } else if (la.kind == 57) {
Get();
x = t;
Expression(out e);
r = new ExprRhs(new UnaryExpr(x, UnaryExpr.Opcode.SetChoose, e));
- } else if (la.kind == 44) {
+ } else if (la.kind == 46) {
Get();
r = new HavocRhs(t);
- } else if (StartOf(8)) {
+ } else if (StartOf(9)) {
Expression(out e);
r = new ExprRhs(e);
- } else SynErr(140);
- while (IsAttribute()) {
+ } else SynErr(151);
+ while (la.kind == 6) {
Attribute(ref attrs);
}
r.Attributes = attrs;
@@ -1397,23 +1519,23 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (la.kind == 1) {
DottedIdentifiersAndFunction(out e);
- while (la.kind == 51 || la.kind == 53) {
+ while (la.kind == 54 || la.kind == 56) {
Suffix(ref e);
}
- } else if (StartOf(14)) {
+ } else if (StartOf(15)) {
ConstAtomExpression(out e);
Suffix(ref e);
- while (la.kind == 51 || la.kind == 53) {
+ while (la.kind == 54 || la.kind == 56) {
Suffix(ref e);
}
- } else SynErr(141);
+ } else SynErr(152);
}
void Expressions(List<Expression/*!*/>/*!*/ args) {
Contract.Requires(cce.NonNullElements(args)); Expression/*!*/ e;
Expression(out e);
args.Add(e);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
Expression(out e);
args.Add(e);
@@ -1422,15 +1544,15 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void Guard(out Expression e) {
Expression/*!*/ ee; e = null;
- Expect(32);
- if (la.kind == 44) {
+ Expect(34);
+ if (la.kind == 46) {
Get();
e = null;
- } else if (StartOf(8)) {
+ } else if (StartOf(9)) {
Expression(out ee);
e = ee;
- } else SynErr(142);
- Expect(33);
+ } else SynErr(153);
+ Expect(35);
}
void AlternativeBlock(out List<GuardedAlternative> alternatives) {
@@ -1440,13 +1562,13 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo List<Statement> body;
Expect(6);
- while (la.kind == 57) {
+ while (la.kind == 60) {
Get();
x = t;
Expression(out e);
- Expect(58);
+ Expect(61);
body = new List<Statement>();
- while (StartOf(9)) {
+ while (StartOf(10)) {
Stmt(body);
}
alternatives.Add(new GuardedAlternative(x, e, body));
@@ -1461,51 +1583,51 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo decreases = new List<Expression/*!*/>();
mod = null;
- while (StartOf(15)) {
- if (la.kind == 28 || la.kind == 60) {
+ while (StartOf(16)) {
+ if (la.kind == 30 || la.kind == 63) {
Invariant(out invariant);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(143); Get();}
- Expect(18);
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(154); Get();}
+ Expect(19);
invariants.Add(invariant);
- } else if (la.kind == 31) {
- while (!(la.kind == 0 || la.kind == 31)) {SynErr(144); Get();}
+ } else if (la.kind == 33) {
+ while (!(la.kind == 0 || la.kind == 33)) {SynErr(155); Get();}
Get();
while (IsAttribute()) {
Attribute(ref decAttrs);
}
DecreasesList(decreases, true);
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(145); Get();}
- Expect(18);
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(156); Get();}
+ Expect(19);
} else {
- while (!(la.kind == 0 || la.kind == 27)) {SynErr(146); Get();}
+ while (!(la.kind == 0 || la.kind == 29)) {SynErr(157); Get();}
Get();
while (IsAttribute()) {
Attribute(ref modAttrs);
}
mod = mod ?? new List<FrameExpression>();
- if (StartOf(8)) {
+ if (StartOf(9)) {
FrameExpression(out fe);
mod.Add(fe);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
FrameExpression(out fe);
mod.Add(fe);
}
}
- while (!(la.kind == 0 || la.kind == 18)) {SynErr(147); Get();}
- Expect(18);
+ while (!(la.kind == 0 || la.kind == 19)) {SynErr(158); Get();}
+ Expect(19);
}
}
}
void Invariant(out MaybeFreeExpression/*!*/ invariant) {
bool isFree = false; Expression/*!*/ e; List<string> ids = new List<string>(); invariant = null; Attributes attrs = null;
- while (!(la.kind == 0 || la.kind == 28 || la.kind == 60)) {SynErr(148); Get();}
- if (la.kind == 28) {
+ while (!(la.kind == 0 || la.kind == 30 || la.kind == 63)) {SynErr(159); Get();}
+ if (la.kind == 30) {
Get();
isFree = true;
}
- Expect(60);
+ Expect(63);
while (IsAttribute()) {
Attribute(ref attrs);
}
@@ -1520,22 +1642,22 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo BoundVar/*!*/ bv;
List<Statement/*!*/> body = new List<Statement/*!*/>();
- Expect(57);
+ Expect(60);
x = t;
Ident(out id);
- if (la.kind == 32) {
+ if (la.kind == 34) {
Get();
IdentTypeOptional(out bv);
arguments.Add(bv);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
IdentTypeOptional(out bv);
arguments.Add(bv);
}
- Expect(33);
+ Expect(35);
}
- Expect(58);
- while (StartOf(9)) {
+ Expect(61);
+ while (StartOf(10)) {
Stmt(body);
}
c = new MatchCaseStmt(x, id.val, arguments, body);
@@ -1546,10 +1668,10 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (la.kind == 4) {
Get();
arg = new Attributes.Argument(t, t.val.Substring(1, t.val.Length-2));
- } else if (StartOf(8)) {
+ } else if (StartOf(9)) {
Expression(out e);
arg = new Attributes.Argument(t, e);
- } else SynErr(149);
+ } else SynErr(160);
}
void QuantifierDomain(out List<BoundVar/*!*/> bvars, out Attributes attrs, out Expression range) {
@@ -1560,7 +1682,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo IdentTypeOptional(out bv);
bvars.Add(bv);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
IdentTypeOptional(out bv);
bvars.Add(bv);
@@ -1568,7 +1690,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo while (la.kind == 6) {
Attribute(ref attrs);
}
- if (la.kind == 17) {
+ if (la.kind == 18) {
Get();
Expression(out range);
}
@@ -1577,7 +1699,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void EquivExpression(out Expression/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1;
ImpliesExpression(out e0);
- while (la.kind == 66 || la.kind == 67) {
+ while (la.kind == 69 || la.kind == 70) {
EquivOp();
x = t;
ImpliesExpression(out e1);
@@ -1588,7 +1710,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void ImpliesExpression(out Expression/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1;
LogicalExpression(out e0);
- if (la.kind == 68 || la.kind == 69) {
+ if (la.kind == 71 || la.kind == 72) {
ImpliesOp();
x = t;
ImpliesExpression(out e1);
@@ -1597,23 +1719,23 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
void EquivOp() {
- if (la.kind == 66) {
+ if (la.kind == 69) {
Get();
- } else if (la.kind == 67) {
+ } else if (la.kind == 70) {
Get();
- } else SynErr(150);
+ } else SynErr(161);
}
void LogicalExpression(out Expression/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1;
RelationalExpression(out e0);
- if (StartOf(16)) {
- if (la.kind == 70 || la.kind == 71) {
+ if (StartOf(17)) {
+ if (la.kind == 73 || la.kind == 74) {
AndOp();
x = t;
RelationalExpression(out e1);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.And, e0, e1);
- while (la.kind == 70 || la.kind == 71) {
+ while (la.kind == 73 || la.kind == 74) {
AndOp();
x = t;
RelationalExpression(out e1);
@@ -1624,7 +1746,7 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo x = t;
RelationalExpression(out e1);
e0 = new BinaryExpr(x, BinaryExpr.Opcode.Or, e0, e1);
- while (la.kind == 72 || la.kind == 73) {
+ while (la.kind == 75 || la.kind == 76) {
OrOp();
x = t;
RelationalExpression(out e1);
@@ -1635,11 +1757,11 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
void ImpliesOp() {
- if (la.kind == 68) {
+ if (la.kind == 71) {
Get();
- } else if (la.kind == 69) {
+ } else if (la.kind == 72) {
Get();
- } else SynErr(151);
+ } else SynErr(162);
}
void RelationalExpression(out Expression/*!*/ e) {
@@ -1648,23 +1770,23 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo List<Expression> chain = null;
List<BinaryExpr.Opcode> ops = null;
int kind = 0; // 0 ("uncommitted") indicates chain of ==, possibly with one !=
- // 1 ("ascending") indicates chain of ==, <, <=, possibly with one !=
- // 2 ("descending") indicates chain of ==, >, >=, possibly with one !=
- // 3 ("illegal") indicates illegal chain
- // 4 ("disjoint") indicates chain of disjoint set operators
+ // 1 ("ascending") indicates chain of ==, <, <=, possibly with one !=
+ // 2 ("descending") indicates chain of ==, >, >=, possibly with one !=
+ // 3 ("illegal") indicates illegal chain
+ // 4 ("disjoint") indicates chain of disjoint set operators
bool hasSeenNeq = false;
Term(out e0);
e = e0;
- if (StartOf(17)) {
+ if (StartOf(18)) {
RelOp(out x, out op);
firstOpTok = x;
Term(out e1);
e = new BinaryExpr(x, op, e0, e1);
if (op == BinaryExpr.Opcode.Disjoint)
- acc = new BinaryExpr(x, BinaryExpr.Opcode.Add, e0, e1); // accumulate first two operands.
+ acc = new BinaryExpr(x, BinaryExpr.Opcode.Add, e0, e1); // accumulate first two operands.
- while (StartOf(17)) {
+ while (StartOf(18)) {
if (chain == null) {
chain = new List<Expression>();
ops = new List<BinaryExpr.Opcode>();
@@ -1718,11 +1840,11 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Term(out e1);
ops.Add(op); chain.Add(e1);
if (op == BinaryExpr.Opcode.Disjoint) {
- e = new BinaryExpr(x, BinaryExpr.Opcode.And, e, new BinaryExpr(x, op, acc, e1));
- acc = new BinaryExpr(x, BinaryExpr.Opcode.Add, acc, e1); //e0 has already been added.
+ e = new BinaryExpr(x, BinaryExpr.Opcode.And, e, new BinaryExpr(x, op, acc, e1));
+ acc = new BinaryExpr(x, BinaryExpr.Opcode.Add, acc, e1); //e0 has already been added.
}
else
- e = new BinaryExpr(x, BinaryExpr.Opcode.And, e, new BinaryExpr(x, op, e0, e1));
+ e = new BinaryExpr(x, BinaryExpr.Opcode.And, e, new BinaryExpr(x, op, e0, e1));
}
}
@@ -1733,25 +1855,25 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo }
void AndOp() {
- if (la.kind == 70) {
+ if (la.kind == 73) {
Get();
- } else if (la.kind == 71) {
+ } else if (la.kind == 74) {
Get();
- } else SynErr(152);
+ } else SynErr(163);
}
void OrOp() {
- if (la.kind == 72) {
+ if (la.kind == 75) {
Get();
- } else if (la.kind == 73) {
+ } else if (la.kind == 76) {
Get();
- } else SynErr(153);
+ } else SynErr(164);
}
void Term(out Expression/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; BinaryExpr.Opcode op;
Factor(out e0);
- while (la.kind == 84 || la.kind == 85) {
+ while (la.kind == 87 || la.kind == 88) {
AddOp(out x, out op);
Factor(out e1);
e0 = new BinaryExpr(x, op, e0, e1);
@@ -1764,87 +1886,87 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo IToken y;
switch (la.kind) {
- case 74: {
+ case 77: {
Get();
x = t; op = BinaryExpr.Opcode.Eq;
break;
}
- case 22: {
+ case 23: {
Get();
x = t; op = BinaryExpr.Opcode.Lt;
break;
}
- case 23: {
+ case 24: {
Get();
x = t; op = BinaryExpr.Opcode.Gt;
break;
}
- case 75: {
+ case 78: {
Get();
x = t; op = BinaryExpr.Opcode.Le;
break;
}
- case 76: {
+ case 79: {
Get();
x = t; op = BinaryExpr.Opcode.Ge;
break;
}
- case 77: {
+ case 80: {
Get();
x = t; op = BinaryExpr.Opcode.Neq;
break;
}
- case 78: {
+ case 81: {
Get();
x = t; op = BinaryExpr.Opcode.Disjoint;
break;
}
- case 79: {
+ case 82: {
Get();
x = t; op = BinaryExpr.Opcode.In;
break;
}
- case 80: {
+ case 83: {
Get();
x = t; y = Token.NoToken;
- if (la.kind == 79) {
+ if (la.kind == 82) {
Get();
y = t;
}
if (y == Token.NoToken) {
SemErr(x, "invalid RelOp");
} else if (y.pos != x.pos + 1) {
- SemErr(x, "invalid RelOp (perhaps you intended \"!in\" with no intervening whitespace?)");
+ SemErr(x, "invalid RelOp (perhaps you intended \"!in\" with no intervening whitespace?)");
} else {
- x.val = "!in";
- op = BinaryExpr.Opcode.NotIn;
+ x.val = "!in";
+ op = BinaryExpr.Opcode.NotIn;
}
break;
}
- case 81: {
+ case 84: {
Get();
x = t; op = BinaryExpr.Opcode.Neq;
break;
}
- case 82: {
+ case 85: {
Get();
x = t; op = BinaryExpr.Opcode.Le;
break;
}
- case 83: {
+ case 86: {
Get();
x = t; op = BinaryExpr.Opcode.Ge;
break;
}
- default: SynErr(154); break;
+ default: SynErr(165); break;
}
}
void Factor(out Expression/*!*/ e0) {
Contract.Ensures(Contract.ValueAtReturn(out e0) != null); IToken/*!*/ x; Expression/*!*/ e1; BinaryExpr.Opcode op;
UnaryExpression(out e0);
- while (la.kind == 44 || la.kind == 86 || la.kind == 87) {
+ while (la.kind == 46 || la.kind == 89 || la.kind == 90) {
MulOp(out x, out op);
UnaryExpression(out e1);
e0 = new BinaryExpr(x, op, e0, e1);
@@ -1853,82 +1975,82 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo void AddOp(out IToken/*!*/ x, out BinaryExpr.Opcode op) {
Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op=BinaryExpr.Opcode.Add/*(dummy)*/;
- if (la.kind == 84) {
+ if (la.kind == 87) {
Get();
x = t; op = BinaryExpr.Opcode.Add;
- } else if (la.kind == 85) {
+ } else if (la.kind == 88) {
Get();
x = t; op = BinaryExpr.Opcode.Sub;
- } else SynErr(155);
+ } else SynErr(166);
}
void UnaryExpression(out Expression/*!*/ e) {
Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; e = dummyExpr;
switch (la.kind) {
- case 85: {
+ case 88: {
Get();
x = t;
UnaryExpression(out e);
e = new BinaryExpr(x, BinaryExpr.Opcode.Sub, new LiteralExpr(x, 0), e);
break;
}
- case 80: case 88: {
+ case 83: case 91: {
NegOp();
x = t;
UnaryExpression(out e);
e = new UnaryExpr(x, UnaryExpr.Opcode.Not, e);
break;
}
- case 19: case 37: case 55: case 61: case 62: case 63: case 98: case 99: case 100: case 101: {
+ case 20: case 39: case 58: case 64: case 65: case 66: case 101: case 102: case 103: case 104: {
EndlessExpression(out e);
break;
}
case 1: {
DottedIdentifiersAndFunction(out e);
- while (la.kind == 51 || la.kind == 53) {
+ while (la.kind == 54 || la.kind == 56) {
Suffix(ref e);
}
break;
}
- case 6: case 51: {
+ case 6: case 54: {
DisplayExpr(out e);
break;
}
- case 38: {
+ case 40: {
MultiSetExpr(out e);
break;
}
- case 2: case 17: case 32: case 89: case 90: case 91: case 92: case 93: case 94: case 95: {
+ case 2: case 18: case 34: case 92: case 93: case 94: case 95: case 96: case 97: case 98: {
ConstAtomExpression(out e);
- while (la.kind == 51 || la.kind == 53) {
+ while (la.kind == 54 || la.kind == 56) {
Suffix(ref e);
}
break;
}
- default: SynErr(156); break;
+ default: SynErr(167); break;
}
}
void MulOp(out IToken/*!*/ x, out BinaryExpr.Opcode op) {
Contract.Ensures(Contract.ValueAtReturn(out x) != null); x = Token.NoToken; op = BinaryExpr.Opcode.Add/*(dummy)*/;
- if (la.kind == 44) {
+ if (la.kind == 46) {
Get();
x = t; op = BinaryExpr.Opcode.Mul;
- } else if (la.kind == 86) {
+ } else if (la.kind == 89) {
Get();
x = t; op = BinaryExpr.Opcode.Div;
- } else if (la.kind == 87) {
+ } else if (la.kind == 90) {
Get();
x = t; op = BinaryExpr.Opcode.Mod;
- } else SynErr(157);
+ } else SynErr(168);
}
void NegOp() {
- if (la.kind == 80) {
+ if (la.kind == 83) {
Get();
- } else if (la.kind == 88) {
+ } else if (la.kind == 91) {
Get();
- } else SynErr(158);
+ } else SynErr(169);
}
void EndlessExpression(out Expression e) {
@@ -1939,73 +2061,73 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo List<BoundVar> letVars; List<Expression> letRHSs;
switch (la.kind) {
- case 55: {
+ case 58: {
Get();
x = t;
Expression(out e);
- Expect(96);
+ Expect(99);
Expression(out e0);
- Expect(56);
+ Expect(59);
Expression(out e1);
e = new ITEExpr(x, e, e0, e1);
break;
}
- case 61: {
+ case 64: {
MatchExpression(out e);
break;
}
- case 98: case 99: case 100: case 101: {
+ case 101: case 102: case 103: case 104: {
QuantifierGuts(out e);
break;
}
- case 37: {
+ case 39: {
ComprehensionExpr(out e);
break;
}
- case 62: {
+ case 65: {
Get();
x = t;
Expression(out e0);
- Expect(18);
+ Expect(19);
Expression(out e1);
e = new AssertExpr(x, e0, e1);
break;
}
- case 63: {
+ case 66: {
Get();
x = t;
Expression(out e0);
- Expect(18);
+ Expect(19);
Expression(out e1);
e = new AssumeExpr(x, e0, e1);
break;
}
- case 19: {
+ case 20: {
Get();
x = t;
letVars = new List<BoundVar>();
letRHSs = new List<Expression>();
IdentTypeOptional(out d);
letVars.Add(d);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
IdentTypeOptional(out d);
letVars.Add(d);
}
- Expect(49);
+ Expect(51);
Expression(out e);
letRHSs.Add(e);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
Expression(out e);
letRHSs.Add(e);
}
- Expect(18);
+ Expect(19);
Expression(out e);
e = new LetExpr(x, letVars, letRHSs, e);
break;
}
- default: SynErr(159); break;
+ default: SynErr(170); break;
}
}
@@ -2016,18 +2138,18 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Ident(out id);
idents.Add(id);
- while (la.kind == 53) {
+ while (la.kind == 56) {
Get();
Ident(out id);
idents.Add(id);
}
- if (la.kind == 32) {
+ if (la.kind == 34) {
Get();
openParen = t; args = new List<Expression>();
- if (StartOf(8)) {
+ if (StartOf(9)) {
Expressions(args);
}
- Expect(33);
+ Expect(35);
}
e = new IdentifierSequence(idents, openParen, args);
}
@@ -2038,38 +2160,38 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo List<Expression> multipleIndices = null;
bool func = false;
- if (la.kind == 53) {
+ if (la.kind == 56) {
Get();
Ident(out id);
- if (la.kind == 32) {
+ if (la.kind == 34) {
Get();
IToken openParen = t; args = new List<Expression/*!*/>(); func = true;
- if (StartOf(8)) {
+ if (StartOf(9)) {
Expressions(args);
}
- Expect(33);
+ Expect(35);
e = new FunctionCallExpr(id, id.val, e, openParen, args);
}
if (!func) { e = new ExprDotName(id, e, id.val); }
- } else if (la.kind == 51) {
+ } else if (la.kind == 54) {
Get();
x = t;
- if (StartOf(8)) {
+ if (StartOf(9)) {
Expression(out ee);
e0 = ee;
- if (la.kind == 97) {
+ if (la.kind == 100) {
Get();
anyDots = true;
- if (StartOf(8)) {
+ if (StartOf(9)) {
Expression(out ee);
e1 = ee;
}
- } else if (la.kind == 49) {
+ } else if (la.kind == 51) {
Get();
Expression(out ee);
e1 = ee;
- } else if (la.kind == 20 || la.kind == 52) {
- while (la.kind == 20) {
+ } else if (la.kind == 21 || la.kind == 55) {
+ while (la.kind == 21) {
Get();
Expression(out ee);
if (multipleIndices == null) {
@@ -2079,39 +2201,39 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo multipleIndices.Add(ee);
}
- } else SynErr(160);
- } else if (la.kind == 97) {
+ } else SynErr(171);
+ } else if (la.kind == 100) {
Get();
anyDots = true;
- if (StartOf(8)) {
+ if (StartOf(9)) {
Expression(out ee);
e1 = ee;
}
- } else SynErr(161);
+ } else SynErr(172);
if (multipleIndices != null) {
e = new MultiSelectExpr(x, e, multipleIndices);
// make sure an array class with this dimensionality exists
UserDefinedType tmp = theBuiltIns.ArrayType(x, multipleIndices.Count, new IntType(), true);
} else {
- if (!anyDots && e0 == null) {
- /* a parsing error occurred */
- e0 = dummyExpr;
- }
- Contract.Assert(anyDots || e0 != null);
- if (anyDots) {
- //Contract.Assert(e0 != null || e1 != null);
- e = new SeqSelectExpr(x, false, e, e0, e1);
- } else if (e1 == null) {
- Contract.Assert(e0 != null);
- e = new SeqSelectExpr(x, true, e, e0, null);
- } else {
- Contract.Assert(e0 != null);
- e = new SeqUpdateExpr(x, e, e0, e1);
- }
+ if (!anyDots && e0 == null) {
+ /* a parsing error occurred */
+ e0 = dummyExpr;
+ }
+ Contract.Assert(anyDots || e0 != null);
+ if (anyDots) {
+ //Contract.Assert(e0 != null || e1 != null);
+ e = new SeqSelectExpr(x, false, e, e0, e1);
+ } else if (e1 == null) {
+ Contract.Assert(e0 != null);
+ e = new SeqSelectExpr(x, true, e, e0, null);
+ } else {
+ Contract.Assert(e0 != null);
+ e = new SeqUpdateExpr(x, e, e0, e1);
+ }
}
- Expect(52);
- } else SynErr(162);
+ Expect(55);
+ } else SynErr(173);
}
void DisplayExpr(out Expression e) {
@@ -2122,20 +2244,20 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo if (la.kind == 6) {
Get();
x = t; elements = new List<Expression/*!*/>();
- if (StartOf(8)) {
+ if (StartOf(9)) {
Expressions(elements);
}
e = new SetDisplayExpr(x, elements);
Expect(7);
- } else if (la.kind == 51) {
+ } else if (la.kind == 54) {
Get();
x = t; elements = new List<Expression/*!*/>();
- if (StartOf(8)) {
+ if (StartOf(9)) {
Expressions(elements);
}
e = new SeqDisplayExpr(x, elements);
- Expect(52);
- } else SynErr(163);
+ Expect(55);
+ } else SynErr(174);
}
void MultiSetExpr(out Expression e) {
@@ -2143,25 +2265,25 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo IToken/*!*/ x = null; List<Expression/*!*/>/*!*/ elements;
e = dummyExpr;
- Expect(38);
+ Expect(40);
x = t;
if (la.kind == 6) {
Get();
elements = new List<Expression/*!*/>();
- if (StartOf(8)) {
+ if (StartOf(9)) {
Expressions(elements);
}
e = new MultiSetDisplayExpr(x, elements);
Expect(7);
- } else if (la.kind == 32) {
+ } else if (la.kind == 34) {
Get();
x = t; elements = new List<Expression/*!*/>();
Expression(out e);
e = new MultiSetFormingExpr(x, e);
- Expect(33);
- } else if (StartOf(18)) {
+ Expect(35);
+ } else if (StartOf(19)) {
SemErr("multiset must be followed by multiset literal or expression to coerce in parentheses.");
- } else SynErr(164);
+ } else SynErr(175);
}
void ConstAtomExpression(out Expression/*!*/ e) {
@@ -2170,17 +2292,17 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo e = dummyExpr;
switch (la.kind) {
- case 89: {
+ case 92: {
Get();
e = new LiteralExpr(t, false);
break;
}
- case 90: {
+ case 93: {
Get();
e = new LiteralExpr(t, true);
break;
}
- case 91: {
+ case 94: {
Get();
e = new LiteralExpr(t);
break;
@@ -2190,55 +2312,55 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo e = new LiteralExpr(t, n);
break;
}
- case 92: {
+ case 95: {
Get();
e = new ThisExpr(t);
break;
}
- case 93: {
+ case 96: {
Get();
x = t;
- Expect(32);
+ Expect(34);
Expression(out e);
- Expect(33);
+ Expect(35);
e = new FreshExpr(x, e);
break;
}
- case 94: {
+ case 97: {
Get();
x = t;
- Expect(32);
+ Expect(34);
Expression(out e);
- Expect(33);
+ Expect(35);
e = new AllocatedExpr(x, e);
break;
}
- case 95: {
+ case 98: {
Get();
x = t;
- Expect(32);
+ Expect(34);
Expression(out e);
- Expect(33);
+ Expect(35);
e = new OldExpr(x, e);
break;
}
- case 17: {
+ case 18: {
Get();
x = t;
Expression(out e);
e = new UnaryExpr(x, UnaryExpr.Opcode.SeqLength, e);
- Expect(17);
+ Expect(18);
break;
}
- case 32: {
+ case 34: {
Get();
x = t;
Expression(out e);
e = new ParensExpression(x, e);
- Expect(33);
+ Expect(35);
break;
}
- default: SynErr(165); break;
+ default: SynErr(176); break;
}
}
@@ -2247,8 +2369,8 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo try {
n = BigInteger.Parse(t.val);
} catch (System.FormatException) {
- SemErr("incorrectly formatted number");
- n = BigInteger.Zero;
+ SemErr("incorrectly formatted number");
+ n = BigInteger.Zero;
}
}
@@ -2257,10 +2379,10 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Contract.Ensures(Contract.ValueAtReturn(out e) != null); IToken/*!*/ x; MatchCaseExpr/*!*/ c;
List<MatchCaseExpr/*!*/> cases = new List<MatchCaseExpr/*!*/>();
- Expect(61);
+ Expect(64);
x = t;
Expression(out e);
- while (la.kind == 57) {
+ while (la.kind == 60) {
CaseExpression(out c);
cases.Add(c);
}
@@ -2275,20 +2397,20 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expression range;
Expression/*!*/ body;
- if (la.kind == 98 || la.kind == 99) {
+ if (la.kind == 101 || la.kind == 102) {
Forall();
x = t; univ = true;
- } else if (la.kind == 100 || la.kind == 101) {
+ } else if (la.kind == 103 || la.kind == 104) {
Exists();
x = t;
- } else SynErr(166);
+ } else SynErr(177);
QuantifierDomain(out bvars, out attrs, out range);
QSep();
Expression(out body);
if (univ) {
q = new ForallExpr(x, bvars, range, body, attrs);
} else {
- q = new ExistsExpr(x, bvars, range, body, attrs);
+ q = new ExistsExpr(x, bvars, range, body, attrs);
}
}
@@ -2301,18 +2423,18 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expression/*!*/ range;
Expression body = null;
- Expect(37);
+ Expect(39);
x = t;
IdentTypeOptional(out bv);
bvars.Add(bv);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
IdentTypeOptional(out bv);
bvars.Add(bv);
}
- Expect(17);
+ Expect(18);
Expression(out range);
- if (la.kind == 102 || la.kind == 103) {
+ if (la.kind == 105 || la.kind == 106) {
QSep();
Expression(out body);
}
@@ -2327,47 +2449,47 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo BoundVar/*!*/ bv;
Expression/*!*/ body;
- Expect(57);
+ Expect(60);
x = t;
Ident(out id);
- if (la.kind == 32) {
+ if (la.kind == 34) {
Get();
IdentTypeOptional(out bv);
arguments.Add(bv);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
IdentTypeOptional(out bv);
arguments.Add(bv);
}
- Expect(33);
+ Expect(35);
}
- Expect(58);
+ Expect(61);
Expression(out body);
c = new MatchCaseExpr(x, id.val, arguments, body);
}
void Forall() {
- if (la.kind == 98) {
+ if (la.kind == 101) {
Get();
- } else if (la.kind == 99) {
+ } else if (la.kind == 102) {
Get();
- } else SynErr(167);
+ } else SynErr(178);
}
void Exists() {
- if (la.kind == 100) {
+ if (la.kind == 103) {
Get();
- } else if (la.kind == 101) {
+ } else if (la.kind == 104) {
Get();
- } else SynErr(168);
+ } else SynErr(179);
}
void QSep() {
- if (la.kind == 102) {
+ if (la.kind == 105) {
Get();
- } else if (la.kind == 103) {
+ } else if (la.kind == 106) {
Get();
- } else SynErr(169);
+ } else SynErr(180);
}
void AttributeBody(ref Attributes attrs) {
@@ -2378,10 +2500,10 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo Expect(5);
Expect(1);
aName = t.val;
- if (StartOf(19)) {
+ if (StartOf(20)) {
AttributeArg(out aArg);
aArgs.Add(aArg);
- while (la.kind == 20) {
+ while (la.kind == 21) {
Get();
AttributeArg(out aArg);
aArgs.Add(aArg);
@@ -2394,34 +2516,36 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo public void Parse() {
la = new Token();
- la.val = "";
+ la.val = "";
Get();
Dafny();
+ Expect(0);
- Expect(0);
+ Expect(0);
}
-
+
static readonly bool[,]/*!*/ set = {
- {T,T,T,x, x,x,T,x, x,x,x,T, T,x,x,T, x,T,T,T, x,x,x,x, T,T,x,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,T, x,x,x,T, T,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, T,x,x,T, T,T,T,T, x,x,x,T, x,T,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,T, x,x,x,T, x,T,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,x,T, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,x, x,x,T,x, x,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,T, x,x,x,x, x,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,x,x, T,T,T,T, T,T,T,T, x,x,T,T, T,T,x,x, x,x},
- {x,T,T,x, x,x,T,x, x,x,x,x, T,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,T, x,x,x,T, x,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,x, x,x,T,x, x,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,T,x, x,x,x,x, T,x,x,x, x,x,x,T, x,x,x,T, x,x,x,x, x,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,x,x, T,T,T,T, T,T,T,T, x,x,T,T, T,T,x,x, x,x},
- {T,T,T,x, x,x,T,x, x,x,x,x, T,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,x,x,x, x,x,x,T, x,x,x,T, x,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,T,T,x, x,x,T,x, x,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,T,x, x,x,x,x, T,x,x,x, x,x,T,T, x,x,T,T, x,x,x,x, x,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,x,x, T,T,T,T, T,T,T,T, x,x,T,T, T,T,x,x, x,x},
- {x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x},
- {x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,T,T,x, T,x,T,T, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, T,T,x,x, x,T,x,x, T,x,x,x, T,T,T,x, x,x,x,x, x,x,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, x,x,x,x, x,x,x,x, T,T,x,x, x,x,T,T, x,x},
- {x,T,T,x, T,x,T,x, x,x,x,x, x,x,x,x, x,T,x,T, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,T, x,x,x,x, x,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,x, x,T,x,x, T,T,T,T, T,T,T,T, x,x,T,T, T,T,x,x, x,x}
+ {T,T,T,x, x,x,T,x, T,x,x,x, T,x,x,T, T,x,T,T, T,x,x,x, x,T,T,x, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,x, x,x,x,x, x,x,T,x, x,x,T,T, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,x,x, T,T,x,x, T,T,T,T, T,x,x,x, T,x,T,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,x,x, T,x,x,x, T,T,T,T, T,x,x,x, T,x,T,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,x,x, T,x,x,x, x,T,T,x, x,x,x,x, T,x,x,x, x,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {T,x,x,x, x,x,T,T, T,T,x,x, T,T,T,T, T,x,x,x, T,x,T,T, x,T,T,x, x,x,x,T, T,T,T,x, x,x,x,x, x,x,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,T,x,x, x,x,x,x, x,x,x,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,T,x,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,T,T,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,T,x, x,x,x,x, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,T, T,T,T,T, T,T,T,x, x,T,T,T, T,x,x,x, x},
+ {x,T,T,x, x,x,T,x, T,x,x,x, x,x,x,x, x,x,T,x, T,x,x,x, x,x,x,x, T,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,x, x,x,x,x, x,x,T,x, x,x,T,x, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x},
+ {x,T,T,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,T, T,x,x,x, x,x,T,x, x,x,x,x, x,x,T,x, x,x,T,x, x,x,x,x, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,T, T,T,T,T, T,T,T,x, x,T,T,T, T,x,x,x, x},
+ {T,T,T,x, x,x,T,x, T,x,x,x, x,x,x,x, x,x,T,x, T,x,x,x, x,x,x,x, T,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,x, x,x,x,x, x,x,T,x, x,x,T,x, T,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,T,T,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,T, T,x,x,x, x,x,T,x, x,x,x,x, x,T,T,x, x,T,T,x, x,x,x,x, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,T, T,T,T,T, T,T,T,x, x,T,T,T, T,x,x,x, x},
+ {x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,x, x,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,T,T,T, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x},
+ {x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,T,T, x,T,x,T, T,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,T, x,x,x,T, x,x,x,T, T,T,x,x, x,x,x,x, x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,x, x,x,x,x, x,x,x,T, T,x,x,x, x,T,T,x, x},
+ {x,T,T,x, T,x,T,x, x,x,x,x, x,x,x,x, x,x,T,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,x,T, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,x, x,x,T,x, x,x,x,x, T,T,T,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,T, x,x,x,x, T,x,x,T, T,T,T,T, T,T,T,x, x,T,T,T, T,x,x,x, x}
};
} // end Parser
@@ -2430,18 +2554,20 @@ List<Expression/*!*/>/*!*/ decreases, ref Attributes decAttrs, ref Attributes mo public class Errors {
public int count = 0; // number of errors detected
public System.IO.TextWriter/*!*/ errorStream = Console.Out; // error messages go to this stream
- public string errMsgFormat = "{0}({1},{2}): error: {3}"; // 0=filename, 1=line, 2=column, 3=text
- public string warningMsgFormat = "{0}({1},{2}): warning: {3}"; // 0=filename, 1=line, 2=column, 3=text
-
+ public string errMsgFormat = "{0}({1},{2}): error: {3}"; // 0=filename, 1=line, 2=column, 3=text
+ public string warningMsgFormat = "{0}({1},{2}): warning: {3}"; // 0=filename, 1=line, 2=column, 3=text
+
public void SynErr(string filename, int line, int col, int n) {
- SynErr(filename, line, col, GetSyntaxErrorString(n));
- }
- public virtual void SynErr(string filename, int line, int col, string msg) {
- Contract.Requires(msg != null);
+ SynErr(filename, line, col, GetSyntaxErrorString(n));
+ }
+
+ public virtual void SynErr(string filename, int line, int col, string/*!*/ msg) {
+ Contract.Requires(msg != null);
errorStream.WriteLine(errMsgFormat, filename, line, col, msg);
count++;
- }
- string GetSyntaxErrorString(int n) {
+ }
+
+ string GetSyntaxErrorString(int n) {
string s;
switch (n) {
case 0: s = "EOF expected"; break;
@@ -2452,172 +2578,183 @@ public class Errors { case 5: s = "colon expected"; break;
case 6: s = "lbrace expected"; break;
case 7: s = "rbrace expected"; break;
- case 8: s = "\"module\" expected"; break;
- case 9: s = "\"refines\" expected"; break;
- case 10: s = "\"imports\" expected"; break;
- case 11: s = "\"class\" expected"; break;
- case 12: s = "\"ghost\" expected"; break;
+ case 8: s = "\"ghost\" expected"; break;
+ case 9: s = "\"module\" expected"; break;
+ case 10: s = "\"refines\" expected"; break;
+ case 11: s = "\"imports\" expected"; break;
+ case 12: s = "\"class\" expected"; break;
case 13: s = "\"static\" expected"; break;
case 14: s = "\"unlimited\" expected"; break;
case 15: s = "\"datatype\" expected"; break;
- case 16: s = "\"=\" expected"; break;
- case 17: s = "\"|\" expected"; break;
- case 18: s = "\";\" expected"; break;
- case 19: s = "\"var\" expected"; break;
- case 20: s = "\",\" expected"; break;
- case 21: s = "\"type\" expected"; break;
- case 22: s = "\"<\" expected"; break;
- case 23: s = "\">\" expected"; break;
- case 24: s = "\"method\" expected"; break;
- case 25: s = "\"constructor\" expected"; break;
- case 26: s = "\"returns\" expected"; break;
- case 27: s = "\"modifies\" expected"; break;
- case 28: s = "\"free\" expected"; break;
- case 29: s = "\"requires\" expected"; break;
- case 30: s = "\"ensures\" expected"; break;
- case 31: s = "\"decreases\" expected"; break;
- case 32: s = "\"(\" expected"; break;
- case 33: s = "\")\" expected"; break;
- case 34: s = "\"bool\" expected"; break;
- case 35: s = "\"nat\" expected"; break;
- case 36: s = "\"int\" expected"; break;
- case 37: s = "\"set\" expected"; break;
- case 38: s = "\"multiset\" expected"; break;
- case 39: s = "\"seq\" expected"; break;
- case 40: s = "\"object\" expected"; break;
- case 41: s = "\"function\" expected"; break;
- case 42: s = "\"predicate\" expected"; break;
- case 43: s = "\"reads\" expected"; break;
- case 44: s = "\"*\" expected"; break;
- case 45: s = "\"`\" expected"; break;
- case 46: s = "\"label\" expected"; break;
- case 47: s = "\"break\" expected"; break;
- case 48: s = "\"return\" expected"; break;
- case 49: s = "\":=\" expected"; break;
- case 50: s = "\"new\" expected"; break;
- case 51: s = "\"[\" expected"; break;
- case 52: s = "\"]\" expected"; break;
- case 53: s = "\".\" expected"; break;
- case 54: s = "\"choose\" expected"; break;
- case 55: s = "\"if\" expected"; break;
- case 56: s = "\"else\" expected"; break;
- case 57: s = "\"case\" expected"; break;
- case 58: s = "\"=>\" expected"; break;
- case 59: s = "\"while\" expected"; break;
- case 60: s = "\"invariant\" expected"; break;
- case 61: s = "\"match\" expected"; break;
- case 62: s = "\"assert\" expected"; break;
- case 63: s = "\"assume\" expected"; break;
- case 64: s = "\"print\" expected"; break;
- case 65: s = "\"parallel\" expected"; break;
- case 66: s = "\"<==>\" expected"; break;
- case 67: s = "\"\\u21d4\" expected"; break;
- case 68: s = "\"==>\" expected"; break;
- case 69: s = "\"\\u21d2\" expected"; break;
- case 70: s = "\"&&\" expected"; break;
- case 71: s = "\"\\u2227\" expected"; break;
- case 72: s = "\"||\" expected"; break;
- case 73: s = "\"\\u2228\" expected"; break;
- case 74: s = "\"==\" expected"; break;
- case 75: s = "\"<=\" expected"; break;
- case 76: s = "\">=\" expected"; break;
- case 77: s = "\"!=\" expected"; break;
- case 78: s = "\"!!\" expected"; break;
- case 79: s = "\"in\" expected"; break;
- case 80: s = "\"!\" expected"; break;
- case 81: s = "\"\\u2260\" expected"; break;
- case 82: s = "\"\\u2264\" expected"; break;
- case 83: s = "\"\\u2265\" expected"; break;
- case 84: s = "\"+\" expected"; break;
- case 85: s = "\"-\" expected"; break;
- case 86: s = "\"/\" expected"; break;
- case 87: s = "\"%\" expected"; break;
- case 88: s = "\"\\u00ac\" expected"; break;
- case 89: s = "\"false\" expected"; break;
- case 90: s = "\"true\" expected"; break;
- case 91: s = "\"null\" expected"; break;
- case 92: s = "\"this\" expected"; break;
- case 93: s = "\"fresh\" expected"; break;
- case 94: s = "\"allocated\" expected"; break;
- case 95: s = "\"old\" expected"; break;
- case 96: s = "\"then\" expected"; break;
- case 97: s = "\"..\" expected"; break;
- case 98: s = "\"forall\" expected"; break;
- case 99: s = "\"\\u2200\" expected"; break;
- case 100: s = "\"exists\" expected"; break;
- case 101: s = "\"\\u2203\" expected"; break;
- case 102: s = "\"::\" expected"; break;
- case 103: s = "\"\\u2022\" expected"; break;
- case 104: s = "??? expected"; break;
- case 105: s = "this symbol not expected in ClassDecl"; break;
- case 106: s = "this symbol not expected in DatatypeDecl"; break;
- case 107: s = "this symbol not expected in DatatypeDecl"; break;
- case 108: s = "this symbol not expected in ArbitraryTypeDecl"; break;
- case 109: s = "invalid ClassMemberDecl"; break;
- case 110: s = "this symbol not expected in FieldDecl"; break;
- case 111: s = "this symbol not expected in FieldDecl"; break;
- case 112: s = "invalid FunctionDecl"; break;
- case 113: s = "this symbol not expected in MethodDecl"; break;
- case 114: s = "invalid MethodDecl"; break;
- case 115: s = "invalid TypeAndToken"; break;
- case 116: s = "this symbol not expected in MethodSpec"; break;
- case 117: s = "this symbol not expected in MethodSpec"; break;
- case 118: s = "this symbol not expected in MethodSpec"; break;
- case 119: s = "this symbol not expected in MethodSpec"; break;
- case 120: s = "invalid MethodSpec"; break;
- case 121: s = "this symbol not expected in MethodSpec"; break;
- case 122: s = "invalid MethodSpec"; break;
- case 123: s = "invalid ReferenceType"; break;
- case 124: s = "this symbol not expected in FunctionSpec"; break;
- case 125: s = "this symbol not expected in FunctionSpec"; break;
- case 126: s = "this symbol not expected in FunctionSpec"; break;
- case 127: s = "this symbol not expected in FunctionSpec"; break;
- case 128: s = "this symbol not expected in FunctionSpec"; break;
- case 129: s = "invalid FunctionSpec"; break;
- case 130: s = "invalid PossiblyWildFrameExpression"; break;
- case 131: s = "invalid PossiblyWildExpression"; break;
- case 132: s = "this symbol not expected in OneStmt"; break;
- case 133: s = "invalid OneStmt"; break;
- case 134: s = "this symbol not expected in OneStmt"; break;
- case 135: s = "invalid OneStmt"; break;
- case 136: s = "invalid UpdateStmt"; break;
- case 137: s = "invalid IfStmt"; break;
- case 138: s = "invalid IfStmt"; break;
- case 139: s = "invalid WhileStmt"; break;
- case 140: s = "invalid Rhs"; break;
- case 141: s = "invalid Lhs"; break;
- case 142: s = "invalid Guard"; break;
- case 143: s = "this symbol not expected in LoopSpec"; break;
- case 144: s = "this symbol not expected in LoopSpec"; break;
- case 145: s = "this symbol not expected in LoopSpec"; break;
- case 146: s = "this symbol not expected in LoopSpec"; break;
- case 147: s = "this symbol not expected in LoopSpec"; break;
- case 148: s = "this symbol not expected in Invariant"; break;
- case 149: s = "invalid AttributeArg"; break;
- case 150: s = "invalid EquivOp"; break;
- case 151: s = "invalid ImpliesOp"; break;
- case 152: s = "invalid AndOp"; break;
- case 153: s = "invalid OrOp"; break;
- case 154: s = "invalid RelOp"; break;
- case 155: s = "invalid AddOp"; break;
- case 156: s = "invalid UnaryExpression"; break;
- case 157: s = "invalid MulOp"; break;
- case 158: s = "invalid NegOp"; break;
- case 159: s = "invalid EndlessExpression"; break;
- case 160: s = "invalid Suffix"; break;
- case 161: s = "invalid Suffix"; break;
- case 162: s = "invalid Suffix"; break;
- case 163: s = "invalid DisplayExpr"; break;
- case 164: s = "invalid MultiSetExpr"; break;
- case 165: s = "invalid ConstAtomExpression"; break;
- case 166: s = "invalid QuantifierGuts"; break;
- case 167: s = "invalid Forall"; break;
- case 168: s = "invalid Exists"; break;
- case 169: s = "invalid QSep"; break;
+ case 16: s = "\"codatatype\" expected"; break;
+ case 17: s = "\"=\" expected"; break;
+ case 18: s = "\"|\" expected"; break;
+ case 19: s = "\";\" expected"; break;
+ case 20: s = "\"var\" expected"; break;
+ case 21: s = "\",\" expected"; break;
+ case 22: s = "\"type\" expected"; break;
+ case 23: s = "\"<\" expected"; break;
+ case 24: s = "\">\" expected"; break;
+ case 25: s = "\"method\" expected"; break;
+ case 26: s = "\"constructor\" expected"; break;
+ case 27: s = "\"returns\" expected"; break;
+ case 28: s = "\"...\" expected"; break;
+ case 29: s = "\"modifies\" expected"; break;
+ case 30: s = "\"free\" expected"; break;
+ case 31: s = "\"requires\" expected"; break;
+ case 32: s = "\"ensures\" expected"; break;
+ case 33: s = "\"decreases\" expected"; break;
+ case 34: s = "\"(\" expected"; break;
+ case 35: s = "\")\" expected"; break;
+ case 36: s = "\"bool\" expected"; break;
+ case 37: s = "\"nat\" expected"; break;
+ case 38: s = "\"int\" expected"; break;
+ case 39: s = "\"set\" expected"; break;
+ case 40: s = "\"multiset\" expected"; break;
+ case 41: s = "\"seq\" expected"; break;
+ case 42: s = "\"object\" expected"; break;
+ case 43: s = "\"function\" expected"; break;
+ case 44: s = "\"predicate\" expected"; break;
+ case 45: s = "\"reads\" expected"; break;
+ case 46: s = "\"*\" expected"; break;
+ case 47: s = "\"`\" expected"; break;
+ case 48: s = "\"label\" expected"; break;
+ case 49: s = "\"break\" expected"; break;
+ case 50: s = "\"return\" expected"; break;
+ case 51: s = "\":=\" expected"; break;
+ case 52: s = "\":|\" expected"; break;
+ case 53: s = "\"new\" expected"; break;
+ case 54: s = "\"[\" expected"; break;
+ case 55: s = "\"]\" expected"; break;
+ case 56: s = "\".\" expected"; break;
+ case 57: s = "\"choose\" expected"; break;
+ case 58: s = "\"if\" expected"; break;
+ case 59: s = "\"else\" expected"; break;
+ case 60: s = "\"case\" expected"; break;
+ case 61: s = "\"=>\" expected"; break;
+ case 62: s = "\"while\" expected"; break;
+ case 63: s = "\"invariant\" expected"; break;
+ case 64: s = "\"match\" expected"; break;
+ case 65: s = "\"assert\" expected"; break;
+ case 66: s = "\"assume\" expected"; break;
+ case 67: s = "\"print\" expected"; break;
+ case 68: s = "\"parallel\" expected"; break;
+ case 69: s = "\"<==>\" expected"; break;
+ case 70: s = "\"\\u21d4\" expected"; break;
+ case 71: s = "\"==>\" expected"; break;
+ case 72: s = "\"\\u21d2\" expected"; break;
+ case 73: s = "\"&&\" expected"; break;
+ case 74: s = "\"\\u2227\" expected"; break;
+ case 75: s = "\"||\" expected"; break;
+ case 76: s = "\"\\u2228\" expected"; break;
+ case 77: s = "\"==\" expected"; break;
+ case 78: s = "\"<=\" expected"; break;
+ case 79: s = "\">=\" expected"; break;
+ case 80: s = "\"!=\" expected"; break;
+ case 81: s = "\"!!\" expected"; break;
+ case 82: s = "\"in\" expected"; break;
+ case 83: s = "\"!\" expected"; break;
+ case 84: s = "\"\\u2260\" expected"; break;
+ case 85: s = "\"\\u2264\" expected"; break;
+ case 86: s = "\"\\u2265\" expected"; break;
+ case 87: s = "\"+\" expected"; break;
+ case 88: s = "\"-\" expected"; break;
+ case 89: s = "\"/\" expected"; break;
+ case 90: s = "\"%\" expected"; break;
+ case 91: s = "\"\\u00ac\" expected"; break;
+ case 92: s = "\"false\" expected"; break;
+ case 93: s = "\"true\" expected"; break;
+ case 94: s = "\"null\" expected"; break;
+ case 95: s = "\"this\" expected"; break;
+ case 96: s = "\"fresh\" expected"; break;
+ case 97: s = "\"allocated\" expected"; break;
+ case 98: s = "\"old\" expected"; break;
+ case 99: s = "\"then\" expected"; break;
+ case 100: s = "\"..\" expected"; break;
+ case 101: s = "\"forall\" expected"; break;
+ case 102: s = "\"\\u2200\" expected"; break;
+ case 103: s = "\"exists\" expected"; break;
+ case 104: s = "\"\\u2203\" expected"; break;
+ case 105: s = "\"::\" expected"; break;
+ case 106: s = "\"\\u2022\" expected"; break;
+ case 107: s = "??? expected"; break;
+ case 108: s = "invalid Dafny"; break;
+ case 109: s = "this symbol not expected in ClassDecl"; break;
+ case 110: s = "this symbol not expected in DatatypeDecl"; break;
+ case 111: s = "invalid DatatypeDecl"; break;
+ case 112: s = "this symbol not expected in DatatypeDecl"; break;
+ case 113: s = "this symbol not expected in ArbitraryTypeDecl"; break;
+ case 114: s = "invalid ClassMemberDecl"; break;
+ case 115: s = "this symbol not expected in FieldDecl"; break;
+ case 116: s = "this symbol not expected in FieldDecl"; break;
+ case 117: s = "invalid FunctionDecl"; break;
+ case 118: s = "invalid FunctionDecl"; break;
+ case 119: s = "invalid FunctionDecl"; break;
+ case 120: s = "this symbol not expected in MethodDecl"; break;
+ case 121: s = "invalid MethodDecl"; break;
+ case 122: s = "invalid MethodDecl"; break;
+ case 123: s = "invalid TypeAndToken"; break;
+ case 124: s = "this symbol not expected in MethodSpec"; break;
+ case 125: s = "this symbol not expected in MethodSpec"; break;
+ case 126: s = "this symbol not expected in MethodSpec"; break;
+ case 127: s = "this symbol not expected in MethodSpec"; break;
+ case 128: s = "invalid MethodSpec"; break;
+ case 129: s = "this symbol not expected in MethodSpec"; break;
+ case 130: s = "invalid MethodSpec"; break;
+ case 131: s = "invalid ReferenceType"; break;
+ case 132: s = "this symbol not expected in FunctionSpec"; break;
+ case 133: s = "this symbol not expected in FunctionSpec"; break;
+ case 134: s = "this symbol not expected in FunctionSpec"; break;
+ case 135: s = "this symbol not expected in FunctionSpec"; break;
+ case 136: s = "this symbol not expected in FunctionSpec"; break;
+ case 137: s = "invalid FunctionSpec"; break;
+ case 138: s = "invalid PossiblyWildFrameExpression"; break;
+ case 139: s = "invalid PossiblyWildExpression"; break;
+ case 140: s = "this symbol not expected in OneStmt"; break;
+ case 141: s = "invalid OneStmt"; break;
+ case 142: s = "this symbol not expected in OneStmt"; break;
+ case 143: s = "invalid OneStmt"; break;
+ case 144: s = "invalid AssertStmt"; break;
+ case 145: s = "invalid UpdateStmt"; break;
+ case 146: s = "invalid UpdateStmt"; break;
+ case 147: s = "invalid IfStmt"; break;
+ case 148: s = "invalid IfStmt"; break;
+ case 149: s = "invalid WhileStmt"; break;
+ case 150: s = "invalid WhileStmt"; break;
+ case 151: s = "invalid Rhs"; break;
+ case 152: s = "invalid Lhs"; break;
+ case 153: s = "invalid Guard"; break;
+ case 154: s = "this symbol not expected in LoopSpec"; break;
+ case 155: s = "this symbol not expected in LoopSpec"; break;
+ case 156: s = "this symbol not expected in LoopSpec"; break;
+ case 157: s = "this symbol not expected in LoopSpec"; break;
+ case 158: s = "this symbol not expected in LoopSpec"; break;
+ case 159: s = "this symbol not expected in Invariant"; break;
+ case 160: s = "invalid AttributeArg"; break;
+ case 161: s = "invalid EquivOp"; break;
+ case 162: s = "invalid ImpliesOp"; break;
+ case 163: s = "invalid AndOp"; break;
+ case 164: s = "invalid OrOp"; break;
+ case 165: s = "invalid RelOp"; break;
+ case 166: s = "invalid AddOp"; break;
+ case 167: s = "invalid UnaryExpression"; break;
+ case 168: s = "invalid MulOp"; break;
+ case 169: s = "invalid NegOp"; break;
+ case 170: s = "invalid EndlessExpression"; break;
+ case 171: s = "invalid Suffix"; break;
+ case 172: s = "invalid Suffix"; break;
+ case 173: s = "invalid Suffix"; break;
+ case 174: s = "invalid DisplayExpr"; break;
+ case 175: s = "invalid MultiSetExpr"; break;
+ case 176: s = "invalid ConstAtomExpression"; break;
+ case 177: s = "invalid QuantifierGuts"; break;
+ case 178: s = "invalid Forall"; break;
+ case 179: s = "invalid Exists"; break;
+ case 180: s = "invalid QSep"; break;
default: s = "error " + n; break;
}
- return s;
+ return s;
}
public void SemErr(IToken/*!*/ tok, string/*!*/ msg) { // semantic errors
@@ -2625,8 +2762,9 @@ public class Errors { Contract.Requires(msg != null);
SemErr(tok.filename, tok.line, tok.col, msg);
}
+
public virtual void SemErr(string filename, int line, int col, string/*!*/ msg) {
- Contract.Requires(msg != null);
+ Contract.Requires(msg != null);
errorStream.WriteLine(errMsgFormat, filename, line, col, msg);
count++;
}
@@ -2642,4 +2780,5 @@ public class FatalError: Exception { public FatalError(string m): base(m) {}
}
+
}
\ No newline at end of file diff --git a/Dafny/Printer.cs b/Dafny/Printer.cs index 9bd29da0..2c6fb96a 100644 --- a/Dafny/Printer.cs +++ b/Dafny/Printer.cs @@ -158,7 +158,7 @@ namespace Microsoft.Dafny { public void PrintDatatype(DatatypeDecl dt, int indent) {
Contract.Requires(dt != null);
Indent(indent);
- PrintClassMethodHelper("datatype", dt.Attributes, dt.Name, dt.TypeArgs);
+ PrintClassMethodHelper(dt is IndDatatypeDecl ? "datatype" : "codatatype", dt.Attributes, dt.Name, dt.TypeArgs);
wr.Write(" =");
string sep = "";
foreach (DatatypeCtor ctor in dt.Ctors) {
@@ -226,16 +226,20 @@ namespace Microsoft.Dafny { if (f.IsStatic) { k = "static " + k; }
if (!f.IsGhost) { k += " method"; }
PrintClassMethodHelper(k, f.Attributes, f.Name, f.TypeArgs);
- if (f.OpenParen != null) {
- PrintFormals(f.Formals);
+ if (f.SignatureIsOmitted) {
+ wr.WriteLine(" ...");
} else {
- Contract.Assert(isPredicate);
- }
- if (!isPredicate) {
- wr.Write(": ");
- PrintType(f.ResultType);
+ if (f.OpenParen != null) {
+ PrintFormals(f.Formals);
+ } else {
+ Contract.Assert(isPredicate);
+ }
+ if (!isPredicate) {
+ wr.Write(": ");
+ PrintType(f.ResultType);
+ }
+ wr.WriteLine();
}
- wr.WriteLine();
int ind = indent + IndentAmount;
PrintSpec("requires", f.Req, ind);
@@ -272,18 +276,22 @@ namespace Microsoft.Dafny { if (method.IsStatic) { k = "static " + k; }
if (method.IsGhost) { k = "ghost " + k; }
PrintClassMethodHelper(k, method.Attributes, method.Name, method.TypeArgs);
- PrintFormals(method.Ins);
- if (method.Outs.Count != 0) {
- if (method.Ins.Count + method.Outs.Count <= 3) {
- wr.Write(" returns ");
- } else {
- wr.WriteLine();
- Indent(3 * IndentAmount);
- wr.Write("returns ");
+ if (method.SignatureIsOmitted) {
+ wr.WriteLine(" ...");
+ } else {
+ PrintFormals(method.Ins);
+ if (method.Outs.Count != 0) {
+ if (method.Ins.Count + method.Outs.Count <= 3) {
+ wr.Write(" returns ");
+ } else {
+ wr.WriteLine();
+ Indent(3 * IndentAmount);
+ wr.Write("returns ");
+ }
+ PrintFormals(method.Outs);
}
- PrintFormals(method.Outs);
+ wr.WriteLine();
}
- wr.WriteLine();
int ind = indent + IndentAmount;
PrintSpec("requires", method.Req, ind);
@@ -339,7 +347,7 @@ namespace Microsoft.Dafny { void PrintDecreasesSpec(Specification<Expression> decs, int indent) {
Contract.Requires(decs != null);
- if (decs.Expressions.Count != 0) {
+ if (decs.Expressions != null && decs.Expressions.Count != 0) {
Indent(indent);
wr.Write("decreases");
if (decs.HasAttributes())
@@ -352,14 +360,14 @@ namespace Microsoft.Dafny { }
}
- void PrintFrameSpecLine(string kind, List<FrameExpression/*!*/>/*!*/ ee, int indent, Attributes attrs) {
+ void PrintFrameSpecLine(string kind, List<FrameExpression/*!*/> ee, int indent, Attributes attrs) {
Contract.Requires(kind != null);
Contract.Requires(cce.NonNullElements(ee));
- if (ee.Count != 0) {
+ if (ee != null && ee.Count != 0) {
Indent(indent);
wr.Write("{0}", kind);
if (attrs != null) {
- PrintAttributes(attrs);
+ PrintAttributes(attrs);
}
wr.Write(" ");
PrintFrameExpressionList(ee);
@@ -520,22 +528,7 @@ namespace Microsoft.Dafny { } else if (stmt is IfStmt) {
IfStmt s = (IfStmt)stmt;
- while (true) {
- wr.Write("if (");
- PrintGuard(s.Guard);
- wr.Write(") ");
- PrintStatement(s.Thn, indent);
- if (s.Els == null) {
- break;
- }
- wr.Write(" else ");
- if (s.Els is IfStmt) {
- s = (IfStmt)s.Els;
- } else {
- PrintStatement(s.Els, indent);
- break;
- }
- }
+ PrintIfStatement(indent, s, false);
} else if (stmt is AlternativeStmt) {
var s = (AlternativeStmt)stmt;
@@ -546,18 +539,7 @@ namespace Microsoft.Dafny { } else if (stmt is WhileStmt) {
WhileStmt s = (WhileStmt)stmt;
- wr.Write("while (");
- PrintGuard(s.Guard);
- wr.WriteLine(")");
-
- PrintSpec("invariant", s.Invariants, indent + IndentAmount);
- PrintDecreasesSpec(s.Decreases, indent + IndentAmount);
- if (s.Mod.Expressions != null)
- {
- PrintFrameSpecLine("modifies", s.Mod.Expressions, indent + IndentAmount, s.Mod.HasAttributes() ? s.Mod.Attributes : null);
- }
- Indent(indent);
- PrintStatement(s.Body, indent);
+ PrintWhileStatement(indent, s, false, false);
} else if (stmt is AlternativeLoopStmt) {
var s = (AlternativeLoopStmt)stmt;
@@ -613,23 +595,15 @@ namespace Microsoft.Dafny { Indent(indent);
wr.Write("}");
- } else if (stmt is UpdateStmt) {
- var s = (UpdateStmt)stmt;
+ } else if (stmt is ConcreteUpdateStatement) {
+ var s = (ConcreteUpdateStatement)stmt;
string sep = "";
foreach (var lhs in s.Lhss) {
wr.Write(sep);
PrintExpression(lhs);
sep = ", ";
}
- if (s.Lhss.Count != 0) {
- sep = " := ";
- }
- foreach (var rhs in s.Rhss) {
- wr.Write(sep);
- PrintRhs(rhs);
- sep = ", ";
- }
-
+ PrintUpdateRHS(s);
wr.Write(";");
} else if (stmt is VarDeclStmt) {
@@ -645,21 +619,100 @@ namespace Microsoft.Dafny { sep = ", ";
}
if (s.Update != null) {
- wr.Write(" := ");
- sep = "";
- foreach (var rhs in s.Update.Rhss) {
- wr.Write(sep);
- PrintRhs(rhs);
- sep = ", ";
- }
+ PrintUpdateRHS(s.Update);
}
wr.Write(";");
+ } else if (stmt is SkeletonStatement) {
+ var s = (SkeletonStatement)stmt;
+ if (s.S == null) {
+ wr.Write("...;");
+ } else if (s.S is AssertStmt) {
+ Contract.Assert(s.ConditionOmitted);
+ wr.Write("assert ...;");
+ } else if (s.S is IfStmt) {
+ PrintIfStatement(indent, (IfStmt)s.S, s.ConditionOmitted);
+ } else if (s.S is WhileStmt) {
+ PrintWhileStatement(indent, (WhileStmt)s.S, s.ConditionOmitted, s.BodyOmitted);
+ } else {
+ Contract.Assert(false); throw new cce.UnreachableException(); // unexpected skeleton statement
+ }
+
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected statement
}
}
+ /// <summary>
+ /// Does not print LHS
+ /// </summary>
+ void PrintUpdateRHS(ConcreteUpdateStatement s) {
+ Contract.Requires(s != null);
+ if (s is UpdateStmt) {
+ var update = (UpdateStmt)s;
+ if (update.Lhss.Count != 0) {
+ wr.Write(" := ");
+ }
+ var sep = "";
+ foreach (var rhs in update.Rhss) {
+ wr.Write(sep);
+ PrintRhs(rhs);
+ sep = ", ";
+ }
+ } else if (s is AssignSuchThatStmt) {
+ var update = (AssignSuchThatStmt)s;
+ wr.Write(" :| ");
+ PrintExpression(update.Assume.Expr);
+ } else {
+ Contract.Assert(s == null); // otherwise, unknown type
+ }
+ }
+
+ void PrintIfStatement(int indent, IfStmt s, bool omitGuard) {
+ while (true) {
+ if (omitGuard) {
+ wr.Write("if ... ");
+ } else {
+ wr.Write("if (");
+ PrintGuard(s.Guard);
+ wr.Write(") ");
+ }
+ PrintStatement(s.Thn, indent);
+ if (s.Els == null) {
+ break;
+ }
+ wr.Write(" else ");
+ if (s.Els is IfStmt) {
+ s = (IfStmt)s.Els;
+ } else {
+ PrintStatement(s.Els, indent);
+ break;
+ }
+ }
+ }
+
+ void PrintWhileStatement(int indent, WhileStmt s, bool omitGuard, bool omitBody) {
+ if (omitGuard) {
+ wr.WriteLine("while ...");
+ } else {
+ wr.Write("while (");
+ PrintGuard(s.Guard);
+ wr.WriteLine(")");
+ }
+
+ PrintSpec("invariant", s.Invariants, indent + IndentAmount);
+ PrintDecreasesSpec(s.Decreases, indent + IndentAmount);
+ if (s.Mod.Expressions != null) {
+ PrintFrameSpecLine("modifies", s.Mod.Expressions, indent + IndentAmount, s.Mod.HasAttributes() ? s.Mod.Attributes : null);
+ }
+ Indent(indent);
+ if (omitBody) {
+ wr.WriteLine("...;");
+ } else {
+ PrintStatement(s.Body, indent);
+ }
+ }
+
void PrintAlternatives(int indent, List<GuardedAlternative> alternatives) {
int caseInd = indent + IndentAmount;
foreach (var alternative in alternatives) {
diff --git a/Dafny/RefinementTransformer.cs b/Dafny/RefinementTransformer.cs index ffa54826..c73ffda8 100644 --- a/Dafny/RefinementTransformer.cs +++ b/Dafny/RefinementTransformer.cs @@ -136,11 +136,17 @@ namespace Microsoft.Dafny { if (d is ArbitraryTypeDecl) {
var dd = (ArbitraryTypeDecl)d;
return new ArbitraryTypeDecl(Tok(dd.tok), dd.Name, m, null);
- } else if (d is DatatypeDecl) {
- var dd = (DatatypeDecl)d;
+ } else if (d is IndDatatypeDecl) {
+ var dd = (IndDatatypeDecl)d;
var tps = dd.TypeArgs.ConvertAll(CloneTypeParam);
var ctors = dd.Ctors.ConvertAll(CloneCtor);
- var dt = new DatatypeDecl(Tok(dd.tok), dd.Name, m, tps, ctors, null);
+ var dt = new IndDatatypeDecl(Tok(dd.tok), dd.Name, m, tps, ctors, null);
+ return dt;
+ } else if (d is CoDatatypeDecl) {
+ var dd = (CoDatatypeDecl)d;
+ var tps = dd.TypeArgs.ConvertAll(CloneTypeParam);
+ var ctors = dd.Ctors.ConvertAll(CloneCtor);
+ var dt = new CoDatatypeDecl(Tok(dd.tok), dd.Name, m, tps, ctors, null);
return dt;
} else if (d is ClassDecl) {
var dd = (ClassDecl)d;
@@ -450,7 +456,7 @@ namespace Microsoft.Dafny { } else if (stmt is IfStmt) {
var s = (IfStmt)stmt;
- r = new IfStmt(Tok(s.Tok), CloneExpr(s.Guard), CloneStmt(s.Thn), CloneStmt(s.Els));
+ r = new IfStmt(Tok(s.Tok), CloneExpr(s.Guard), CloneBlockStmt(s.Thn), CloneStmt(s.Els));
} else if (stmt is AlternativeStmt) {
var s = (AlternativeStmt)stmt;
@@ -458,7 +464,7 @@ namespace Microsoft.Dafny { } else if (stmt is WhileStmt) {
var s = (WhileStmt)stmt;
- r = new WhileStmt(Tok(s.Tok), CloneExpr(s.Guard), s.Invariants.ConvertAll(CloneMayBeFreeExpr), CloneSpecExpr(s.Decreases), CloneSpecFrameExpr(s.Mod), CloneStmt(s.Body));
+ r = new WhileStmt(Tok(s.Tok), CloneExpr(s.Guard), s.Invariants.ConvertAll(CloneMayBeFreeExpr), CloneSpecExpr(s.Decreases), CloneSpecFrameExpr(s.Mod), CloneBlockStmt(s.Body));
} else if (stmt is AlternativeLoopStmt) {
var s = (AlternativeLoopStmt)stmt;
@@ -473,13 +479,17 @@ namespace Microsoft.Dafny { r = new MatchStmt(Tok(s.Tok), CloneExpr(s.Source),
s.Cases.ConvertAll(c => new MatchCaseStmt(Tok(c.tok), c.Id, c.Arguments.ConvertAll(CloneBoundVar), c.Body.ConvertAll(CloneStmt))));
+ } else if (stmt is AssignSuchThatStmt) {
+ var s = (AssignSuchThatStmt)stmt;
+ r = new AssignSuchThatStmt(Tok(s.Tok), s.Lhss.ConvertAll(CloneExpr), CloneExpr(s.Assume.Expr));
+
} else if (stmt is UpdateStmt) {
var s = (UpdateStmt)stmt;
r = new UpdateStmt(Tok(s.Tok), s.Lhss.ConvertAll(CloneExpr), s.Rhss.ConvertAll(CloneRHS), s.CanMutateKnownState);
} else if (stmt is VarDeclStmt) {
var s = (VarDeclStmt)stmt;
- r = new VarDeclStmt(Tok(s.Tok), s.Lhss.ConvertAll(c => (VarDecl)CloneStmt(c)), (UpdateStmt)CloneStmt(s.Update));
+ r = new VarDeclStmt(Tok(s.Tok), s.Lhss.ConvertAll(c => (VarDecl)CloneStmt(c)), (ConcreteUpdateStatement)CloneStmt(s.Update));
} else {
Contract.Assert(false); throw new cce.UnreachableException(); // unexpected statement
@@ -494,7 +504,11 @@ namespace Microsoft.Dafny { void AddStmtLabels(Statement s, LabelNode node) {
if (node != null) {
AddStmtLabels(s, node.Next);
- s.Labels = new LabelNode(Tok(node.Tok), node.Label, s.Labels);
+ if (node.Label == null) {
+ // this indicates an implicit-target break statement that has been resolved; don't add it
+ } else {
+ s.Labels = new LabelNode(Tok(node.Tok), node.Label, s.Labels);
+ }
}
}
@@ -535,10 +549,10 @@ namespace Microsoft.Dafny { if (f is Predicate) {
return new Predicate(tok, f.Name, f.IsStatic, isGhost, f.IsUnlimited, tps, f.OpenParen, formals,
- req, reads, ens, decreases, body, moreBody != null, null);
+ req, reads, ens, decreases, body, moreBody != null, null, false);
} else {
return new Function(tok, f.Name, f.IsStatic, isGhost, f.IsUnlimited, tps, f.OpenParen, formals, CloneType(f.ResultType),
- req, reads, ens, decreases, body, null);
+ req, reads, ens, decreases, body, null, false);
}
}
@@ -562,10 +576,10 @@ namespace Microsoft.Dafny { var body = replacementBody ?? CloneBlockStmt(m.Body);
if (m is Constructor) {
return new Constructor(Tok(m.tok), m.Name, tps, ins,
- req, mod, ens, decreases, body, null);
+ req, mod, ens, decreases, body, null, false);
} else {
return new Method(Tok(m.tok), m.Name, m.IsStatic, m.IsGhost, tps, ins, m.Outs.ConvertAll(CloneFormal),
- req, mod, ens, decreases, body, null);
+ req, mod, ens, decreases, body, null, false);
}
}
@@ -620,10 +634,15 @@ namespace Microsoft.Dafny { } else if (prevFunction.IsGhost && !f.IsGhost && prevFunction.Body != null) {
reporter.Error(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);
}
- CheckAgreement_TypeParameters(f.tok, prevFunction.TypeArgs, f.TypeArgs, f.Name, "function");
- CheckAgreement_Parameters(f.tok, prevFunction.Formals, f.Formals, f.Name, "function", "parameter");
- if (!TypesAreEqual(prevFunction.ResultType, f.ResultType)) {
- reporter.Error(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);
+ if (f.SignatureIsOmitted) {
+ Contract.Assert(f.TypeArgs.Count == 0);
+ Contract.Assert(f.Formals.Count == 0);
+ } 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 (!TypesAreEqual(prevFunction.ResultType, f.ResultType)) {
+ reporter.Error(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;
@@ -662,17 +681,22 @@ namespace Microsoft.Dafny { } else if (!prevMethod.IsGhost && m.IsGhost) {
reporter.Error(m, "a ghost method cannot be changed into a non-ghost method in a refining module: {0}", m.Name);
}
- 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");
+ if (m.SignatureIsOmitted) {
+ Contract.Assert(m.TypeArgs.Count == 0);
+ Contract.Assert(m.Ins.Count == 0);
+ Contract.Assert(m.Outs.Count == 0);
+ } 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");
+ }
var replacementBody = m.Body;
if (replacementBody != null) {
if (prevMethod.Body == null) {
// cool
} else {
- reporter.Error(m, "body of refining method is not yet supported"); // TODO (merge the new body into the old)
- replacementBody = null;
+ replacementBody = MergeBlockStmt(replacementBody, prevMethod.Body);
}
}
nw.Members[index] = CloneMethod(prevMethod, m.Ens, replacementBody);
@@ -735,6 +759,356 @@ namespace Microsoft.Dafny { return t.ToString() == u.ToString();
}
+ BlockStmt MergeBlockStmt(BlockStmt skeleton, BlockStmt oldStmt) {
+ Contract.Requires(skeleton != null);
+ Contract.Requires(oldStmt != null);
+
+ var body = new List<Statement>();
+ int i = 0, j = 0;
+ while (i < skeleton.Body.Count) {
+ var cur = skeleton.Body[i];
+ if (j == oldStmt.Body.Count) {
+ if (!(cur is SkeletonStatement)) {
+ MergeAddStatement(cur, body);
+ } else if (((SkeletonStatement)cur).S == null) {
+ // the "..." matches the empty statement sequence
+ } else {
+ reporter.Error(cur.Tok, "skeleton statement does not match old statement");
+ }
+ i++;
+ } else {
+ var oldS = oldStmt.Body[j];
+ /* See how the two statements match up.
+ * cur oldS result
+ * ------ ------ ------
+ * assert ...; assume E; assert E;
+ * assert ...; assert E; assert E;
+ * assert E; assert E;
+ *
+ * var x := E; var x; var x := E;
+ * var x := E; var x := *; var x := E;
+ * var x := E1; var x :| E0; var x := E1; assert E0;
+ * var VarProduction; var VarProduction;
+ *
+ * x := E; x := *; x := E;
+ *
+ * if ... Then else Else if (G) Then' else Else' if (G) Merge(Then,Then') else Merge(Else,Else')
+ * if (G) Then else Else if (*) Then' else Else' if (G) Merge(Then,Then') else Merge(Else,Else')
+ *
+ * while ... LoopSpec ... while (G) LoopSpec' Body while (G) Merge(LoopSpec,LoopSpec') Body
+ * while ... LoopSpec Body while (G) LoopSpec' Body' while (G) Merge(LoopSpec,LoopSpec') Merge(Body,Body')
+ * while (G) LoopSpec ... while (*) LoopSpec' Body while (G) Merge(LoopSpec,LoopSpec') Body
+ * while (G) LoopSpec Body while (*) LoopSpec' Body' while (G) Merge(LoopSpec,LoopSpec') Merge(Body,Body')
+ *
+ * ...; S StmtThatDoesNotMatchS; S' StatementThatDoesNotMatchS; Merge( ...;S , S')
+ *
+ * Note, LoopSpec must contain only invariant declarations (as the parser ensures for the first three cases).
+ * Note, there is an implicit "...;" at the end of every block in a skeleton.
+ *
+ * TODO: should also handle labels and some form of new "replace" statement
+ */
+ if (cur is SkeletonStatement) {
+ var S = ((SkeletonStatement)cur).S;
+ if (S == null) {
+ if (i + 1 == skeleton.Body.Count) {
+ // this "...;" is the last statement of the skeleton, so treat it like the default case
+ } else {
+ var nxt = skeleton.Body[i+1];
+ if (nxt is SkeletonStatement && ((SkeletonStatement)nxt).S == null) {
+ // "...; ...;" is the same as just "...;", so skip this one
+ } else {
+ // skip up until the next thing that matches "nxt"
+ while (!PotentialMatch(nxt, oldS)) {
+ // loop invariant: oldS == oldStmt.Body[j]
+ body.Add(CloneStmt(oldS));
+ j++;
+ if (j == oldStmt.Body.Count) { break; }
+ oldS = oldStmt.Body[j];
+ }
+ }
+ }
+ i++;
+
+ } else if (S is AssertStmt) {
+ var skel = (AssertStmt)S;
+ Contract.Assert(((SkeletonStatement)cur).ConditionOmitted);
+ var oldAssume = oldS as PredicateStmt;
+ if (oldAssume == null) {
+ reporter.Error(cur.Tok, "assert template does not match inherited statement");
+ i++;
+ } else {
+ // Clone the expression, but among the new assert's attributes, indicate
+ // that this assertion is supposed to be translated into a check. That is,
+ // it is not allowed to be just assumed in the translation, despite the fact
+ // that the condition is inherited.
+ var e = CloneExpr(oldAssume.Expr);
+ body.Add(new AssertStmt(skel.Tok, e, new Attributes("prependAssertToken", new List<Attributes.Argument>(), null)));
+ i++; j++;
+ }
+
+ } else if (S is IfStmt) {
+ var skel = (IfStmt)S;
+ Contract.Assert(((SkeletonStatement)cur).ConditionOmitted);
+ var oldIf = oldS as IfStmt;
+ if (oldIf == null) {
+ reporter.Error(cur.Tok, "if-statement template does not match inherited statement");
+ i++;
+ } else {
+ var resultingThen = MergeBlockStmt(skel.Thn, oldIf.Thn);
+ var resultingElse = MergeElse(skel.Els, oldIf.Els);
+ var r = new IfStmt(skel.Tok, skel.Guard, resultingThen, resultingElse);
+ body.Add(r);
+ i++; j++;
+ }
+
+ } else if (S is WhileStmt) {
+ var skel = (WhileStmt)S;
+ var oldWhile = oldS as WhileStmt;
+ if (oldWhile == null) {
+ reporter.Error(cur.Tok, "while-statement template does not match inherited statement");
+ i++;
+ } else {
+ Expression guard;
+ if (((SkeletonStatement)cur).ConditionOmitted) {
+ guard = CloneExpr(oldWhile.Guard);
+ } else {
+ if (oldWhile.Guard != null) {
+ reporter.Error(skel.Guard.tok, "a skeleton while statement with a guard can only replace a while statement with a non-deterministic guard");
+ }
+ guard = skel.Guard;
+ }
+ // Note, if the loop body is omitted in the skeleton, the parser will have set the loop body to an empty block,
+ // which has the same merging behavior.
+ var r = MergeWhileStmt(skel, oldWhile, guard);
+ body.Add(r);
+ i++; j++;
+ }
+
+ } else {
+ Contract.Assume(false); // unexpected skeleton statement
+ }
+
+ } else if (cur is AssertStmt) {
+ MergeAddStatement(cur, body);
+ i++;
+
+ } else if (cur is VarDeclStmt) {
+ var cNew = (VarDeclStmt)cur;
+ var cOld = oldS as VarDeclStmt;
+ bool doMerge = false;
+ Expression addedAssert = null;
+ if (cOld != null && cNew.Lhss.Count == 1 && cOld.Lhss.Count == 1 && cNew.Lhss[0].Name == cOld.Lhss[0].Name) {
+ var update = cNew.Update as UpdateStmt;
+ if (update != null && update.Rhss.Count == 1 && update.Rhss[0] is ExprRhs) {
+ // Note, we allow switching between ghost and non-ghost, since that seems unproblematic.
+ if (cOld.Update == null) {
+ doMerge = true;
+ } else if (cOld.Update is AssignSuchThatStmt) {
+ doMerge = true;
+ addedAssert = CloneExpr(((AssignSuchThatStmt)cOld.Update).Assume.Expr);
+ } else {
+ var updateOld = (UpdateStmt)cOld.Update; // if cast fails, there are more ConcreteUpdateStatement subclasses than expected
+ if (updateOld.Rhss.Count == 1 && updateOld.Rhss[0] is HavocRhs) {
+ doMerge = true;
+ }
+ }
+ }
+ }
+ if (doMerge) {
+ // Go ahead with the merge:
+ body.Add(cNew);
+ i++; j++;
+ if (addedAssert != null) {
+ body.Add(new AssertStmt(addedAssert.tok, addedAssert));
+ }
+ } else {
+ MergeAddStatement(cur, body);
+ i++;
+ }
+
+ } else if (cur is AssignStmt) {
+ var cNew = (AssignStmt)cur;
+ var cOld = oldS as AssignStmt;
+ if (cOld == null && oldS is UpdateStmt) {
+ var us = (UpdateStmt)oldS;
+ if (us.ResolvedStatements.Count == 1) {
+ cOld = us.ResolvedStatements[0] as AssignStmt;
+ }
+ }
+ bool doMerge = false;
+ if (cOld != null && cNew.Lhs.Resolved is IdentifierExpr && cOld.Lhs.Resolved is IdentifierExpr) {
+ if (((IdentifierExpr)cNew.Lhs.Resolved).Name == ((IdentifierExpr)cOld.Lhs.Resolved).Name) {
+ if (!(cNew.Rhs is TypeRhs) && cOld.Rhs is HavocRhs) {
+ doMerge = true;
+ }
+ }
+ }
+ if (doMerge) {
+ // Go ahead with the merge:
+ body.Add(cNew);
+ i++; j++;
+ } else {
+ MergeAddStatement(cur, body);
+ i++;
+ }
+
+ } else if (cur is IfStmt) {
+ var cNew = (IfStmt)cur;
+ var cOld = oldS as IfStmt;
+ if (cOld != null && cOld.Guard == null) {
+ var r = new IfStmt(cNew.Tok, cNew.Guard, MergeBlockStmt(cNew.Thn, cOld.Thn), MergeElse(cNew.Els, cOld.Els));
+ body.Add(r);
+ i++; j++;
+ } else {
+ MergeAddStatement(cur, body);
+ i++;
+ }
+
+ } else if (cur is WhileStmt) {
+ var cNew = (WhileStmt)cur;
+ var cOld = oldS as WhileStmt;
+ if (cOld != null && cOld.Guard == null) {
+ var r = MergeWhileStmt(cNew, cOld, cNew.Guard);
+ body.Add(r);
+ i++; j++;
+ } else {
+ MergeAddStatement(cur, body);
+ i++;
+ }
+
+ } else {
+ MergeAddStatement(cur, body);
+ i++;
+ }
+ }
+ }
+ // implement the implicit "...;" at the end of each block statement skeleton
+ for (; j < oldStmt.Body.Count; j++) {
+ body.Add(CloneStmt(oldStmt.Body[j]));
+ }
+ return new BlockStmt(skeleton.Tok, body);
+ }
+
+ bool PotentialMatch(Statement nxt, Statement other) {
+ Contract.Requires(!(nxt is SkeletonStatement) || ((SkeletonStatement)nxt).S != null); // nxt is not "...;"
+ Contract.Requires(other != null);
+
+ if (nxt is SkeletonStatement) {
+ var S = ((SkeletonStatement)nxt).S;
+ if (S is AssertStmt) {
+ return other is PredicateStmt;
+ } else if (S is IfStmt) {
+ return other is IfStmt;
+ } else if (S is WhileStmt) {
+ return other is WhileStmt;
+ } else {
+ Contract.Assume(false); // unexpected skeleton
+ }
+
+ } else if (nxt is IfStmt) {
+ var oth = other as IfStmt;
+ return oth != null && oth.Guard == null;
+ } else if (nxt is WhileStmt) {
+ var oth = other as WhileStmt;
+ return oth != null && oth.Guard == null;
+ }
+
+ // not a potential match
+ return false;
+ }
+
+ WhileStmt MergeWhileStmt(WhileStmt cNew, WhileStmt cOld, Expression guard) {
+ Contract.Requires(cNew != null);
+ Contract.Requires(cOld != null);
+
+ // Note, the parser produces errors if there are any decreases or modifies clauses (and it creates
+ // the Specification structures with a null list).
+ Contract.Assume(cNew.Decreases.Expressions == null);
+ Contract.Assume(cNew.Mod.Expressions == null);
+
+ var invs = cOld.Invariants.ConvertAll(CloneMayBeFreeExpr);
+ invs.AddRange(cNew.Invariants);
+ var r = new WhileStmt(cNew.Tok, guard, invs, CloneSpecExpr(cOld.Decreases), CloneSpecFrameExpr(cOld.Mod), MergeBlockStmt(cNew.Body, cOld.Body));
+ return r;
+ }
+
+ Statement MergeElse(Statement skeleton, Statement oldStmt) {
+ Contract.Requires(skeleton == null || skeleton is BlockStmt || skeleton is IfStmt);
+ Contract.Requires(oldStmt == null || oldStmt is BlockStmt || oldStmt is IfStmt);
+
+ if (skeleton == null) {
+ return CloneStmt(oldStmt);
+ } else if (skeleton is IfStmt) {
+ // wrap a block statement around the if statement
+ skeleton = new BlockStmt(skeleton.Tok, new List<Statement>() { skeleton });
+ }
+
+ if (oldStmt == null) {
+ // make it into an empty block statement
+ oldStmt = new BlockStmt(skeleton.Tok, new List<Statement>());
+ } else if (oldStmt is IfStmt) {
+ // wrap a block statement around the if statement
+ oldStmt = new BlockStmt(oldStmt.Tok, new List<Statement>() { oldStmt });
+ }
+
+ Contract.Assert(skeleton is BlockStmt && oldStmt is BlockStmt);
+ return MergeBlockStmt((BlockStmt)skeleton, (BlockStmt)oldStmt);
+ }
+
+ /// <summary>
+ /// Add "s" to "stmtList", but complain if "s" contains further occurrences of "...", if "s" assigns to a
+ /// variable that was not declared in the refining module, or if "s" has some control flow that jumps to a
+ /// place outside "s".
+ /// </summary>
+ void MergeAddStatement(Statement s, List<Statement> stmtList) {
+ Contract.Requires(s != null);
+ Contract.Requires(stmtList != null);
+ var prevErrorCount = reporter.ErrorCount;
+ CheckIsOkayNewStatement(s, new Stack<string>(), 0);
+ if (reporter.ErrorCount == prevErrorCount) {
+ stmtList.Add(s);
+ }
+ }
+
+ /// <summary>
+ /// See comment on MergeAddStatement.
+ /// </summary>
+ void CheckIsOkayNewStatement(Statement s, Stack<string> labels, int loopLevels) {
+ Contract.Requires(s != null);
+ Contract.Requires(labels != null);
+ Contract.Requires(0 <= loopLevels);
+
+ for (LabelNode n = s.Labels; n != null; n = n.Next) {
+ labels.Push(n.Label);
+ }
+
+ if (s is SkeletonStatement) {
+ reporter.Error(s, "skeleton statement may not be used here; it does not have a matching statement in what is being replaced");
+ } else if (s is ReturnStmt) {
+ reporter.Error(s, "return statements are not allowed in skeletons");
+ } else if (s is BreakStmt) {
+ var b = (BreakStmt)s;
+ if (b.TargetLabel != null ? !labels.Contains(b.TargetLabel) : loopLevels < b.BreakCount) {
+ reporter.Error(s, "break statement in skeleton is not allowed to break outside the skeleton fragment");
+ }
+ } else if (s is AssignStmt) {
+ // TODO: To be a refinement automatically (that is, without any further verification), only variables and fields defined
+ // in this module are allowed. This needs to be checked. If the LHS refers to an l-value that was not declared within
+ // this module, then either an error should be reported or the Translator needs to know to translate new proof obligations.
+ } else {
+ if (s is WhileStmt || s is AlternativeLoopStmt) {
+ loopLevels++;
+ }
+ foreach (var ss in s.SubStatements) {
+ CheckIsOkayNewStatement(ss, labels, loopLevels);
+ }
+ }
+
+ for (LabelNode n = s.Labels; n != null; n = n.Next) {
+ labels.Pop();
+ }
+ }
+
// ---------------------- additional methods -----------------------------------------------------------------------------
public static bool ContainsChange(Expression expr, ModuleDecl m) {
diff --git a/Dafny/Resolver.cs b/Dafny/Resolver.cs index 116ca201..63048637 100644 --- a/Dafny/Resolver.cs +++ b/Dafny/Resolver.cs @@ -170,29 +170,30 @@ namespace Microsoft.Dafny { }
// register top-level declarations
+ Rewriter rewriter = new AutoContractsRewriter();
var systemNameInfo = RegisterTopLevelDecls(prog.BuiltIns.SystemModule.TopLevelDecls);
var moduleNameInfo = new ModuleNameInformation[h];
foreach (var m in mm) {
+ rewriter.PreResolve(m);
if (m.RefinementBase != null) {
var transformer = new RefinementTransformer(this);
transformer.Construct(m);
}
moduleNameInfo[m.Height] = RegisterTopLevelDecls(m.TopLevelDecls);
- }
- // resolve top-level declarations
- Graph<DatatypeDecl> datatypeDependencies = new Graph<DatatypeDecl>();
- foreach (ModuleDecl m in mm) {
// set up environment
ModuleNameInformation info = ModuleNameInformation.Merge(m, systemNameInfo, moduleNameInfo);
classes = info.Classes;
allDatatypeCtors = info.Ctors;
// resolve
+ var datatypeDependencies = new Graph<IndDatatypeDecl>();
ResolveTopLevelDecls_Signatures(m.TopLevelDecls, datatypeDependencies);
ResolveTopLevelDecls_Meat(m.TopLevelDecls, datatypeDependencies);
// tear down
classes = null;
allDatatypeCtors = null;
+ // give rewriter a chance to do processing
+ rewriter.PostResolve(m);
}
// compute IsRecursive bit for mutually recursive functions
@@ -358,9 +359,9 @@ namespace Microsoft.Dafny { return info;
}
- public void ResolveTopLevelDecls_Signatures(List<TopLevelDecl/*!*/>/*!*/ declarations, Graph<DatatypeDecl/*!*/>/*!*/ datatypeDependencies) {
+ public void ResolveTopLevelDecls_Signatures(List<TopLevelDecl/*!*/>/*!*/ declarations, Graph<IndDatatypeDecl/*!*/>/*!*/ datatypeDependencies) {
Contract.Requires(declarations != null);
- Contract.Requires(cce.NonNullElements(datatypeDependencies));
+ Contract.Requires(datatypeDependencies != null); // more expensive check: Contract.Requires(cce.NonNullElements(datatypeDependencies));
foreach (TopLevelDecl d in declarations) {
Contract.Assert(d != null);
allTypeParameters.PushMarker();
@@ -376,26 +377,28 @@ namespace Microsoft.Dafny { }
}
- public void ResolveTopLevelDecls_Meat(List<TopLevelDecl/*!*/>/*!*/ declarations, Graph<DatatypeDecl/*!*/>/*!*/ datatypeDependencies) {
+ public void ResolveTopLevelDecls_Meat(List<TopLevelDecl/*!*/>/*!*/ declarations, Graph<IndDatatypeDecl/*!*/>/*!*/ datatypeDependencies) {
Contract.Requires(declarations != null);
Contract.Requires(cce.NonNullElements(datatypeDependencies));
+
+ // Resolve the meat of classes, and the type parameters of all top-level type declarations
foreach (TopLevelDecl d in declarations) {
Contract.Assert(d != null);
allTypeParameters.PushMarker();
ResolveTypeParameters(d.TypeArgs, false, d);
- if (d is ArbitraryTypeDecl) {
- // nothing to do
- } else if (d is ClassDecl) {
+ if (d is ClassDecl) {
ResolveClassMemberBodies((ClassDecl)d);
- } else {
- DatatypeDecl dtd = (DatatypeDecl)d;
- if (datatypeDependencies.GetSCCRepresentative(dtd) == dtd) {
- // do the following check once per SCC, so call it on each SCC representative
- SccStratosphereCheck(dtd, datatypeDependencies);
- }
}
allTypeParameters.PopMarker();
}
+
+ // Perform the stratosphere check on inductive datatypes
+ foreach (var dtd in datatypeDependencies.TopologicallySortedComponents()) {
+ if (datatypeDependencies.GetSCCRepresentative(dtd) == dtd) {
+ // do the following check once per SCC, so call it on each SCC representative
+ SccStratosphereCheck(dtd, datatypeDependencies);
+ }
+ }
}
ClassDecl currentClass;
@@ -419,7 +422,7 @@ namespace Microsoft.Dafny { foreach (MemberDecl member in cl.Members) {
member.EnclosingClass = cl;
if (member is Field) {
- ResolveType(member.tok, ((Field)member).Type);
+ ResolveType(member.tok, ((Field)member).Type, null, false);
} else if (member is Function) {
Function f = (Function)member;
@@ -481,59 +484,86 @@ namespace Microsoft.Dafny { /// <summary>
/// Assumes type parameters have already been pushed
/// </summary>
- void ResolveCtorTypes(DatatypeDecl/*!*/ dt, Graph<DatatypeDecl/*!*/>/*!*/ dependencies)
+ void ResolveCtorTypes(DatatypeDecl/*!*/ dt, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies)
{
Contract.Requires(dt != null);
- Contract.Requires(cce.NonNullElements(dependencies));
+ Contract.Requires(dependencies != null); // more expensive check: Contract.Requires(cce.NonNullElements(dependencies));
foreach (DatatypeCtor ctor in dt.Ctors) {
ctor.EnclosingDatatype = dt;
allTypeParameters.PushMarker();
- ResolveCtorSignature(ctor);
+ ResolveCtorSignature(ctor, dt.TypeArgs);
allTypeParameters.PopMarker();
- foreach (Formal p in ctor.Formals) {
- DatatypeDecl dependee = p.Type.AsDatatype;
- if (dependee != null) {
- dependencies.AddEdge(dt, dependee);
+ if (dt is IndDatatypeDecl) {
+ var idt = (IndDatatypeDecl)dt;
+ dependencies.AddVertex(idt);
+ foreach (Formal p in ctor.Formals) {
+ AddDatatypeDependencyEdge(idt, p.Type, dependencies);
}
}
}
}
+ void AddDatatypeDependencyEdge(IndDatatypeDecl/*!*/ dt, Type/*!*/ tp, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies) {
+ Contract.Requires(dt != null);
+ Contract.Requires(tp != null);
+ Contract.Requires(dependencies != null); // more expensive check: Contract.Requires(cce.NonNullElements(dependencies));
+
+ var dependee = tp.AsIndDatatype;
+ if (dependee != null && dt.Module == dependee.Module) {
+ dependencies.AddEdge((IndDatatypeDecl)dt, dependee);
+ foreach (var ta in ((UserDefinedType)tp).TypeArgs) {
+ AddDatatypeDependencyEdge(dt, ta, dependencies);
+ }
+ }
+ }
+
/// <summary>
/// Check that the SCC of 'startingPoint' can be carved up into stratospheres in such a way that each
/// datatype has some value that can be constructed from datatypes in lower stratospheres only.
/// The algorithm used here is quadratic in the number of datatypes in the SCC. Since that number is
/// deemed to be rather small, this seems okay.
+ ///
+ /// As a side effect of this checking, the DefaultCtor field is filled in (for every inductive datatype
+ /// that passes the check). It may be that several constructors could be used as the default, but
+ /// only the first one encountered as recorded. This particular choice is slightly more than an
+ /// implementation detail, because it affects how certain cycles among inductive datatypes (having
+ /// to do with the types used to instantiate type parameters of datatypes) are used.
+ ///
+ /// The role of the SCC here is simply to speed up this method. It would still be correct if the
+ /// equivalence classes in the given SCC were unions of actual SCC's. In particular, this method
+ /// would still work if "dependencies" consisted of one large SCC containing all the inductive
+ /// datatypes in the module.
/// </summary>
- void SccStratosphereCheck(DatatypeDecl startingPoint, Graph<DatatypeDecl/*!*/>/*!*/ dependencies)
+ void SccStratosphereCheck(IndDatatypeDecl startingPoint, Graph<IndDatatypeDecl/*!*/>/*!*/ dependencies)
{
Contract.Requires(startingPoint != null);
- Contract.Requires(cce.NonNullElements(dependencies));
- List<DatatypeDecl> scc = dependencies.GetSCC(startingPoint);
- List<DatatypeDecl> cleared = new List<DatatypeDecl>(); // this is really a set
+ Contract.Requires(dependencies != null); // more expensive check: Contract.Requires(cce.NonNullElements(dependencies));
+
+ var scc = dependencies.GetSCC(startingPoint);
+ int totalCleared = 0;
while (true) {
int clearedThisRound = 0;
- foreach (DatatypeDecl dt in scc) {
- if (cleared.Contains(dt)) {
+ foreach (var dt in scc) {
+ if (dt.DefaultCtor != null) {
// previously cleared
- } else if (StratosphereCheck(dt, dependencies, cleared)) {
+ } else if (ComputeDefaultCtor(dt)) {
+ Contract.Assert(dt.DefaultCtor != null); // should have been set by the successful call to StratosphereCheck)
clearedThisRound++;
- cleared.Add(dt);
- // (it would be nice if the List API allowed us to remove 'dt' from 'scc' here; then we wouldn't have to check 'cleared.Contains(dt)' above and below)
+ totalCleared++;
}
}
- if (cleared.Count == scc.Count) {
+ if (totalCleared == scc.Count) {
// all is good
return;
} else if (clearedThisRound != 0) {
// some progress was made, so let's keep going
} else {
// whatever is in scc-cleared now failed to pass the test
- foreach (DatatypeDecl dt in scc) {
- if (!cleared.Contains(dt)) {
+ foreach (var dt in scc) {
+ if (dt.DefaultCtor == null) {
Error(dt, "because of cyclic dependencies among constructor argument types, no instances of datatype '{0}' can be constructed", dt.Name);
}
}
@@ -543,33 +573,29 @@ namespace Microsoft.Dafny { }
/// <summary>
- /// Check that the datatype has some constructor all whose argument types go to a lower stratum, which means
- /// go to a different SCC or to a type in 'goodOnes'.
+ /// Check that the datatype has some constructor all whose argument types can be constructed.
/// Returns 'true' and sets dt.DefaultCtor if that is the case.
/// </summary>
- bool StratosphereCheck(DatatypeDecl dt, Graph<DatatypeDecl/*!*/>/*!*/ dependencies, List<DatatypeDecl/*!*/>/*!*/ goodOnes) {
+ bool ComputeDefaultCtor(IndDatatypeDecl dt) {
Contract.Requires(dt != null);
- Contract.Requires(cce.NonNullElements(dependencies));
- Contract.Requires(cce.NonNullElements(goodOnes));
+ Contract.Requires(dt.DefaultCtor == null); // the intention is that this method be called only when DefaultCtor hasn't already been set
+ Contract.Ensures(!Contract.Result<bool>() || dt.DefaultCtor != null);
+
// Stated differently, check that there is some constuctor where no argument type goes to the same stratum.
- DatatypeDecl stratumRepresentative = dependencies.GetSCCRepresentative(dt);
foreach (DatatypeCtor ctor in dt.Ctors) {
+ var typeParametersUsed = new List<TypeParameter>();
foreach (Formal p in ctor.Formals) {
- DatatypeDecl dependee = p.Type.AsDatatype;
- if (dependee == null) {
- // the type is not a datatype, which means it's in the lowest stratum (below all datatypes)
- } else if (dependencies.GetSCCRepresentative(dependee) != stratumRepresentative) {
- // the argument type goes to a different stratum, which must be a "lower" one, so this argument is fine
- } else if (goodOnes.Contains(dependee)) {
- // the argument type is in the same SCC, but has already passed the test, so it is to be considered as
- // being in a lower stratum
- } else {
- // the argument type is in the same stratum as 'dt', so this constructor is not what we're looking for
+ if (!CheckCanBeConstructed(p.Type, typeParametersUsed)) {
+ // the argument type (has a component which) is not yet known to be constructable
goto NEXT_OUTER_ITERATION;
}
}
// this constructor satisfies the requirements, so the datatype is allowed
dt.DefaultCtor = ctor;
+ dt.TypeParametersUsedInConstructionByDefaultCtor = new bool[dt.TypeArgs.Count];
+ for (int i = 0; i < dt.TypeArgs.Count; i++) {
+ dt.TypeParametersUsedInConstructionByDefaultCtor[i] = typeParametersUsed.Contains(dt.TypeArgs[i]);
+ }
return true;
NEXT_OUTER_ITERATION: {}
}
@@ -577,6 +603,30 @@ namespace Microsoft.Dafny { return false;
}
+ bool CheckCanBeConstructed(Type tp, List<TypeParameter> typeParametersUsed) {
+ var dependee = tp.AsIndDatatype;
+ if (dependee == null) {
+ // the type is not an inductive datatype, which means it is always possible to construct it
+ if (tp.IsTypeParameter) {
+ typeParametersUsed.Add(((UserDefinedType)tp).ResolvedParam);
+ }
+ return true;
+ } else if (dependee.DefaultCtor == null) {
+ // the type is an inductive datatype that we don't yet know how to construct
+ return false;
+ }
+ // also check the type arguments of the inductive datatype
+ Contract.Assert(((UserDefinedType)tp).TypeArgs.Count == dependee.TypeParametersUsedInConstructionByDefaultCtor.Length);
+ var i = 0;
+ foreach (var ta in ((UserDefinedType)tp).TypeArgs) { // note, "tp" is known to be a UserDefinedType, because that follows from tp being an inductive datatype
+ if (dependee.TypeParametersUsedInConstructionByDefaultCtor[i] && !CheckCanBeConstructed(ta, typeParametersUsed)) {
+ return false;
+ }
+ i++;
+ }
+ return true;
+ }
+
void ResolveAttributes(Attributes attrs, bool twoState) {
// order does not matter much for resolution, so resolve them in reverse order
for (; attrs != null; attrs = attrs.Prev) {
@@ -623,13 +673,17 @@ namespace Microsoft.Dafny { void ResolveFunctionSignature(Function f) {
Contract.Requires(f != null);
scope.PushMarker();
+ if (f.SignatureIsOmitted) {
+ Error(f, "function signature can be omitted only in refining functions");
+ }
+ var defaultTypeArguments = f.TypeArgs.Count == 0 ? f.TypeArgs : null;
foreach (Formal p in f.Formals) {
if (!scope.Push(p.Name, p)) {
Error(p, "Duplicate parameter name: {0}", p.Name);
}
- ResolveType(p.tok, p.Type);
+ ResolveType(p.tok, p.Type, defaultTypeArguments, true);
}
- ResolveType(f.tok, f.ResultType);
+ ResolveType(f.tok, f.ResultType, defaultTypeArguments, true);
scope.PopMarker();
}
@@ -673,7 +727,7 @@ namespace Microsoft.Dafny { }
if (f.Body != null) {
List<IVariable> matchVarContext = new List<IVariable>(f.Formals);
- ResolveExpression(f.Body, false, matchVarContext);
+ ResolveExpression(f.Body, false, matchVarContext, null);
if (!f.IsGhost) {
CheckIsNonGhost(f.Body);
}
@@ -726,19 +780,23 @@ namespace Microsoft.Dafny { void ResolveMethodSignature(Method m) {
Contract.Requires(m != null);
scope.PushMarker();
+ if (m.SignatureIsOmitted) {
+ Error(m, "method signature can be omitted only in refining methods");
+ }
+ var defaultTypeArguments = m.TypeArgs.Count == 0 ? m.TypeArgs : null;
// resolve in-parameters
foreach (Formal p in m.Ins) {
if (!scope.Push(p.Name, p)) {
Error(p, "Duplicate parameter name: {0}", p.Name);
}
- ResolveType(p.tok, p.Type);
+ ResolveType(p.tok, p.Type, defaultTypeArguments, true);
}
// resolve out-parameters
foreach (Formal p in m.Outs) {
if (!scope.Push(p.Name, p)) {
Error(p, "Duplicate parameter name: {0}", p.Name);
}
- ResolveType(p.tok, p.Type);
+ ResolveType(p.tok, p.Type, defaultTypeArguments, true);
}
scope.PopMarker();
}
@@ -806,28 +864,40 @@ namespace Microsoft.Dafny { scope.PopMarker(); // for the in-parameters
}
- void ResolveCtorSignature(DatatypeCtor ctor) {
+ void ResolveCtorSignature(DatatypeCtor ctor, List<TypeParameter> dtTypeArguments) {
Contract.Requires(ctor != null);
+ Contract.Requires(dtTypeArguments != null);
foreach (Formal p in ctor.Formals) {
- ResolveType(p.tok, p.Type);
+ ResolveType(p.tok, p.Type, dtTypeArguments, false);
}
}
- public void ResolveType(IToken tok, Type type) {
+ /// <summary>
+ /// If ResolveType encounters a type "T" that takes type arguments but wasn't given any, then:
+ /// * If "defaultTypeArguments" is non-null and "defaultTypeArgument.Count" equals the number
+ /// of type arguments that "T" expects, then use these default type arguments as "T"'s arguments.
+ /// * If "allowAutoTypeArguments" is true, then infer "T"'s arguments.
+ /// * If "defaultTypeArguments" is non-null AND "allowAutoTypeArguments" is true, then enough
+ /// type parameters will be added to "defaultTypeArguments" to have at least as many type
+ /// parameters as "T" expects, and then a prefix of the "defaultTypeArguments" will be supplied
+ /// as arguments to "T".
+ /// </summary>
+ public void ResolveType(IToken tok, Type type, List<TypeParameter> defaultTypeArguments, bool allowAutoTypeArguments) {
+ Contract.Requires(tok != null);
Contract.Requires(type != null);
if (type is BasicType) {
// nothing to resolve
} else if (type is CollectionType) {
var t = (CollectionType)type;
var argType = t.Arg;
- ResolveType(tok, argType);
+ ResolveType(tok, argType, defaultTypeArguments, allowAutoTypeArguments);
if (argType.IsSubrangeType) {
Error(tok, "sorry, cannot instantiate collection type with a subrange type");
}
} else if (type is UserDefinedType) {
UserDefinedType t = (UserDefinedType)type;
foreach (Type tt in t.TypeArgs) {
- ResolveType(t.tok, tt);
+ ResolveType(t.tok, tt, defaultTypeArguments, allowAutoTypeArguments);
if (tt.IsSubrangeType) {
Error(t.tok, "sorry, cannot instantiate type parameter with a subrange type");
}
@@ -845,19 +915,47 @@ namespace Microsoft.Dafny { Error(t.tok, "Undeclared top-level type or type parameter: {0} (did you forget a module import?)", t.Name);
} else if (d is AmbiguousTopLevelDecl) {
Error(t.tok, "The name {0} ambiguously refers to a type in one of the modules {1}", t.Name, ((AmbiguousTopLevelDecl)d).ModuleNames());
- } else if (d.TypeArgs.Count != t.TypeArgs.Count) {
- Error(t.tok, "Wrong number of type arguments ({0} instead of {1}) passed to class/datatype: {2}", t.TypeArgs.Count, d.TypeArgs.Count, t.Name);
} else if (d is ArbitraryTypeDecl) {
- t.ResolvedParam = ((ArbitraryTypeDecl)d).TheType; // resolve as type parameter
+ t.ResolvedParam = ((ArbitraryTypeDecl)d).TheType; // resolve like a type parameter
} else {
+ // d is a class or datatype, and it may have type parameters
t.ResolvedClass = d;
+ if (d.TypeArgs.Count != t.TypeArgs.Count && t.TypeArgs.Count == 0) {
+ if (allowAutoTypeArguments && defaultTypeArguments == null) {
+ // add type arguments that will be inferred
+ for (int i = 0; i < d.TypeArgs.Count; i++) {
+ t.TypeArgs.Add(new InferredTypeProxy());
+ }
+ } else if (defaultTypeArguments != null) {
+ // add specific type arguments, drawn from defaultTypeArguments (which may have to be extended)
+ if (allowAutoTypeArguments) {
+ // add to defaultTypeArguments the necessary number of arguments
+ for (int i = defaultTypeArguments.Count; i < d.TypeArgs.Count; i++) {
+ defaultTypeArguments.Add(new TypeParameter(t.tok, "_T" + i));
+ }
+ }
+ if (allowAutoTypeArguments || d.TypeArgs.Count == defaultTypeArguments.Count) {
+ Contract.Assert(d.TypeArgs.Count <= defaultTypeArguments.Count);
+ // automatically supply a prefix of the arguments from defaultTypeArguments
+ for (int i = 0; i < d.TypeArgs.Count; i++) {
+ var typeArg = new UserDefinedType(t.tok, defaultTypeArguments[i].Name, new List<Type>());
+ typeArg.ResolvedParam = defaultTypeArguments[i]; // resolve "typeArg" here
+ t.TypeArgs.Add(typeArg);
+ }
+ }
+ }
+ }
+ // defaults and auto have been applied; check if we now have the right number of arguments
+ if (d.TypeArgs.Count != t.TypeArgs.Count) {
+ Error(t.tok, "Wrong number of type arguments ({0} instead of {1}) passed to class/datatype: {2}", t.TypeArgs.Count, d.TypeArgs.Count, t.Name);
+ }
}
}
} else if (type is TypeProxy) {
TypeProxy t = (TypeProxy)type;
if (t.T != null) {
- ResolveType(tok, t.T);
+ ResolveType(tok, t.T, defaultTypeArguments, allowAutoTypeArguments);
}
} else {
@@ -1256,8 +1354,8 @@ namespace Microsoft.Dafny { else {// this is a regular return statement.
s.hiddenUpdate = null;
}
- } else if (stmt is UpdateStmt) {
- ResolveUpdateStmt((UpdateStmt)stmt, specContextOnly, method);
+ } else if (stmt is ConcreteUpdateStatement) {
+ ResolveUpdateStmt((ConcreteUpdateStatement)stmt, specContextOnly, method);
} else if (stmt is VarDeclStmt) {
var s = (VarDeclStmt)stmt;
foreach (var vd in s.Lhss) {
@@ -1382,7 +1480,7 @@ namespace Microsoft.Dafny { } else if (stmt is VarDecl) {
VarDecl s = (VarDecl)stmt;
if (s.OptionalType != null) {
- ResolveType(stmt.Tok, s.OptionalType);
+ ResolveType(stmt.Tok, s.OptionalType, null, true);
s.type = s.OptionalType;
}
// now that the declaration has been processed, add the name to the scope
@@ -1506,7 +1604,7 @@ namespace Microsoft.Dafny { if (!scope.Push(v.Name, v)) {
Error(v, "Duplicate bound-variable name: {0}", v.Name);
}
- ResolveType(v.tok, v.Type);
+ ResolveType(v.tok, v.Type, null, true);
}
ResolveExpression(s.Range, true);
Contract.Assert(s.Range.Type != null); // follows from postcondition of ResolveExpression
@@ -1631,7 +1729,7 @@ namespace Microsoft.Dafny { if (!scope.Push(v.Name, v)) {
Error(v, "Duplicate parameter name: {0}", v.Name);
}
- ResolveType(v.tok, v.Type);
+ ResolveType(v.tok, v.Type, null, true);
if (ctor != null && i < ctor.Formals.Count) {
Formal formal = ctor.Formals[i];
Type st = SubstType(formal.Type, subst);
@@ -1661,12 +1759,19 @@ namespace Microsoft.Dafny { }
+ } else if (stmt is SkeletonStatement) {
+ var s = (SkeletonStatement)stmt;
+ Error(s.Tok, "skeleton statements are allowed only in refining methods");
+ // nevertheless, resolve the underlying statement; hey, why not
+ if (s.S != null) {
+ ResolveStatement(s.S, specContextOnly, method);
+ }
} else {
Contract.Assert(false); throw new cce.UnreachableException();
}
}
- private void ResolveUpdateStmt(UpdateStmt s, bool specContextOnly, Method method)
+ private void ResolveUpdateStmt(ConcreteUpdateStatement s, bool specContextOnly, Method method)
{
int prevErrorCount = ErrorCount;
// First, resolve all LHS's and expression-looking RHS's.
@@ -1678,39 +1783,44 @@ namespace Microsoft.Dafny { if (arrayRangeLhs == null && !sse.SelectOne) {
arrayRangeLhs = sse;
}
- }
- else {
+ } else {
ResolveExpression(lhs, true);
}
}
IToken firstEffectfulRhs = null;
CallRhs callRhs = null;
+ var update = s as UpdateStmt;
// Resolve RHSs
- foreach (var rhs in s.Rhss) {
- bool isEffectful;
- if (rhs is TypeRhs) {
- var tr = (TypeRhs)rhs;
- ResolveTypeRhs(tr, s, specContextOnly, method);
- isEffectful = tr.InitCall != null;
- } else if (rhs is HavocRhs) {
- isEffectful = false;
- } else {
- var er = (ExprRhs)rhs;
- if (er.Expr is IdentifierSequence) {
- var cRhs = ResolveIdentifierSequence((IdentifierSequence)er.Expr, true, true);
- isEffectful = cRhs != null;
- callRhs = callRhs ?? cRhs;
- } else if (er.Expr is FunctionCallExpr) {
- var cRhs = ResolveFunctionCallExpr((FunctionCallExpr)er.Expr, true, true);
- isEffectful = cRhs != null;
- callRhs = callRhs ?? cRhs;
- } else {
- ResolveExpression(er.Expr, true);
+ if (update == null) {
+ var suchThat = (AssignSuchThatStmt)s; // this is the other possible subclass
+ s.ResolvedStatements.Add(suchThat.Assume);
+ } else {
+ foreach (var rhs in update.Rhss) {
+ bool isEffectful;
+ if (rhs is TypeRhs) {
+ var tr = (TypeRhs)rhs;
+ ResolveTypeRhs(tr, s, specContextOnly, method);
+ isEffectful = tr.InitCall != null;
+ } else if (rhs is HavocRhs) {
isEffectful = false;
+ } else {
+ var er = (ExprRhs)rhs;
+ if (er.Expr is IdentifierSequence) {
+ var cRhs = ResolveIdentifierSequence((IdentifierSequence)er.Expr, true, true, null);
+ isEffectful = cRhs != null;
+ callRhs = callRhs ?? cRhs;
+ } else if (er.Expr is FunctionCallExpr) {
+ var cRhs = ResolveFunctionCallExpr((FunctionCallExpr)er.Expr, true, true, null);
+ isEffectful = cRhs != null;
+ callRhs = callRhs ?? cRhs;
+ } else {
+ ResolveExpression(er.Expr, true);
+ isEffectful = false;
+ }
+ }
+ if (isEffectful && firstEffectfulRhs == null) {
+ firstEffectfulRhs = rhs.Tok;
}
- }
- if (isEffectful && firstEffectfulRhs == null) {
- firstEffectfulRhs = rhs.Tok;
}
}
// check for duplicate identifiers on the left (full duplication checking for references and the like is done during verification)
@@ -1726,67 +1836,69 @@ namespace Microsoft.Dafny { }
}
- // figure out what kind of UpdateStmt this is
- if (firstEffectfulRhs == null) {
- if (s.Lhss.Count == 0) {
- Contract.Assert(s.Rhss.Count == 1); // guaranteed by the parser
- Error(s, "expected method call, found expression");
- } else if (s.Lhss.Count != s.Rhss.Count) {
- Error(s, "the number of left-hand sides ({0}) and right-hand sides ({1}) must match for a multi-assignment", s.Lhss.Count, s.Rhss.Count);
- } else if (arrayRangeLhs != null && s.Lhss.Count != 1) {
- Error(arrayRangeLhs, "array-range may not be used as LHS of multi-assignment; use separate assignment statements for each array-range assignment");
- } else if (ErrorCount == prevErrorCount) {
- // add the statements here in a sequence, but don't use that sequence later for translation (instead, should translated properly as multi-assignment)
- for (int i = 0; i < s.Lhss.Count; i++) {
- var a = new AssignStmt(s.Tok, s.Lhss[i].Resolved, s.Rhss[i]);
- s.ResolvedStatements.Add(a);
- }
- }
-
- } else if (s.CanMutateKnownState) {
- if (1 < s.Rhss.Count) {
- Error(firstEffectfulRhs, "cannot have effectful parameter in multi-return statement.");
- } else { // it might be ok, if it is a TypeRhs
- Contract.Assert(s.Rhss.Count == 1);
- if (callRhs != null) {
- Error(callRhs.Tok, "cannot have method call in return statement.");
- } else {
- // we have a TypeRhs
- Contract.Assert(s.Rhss[0] is TypeRhs);
- var tr = (TypeRhs)s.Rhss[0];
- Contract.Assert(tr.InitCall != null); // there were effects, so this must have been a call.
- if (tr.CanAffectPreviouslyKnownExpressions) {
- Error(tr.Tok, "can only have initialization methods which modify at most 'this'.");
+ if (update != null) {
+ // figure out what kind of UpdateStmt this is
+ if (firstEffectfulRhs == null) {
+ if (s.Lhss.Count == 0) {
+ Contract.Assert(update.Rhss.Count == 1); // guaranteed by the parser
+ Error(s, "expected method call, found expression");
+ } else if (s.Lhss.Count != update.Rhss.Count) {
+ Error(s, "the number of left-hand sides ({0}) and right-hand sides ({1}) must match for a multi-assignment", s.Lhss.Count, update.Rhss.Count);
+ } else if (arrayRangeLhs != null && s.Lhss.Count != 1) {
+ Error(arrayRangeLhs, "array-range may not be used as LHS of multi-assignment; use separate assignment statements for each array-range assignment");
+ } else if (ErrorCount == prevErrorCount) {
+ // add the statements here in a sequence, but don't use that sequence later for translation (instead, should translated properly as multi-assignment)
+ for (int i = 0; i < s.Lhss.Count; i++) {
+ var a = new AssignStmt(s.Tok, s.Lhss[i].Resolved, update.Rhss[i]);
+ s.ResolvedStatements.Add(a);
}
- var a = new AssignStmt(s.Tok, s.Lhss[0].Resolved, tr);
- s.ResolvedStatements.Add(a);
}
- }
- } else {
- // if there was an effectful RHS, that must be the only RHS
- if (s.Rhss.Count != 1) {
- Error(firstEffectfulRhs, "an update statement is allowed an effectful RHS only if there is just one RHS");
- } else if (arrayRangeLhs != null) {
- Error(arrayRangeLhs, "Assignment to range of array elements must have a simple expression RHS; try using a temporary local variable");
- } else if (callRhs == null) {
- // must be a single TypeRhs
- if (s.Lhss.Count != 1) {
- Contract.Assert(2 <= s.Lhss.Count); // the parser allows 0 Lhss only if the whole statement looks like an expression (not a TypeRhs)
- Error(s.Lhss[1].tok, "the number of left-hand sides ({0}) and right-hand sides ({1}) must match for a multi-assignment", s.Lhss.Count, s.Rhss.Count);
- } else if (ErrorCount == prevErrorCount) {
- var a = new AssignStmt(s.Tok, s.Lhss[0].Resolved, s.Rhss[0]);
- s.ResolvedStatements.Add(a);
+ } else if (update.CanMutateKnownState) {
+ if (1 < update.Rhss.Count) {
+ Error(firstEffectfulRhs, "cannot have effectful parameter in multi-return statement.");
+ } else { // it might be ok, if it is a TypeRhs
+ Contract.Assert(update.Rhss.Count == 1);
+ if (callRhs != null) {
+ Error(callRhs.Tok, "cannot have method call in return statement.");
+ } else {
+ // we have a TypeRhs
+ Contract.Assert(update.Rhss[0] is TypeRhs);
+ var tr = (TypeRhs)update.Rhss[0];
+ Contract.Assert(tr.InitCall != null); // there were effects, so this must have been a call.
+ if (tr.CanAffectPreviouslyKnownExpressions) {
+ Error(tr.Tok, "can only have initialization methods which modify at most 'this'.");
+ }
+ var a = new AssignStmt(s.Tok, s.Lhss[0].Resolved, tr);
+ s.ResolvedStatements.Add(a);
+ }
}
+
} else {
- // a call statement
- if (ErrorCount == prevErrorCount) {
- var resolvedLhss = new List<Expression>();
- foreach (var ll in s.Lhss) {
- resolvedLhss.Add(ll.Resolved);
+ // if there was an effectful RHS, that must be the only RHS
+ if (update.Rhss.Count != 1) {
+ Error(firstEffectfulRhs, "an update statement is allowed an effectful RHS only if there is just one RHS");
+ } else if (arrayRangeLhs != null) {
+ Error(arrayRangeLhs, "Assignment to range of array elements must have a simple expression RHS; try using a temporary local variable");
+ } else if (callRhs == null) {
+ // must be a single TypeRhs
+ if (s.Lhss.Count != 1) {
+ Contract.Assert(2 <= s.Lhss.Count); // the parser allows 0 Lhss only if the whole statement looks like an expression (not a TypeRhs)
+ Error(s.Lhss[1].tok, "the number of left-hand sides ({0}) and right-hand sides ({1}) must match for a multi-assignment", s.Lhss.Count, update.Rhss.Count);
+ } else if (ErrorCount == prevErrorCount) {
+ var a = new AssignStmt(s.Tok, s.Lhss[0].Resolved, update.Rhss[0]);
+ s.ResolvedStatements.Add(a);
+ }
+ } else {
+ // a call statement
+ if (ErrorCount == prevErrorCount) {
+ var resolvedLhss = new List<Expression>();
+ foreach (var ll in s.Lhss) {
+ resolvedLhss.Add(ll.Resolved);
+ }
+ var a = new CallStmt(callRhs.Tok, resolvedLhss, callRhs.Receiver, callRhs.MethodName, callRhs.Args);
+ s.ResolvedStatements.Add(a);
}
- var a = new CallStmt(callRhs.Tok, resolvedLhss, callRhs.Receiver, callRhs.MethodName, callRhs.Args);
- s.ResolvedStatements.Add(a);
}
}
}
@@ -2031,6 +2143,11 @@ namespace Microsoft.Dafny { // this case is checked already in the first pass through the parallel body, by doing so from an empty set of labeled statements and resetting the loop-stack
} else if (stmt is ReturnStmt) {
Error(stmt, "return statement is not allowed inside a parallel statement");
+ } else if (stmt is AssignSuchThatStmt) {
+ var s = (AssignSuchThatStmt)stmt;
+ foreach (var lhs in s.Lhss) {
+ CheckParallelBodyLhs(s.Tok, lhs.Resolved, kind);
+ }
} else if (stmt is ConcreteSyntaxStatement) {
var s = (ConcreteSyntaxStatement)stmt;
foreach (var ss in s.ResolvedStatements) {
@@ -2038,14 +2155,7 @@ namespace Microsoft.Dafny { }
} else if (stmt is AssignStmt) {
var s = (AssignStmt)stmt;
- var idExpr = s.Lhs.Resolved as IdentifierExpr;
- if (idExpr != null) {
- if (scope.ContainsDecl(idExpr.Var)) {
- Error(stmt, "body of parallel statement is attempting to update a variable declared outside the parallel statement");
- }
- } else if (kind != ParallelStmt.ParBodyKind.Assign) {
- Error(stmt, "the body of the enclosing parallel statement is not allowed to update heap locations");
- }
+ CheckParallelBodyLhs(s.Tok, s.Lhs.Resolved, kind);
var rhs = s.Rhs; // ExprRhs and HavocRhs are fine, but TypeRhs is not
if (rhs is TypeRhs) {
if (kind == ParallelStmt.ParBodyKind.Assign) {
@@ -2148,6 +2258,17 @@ namespace Microsoft.Dafny { }
}
+ void CheckParallelBodyLhs(IToken tok, Expression lhs, ParallelStmt.ParBodyKind kind) {
+ var idExpr = lhs as IdentifierExpr;
+ if (idExpr != null) {
+ if (scope.ContainsDecl(idExpr.Var)) {
+ Error(tok, "body of parallel statement is attempting to update a variable declared outside the parallel statement");
+ }
+ } else if (kind != ParallelStmt.ParBodyKind.Assign) {
+ Error(tok, "the body of the enclosing parallel statement is not allowed to update heap locations");
+ }
+ }
+
Type ResolveTypeRhs(TypeRhs rr, Statement stmt, bool specContextOnly, Method method) {
Contract.Requires(rr != null);
Contract.Requires(stmt != null);
@@ -2155,7 +2276,7 @@ namespace Microsoft.Dafny { Contract.Ensures(Contract.Result<Type>() != null);
if (rr.Type == null) {
- ResolveType(stmt.Tok, rr.EType);
+ ResolveType(stmt.Tok, rr.EType, null, true);
if (rr.ArrayDimensions == null) {
if (!rr.EType.IsRefType) {
Error(stmt, "new can be applied only to reference types (got {0})", rr.EType);
@@ -2338,14 +2459,14 @@ namespace Microsoft.Dafny { /// "twoState" implies that "old" and "fresh" expressions are allowed
/// </summary>
void ResolveExpression(Expression expr, bool twoState) {
- ResolveExpression(expr, twoState, null);
+ ResolveExpression(expr, twoState, null, null);
}
/// <summary>
/// "matchVarContext" says which variables are allowed to be used as the source expression in a "match" expression;
/// if null, no "match" expression will be allowed.
/// </summary>
- void ResolveExpression(Expression expr, bool twoState, List<IVariable> matchVarContext) {
+ void ResolveExpression(Expression expr, bool twoState, List<IVariable> matchVarContext, DatatypeValue coContext) {
Contract.Requires(expr != null);
Contract.Requires(currentClass != null);
Contract.Ensures(expr.Type != null);
@@ -2361,7 +2482,7 @@ namespace Microsoft.Dafny { if (expr is ParensExpression) {
var e = (ParensExpression)expr;
- ResolveExpression(e.E, twoState, matchVarContext); // allow "match" expressions inside e.E if the parenthetic expression had been allowed to be a "match" expression
+ ResolveExpression(e.E, twoState, matchVarContext, coContext); // allow "match" expressions inside e.E if the parenthetic expression had been allowed to be a "match" expression
e.ResolvedExpression = e.E;
e.Type = e.E.Type;
@@ -2373,7 +2494,7 @@ namespace Microsoft.Dafny { } else if (expr is IdentifierSequence) {
var e = (IdentifierSequence)expr;
- ResolveIdentifierSequence(e, twoState, false);
+ ResolveIdentifierSequence(e, twoState, false, coContext);
} else if (expr is LiteralExpr) {
LiteralExpr e = (LiteralExpr)expr;
@@ -2423,7 +2544,7 @@ namespace Microsoft.Dafny { subst.Add(dt.TypeArgs[i], t);
}
expr.Type = new UserDefinedType(dtv.tok, dtv.DatatypeName, gt);
- ResolveType(expr.tok, expr.Type);
+ ResolveType(expr.tok, expr.Type, null, true);
DatatypeCtor ctor;
if (!datatypeCtors[dt].TryGetValue(dtv.MemberName, out ctor)) {
@@ -2438,7 +2559,7 @@ namespace Microsoft.Dafny { int j = 0;
foreach (Expression arg in dtv.Arguments) {
Formal formal = ctor != null && j < ctor.Formals.Count ? ctor.Formals[j] : null;
- ResolveExpression(arg, twoState);
+ ResolveExpression(arg, twoState, null, ctor != null && ctor.EnclosingDatatype is CoDatatypeDecl ? dtv : null);
Contract.Assert(arg.Type != null); // follows from postcondition of ResolveExpression
if (formal != null) {
Type st = SubstType(formal.Type, subst);
@@ -2560,14 +2681,14 @@ namespace Microsoft.Dafny { } else if (expr is FunctionCallExpr) {
FunctionCallExpr e = (FunctionCallExpr)expr;
- ResolveFunctionCallExpr(e, twoState, false);
+ ResolveFunctionCallExpr(e, twoState, false, coContext);
} else if (expr is OldExpr) {
OldExpr e = (OldExpr)expr;
if (!twoState) {
Error(expr, "old expressions are not allowed in this context");
}
- ResolveExpression(e.E, twoState);
+ ResolveExpression(e.E, twoState, null, coContext);
expr.Type = e.E.Type;
} else if (expr is MultiSetFormingExpr) {
@@ -2771,7 +2892,7 @@ namespace Microsoft.Dafny { if (!scope.Push(v.Name, v)) {
Error(v, "Duplicate let-variable name: {0}", v.Name);
}
- ResolveType(v.tok, v.Type);
+ ResolveType(v.tok, v.Type, null, true);
if (i < e.RHSs.Count && !UnifyTypes(v.Type, e.RHSs[i].Type)) {
Error(e.RHSs[i].tok, "type of RHS ({0}) does not match type of bound variable ({1})", e.RHSs[i].Type, v.Type);
}
@@ -2789,7 +2910,7 @@ namespace Microsoft.Dafny { if (!scope.Push(v.Name, v)) {
Error(v, "Duplicate bound-variable name: {0}", v.Name);
}
- ResolveType(v.tok, v.Type);
+ ResolveType(v.tok, v.Type, null, true);
}
if (e.Range != null) {
ResolveExpression(e.Range, twoState);
@@ -2813,7 +2934,21 @@ namespace Microsoft.Dafny { var missingBounds = new List<BoundVar>();
e.Bounds = DiscoverBounds(e.tok, e.BoundVars, e.LogicalBody(), e is ExistsExpr, missingBounds);
if (missingBounds.Count != 0) {
- e.MissingBounds = missingBounds;
+ // Report errors here about quantifications that depend on the allocation state.
+ var mb = missingBounds;
+ if (currentFunction != null) {
+ mb = new List<BoundVar>(); // (who cares if we allocate another array; this happens only in the case of a resolution error anyhow)
+ foreach (var bv in missingBounds) {
+ if (bv.Type.IsRefType) {
+ Error(expr, "a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of '{0}'", bv.Name);
+ } else {
+ mb.Add(bv);
+ }
+ }
+ }
+ if (mb.Count != 0) {
+ e.MissingBounds = mb;
+ }
}
}
@@ -2825,7 +2960,7 @@ namespace Microsoft.Dafny { if (!scope.Push(v.Name, v)) {
Error(v, "Duplicate bound-variable name: {0}", v.Name);
}
- ResolveType(v.tok, v.Type);
+ ResolveType(v.tok, v.Type, null, true);
}
ResolveExpression(e.Range, twoState);
Contract.Assert(e.Range.Type != null); // follows from postcondition of ResolveExpression
@@ -2949,7 +3084,7 @@ namespace Microsoft.Dafny { if (!scope.Push(v.Name, v)) {
Error(v, "Duplicate parameter name: {0}", v.Name);
}
- ResolveType(v.tok, v.Type);
+ ResolveType(v.tok, v.Type, null, true);
if (ctor != null && i < ctor.Formals.Count) {
Formal formal = ctor.Formals[i];
Type st = SubstType(formal.Type, subst);
@@ -2965,7 +3100,7 @@ namespace Microsoft.Dafny { innerMatchVarContext.Remove(goodMatchVariable); // this variable is no longer available for matching
}
innerMatchVarContext.AddRange(mc.Arguments);
- ResolveExpression(mc.Body, twoState, innerMatchVarContext);
+ ResolveExpression(mc.Body, twoState, innerMatchVarContext, null);
Contract.Assert(mc.Body.Type != null); // follows from postcondition of ResolveExpression
if (!UnifyTypes(expr.Type, mc.Body.Type)) {
Error(mc.Body.tok, "type of case bodies do not agree (found {0}, previous types {1})", mc.Body.Type, expr.Type);
@@ -3093,8 +3228,9 @@ namespace Microsoft.Dafny { /// If "!allowMethodCall" or if what is being called does not refer to a method, resolves "e" and returns "null".
/// Otherwise (that is, if "allowMethodCall" and what is being called refers to a method), resolves the receiver
/// of "e" but NOT the arguments, and returns a CallRhs corresponding to the call.
+ /// "coContext" is to be non-null if this function call is a direct argument to a co-constructor.
/// </summary>
- CallRhs ResolveFunctionCallExpr(FunctionCallExpr e, bool twoState, bool allowMethodCall) {
+ CallRhs ResolveFunctionCallExpr(FunctionCallExpr e, bool twoState, bool allowMethodCall, DatatypeValue coContext) {
ResolveReceiver(e.Receiver, twoState);
Contract.Assert(e.Receiver.Type != null); // follows from postcondition of ResolveExpression
NonProxyType nptype;
@@ -3159,17 +3295,25 @@ namespace Microsoft.Dafny { }
// Resolution termination check
- if (currentFunction != null && currentFunction.EnclosingClass != null && function.EnclosingClass != null) {
- ModuleDecl callerModule = currentFunction.EnclosingClass.Module;
- ModuleDecl calleeModule = function.EnclosingClass.Module;
- if (callerModule == calleeModule) {
- // intra-module call; this is allowed; add edge in module's call graph
- callerModule.CallGraph.AddEdge(currentFunction, function);
- if (currentFunction == function) {
- currentFunction.IsRecursive = true; // self recursion (mutual recursion is determined elsewhere)
+ if (coContext != null && function.Reads.Count == 0) {
+ e.CoCall = FunctionCallExpr.CoCallResolution.Yes;
+ coContext.IsCoCall = true;
+ } else {
+ if (coContext != null) {
+ e.CoCall = FunctionCallExpr.CoCallResolution.NoBecauseFunctionHasSideEffects;
+ }
+ if (currentFunction != null && currentFunction.EnclosingClass != null && function.EnclosingClass != null) {
+ ModuleDecl callerModule = currentFunction.EnclosingClass.Module;
+ ModuleDecl calleeModule = function.EnclosingClass.Module;
+ if (callerModule == calleeModule) {
+ // intra-module call; this is allowed; add edge in module's call graph
+ callerModule.CallGraph.AddEdge(currentFunction, function);
+ if (currentFunction == function) {
+ currentFunction.IsRecursive = true; // self recursion (mutual recursion is determined elsewhere)
+ }
+ } else {
+ Contract.Assert(importGraph.Reaches(callerModule, calleeModule));
}
- } else {
- Contract.Assert(importGraph.Reaches(callerModule, calleeModule));
}
}
}
@@ -3180,7 +3324,7 @@ namespace Microsoft.Dafny { /// If "!allowMethodCall", or if "e" does not designate a method call, resolves "e" and returns "null".
/// Otherwise, resolves all sub-parts of "e" and returns a (resolved) CallRhs expression representing the call.
/// </summary>
- CallRhs ResolveIdentifierSequence(IdentifierSequence e, bool twoState, bool allowMethodCall) {
+ CallRhs ResolveIdentifierSequence(IdentifierSequence e, bool twoState, bool allowMethodCall, DatatypeValue coContext) {
// Look up "id" as follows:
// - local variable, parameter, or bound variable (if this clashes with something of interest, one can always rename the local variable locally)
// - unamibugous type name (class or datatype or arbitrary-type) (if two imported types have the same name, an error message is produced here)
@@ -3200,7 +3344,7 @@ namespace Microsoft.Dafny { // ----- root is a local variable, parameter, or bound variable
r = new IdentifierExpr(id, id.val);
ResolveExpression(r, twoState);
- r = ResolveSuffix(r, e, 1, twoState, allowMethodCall, out call);
+ r = ResolveSuffix(r, e, 1, twoState, allowMethodCall, coContext, out call);
} else if (classes.TryGetValue(id.val, out decl)) {
if (decl is AmbiguousTopLevelDecl) {
@@ -3216,7 +3360,7 @@ namespace Microsoft.Dafny { } else if (decl is ClassDecl) {
// ----- root is a class
var cd = (ClassDecl)decl;
- r = ResolveSuffix(new StaticReceiverExpr(id, cd), e, 1, twoState, allowMethodCall, out call);
+ r = ResolveSuffix(new StaticReceiverExpr(id, cd), e, 1, twoState, allowMethodCall, coContext, out call);
} else {
// ----- root is a datatype
@@ -3225,7 +3369,7 @@ namespace Microsoft.Dafny { r = new DatatypeValue(id, id.val, e.Tokens[1].val, args);
ResolveExpression(r, twoState);
if (e.Tokens.Count != 2) {
- r = ResolveSuffix(r, e, 2, twoState, allowMethodCall, out call);
+ r = ResolveSuffix(r, e, 2, twoState, allowMethodCall, coContext, out call);
}
}
@@ -3239,7 +3383,7 @@ namespace Microsoft.Dafny { r = new DatatypeValue(id, pair.Item1.EnclosingDatatype.Name, id.val, args);
ResolveExpression(r, twoState);
if (e.Tokens.Count != 1) {
- r = ResolveSuffix(r, e, 1, twoState, allowMethodCall, out call);
+ r = ResolveSuffix(r, e, 1, twoState, allowMethodCall, coContext, out call);
}
}
@@ -3256,7 +3400,7 @@ namespace Microsoft.Dafny { receiver = new ImplicitThisExpr(id);
receiver.Type = GetThisType(id, currentClass); // resolve here
}
- r = ResolveSuffix(receiver, e, 0, twoState, allowMethodCall, out call);
+ r = ResolveSuffix(receiver, e, 0, twoState, allowMethodCall, coContext, out call);
} else {
Error(id, "unresolved identifier: {0}", id.val);
@@ -3282,7 +3426,7 @@ namespace Microsoft.Dafny { /// Except, if "allowMethodCall" is "true" and the would-be-returned value designates a method
/// call, instead returns null and returns "call" as a non-null value.
/// </summary>
- Expression ResolveSuffix(Expression r, IdentifierSequence e, int p, bool twoState, bool allowMethodCall, out CallRhs call) {
+ Expression ResolveSuffix(Expression r, IdentifierSequence e, int p, bool twoState, bool allowMethodCall, DatatypeValue coContext, out CallRhs call) {
Contract.Requires(r != null);
Contract.Requires(e != null);
Contract.Requires(0 <= p && p <= e.Tokens.Count);
@@ -3295,7 +3439,7 @@ namespace Microsoft.Dafny { var resolved = ResolvePredicateOrField(e.Tokens[p], r, e.Tokens[p].val);
if (resolved != null) {
r = resolved;
- ResolveExpression(r, twoState);
+ ResolveExpression(r, twoState, null, p == e.Tokens.Count - 1 ? coContext : null);
}
}
@@ -3315,7 +3459,7 @@ namespace Microsoft.Dafny { r = null;
} else {
r = new FunctionCallExpr(e.Tokens[p], e.Tokens[p].val, r, e.OpenParen, e.Arguments);
- ResolveExpression(r, twoState);
+ ResolveExpression(r, twoState, null, coContext);
}
} else if (e.Arguments != null) {
Contract.Assert(p == e.Tokens.Count);
@@ -3380,7 +3524,7 @@ namespace Microsoft.Dafny { // easy
bounds.Add(new QuantifierExpr.BoolBoundedPool());
} else {
- // Go through the conjuncts of the range expression look for bounds.
+ // Go through the conjuncts of the range expression to look for bounds.
Expression lowerBound = bv.Type is NatType ? new LiteralExpr(bv.tok, new BigInteger(0)) : null;
Expression upperBound = null;
foreach (var conjunct in NormalizedConjuncts(expr, polarity)) {
diff --git a/Dafny/Rewriter.cs b/Dafny/Rewriter.cs new file mode 100644 index 00000000..26ec496e --- /dev/null +++ b/Dafny/Rewriter.cs @@ -0,0 +1,321 @@ +using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+
+namespace Microsoft.Dafny
+{
+ public interface Rewriter
+ {
+ void PreResolve(ModuleDecl m);
+ void PostResolve(ModuleDecl m);
+ }
+
+ /// <summary>
+ /// AutoContracts is an experimental feature that will fill much of the dynamic-frames boilerplate
+ /// into a class. From the user's perspective, what needs to be done is simply:
+ /// - mark the class with {:autocontracts}
+ /// - declare a function (or predicate) called Valid()
+ ///
+ /// AutoContracts will then:
+ ///
+ /// Declare:
+ /// ghost var Repr: set(object);
+ ///
+ /// For function/predicate Valid(), insert:
+ /// reads this, Repr;
+ /// Into body of Valid(), insert (at the beginning of the body):
+ /// this in Repr && null !in Repr
+ /// and also insert, for every array-valued field A declared in the class:
+ /// (A != null ==> A in Repr) &&
+ /// and for every field F of a class type T where T has a field called Repr, also insert:
+ /// (F != null ==> F in Repr && F.Repr SUBSET Repr && this !in Repr)
+ /// Except, if A or F is declared with {:autocontracts false}, then the implication will not
+ /// be added.
+ ///
+ /// For every constructor, add:
+ /// modifies this;
+ /// ensures Valid() && fresh(Repr - {this});
+ /// At the end of the body of the constructor, add:
+ /// Repr := {this};
+ /// if (A != null) { Repr := Repr + {A}; }
+ /// if (F != null) { Repr := Repr + {F} + F.Repr; }
+ ///
+ /// For every method, add:
+ /// requires Valid();
+ /// modifies Repr;
+ /// ensures Valid() && fresh(Repr - old(Repr));
+ /// At the end of the body of the method, add:
+ /// if (A != null) { Repr := Repr + {A}; }
+ /// if (F != null) { Repr := Repr + {F} + F.Repr; }
+ /// </summary>
+ public class AutoContractsRewriter : Rewriter
+ {
+ public void PreResolve(ModuleDecl m) {
+ foreach (var d in m.TopLevelDecls) {
+ bool sayYes = true;
+ if (d is ClassDecl && Attributes.ContainsBool(d.Attributes, "autocontracts", ref sayYes) && sayYes) {
+ ProcessClassPreResolve((ClassDecl)d);
+ }
+ }
+ }
+
+ void ProcessClassPreResolve(ClassDecl cl) {
+ // Add: ghost var Repr: set<object>;
+ // ...unless a field with that name is already present
+ if (!cl.Members.Exists(member => member is Field && member.Name == "Repr")) {
+ Type ty = new SetType(new ObjectType());
+ cl.Members.Add(new Field(cl.tok, "Repr", true, ty, null));
+ }
+
+ foreach (var member in cl.Members) {
+ bool sayYes = true;
+ if (Attributes.ContainsBool(member.Attributes, "autocontracts", ref sayYes) && !sayYes) {
+ continue;
+ }
+ var tok = member.tok;
+ if (member is Function && member.Name == "Valid" && !member.IsStatic) {
+ var valid = (Function)member;
+ // reads this;
+ valid.Reads.Add(new FrameExpression(new ThisExpr(tok), null));
+ // reads Repr;
+ valid.Reads.Add(new FrameExpression(new FieldSelectExpr(tok, new ImplicitThisExpr(tok), "Repr"), null));
+ } else if (member is Constructor) {
+ var ctor = (Constructor)member;
+ // modifies this;
+ ctor.Mod.Expressions.Add(new FrameExpression(new ImplicitThisExpr(tok), null));
+ // ensures Valid();
+ ctor.Ens.Insert(0, new MaybeFreeExpression(new FunctionCallExpr(tok, "Valid", new ImplicitThisExpr(tok), tok, new List<Expression>())));
+ // ensures fresh(Repr - {this});
+ var freshness = new FreshExpr(tok, new BinaryExpr(tok, BinaryExpr.Opcode.Sub,
+ new FieldSelectExpr(tok, new ImplicitThisExpr(tok), "Repr"),
+ new SetDisplayExpr(tok, new List<Expression>() { new ThisExpr(tok) })));
+ ctor.Ens.Insert(1, new MaybeFreeExpression(freshness));
+ } else if (member is Method && !member.IsStatic) {
+ var m = (Method)member;
+ // requires Valid();
+ m.Req.Insert(0, new MaybeFreeExpression(new FunctionCallExpr(tok, "Valid", new ImplicitThisExpr(tok), tok, new List<Expression>())));
+ // If this is a mutating method, we should also add a modifies clause and a postcondition, but we don't do that if it's
+ // a simple query method. However, we won't know if it's a simple query method until after resolution, so we'll add the
+ // rest of the spec then.
+ }
+ }
+ }
+
+ public void PostResolve(ModuleDecl m) {
+ foreach (var d in m.TopLevelDecls) {
+ bool sayYes = true;
+ if (d is ClassDecl && Attributes.ContainsBool(d.Attributes, "autocontracts", ref sayYes) && sayYes) {
+ ProcessClassPostResolve((ClassDecl)d);
+ }
+ }
+ }
+
+ void ProcessClassPostResolve(ClassDecl cl) {
+ // Find all fields of a reference type, and make a note of whether or not the reference type has a Repr field.
+ // Also, find the Repr field and the function Valid in class "cl"
+ Field ReprField = null;
+ Function Valid = null;
+ var subobjects = new List<Tuple<Field, Field>>();
+ foreach (var member in cl.Members) {
+ var field = member as Field;
+ if (field != null) {
+ bool sayYes = true;
+ if (field.Name == "Repr") {
+ ReprField = field;
+ } else if (Attributes.ContainsBool(field.Attributes, "autocontracts", ref sayYes) && !sayYes) {
+ // ignore this field
+ } else if (field.Type is ObjectType) {
+ subobjects.Add(new Tuple<Field, Field>(field, null));
+ } else if (field.Type.IsRefType) {
+ var rcl = (ClassDecl)((UserDefinedType)field.Type).ResolvedClass;
+ Field rRepr = null;
+ foreach (var memb in rcl.Members) {
+ var f = memb as Field;
+ if (f != null && f.Name == "Repr") {
+ rRepr = f;
+ break;
+ }
+ }
+ subobjects.Add(new Tuple<Field, Field>(field, rRepr));
+ }
+ } else if (member is Function && member.Name == "Valid" && !member.IsStatic) {
+ var fn = (Function)member;
+ if (fn.Formals.Count == 0 && fn.ResultType is BoolType) {
+ Valid = fn;
+ }
+ }
+ }
+ Contract.Assert(ReprField != null); // we expect there to be a "Repr" field, since we added one in PreResolve
+
+ Type ty = new UserDefinedType(cl.tok, cl.Name, cl, new List<Type>());
+ var self = new ThisExpr(cl.tok);
+ self.Type = ty;
+ var implicitSelf = new ImplicitThisExpr(cl.tok);
+ implicitSelf.Type = ty;
+ var Repr = new FieldSelectExpr(cl.tok, implicitSelf, "Repr");
+ Repr.Field = ReprField;
+ Repr.Type = ReprField.Type;
+ var cNull = new LiteralExpr(cl.tok);
+ cNull.Type = new ObjectType();
+
+ foreach (var member in cl.Members) {
+ bool sayYes = true;
+ if (Attributes.ContainsBool(member.Attributes, "autocontracts", ref sayYes) && !sayYes) {
+ continue;
+ }
+ var tok = member.tok;
+ if (member is Function && member.Name == "Valid" && !member.IsStatic) {
+ var valid = (Function)member;
+ if (valid.IsGhost && valid.ResultType is BoolType) {
+ var c0 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.InSet, self, Repr); // this in Repr
+ var c1 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.NotInSet, cNull, Repr); // null !in Repr
+ var c = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.And, c0, c1);
+
+ foreach (var ff in subobjects) {
+ var F = new FieldSelectExpr(tok, implicitSelf, ff.Item1.Name);
+ F.Field = ff.Item1;
+ F.Type = ff.Item1.Type;
+
+ c0 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.NeqCommon, F, cNull);
+ c1 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.InSet, F, Repr);
+ if (ff.Item2 == null) {
+ // F != null ==> F in Repr (so, nothing else to do)
+ } else {
+ // F != null ==> F in Repr && F.Repr <= Repr && this !in F.Repr
+ var FRepr = new FieldSelectExpr(tok, F, ff.Item2.Name);
+ FRepr.Field = ff.Item2;
+ FRepr.Type = ff.Item2.Type;
+ var c2 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.Subset, FRepr, Repr);
+ var c3 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.NotInSet, self, FRepr);
+ c1 = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.And, c1, BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.And, c2, c3));
+ }
+ c = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.And, c, BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.Imp, c0, c1));
+ }
+
+ if (valid.Body == null) {
+ valid.Body = c;
+ } else {
+ valid.Body = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.And, c, valid.Body);
+ }
+ }
+
+ } else if (member is Constructor) {
+ var ctor = (Constructor)member;
+ if (ctor.Body == null) {
+ ctor.Body = new BlockStmt(tok, new List<Statement>());
+ }
+ // TODO: these assignments should be included on every return path
+ var bodyStatements = ((BlockStmt)ctor.Body).Body;
+ // Repr := {this};
+ var e = new SetDisplayExpr(tok, new List<Expression>() { self });
+ e.Type = new SetType(new ObjectType());
+ Statement s = new AssignStmt(tok, Repr, new ExprRhs(e));
+ s.IsGhost = true;
+ bodyStatements.Add(s);
+
+ AddSubobjectReprs(tok, subobjects, bodyStatements, self, implicitSelf, cNull, Repr);
+
+ } else if (member is Method && !member.IsStatic) {
+ var m = (Method)member;
+ if (Valid != null && !IsSimpleQueryMethod(m)) {
+ // modifies Repr;
+ m.Mod.Expressions.Add(new FrameExpression(Repr, null));
+ // ensures Valid();
+ var valid = new FunctionCallExpr(tok, "Valid", implicitSelf, tok, new List<Expression>());
+ valid.Function = Valid;
+ valid.Type = Type.Bool;
+ m.Ens.Insert(0, new MaybeFreeExpression(valid));
+ // ensures fresh(Repr - old(Repr));
+ var e0 = new OldExpr(tok, Repr);
+ e0.Type = Repr.Type;
+ var e1 = new BinaryExpr(tok, BinaryExpr.Opcode.Sub, Repr, e0);
+ e1.ResolvedOp = BinaryExpr.ResolvedOpcode.SetDifference;
+ e1.Type = Repr.Type;
+ var freshness = new FreshExpr(tok, e1);
+ freshness.Type = Type.Bool;
+ m.Ens.Insert(1, new MaybeFreeExpression(freshness));
+
+ if (m.Body == null) {
+ m.Body = new BlockStmt(tok, new List<Statement>());
+ }
+ // TODO: these assignments should be included on every return path
+ var bodyStatements = ((BlockStmt)m.Body).Body;
+ AddSubobjectReprs(tok, subobjects, bodyStatements, self, implicitSelf, cNull, Repr);
+ }
+ }
+ }
+ }
+
+ void AddSubobjectReprs(Boogie.IToken tok, List<Tuple<Field, Field>> subobjects, List<Statement> bodyStatements,
+ Expression self, Expression implicitSelf, Expression cNull, Expression Repr) {
+
+ foreach (var ff in subobjects) {
+ var F = new FieldSelectExpr(tok, implicitSelf, ff.Item1.Name);
+ F.Field = ff.Item1;
+ F.Type = ff.Item1.Type;
+
+ Expression e = new SetDisplayExpr(tok, new List<Expression>() { F });
+ e.Type = new SetType(new ObjectType());
+ var rhs = new BinaryExpr(tok, BinaryExpr.Opcode.Add, Repr, e);
+ rhs.ResolvedOp = BinaryExpr.ResolvedOpcode.Union;
+ rhs.Type = Repr.Type;
+ if (ff.Item2 == null) {
+ // Repr := Repr + {F} (so, nothing else to do)
+ } else {
+ // Repr := Repr + {F} + F.Repr
+ var FRepr = new FieldSelectExpr(tok, F, ff.Item2.Name);
+ FRepr.Field = ff.Item2;
+ FRepr.Type = ff.Item2.Type;
+ rhs = new BinaryExpr(tok, BinaryExpr.Opcode.Add, rhs, FRepr);
+ rhs.ResolvedOp = BinaryExpr.ResolvedOpcode.Union;
+ rhs.Type = Repr.Type;
+ }
+ // Repr := Repr + ...;
+ Statement s = new AssignStmt(tok, Repr, new ExprRhs(rhs));
+ s.IsGhost = true;
+ // wrap if statement around s
+ e = BinBoolExpr(tok, BinaryExpr.ResolvedOpcode.NeqCommon, F, cNull);
+ var thn = new BlockStmt(tok, new List<Statement>() { s });
+ thn.IsGhost = true;
+ s = new IfStmt(tok, e, thn, null);
+ s.IsGhost = true;
+ // finally, add s to the body
+ bodyStatements.Add(s);
+ }
+ }
+
+ bool IsSimpleQueryMethod(Method m) {
+ // A simple query method has out parameters, its body has no effect other than to assign to them,
+ // and the postcondition does not explicitly mention the pre-state.
+ return m.Outs.Count != 0 && m.Body != null && LocalAssignsOnly(m.Body) &&
+ m.Ens.TrueForAll(mfe => !Translator.MentionsOldState(mfe.E));
+ }
+
+ bool LocalAssignsOnly(Statement s) {
+ Contract.Requires(s != null);
+ if (s is AssignStmt) {
+ var ss = (AssignStmt)s;
+ return ss.Lhs.Resolved is IdentifierExpr;
+ } else if (s is ConcreteUpdateStatement) {
+ var ss = (ConcreteUpdateStatement)s;
+ return ss.Lhss.TrueForAll(e => e.Resolved is IdentifierExpr);
+ } else if (s is CallStmt) {
+ return false;
+ } else {
+ foreach (var ss in s.SubStatements) {
+ if (!LocalAssignsOnly(ss)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ BinaryExpr BinBoolExpr(Boogie.IToken tok, BinaryExpr.ResolvedOpcode rop, Expression e0, Expression e1) {
+ var p = new BinaryExpr(tok, BinaryExpr.ResolvedOp2SyntacticOp(rop), e0, e1);
+ p.ResolvedOp = rop;
+ p.Type = Type.Bool;
+ return p;
+ }
+ }
+}
diff --git a/Dafny/Scanner.cs b/Dafny/Scanner.cs index 7c3831a7..ffc6f4b0 100644 --- a/Dafny/Scanner.cs +++ b/Dafny/Scanner.cs @@ -19,7 +19,7 @@ public class Buffer { // a) whole stream in buffer
// b) part of stream in buffer
// 2) non seekable stream (network, console)
-
+
public const int EOF = 65535 + 1; // char.MaxValue + 1;
const int MIN_BUFFER_LENGTH = 1024; // 1KB
const int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
@@ -31,15 +31,17 @@ public class Buffer { Stream/*!*/ stream; // input stream (seekable)
bool isUserStream; // was the stream opened by the user?
-[ContractInvariantMethod]
-void ObjectInvariant(){
- Contract.Invariant(buf != null);
- Contract.Invariant(stream != null);}
- [NotDelayed]
- public Buffer (Stream/*!*/ s, bool isUserStream) :base() {
+ [ContractInvariantMethod]
+ void ObjectInvariant(){
+ Contract.Invariant(buf != null);
+ Contract.Invariant(stream != null);
+ }
+
+// [NotDelayed]
+ public Buffer (Stream/*!*/ s, bool isUserStream) : base() {
Contract.Requires(s != null);
stream = s; this.isUserStream = isUserStream;
-
+
int fl, bl;
if (s.CanSeek) {
fl = (int) s.Length;
@@ -51,12 +53,12 @@ void ObjectInvariant(){ buf = new byte[(bl>0) ? bl : MIN_BUFFER_LENGTH];
fileLen = fl; bufLen = bl;
-
+
if (fileLen > 0) Pos = 0; // setup buffer to position 0 (start)
else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid
if (bufLen == fileLen && s.CanSeek) Close();
}
-
+
protected Buffer(Buffer/*!*/ b) { // called in UTF8Buffer constructor
Contract.Requires(b != null);
buf = b.buf;
@@ -73,14 +75,14 @@ void ObjectInvariant(){ }
~Buffer() { Close(); }
-
+
protected void Close() {
if (!isUserStream && stream != null) {
stream.Close();
//stream = null;
}
}
-
+
public virtual int Read () {
if (bufPos < bufLen) {
return buf[bufPos++];
@@ -100,7 +102,7 @@ void ObjectInvariant(){ Pos = curPos;
return ch;
}
-
+
public string/*!*/ GetString (int beg, int end) {
Contract.Ensures(Contract.Result<string>() != null);
int len = 0;
@@ -139,7 +141,7 @@ void ObjectInvariant(){ }
}
}
-
+
// Read the next chunk of bytes from the stream, increases the buffer
// if needed and updates the fields fileLen and bufLen.
// Returns the number of bytes read.
@@ -209,26 +211,28 @@ public class UTF8Buffer: Buffer { public class Scanner {
const char EOL = '\n';
const int eofSym = 0; /* pdt */
- const int maxT = 104;
- const int noSym = 104;
-
-
-[ContractInvariantMethod]
-void objectInvariant(){
- Contract.Invariant(buffer!=null);
- Contract.Invariant(t != null);
- Contract.Invariant(start != null);
- Contract.Invariant(tokens != null);
- Contract.Invariant(pt != null);
- Contract.Invariant(tval != null);
- Contract.Invariant(Filename != null);
- Contract.Invariant(errorHandler != null);
-}
+ const int maxT = 107;
+ const int noSym = 107;
+
+
+ [ContractInvariantMethod]
+ void objectInvariant(){
+ Contract.Invariant(buffer!=null);
+ Contract.Invariant(t != null);
+ Contract.Invariant(start != null);
+ Contract.Invariant(tokens != null);
+ Contract.Invariant(pt != null);
+ Contract.Invariant(tval != null);
+ Contract.Invariant(Filename != null);
+ Contract.Invariant(errorHandler != null);
+ }
+
public Buffer/*!*/ buffer; // scanner buffer
-
+
Token/*!*/ t; // current token
int ch; // current input character
int pos; // byte position of current character
+ int charPos;
int col; // column number of current character
int line; // line number of current character
int oldEols; // EOLs that appeared in a comment;
@@ -236,13 +240,13 @@ void objectInvariant(){ Token/*!*/ tokens; // list of tokens already peeked (first token is a dummy)
Token/*!*/ pt; // current peek token
-
+
char[]/*!*/ tval = new char[128]; // text of current token
int tlen; // length of current token
-
+
private string/*!*/ Filename;
private Errors/*!*/ errorHandler;
-
+
static Scanner() {
start = new Hashtable(128);
for (int i = 39; i <= 39; ++i) start[i] = 1;
@@ -254,45 +258,45 @@ void objectInvariant(){ for (int i = 48; i <= 57; ++i) start[i] = 7;
for (int i = 34; i <= 34; ++i) start[i] = 8;
start[97] = 12;
- start[58] = 55;
+ start[58] = 56;
start[123] = 10;
start[125] = 11;
- start[61] = 56;
- start[124] = 57;
+ start[61] = 57;
+ start[124] = 58;
start[59] = 19;
start[44] = 20;
- start[60] = 58;
- start[62] = 59;
- start[40] = 21;
- start[41] = 22;
- start[42] = 23;
- start[96] = 24;
- start[91] = 26;
- start[93] = 27;
- start[46] = 60;
- start[8660] = 31;
- start[8658] = 33;
- start[38] = 34;
- start[8743] = 36;
- start[8744] = 38;
- start[33] = 61;
- start[8800] = 42;
- start[8804] = 43;
- start[8805] = 44;
- start[43] = 45;
- start[45] = 46;
- start[47] = 47;
- start[37] = 48;
- start[172] = 49;
- start[8704] = 51;
- start[8707] = 52;
- start[8226] = 54;
+ start[60] = 59;
+ start[62] = 60;
+ start[46] = 61;
+ start[40] = 22;
+ start[41] = 23;
+ start[42] = 24;
+ start[96] = 25;
+ start[91] = 28;
+ start[93] = 29;
+ start[8660] = 33;
+ start[8658] = 35;
+ start[38] = 36;
+ start[8743] = 38;
+ start[8744] = 40;
+ start[33] = 62;
+ start[8800] = 44;
+ start[8804] = 45;
+ start[8805] = 46;
+ start[43] = 47;
+ start[45] = 48;
+ start[47] = 49;
+ start[37] = 50;
+ start[172] = 51;
+ start[8704] = 52;
+ start[8707] = 53;
+ start[8226] = 55;
start[Buffer.EOF] = -1;
}
-
- [NotDelayed]
- public Scanner (string/*!*/ fileName, Errors/*!*/ errorHandler) :base(){
+
+// [NotDelayed]
+ public Scanner (string/*!*/ fileName, Errors/*!*/ errorHandler) : base() {
Contract.Requires(fileName != null);
Contract.Requires(errorHandler != null);
this.errorHandler = errorHandler;
@@ -302,15 +306,14 @@ void objectInvariant(){ Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
buffer = new Buffer(stream, false);
Filename = fileName;
-
Init();
} catch (IOException) {
throw new FatalError("Cannot open file " + fileName);
}
}
-
- [NotDelayed]
- public Scanner (Stream/*!*/ s, Errors/*!*/ errorHandler, string/*!*/ fileName) :base(){
+
+// [NotDelayed]
+ public Scanner (Stream/*!*/ s, Errors/*!*/ errorHandler, string/*!*/ fileName) : base() {
Contract.Requires(s != null);
Contract.Requires(errorHandler != null);
Contract.Requires(fileName != null);
@@ -319,10 +322,9 @@ void objectInvariant(){ buffer = new Buffer(s, true);
this.errorHandler = errorHandler;
this.Filename = fileName;
-
Init();
}
-
+
void Init() {
pos = -1; line = 1; col = 0;
oldEols = 0;
@@ -343,11 +345,11 @@ void objectInvariant(){ Contract.Ensures(Contract.Result<string>() != null);
int p = buffer.Pos;
int ch = buffer.Read();
- // replace isolated '\r' by '\n' in order to make
+ // replace isolated '\r' by '\n' in order to make
// eol handling uniform across Windows, Unix and Mac
if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
while (ch != EOL && ch != Buffer.EOF){
- ch = buffer.Read();
+ ch = buffer.Read();
// replace isolated '\r' by '\n' in order to make
// eol handling uniform across Windows, Unix and Mac
if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
@@ -358,7 +360,7 @@ void objectInvariant(){ }
void NextCh() {
- if (oldEols > 0) { ch = EOL; oldEols--; }
+ if (oldEols > 0) { ch = EOL; oldEols--; }
else {
// pos = buffer.Pos;
// ch = buffer.Read(); col++;
@@ -366,9 +368,9 @@ void objectInvariant(){ // // eol handling uniform across Windows, Unix and Mac
// if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
// if (ch == EOL) { line++; col = 0; }
-
+
while (true) {
- pos = buffer.Pos;
+ pos = buffer.Pos;
ch = buffer.Read(); col++;
// replace isolated '\r' by '\n' in order to make
// eol handling uniform across Windows, Unix and Mac
@@ -418,7 +420,7 @@ void objectInvariant(){ return;
}
-
+
}
}
@@ -438,7 +440,7 @@ void objectInvariant(){ bool Comment0() {
- int level = 1, pos0 = pos, line0 = line, col0 = col;
+ int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
NextCh();
if (ch == '/') {
NextCh();
@@ -451,13 +453,13 @@ void objectInvariant(){ else NextCh();
}
} else {
- buffer.Pos = pos0; NextCh(); line = line0; col = col0;
+ buffer.Pos = pos0; NextCh(); line = line0; col = col0; charPos = charPos0;
}
return false;
}
bool Comment1() {
- int level = 1, pos0 = pos, line0 = line, col0 = col;
+ int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
NextCh();
if (ch == '*') {
NextCh();
@@ -478,7 +480,7 @@ void objectInvariant(){ else NextCh();
}
} else {
- buffer.Pos = pos0; NextCh(); line = line0; col = col0;
+ buffer.Pos = pos0; NextCh(); line = line0; col = col0; charPos = charPos0;
}
return false;
}
@@ -486,60 +488,61 @@ void objectInvariant(){ void CheckLiteral() {
switch (t.val) {
- case "module": t.kind = 8; break;
- case "refines": t.kind = 9; break;
- case "imports": t.kind = 10; break;
- case "class": t.kind = 11; break;
- case "ghost": t.kind = 12; break;
+ case "ghost": t.kind = 8; break;
+ case "module": t.kind = 9; break;
+ case "refines": t.kind = 10; break;
+ case "imports": t.kind = 11; break;
+ case "class": t.kind = 12; break;
case "static": t.kind = 13; break;
case "unlimited": t.kind = 14; break;
case "datatype": t.kind = 15; break;
- case "var": t.kind = 19; break;
- case "type": t.kind = 21; break;
- case "method": t.kind = 24; break;
- case "constructor": t.kind = 25; break;
- case "returns": t.kind = 26; break;
- case "modifies": t.kind = 27; break;
- case "free": t.kind = 28; break;
- case "requires": t.kind = 29; break;
- case "ensures": t.kind = 30; break;
- case "decreases": t.kind = 31; break;
- case "bool": t.kind = 34; break;
- case "nat": t.kind = 35; break;
- case "int": t.kind = 36; break;
- case "set": t.kind = 37; break;
- case "multiset": t.kind = 38; break;
- case "seq": t.kind = 39; break;
- case "object": t.kind = 40; break;
- case "function": t.kind = 41; break;
- case "predicate": t.kind = 42; break;
- case "reads": t.kind = 43; break;
- case "label": t.kind = 46; break;
- case "break": t.kind = 47; break;
- case "return": t.kind = 48; break;
- case "new": t.kind = 50; break;
- case "choose": t.kind = 54; break;
- case "if": t.kind = 55; break;
- case "else": t.kind = 56; break;
- case "case": t.kind = 57; break;
- case "while": t.kind = 59; break;
- case "invariant": t.kind = 60; break;
- case "match": t.kind = 61; break;
- case "assert": t.kind = 62; break;
- case "assume": t.kind = 63; break;
- case "print": t.kind = 64; break;
- case "parallel": t.kind = 65; break;
- case "in": t.kind = 79; break;
- case "false": t.kind = 89; break;
- case "true": t.kind = 90; break;
- case "null": t.kind = 91; break;
- case "this": t.kind = 92; break;
- case "fresh": t.kind = 93; break;
- case "allocated": t.kind = 94; break;
- case "old": t.kind = 95; break;
- case "then": t.kind = 96; break;
- case "forall": t.kind = 98; break;
- case "exists": t.kind = 100; break;
+ case "codatatype": t.kind = 16; break;
+ case "var": t.kind = 20; break;
+ case "type": t.kind = 22; break;
+ case "method": t.kind = 25; break;
+ case "constructor": t.kind = 26; break;
+ case "returns": t.kind = 27; break;
+ case "modifies": t.kind = 29; break;
+ case "free": t.kind = 30; break;
+ case "requires": t.kind = 31; break;
+ case "ensures": t.kind = 32; break;
+ case "decreases": t.kind = 33; break;
+ case "bool": t.kind = 36; break;
+ case "nat": t.kind = 37; break;
+ case "int": t.kind = 38; break;
+ case "set": t.kind = 39; break;
+ case "multiset": t.kind = 40; break;
+ case "seq": t.kind = 41; break;
+ case "object": t.kind = 42; break;
+ case "function": t.kind = 43; break;
+ case "predicate": t.kind = 44; break;
+ case "reads": t.kind = 45; break;
+ case "label": t.kind = 48; break;
+ case "break": t.kind = 49; break;
+ case "return": t.kind = 50; break;
+ case "new": t.kind = 53; break;
+ case "choose": t.kind = 57; break;
+ case "if": t.kind = 58; break;
+ case "else": t.kind = 59; break;
+ case "case": t.kind = 60; break;
+ case "while": t.kind = 62; break;
+ case "invariant": t.kind = 63; break;
+ case "match": t.kind = 64; break;
+ case "assert": t.kind = 65; break;
+ case "assume": t.kind = 66; break;
+ case "print": t.kind = 67; break;
+ case "parallel": t.kind = 68; break;
+ case "in": t.kind = 82; break;
+ case "false": t.kind = 92; break;
+ case "true": t.kind = 93; break;
+ case "null": t.kind = 94; break;
+ case "this": t.kind = 95; break;
+ case "fresh": t.kind = 96; break;
+ case "allocated": t.kind = 97; break;
+ case "old": t.kind = 98; break;
+ case "then": t.kind = 99; break;
+ case "forall": t.kind = 101; break;
+ case "exists": t.kind = 103; break;
default: break;
}
}
@@ -556,10 +559,13 @@ void objectInvariant(){ t.pos = pos; t.col = col; t.line = line;
t.filename = this.Filename;
int state;
- if (start.ContainsKey(ch)) { state = (int) cce.NonNull( start[ch]); }
+ if (start.ContainsKey(ch)) {
+ Contract.Assert(start[ch] != null);
+ state = (int) start[ch];
+ }
else { state = 0; }
tlen = 0; AddCh();
-
+
switch (state) {
case -1: { t.kind = eofSym; break; } // NextCh already done
case 0: {
@@ -642,131 +648,138 @@ void objectInvariant(){ else if (ch >= '0' && ch <= '9') {AddCh(); goto case 18;}
else {t.kind = 3; break;}
case 19:
- {t.kind = 18; break;}
+ {t.kind = 19; break;}
case 20:
- {t.kind = 20; break;}
+ {t.kind = 21; break;}
case 21:
- {t.kind = 32; break;}
+ {t.kind = 28; break;}
case 22:
- {t.kind = 33; break;}
+ {t.kind = 34; break;}
case 23:
- {t.kind = 44; break;}
+ {t.kind = 35; break;}
case 24:
- {t.kind = 45; break;}
+ {t.kind = 46; break;}
case 25:
- {t.kind = 49; break;}
+ {t.kind = 47; break;}
case 26:
{t.kind = 51; break;}
case 27:
{t.kind = 52; break;}
case 28:
- {t.kind = 58; break;}
+ {t.kind = 54; break;}
case 29:
- if (ch == '>') {AddCh(); goto case 30;}
- else {goto case 0;}
+ {t.kind = 55; break;}
case 30:
- {t.kind = 66; break;}
+ {t.kind = 61; break;}
case 31:
- {t.kind = 67; break;}
+ if (ch == '>') {AddCh(); goto case 32;}
+ else {goto case 0;}
case 32:
- {t.kind = 68; break;}
- case 33:
{t.kind = 69; break;}
+ case 33:
+ {t.kind = 70; break;}
case 34:
- if (ch == '&') {AddCh(); goto case 35;}
- else {goto case 0;}
+ {t.kind = 71; break;}
case 35:
- {t.kind = 70; break;}
+ {t.kind = 72; break;}
case 36:
- {t.kind = 71; break;}
+ if (ch == '&') {AddCh(); goto case 37;}
+ else {goto case 0;}
case 37:
- {t.kind = 72; break;}
- case 38:
{t.kind = 73; break;}
+ case 38:
+ {t.kind = 74; break;}
case 39:
- {t.kind = 76; break;}
+ {t.kind = 75; break;}
case 40:
- {t.kind = 77; break;}
+ {t.kind = 76; break;}
case 41:
- {t.kind = 78; break;}
+ {t.kind = 79; break;}
case 42:
- {t.kind = 81; break;}
+ {t.kind = 80; break;}
case 43:
- {t.kind = 82; break;}
+ {t.kind = 81; break;}
case 44:
- {t.kind = 83; break;}
- case 45:
{t.kind = 84; break;}
- case 46:
+ case 45:
{t.kind = 85; break;}
- case 47:
+ case 46:
{t.kind = 86; break;}
- case 48:
+ case 47:
{t.kind = 87; break;}
- case 49:
+ case 48:
{t.kind = 88; break;}
+ case 49:
+ {t.kind = 89; break;}
case 50:
- {t.kind = 97; break;}
+ {t.kind = 90; break;}
case 51:
- {t.kind = 99; break;}
+ {t.kind = 91; break;}
case 52:
- {t.kind = 101; break;}
- case 53:
{t.kind = 102; break;}
+ case 53:
+ {t.kind = 104; break;}
case 54:
- {t.kind = 103; break;}
+ {t.kind = 105; break;}
case 55:
+ {t.kind = 106; break;}
+ case 56:
recEnd = pos; recKind = 5;
- if (ch == '=') {AddCh(); goto case 25;}
- else if (ch == ':') {AddCh(); goto case 53;}
+ if (ch == '=') {AddCh(); goto case 26;}
+ else if (ch == '|') {AddCh(); goto case 27;}
+ else if (ch == ':') {AddCh(); goto case 54;}
else {t.kind = 5; break;}
- case 56:
- recEnd = pos; recKind = 16;
- if (ch == '>') {AddCh(); goto case 28;}
- else if (ch == '=') {AddCh(); goto case 62;}
- else {t.kind = 16; break;}
case 57:
recEnd = pos; recKind = 17;
- if (ch == '|') {AddCh(); goto case 37;}
+ if (ch == '>') {AddCh(); goto case 30;}
+ else if (ch == '=') {AddCh(); goto case 63;}
else {t.kind = 17; break;}
case 58:
- recEnd = pos; recKind = 22;
- if (ch == '=') {AddCh(); goto case 63;}
- else {t.kind = 22; break;}
+ recEnd = pos; recKind = 18;
+ if (ch == '|') {AddCh(); goto case 39;}
+ else {t.kind = 18; break;}
case 59:
recEnd = pos; recKind = 23;
- if (ch == '=') {AddCh(); goto case 39;}
+ if (ch == '=') {AddCh(); goto case 64;}
else {t.kind = 23; break;}
case 60:
- recEnd = pos; recKind = 53;
- if (ch == '.') {AddCh(); goto case 50;}
- else {t.kind = 53; break;}
+ recEnd = pos; recKind = 24;
+ if (ch == '=') {AddCh(); goto case 41;}
+ else {t.kind = 24; break;}
case 61:
- recEnd = pos; recKind = 80;
- if (ch == '=') {AddCh(); goto case 40;}
- else if (ch == '!') {AddCh(); goto case 41;}
- else {t.kind = 80; break;}
+ recEnd = pos; recKind = 56;
+ if (ch == '.') {AddCh(); goto case 65;}
+ else {t.kind = 56; break;}
case 62:
- recEnd = pos; recKind = 74;
- if (ch == '>') {AddCh(); goto case 32;}
- else {t.kind = 74; break;}
+ recEnd = pos; recKind = 83;
+ if (ch == '=') {AddCh(); goto case 42;}
+ else if (ch == '!') {AddCh(); goto case 43;}
+ else {t.kind = 83; break;}
case 63:
- recEnd = pos; recKind = 75;
- if (ch == '=') {AddCh(); goto case 29;}
- else {t.kind = 75; break;}
+ recEnd = pos; recKind = 77;
+ if (ch == '>') {AddCh(); goto case 34;}
+ else {t.kind = 77; break;}
+ case 64:
+ recEnd = pos; recKind = 78;
+ if (ch == '=') {AddCh(); goto case 31;}
+ else {t.kind = 78; break;}
+ case 65:
+ recEnd = pos; recKind = 100;
+ if (ch == '.') {AddCh(); goto case 21;}
+ else {t.kind = 100; break;}
}
t.val = new String(tval, 0, tlen);
return t;
}
-
+
private void SetScannerBehindT() {
buffer.Pos = t.pos;
NextCh();
line = t.line; col = t.col;
for (int i = 0; i < tlen; i++) NextCh();
}
-
+
// get the next token (possibly a token already seen during peeking)
public Token/*!*/ Scan () {
Contract.Ensures(Contract.Result<Token>() != null);
@@ -787,7 +800,7 @@ void objectInvariant(){ }
pt = pt.next;
} while (pt.kind > maxT); // skip pragmas
-
+
return pt;
}
diff --git a/Dafny/Translator.cs b/Dafny/Translator.cs index 8135a61a..b2b2bdc9 100644 --- a/Dafny/Translator.cs +++ b/Dafny/Translator.cs @@ -269,7 +269,7 @@ namespace Microsoft.Dafny { }
Bpl.Program prelude;
- int errorCount = Bpl.Parser.Parse(preludePath, null, out prelude);
+ int errorCount = Bpl.Parser.Parse(preludePath, (List<string>)null, out prelude);
if (prelude == null || errorCount > 0) {
return null;
} else {
@@ -433,62 +433,65 @@ namespace Microsoft.Dafny { lhs = FunctionCall(ctor.tok, fn.Name, TrType(arg.Type), lhs);
q = new Bpl.ForallExpr(ctor.tok, bvs, Bpl.Expr.Eq(lhs, args[i]));
sink.TopLevelDeclarations.Add(new Bpl.Axiom(ctor.tok, q));
- if (arg.Type.IsDatatype || arg.Type.IsTypeParameter) {
- // for datatype: axiom (forall params :: DtRank(params_i) < DtRank(#dt.ctor(params)));
- // for type-parameter type: axiom (forall params :: DtRank(Unbox(params_i)) < DtRank(#dt.ctor(params)));
- CreateBoundVariables(ctor.Formals, out bvs, out args);
- lhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null,
- arg.Type.IsDatatype ? args[i] : FunctionCall(ctor.tok, BuiltinFunction.Unbox, predef.DatatypeType, args[i]));
- Bpl.Expr rhs = FunctionCall(ctor.tok, ctor.FullName, predef.DatatypeType, args);
- rhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null, rhs);
- q = new Bpl.ForallExpr(ctor.tok, bvs, Bpl.Expr.Lt(lhs, rhs));
- sink.TopLevelDeclarations.Add(new Bpl.Axiom(ctor.tok, q));
- } else if (arg.Type is SeqType) {
- // axiom (forall params, i: int :: 0 <= i && i < |arg| ==> DtRank(arg[i]) < DtRank(#dt.ctor(params)));
- // that is:
- // axiom (forall params, i: int :: 0 <= i && i < |arg| ==> DtRank(Unbox(Seq#Index(arg,i))) < DtRank(#dt.ctor(params)));
- CreateBoundVariables(ctor.Formals, out bvs, out args);
- Bpl.Variable iVar = new Bpl.BoundVariable(arg.tok, new Bpl.TypedIdent(arg.tok, "i", Bpl.Type.Int));
- bvs.Add(iVar);
- Bpl.IdentifierExpr ie = new Bpl.IdentifierExpr(arg.tok, iVar);
- Bpl.Expr ante = Bpl.Expr.And(
- Bpl.Expr.Le(Bpl.Expr.Literal(0), ie),
- Bpl.Expr.Lt(ie, FunctionCall(arg.tok, BuiltinFunction.SeqLength, null, args[i])));
- lhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null,
- FunctionCall(arg.tok, BuiltinFunction.Unbox, predef.DatatypeType,
- FunctionCall(arg.tok, BuiltinFunction.SeqIndex, predef.DatatypeType, args[i], ie)));
- Bpl.Expr rhs = FunctionCall(ctor.tok, ctor.FullName, predef.DatatypeType, args);
- rhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null, rhs);
- q = new Bpl.ForallExpr(ctor.tok, bvs, Bpl.Expr.Imp(ante, Bpl.Expr.Lt(lhs, rhs)));
- sink.TopLevelDeclarations.Add(new Bpl.Axiom(ctor.tok, q));
- } else if (arg.Type is SetType) {
- // axiom (forall params, d: Datatype :: arg[d] ==> DtRank(d) < DtRank(#dt.ctor(params)));
- // that is:
- // axiom (forall params, d: Datatype :: arg[Box(d)] ==> DtRank(d) < DtRank(#dt.ctor(params)));
- CreateBoundVariables(ctor.Formals, out bvs, out args);
- Bpl.Variable dVar = new Bpl.BoundVariable(arg.tok, new Bpl.TypedIdent(arg.tok, "d", predef.DatatypeType));
- bvs.Add(dVar);
- Bpl.IdentifierExpr ie = new Bpl.IdentifierExpr(arg.tok, dVar);
- Bpl.Expr ante = Bpl.Expr.SelectTok(arg.tok, args[i], FunctionCall(arg.tok, BuiltinFunction.Box, null, ie));
- lhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null, ie);
- Bpl.Expr rhs = FunctionCall(ctor.tok, ctor.FullName, predef.DatatypeType, args);
- rhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null, rhs);
- q = new Bpl.ForallExpr(ctor.tok, bvs, Bpl.Expr.Imp(ante, Bpl.Expr.Lt(lhs, rhs)));
- sink.TopLevelDeclarations.Add(new Bpl.Axiom(ctor.tok, q));
- } else if (arg.Type is MultiSetType) {
- // axiom (forall params, d: Datatype :: 0 < arg[d] ==> DtRank(d) < DtRank(#dt.ctor(params)));
- // that is:
- // axiom (forall params, d: Datatype :: 0 < arg[Box(d)] ==> DtRank(d) < DtRank(#dt.ctor(params)));
- CreateBoundVariables(ctor.Formals, out bvs, out args);
- Bpl.Variable dVar = new Bpl.BoundVariable(arg.tok, new Bpl.TypedIdent(arg.tok, "d", predef.DatatypeType));
- bvs.Add(dVar);
- Bpl.IdentifierExpr ie = new Bpl.IdentifierExpr(arg.tok, dVar);
- Bpl.Expr ante = Bpl.Expr.Gt(Bpl.Expr.SelectTok(arg.tok, args[i], FunctionCall(arg.tok, BuiltinFunction.Box, null, ie)), Bpl.Expr.Literal(0));
- lhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null, ie);
- Bpl.Expr rhs = FunctionCall(ctor.tok, ctor.FullName, predef.DatatypeType, args);
- rhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null, rhs);
- q = new Bpl.ForallExpr(ctor.tok, bvs, Bpl.Expr.Imp(ante, Bpl.Expr.Lt(lhs, rhs)));
- sink.TopLevelDeclarations.Add(new Bpl.Axiom(ctor.tok, q));
+
+ if (dt is IndDatatypeDecl) {
+ if (arg.Type.IsDatatype || arg.Type.IsTypeParameter) {
+ // for datatype: axiom (forall params :: DtRank(params_i) < DtRank(#dt.ctor(params)));
+ // for type-parameter type: axiom (forall params :: DtRank(Unbox(params_i)) < DtRank(#dt.ctor(params)));
+ CreateBoundVariables(ctor.Formals, out bvs, out args);
+ lhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null,
+ arg.Type.IsDatatype ? args[i] : FunctionCall(ctor.tok, BuiltinFunction.Unbox, predef.DatatypeType, args[i]));
+ Bpl.Expr rhs = FunctionCall(ctor.tok, ctor.FullName, predef.DatatypeType, args);
+ rhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null, rhs);
+ q = new Bpl.ForallExpr(ctor.tok, bvs, Bpl.Expr.Lt(lhs, rhs));
+ sink.TopLevelDeclarations.Add(new Bpl.Axiom(ctor.tok, q));
+ } else if (arg.Type is SeqType) {
+ // axiom (forall params, i: int :: 0 <= i && i < |arg| ==> DtRank(arg[i]) < DtRank(#dt.ctor(params)));
+ // that is:
+ // axiom (forall params, i: int :: 0 <= i && i < |arg| ==> DtRank(Unbox(Seq#Index(arg,i))) < DtRank(#dt.ctor(params)));
+ CreateBoundVariables(ctor.Formals, out bvs, out args);
+ Bpl.Variable iVar = new Bpl.BoundVariable(arg.tok, new Bpl.TypedIdent(arg.tok, "i", Bpl.Type.Int));
+ bvs.Add(iVar);
+ Bpl.IdentifierExpr ie = new Bpl.IdentifierExpr(arg.tok, iVar);
+ Bpl.Expr ante = Bpl.Expr.And(
+ Bpl.Expr.Le(Bpl.Expr.Literal(0), ie),
+ Bpl.Expr.Lt(ie, FunctionCall(arg.tok, BuiltinFunction.SeqLength, null, args[i])));
+ lhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null,
+ FunctionCall(arg.tok, BuiltinFunction.Unbox, predef.DatatypeType,
+ FunctionCall(arg.tok, BuiltinFunction.SeqIndex, predef.DatatypeType, args[i], ie)));
+ Bpl.Expr rhs = FunctionCall(ctor.tok, ctor.FullName, predef.DatatypeType, args);
+ rhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null, rhs);
+ q = new Bpl.ForallExpr(ctor.tok, bvs, Bpl.Expr.Imp(ante, Bpl.Expr.Lt(lhs, rhs)));
+ sink.TopLevelDeclarations.Add(new Bpl.Axiom(ctor.tok, q));
+ } else if (arg.Type is SetType) {
+ // axiom (forall params, d: Datatype :: arg[d] ==> DtRank(d) < DtRank(#dt.ctor(params)));
+ // that is:
+ // axiom (forall params, d: Datatype :: arg[Box(d)] ==> DtRank(d) < DtRank(#dt.ctor(params)));
+ CreateBoundVariables(ctor.Formals, out bvs, out args);
+ Bpl.Variable dVar = new Bpl.BoundVariable(arg.tok, new Bpl.TypedIdent(arg.tok, "d", predef.DatatypeType));
+ bvs.Add(dVar);
+ Bpl.IdentifierExpr ie = new Bpl.IdentifierExpr(arg.tok, dVar);
+ Bpl.Expr ante = Bpl.Expr.SelectTok(arg.tok, args[i], FunctionCall(arg.tok, BuiltinFunction.Box, null, ie));
+ lhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null, ie);
+ Bpl.Expr rhs = FunctionCall(ctor.tok, ctor.FullName, predef.DatatypeType, args);
+ rhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null, rhs);
+ q = new Bpl.ForallExpr(ctor.tok, bvs, Bpl.Expr.Imp(ante, Bpl.Expr.Lt(lhs, rhs)));
+ sink.TopLevelDeclarations.Add(new Bpl.Axiom(ctor.tok, q));
+ } else if (arg.Type is MultiSetType) {
+ // axiom (forall params, d: Datatype :: 0 < arg[d] ==> DtRank(d) < DtRank(#dt.ctor(params)));
+ // that is:
+ // axiom (forall params, d: Datatype :: 0 < arg[Box(d)] ==> DtRank(d) < DtRank(#dt.ctor(params)));
+ CreateBoundVariables(ctor.Formals, out bvs, out args);
+ Bpl.Variable dVar = new Bpl.BoundVariable(arg.tok, new Bpl.TypedIdent(arg.tok, "d", predef.DatatypeType));
+ bvs.Add(dVar);
+ Bpl.IdentifierExpr ie = new Bpl.IdentifierExpr(arg.tok, dVar);
+ Bpl.Expr ante = Bpl.Expr.Gt(Bpl.Expr.SelectTok(arg.tok, args[i], FunctionCall(arg.tok, BuiltinFunction.Box, null, ie)), Bpl.Expr.Literal(0));
+ lhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null, ie);
+ Bpl.Expr rhs = FunctionCall(ctor.tok, ctor.FullName, predef.DatatypeType, args);
+ rhs = FunctionCall(ctor.tok, BuiltinFunction.DtRank, null, rhs);
+ q = new Bpl.ForallExpr(ctor.tok, bvs, Bpl.Expr.Imp(ante, Bpl.Expr.Lt(lhs, rhs)));
+ sink.TopLevelDeclarations.Add(new Bpl.Axiom(ctor.tok, q));
+ }
}
i++;
}
@@ -2316,7 +2319,7 @@ namespace Microsoft.Dafny { CheckFrameSubset(expr.tok, e.Function.Reads, e.Receiver, substMap, etran, builder, "insufficient reads clause to invoke function", options.AssertKv);
}
- if (options.Decr != null) {
+ if (options.Decr != null && e.CoCall != FunctionCallExpr.CoCallResolution.Yes) {
// check that the decreases measure goes down
ModuleDecl module = cce.NonNull(e.Function.EnclosingClass).Module;
if (module == cce.NonNull(options.Decr.EnclosingClass).Module) {
@@ -2335,7 +2338,8 @@ namespace Microsoft.Dafny { allowance = BplAnd(allowance, Bpl.Expr.Eq(etran.TrExpr(ee), new Bpl.IdentifierExpr(e.tok, ff.UniqueName, TrType(ff.Type))));
}
}
- CheckCallTermination(expr.tok, contextDecreases, calleeDecreases, allowance, e.Receiver, substMap, etran, builder, contextDecrInferred);
+ CheckCallTermination(expr.tok, contextDecreases, calleeDecreases, allowance, e.Receiver, substMap, etran, builder,
+ contextDecrInferred, e.CoCall == FunctionCallExpr.CoCallResolution.NoBecauseFunctionHasSideEffects);
}
}
}
@@ -2406,10 +2410,21 @@ namespace Microsoft.Dafny { } else if (expr is LetExpr) {
var e = (LetExpr)expr;
- foreach (var rhs in e.RHSs) {
- CheckWellformed(rhs, options, locals, builder, etran);
+
+ var substMap = new Dictionary<IVariable, Expression>();
+ Contract.Assert(e.Vars.Count == e.RHSs.Count); // checked by resolution
+ for (int i = 0; i < e.Vars.Count; i++) {
+ var vr = e.Vars[i];
+ var tp = TrType(vr.Type);
+ var v = new Bpl.LocalVariable(vr.tok, new Bpl.TypedIdent(vr.tok, vr.UniqueName, tp));
+ locals.Add(v);
+ var lhs = new Bpl.IdentifierExpr(vr.tok, vr.UniqueName, tp);
+
+ CheckWellformedWithResult(e.RHSs[i], options, lhs, vr.Type, locals, builder, etran);
+ substMap.Add(vr, new BoogieWrapper(lhs, vr.Type));
}
- CheckWellformedWithResult(etran.GetSubstitutedBody(e), options, result, resultType, locals, builder, etran);
+ CheckWellformedWithResult(Substitute(e.Body, null, substMap), options, result, resultType, locals, builder, etran);
+ result = null;
} else if (expr is ComprehensionExpr) {
var e = (ComprehensionExpr)expr;
@@ -3276,14 +3291,20 @@ namespace Microsoft.Dafny { AddComment(builder, stmt, "assert statement");
PredicateStmt s = (PredicateStmt)stmt;
TrStmt_CheckWellformed(s.Expr, builder, locals, etran, false);
+ IToken enclosingToken = null;
+ if (Attributes.Contains(stmt.Attributes, "prependAssertToken")) {
+ enclosingToken = stmt.Tok;
+ }
bool splitHappened;
var ss = TrSplitExpr(s.Expr, etran, out splitHappened);
if (!splitHappened) {
- builder.Add(Assert(s.Expr.tok, etran.TrExpr(s.Expr), "assertion violation"));
+ var tok = enclosingToken == null ? s.Expr.tok : new NestedToken(enclosingToken, s.Expr.tok);
+ builder.Add(Assert(tok, etran.TrExpr(s.Expr), "assertion violation"));
} else {
foreach (var split in ss) {
if (!split.IsFree) {
- builder.Add(AssertNS(split.E.tok, split.E, "assertion violation"));
+ var tok = enclosingToken == null ? split.E.tok : new NestedToken(enclosingToken, split.E.tok);
+ builder.Add(AssertNS(tok, split.E, "assertion violation"));
}
}
builder.Add(new Bpl.AssumeCmd(stmt.Tok, etran.TrExpr(s.Expr)));
@@ -3314,6 +3335,25 @@ namespace Microsoft.Dafny { TrStmt(s.hiddenUpdate, builder, locals, etran);
}
builder.Add(new Bpl.ReturnCmd(stmt.Tok));
+ } else if (stmt is AssignSuchThatStmt) {
+ var s = (AssignSuchThatStmt)stmt;
+ AddComment(builder, s, "assign-such-that statement");
+ // treat like a parallel havoc, followed by an assume
+ // Here comes the havoc part
+ var lhss = new List<Expression>();
+ var havocRhss = new List<AssignmentRhs>();
+ foreach (var lhs in s.Lhss) {
+ lhss.Add(lhs.Resolved);
+ havocRhss.Add(new HavocRhs(lhs.tok)); // note, a HavocRhs is constructed as already resolved
+ }
+ List<AssignToLhs> lhsBuilder;
+ List<Bpl.IdentifierExpr> bLhss;
+ ProcessLhss(lhss, false, builder, locals, etran, out lhsBuilder, out bLhss);
+ ProcessRhss(lhsBuilder, bLhss, lhss, havocRhss, builder, locals, etran);
+ // End by doing the assume
+ TrStmt(s.Assume, builder, locals, etran);
+ builder.Add(CaptureState(s.Tok)); // just do one capture state--here, at the very end (that is, don't do one before the assume)
+
} else if (stmt is UpdateStmt) {
var s = (UpdateStmt)stmt;
// This UpdateStmt can be single-target assignment, a multi-assignment, a call statement, or
@@ -4222,7 +4262,7 @@ namespace Microsoft.Dafny { bool contextDecrInferred, calleeDecrInferred;
List<Expression> contextDecreases = MethodDecreasesWithDefault(currentMethod, out contextDecrInferred);
List<Expression> calleeDecreases = MethodDecreasesWithDefault(method, out calleeDecrInferred);
- CheckCallTermination(tok, contextDecreases, calleeDecreases, null, receiver, substMap, etran, builder, contextDecrInferred);
+ CheckCallTermination(tok, contextDecreases, calleeDecreases, null, receiver, substMap, etran, builder, contextDecrInferred, false);
}
}
@@ -4392,7 +4432,7 @@ namespace Microsoft.Dafny { void CheckCallTermination(IToken/*!*/ tok, List<Expression/*!*/>/*!*/ contextDecreases, List<Expression/*!*/>/*!*/ calleeDecreases,
Bpl.Expr allowance,
Expression receiverReplacement, Dictionary<IVariable,Expression/*!*/>/*!*/ substMap,
- ExpressionTranslator/*!*/ etran, Bpl.StmtListBuilder/*!*/ builder, bool inferredDecreases) {
+ ExpressionTranslator/*!*/ etran, Bpl.StmtListBuilder/*!*/ builder, bool inferredDecreases, bool wouldBeCoCallButCallHasSideEffects) {
Contract.Requires(tok != null);
Contract.Requires(cce.NonNullElements(contextDecreases));
Contract.Requires(cce.NonNullElements(calleeDecreases));
@@ -4428,7 +4468,11 @@ namespace Microsoft.Dafny { if (allowance != null) {
decrExpr = Bpl.Expr.Or(allowance, decrExpr);
}
- builder.Add(Assert(tok, decrExpr, inferredDecreases ? "cannot prove termination; try supplying a decreases clause" : "failure to decrease termination measure"));
+ var msg = inferredDecreases ? "cannot prove termination; try supplying a decreases clause" : "failure to decrease termination measure";
+ if (wouldBeCoCallButCallHasSideEffects) {
+ msg += " (note that only functions without side effects can called co-recursively)";
+ }
+ builder.Add(Assert(tok, decrExpr, msg));
}
/// <summary>
@@ -6899,7 +6943,7 @@ namespace Microsoft.Dafny { var e = (FunctionCallExpr)expr;
// For recursive functions: arguments are "prominent"
// For non-recursive function: arguments are "prominent" if the call is
- var rec = e.Function.IsRecursive;
+ var rec = e.Function.IsRecursive && e.CoCall != FunctionCallExpr.CoCallResolution.Yes;
bool inferredDecreases; // we don't actually care
var decr = FunctionDecreasesWithDefault(e.Function, out inferredDecreases);
bool variantArgument;
@@ -6994,7 +7038,7 @@ namespace Microsoft.Dafny { }
IEnumerable<Bpl.Expr> InductionCases(Type ty, Bpl.Expr expr, ExpressionTranslator etran) {
- DatatypeDecl dt = ty.AsDatatype;
+ IndDatatypeDecl dt = ty.AsIndDatatype;
if (dt == null) {
yield return Bpl.Expr.True;
} else {
@@ -7009,13 +7053,14 @@ namespace Microsoft.Dafny { List<Bpl.Expr> args;
CreateBoundVariables(ctor.Formals, out bvs, out args);
Bpl.Expr ct = FunctionCall(ctor.tok, ctor.FullName, predef.DatatypeType, args);
- // (exists args :: args-have-the-expected-types ==> ct(args) == expr)
+ // (exists args :: args-have-the-expected-types && ct(args) == expr)
Bpl.Expr q = Bpl.Expr.Binary(ctor.tok, BinaryOperator.Opcode.Eq, ct, expr);
if (bvs.Length != 0) {
int i = 0;
Bpl.Expr typeAntecedent = Bpl.Expr.True;
foreach (Formal arg in ctor.Formals) {
- Bpl.Expr wh = GetWhereClause(arg.tok, args[i], Resolver.SubstType(arg.Type, subst), etran);
+ var instantiatedArgType = Resolver.SubstType(arg.Type, subst);
+ Bpl.Expr wh = GetWhereClause(arg.tok, etran.CondApplyUnbox(arg.tok, args[i], arg.Type, instantiatedArgType), instantiatedArgType, etran);
if (wh != null) {
typeAntecedent = BplAnd(typeAntecedent, wh);
}
@@ -7055,7 +7100,7 @@ namespace Microsoft.Dafny { /// <summary>
/// Returns true iff 'expr' is a two-state expression, that is, if it mentions "old(...)" or "fresh(...)".
/// </summary>
- static bool MentionsOldState(Expression expr) {
+ public static bool MentionsOldState(Expression expr) {
Contract.Requires(expr != null);
if (expr is OldExpr || expr is FreshExpr) {
return true;
diff --git a/DafnyDriver/DafnyDriver.cs b/DafnyDriver/DafnyDriver.cs index 5e227011..4cf64788 100644 --- a/DafnyDriver/DafnyDriver.cs +++ b/DafnyDriver/DafnyDriver.cs @@ -346,7 +346,7 @@ namespace Microsoft.Dafny Bpl.Program programSnippet;
int errorCount;
try {
- errorCount = Microsoft.Boogie.Parser.Parse(bplFileName, null, out programSnippet);
+ errorCount = Microsoft.Boogie.Parser.Parse(bplFileName, (List<string>)null, out programSnippet);
if (programSnippet == null || errorCount != 0) {
Console.WriteLine("{0} parse errors detected in {1}", errorCount, bplFileName);
okay = false;
@@ -444,7 +444,7 @@ namespace Microsoft.Dafny inline = true;
}
}
- if (inline && CommandLineOptions.Clo.LazyInlining == 0 && CommandLineOptions.Clo.StratifiedInlining == 0) {
+ if (inline && CommandLineOptions.Clo.StratifiedInlining == 0) {
foreach (var d in TopLevelDeclarations) {
var impl = d as Implementation;
if (impl != null) {
diff --git a/Test/dafny0/Answer b/Test/dafny0/Answer index 6f160a66..a95eff5e 100644 --- a/Test/dafny0/Answer +++ b/Test/dafny0/Answer @@ -66,7 +66,6 @@ TypeTests.dfy(5,13): Error: incorrect type of function argument 1 (expected D, g TypeTests.dfy(11,15): Error: incorrect type of method in-parameter 0 (expected int, got bool)
TypeTests.dfy(12,11): Error: incorrect type of method out-parameter 0 (expected int, got C)
TypeTests.dfy(12,11): Error: incorrect type of method out-parameter 1 (expected C, got int)
-TypeTests.dfy(18,9): Error: because of cyclic dependencies among constructor argument types, no instances of datatype 'NeverendingList' can be constructed
TypeTests.dfy(44,9): Error: Assignment to array element is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
TypeTests.dfy(53,6): Error: Duplicate local-variable name: z
TypeTests.dfy(55,6): Error: Duplicate local-variable name: x
@@ -92,6 +91,7 @@ TypeTests.dfy(84,10): Error: cannot assign to a range of array elements (try the TypeTests.dfy(90,9): Error: sorry, cannot instantiate type parameter with a subrange type
TypeTests.dfy(91,8): Error: sorry, cannot instantiate 'array' type with a subrange type
TypeTests.dfy(92,8): Error: sorry, cannot instantiate 'array' type with a subrange type
+TypeTests.dfy(18,9): Error: because of cyclic dependencies among constructor argument types, no instances of datatype 'NeverendingList' can be constructed
34 resolution/type errors detected in TypeTests.dfy
-------------------- NatTypes.dfy --------------------
@@ -247,8 +247,47 @@ SmallTests.dfy(408,10): Error BP5003: A postcondition might not hold on this ret SmallTests.dfy(411,41): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon6_Else
+SmallTests.dfy(561,12): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Then
+ (0,0): anon2
+SmallTests.dfy(575,20): Error: left-hand sides 0 and 1 may refer to the same location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon27_Then
+ (0,0): anon28_Then
+ (0,0): anon4
+ (0,0): anon29_Then
+ (0,0): anon30_Then
+ (0,0): anon9
+ (0,0): anon31_Then
+ (0,0): anon32_Then
+ (0,0): anon12
+SmallTests.dfy(577,15): Error: left-hand sides 1 and 2 may refer to the same location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon27_Then
+ SmallTests.dfy(570,18): anon28_Else
+ (0,0): anon4
+ (0,0): anon29_Else
+ (0,0): anon7
+ (0,0): anon30_Then
+ (0,0): anon9
+ (0,0): anon31_Else
+ (0,0): anon35_Then
+ (0,0): anon36_Then
+ (0,0): anon37_Then
+ (0,0): anon22
+ (0,0): anon38_Then
+SmallTests.dfy(584,18): Error: target object may be null
+Execution trace:
+ (0,0): anon0
+SmallTests.dfy(597,10): Error: assertion violation
+Execution trace:
+ (0,0): anon0
-Dafny program verifier finished with 58 verified, 21 errors
+Dafny program verifier finished with 68 verified, 26 errors
-------------------- Definedness.dfy --------------------
Definedness.dfy(8,7): Error: possible division by zero
@@ -498,7 +537,9 @@ ResolutionErrors.dfy(305,16): Error: arguments must have the same type (got DTD_ ResolutionErrors.dfy(306,25): Error: arguments must have the same type (got bool and int)
ResolutionErrors.dfy(309,18): Error: ghost fields are allowed only in specification contexts
ResolutionErrors.dfy(318,15): Error: ghost variables are allowed only in specification contexts
-46 resolution/type errors detected in ResolutionErrors.dfy
+ResolutionErrors.dfy(343,2): Error: incorrect type of method in-parameter 1 (expected GenericClass<int>, got GenericClass<bool>)
+ResolutionErrors.dfy(355,18): Error: incorrect type of datatype constructor argument (found GList<_T0>, expected GList<int>)
+48 resolution/type errors detected in ResolutionErrors.dfy
-------------------- ParseErrors.dfy --------------------
ParseErrors.dfy(4,19): error: a chain cannot have more than one != operator
@@ -629,6 +670,15 @@ Execution trace: Dafny program verifier finished with 8 verified, 2 errors
-------------------- NonGhostQuantifiers.dfy --------------------
+NonGhostQuantifiers.dfy(146,4): Error: a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'c'
+NonGhostQuantifiers.dfy(150,4): Error: a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'c'
+NonGhostQuantifiers.dfy(155,4): Error: a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'c'
+NonGhostQuantifiers.dfy(160,4): Error: a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'c'
+NonGhostQuantifiers.dfy(164,4): Error: a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'c'
+NonGhostQuantifiers.dfy(168,4): Error: a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'c'
+NonGhostQuantifiers.dfy(173,4): Error: a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'c'
+NonGhostQuantifiers.dfy(178,4): Error: a quantifier involved in a function definition is not allowed to depend on the set of allocated references; Dafny's heuristics can't figure out a bound for the values of 'c'
+NonGhostQuantifiers.dfy(183,13): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'c'
NonGhostQuantifiers.dfy(13,5): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'n'
NonGhostQuantifiers.dfy(42,4): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'n'
NonGhostQuantifiers.dfy(46,4): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'd'
@@ -640,7 +690,7 @@ NonGhostQuantifiers.dfy(103,5): Error: quantifiers in non-ghost contexts must be NonGhostQuantifiers.dfy(111,10): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'y'
NonGhostQuantifiers.dfy(120,8): Error: quantifiers in non-ghost contexts must be compilable, but Dafny's heuristics can't figure out how to produce a bounded set of values for 'x'
NonGhostQuantifiers.dfy(137,8): Error: Assignment to non-ghost variable is not allowed in this context (because this is a ghost method or because the statement is guarded by a specification-only expression)
-11 resolution/type errors detected in NonGhostQuantifiers.dfy
+20 resolution/type errors detected in NonGhostQuantifiers.dfy
-------------------- AdvancedLHS.dfy --------------------
AdvancedLHS.dfy(32,23): Error: target object may be null
@@ -1037,7 +1087,9 @@ ParallelResolveErrors.dfy(86,20): Error: trying to break out of more loop levels ParallelResolveErrors.dfy(87,20): Error: break label is undefined or not in scope: OutsideLoop
ParallelResolveErrors.dfy(96,24): Error: trying to break out of more loop levels than there are enclosing loops
ParallelResolveErrors.dfy(97,24): Error: break label is undefined or not in scope: OutsideLoop
-14 resolution/type errors detected in ParallelResolveErrors.dfy
+ParallelResolveErrors.dfy(105,2): Warning: the conclusion of the body of this parallel statement will not be known outside the parallel statement; consider using an 'ensures' clause
+ParallelResolveErrors.dfy(106,9): Error: the body of the enclosing parallel statement is not allowed to update heap locations
+15 resolution/type errors detected in ParallelResolveErrors.dfy
-------------------- Parallel.dfy --------------------
Parallel.dfy(31,5): Error BP5002: A precondition for this call might not hold.
@@ -1220,6 +1272,20 @@ Execution trace: Dafny program verifier finished with 32 verified, 6 errors
+-------------------- Coinductive.dfy --------------------
+Coinductive.dfy(10,11): Error: because of cyclic dependencies among constructor argument types, no instances of datatype 'Rec_Forever' can be constructed
+Coinductive.dfy(13,11): Error: because of cyclic dependencies among constructor argument types, no instances of datatype 'D' can be constructed
+Coinductive.dfy(35,11): Error: because of cyclic dependencies among constructor argument types, no instances of datatype 'K' can be constructed
+Coinductive.dfy(61,11): Error: because of cyclic dependencies among constructor argument types, no instances of datatype 'NotFiniteEnough_Dt' can be constructed
+4 resolution/type errors detected in Coinductive.dfy
+
+-------------------- Corecursion.dfy --------------------
+Corecursion.dfy(15,13): Error: failure to decrease termination measure (note that only functions without side effects can called co-recursively)
+Execution trace:
+ (0,0): anon3_Else
+
+Dafny program verifier finished with 2 verified, 1 error
+
-------------------- TypeAntecedents.dfy --------------------
TypeAntecedents.dfy(32,13): Error: assertion violation
Execution trace:
@@ -1250,6 +1316,10 @@ Execution trace: Dafny program verifier finished with 12 verified, 3 errors
+-------------------- NoTypeArgs.dfy --------------------
+
+Dafny program verifier finished with 12 verified, 0 errors
+
-------------------- SplitExpr.dfy --------------------
Dafny program verifier finished with 5 verified, 0 errors
@@ -1353,8 +1423,24 @@ Refinement.dfy(93,3): Error BP5003: A postcondition might not hold on this retur Refinement.dfy(74,15): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon0
+Refinement.dfy(179,5): Error BP5003: A postcondition might not hold on this return path.
+Refinement.dfy(112,15): Related location: This is the postcondition that might not hold.
+Refinement.dfy(176,9): Related location: Related location
+Execution trace:
+ (0,0): anon0
+Refinement.dfy(183,5): Error BP5003: A postcondition might not hold on this return path.
+Refinement.dfy(120,15): Related location: This is the postcondition that might not hold.
+Refinement.dfy(176,9): Related location: Related location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon4_Then
+ (0,0): anon3
+Refinement.dfy(189,7): Error: assertion violation
+Refinement.dfy[IncorrectConcrete](128,24): Related location: Related location
+Execution trace:
+ (0,0): anon0
-Dafny program verifier finished with 28 verified, 6 errors
+Dafny program verifier finished with 48 verified, 9 errors
-------------------- RefinementErrors.dfy --------------------
RefinementErrors.dfy(27,17): Error: a refining method is not allowed to add preconditions
@@ -1367,9 +1453,8 @@ RefinementErrors.dfy(35,11): Error: type parameters are not allowed to be rename RefinementErrors.dfy(35,13): Error: type parameters are not allowed to be renamed from the names given in the function in the module being refined (expected 'C', found 'B')
RefinementErrors.dfy(36,23): Error: the type of parameter 'z' is different from the type of the same parameter in the corresponding function in the module it refines ('seq<C>' instead of 'set<C>')
RefinementErrors.dfy(37,9): Error: there is a difference in name of parameter 3 ('k' versus 'b') of function F compared to corresponding function in the module it refines
-RefinementErrors.dfy(46,11): Error: body of refining method is not yet supported
RefinementErrors.dfy(54,20): Error: a function can be changed into a function method in a refining module only if the function has not yet been given a body: G
-12 resolution/type errors detected in RefinementErrors.dfy
+11 resolution/type errors detected in RefinementErrors.dfy
-------------------- ReturnErrors.dfy --------------------
ReturnErrors.dfy(30,10): Error: cannot have method call in return statement.
@@ -1424,7 +1509,7 @@ Execution trace: (0,0): anon0
(0,0): anon11_Then
-Dafny program verifier finished with 13 verified, 2 errors
+Dafny program verifier finished with 19 verified, 2 errors
-------------------- Predicates.dfy --------------------
Predicates.dfy[B](18,5): Error BP5003: A postcondition might not hold on this return path.
@@ -1455,6 +1540,20 @@ Execution trace: Dafny program verifier finished with 52 verified, 6 errors
+-------------------- Skeletons.dfy --------------------
+Skeletons.dfy(42,3): Error BP5003: A postcondition might not hold on this return path.
+Skeletons.dfy(41,15): Related location: This is the postcondition that might not hold.
+Execution trace:
+ (0,0): anon0
+ Skeletons.dfy[C0](29,5): anon12_LoopHead
+ (0,0): anon12_LoopBody
+ Skeletons.dfy[C0](29,5): anon13_Else
+ (0,0): anon9
+ Skeletons.dfy[C0](34,19): anon16_Else
+ (0,0): anon11
+
+Dafny program verifier finished with 9 verified, 1 error
+
-------------------- SmallTests.dfy --------------------
SmallTests.dfy(30,11): Error: index out of range
Execution trace:
@@ -1563,8 +1662,47 @@ SmallTests.dfy(408,10): Error BP5003: A postcondition might not hold on this ret SmallTests.dfy(411,41): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon6_Else
+SmallTests.dfy(561,12): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Then
+ (0,0): anon2
+SmallTests.dfy(575,20): Error: left-hand sides 0 and 1 may refer to the same location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon27_Then
+ (0,0): anon28_Then
+ (0,0): anon4
+ (0,0): anon29_Then
+ (0,0): anon30_Then
+ (0,0): anon9
+ (0,0): anon31_Then
+ (0,0): anon32_Then
+ (0,0): anon12
+SmallTests.dfy(577,15): Error: left-hand sides 1 and 2 may refer to the same location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon27_Then
+ SmallTests.dfy(570,18): anon28_Else
+ (0,0): anon4
+ (0,0): anon29_Else
+ (0,0): anon7
+ (0,0): anon30_Then
+ (0,0): anon9
+ (0,0): anon31_Else
+ (0,0): anon35_Then
+ (0,0): anon36_Then
+ (0,0): anon37_Then
+ (0,0): anon22
+ (0,0): anon38_Then
+SmallTests.dfy(584,18): Error: target object may be null
+Execution trace:
+ (0,0): anon0
+SmallTests.dfy(597,10): Error: assertion violation
+Execution trace:
+ (0,0): anon0
-Dafny program verifier finished with 58 verified, 21 errors
+Dafny program verifier finished with 68 verified, 26 errors
out.tmp.dfy(33,11): Error: index out of range
Execution trace:
(0,0): anon0
@@ -1672,8 +1810,47 @@ out.tmp.dfy(469,10): Error BP5003: A postcondition might not hold on this return out.tmp.dfy(470,41): Related location: This is the postcondition that might not hold.
Execution trace:
(0,0): anon6_Else
+out.tmp.dfy(507,12): Error: assertion violation
+Execution trace:
+ (0,0): anon0
+ (0,0): anon3_Then
+ (0,0): anon2
+out.tmp.dfy(521,20): Error: left-hand sides 0 and 1 may refer to the same location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon27_Then
+ (0,0): anon28_Then
+ (0,0): anon4
+ (0,0): anon29_Then
+ (0,0): anon30_Then
+ (0,0): anon9
+ (0,0): anon31_Then
+ (0,0): anon32_Then
+ (0,0): anon12
+out.tmp.dfy(523,15): Error: left-hand sides 1 and 2 may refer to the same location
+Execution trace:
+ (0,0): anon0
+ (0,0): anon27_Then
+ out.tmp.dfy(516,18): anon28_Else
+ (0,0): anon4
+ (0,0): anon29_Else
+ (0,0): anon7
+ (0,0): anon30_Then
+ (0,0): anon9
+ (0,0): anon31_Else
+ (0,0): anon35_Then
+ (0,0): anon36_Then
+ (0,0): anon37_Then
+ (0,0): anon22
+ (0,0): anon38_Then
+out.tmp.dfy(530,18): Error: target object may be null
+Execution trace:
+ (0,0): anon0
+out.tmp.dfy(543,10): Error: assertion violation
+Execution trace:
+ (0,0): anon0
-Dafny program verifier finished with 58 verified, 21 errors
+Dafny program verifier finished with 68 verified, 26 errors
-------------------- LetExpr.dfy --------------------
LetExpr.dfy(5,12): Error: assertion violation
@@ -1684,7 +1861,7 @@ Execution trace: (0,0): anon0
(0,0): anon11_Then
-Dafny program verifier finished with 13 verified, 2 errors
+Dafny program verifier finished with 19 verified, 2 errors
out.tmp.dfy(10,12): Error: assertion violation
Execution trace:
(0,0): anon0
@@ -1693,4 +1870,7 @@ Execution trace: (0,0): anon0
(0,0): anon11_Then
-Dafny program verifier finished with 13 verified, 2 errors
+Dafny program verifier finished with 19 verified, 2 errors
+
+Dafny program verifier finished with 6 verified, 0 errors
+Compiled assembly into Compilation.exe
diff --git a/Test/dafny0/Coinductive.dfy b/Test/dafny0/Coinductive.dfy new file mode 100644 index 00000000..35f17c1c --- /dev/null +++ b/Test/dafny0/Coinductive.dfy @@ -0,0 +1,65 @@ +// --------------------------------------------------
+
+module TestInductiveDatatypes
+{
+ // The following types test for cycles that go via instantiated type arguments
+
+ datatype Record<T> = Ctor(T);
+
+ datatype RecInt = Ctor(Record<int>); // this is fine
+ datatype Rec_Forever = Ctor(Record<Rec_Forever>); // error
+ datatype Rec_Stops = Cons(Record<Rec_Stops>, Rec_Stops) | Nil; // this is okay
+
+ datatype D<T> = Ctor(E<D<T>>); // error: illegal cycle
+ datatype E<T> = Ctor(T);
+
+ // the following is okay
+ datatype MD<T> = Ctor(ME<T>);
+ datatype ME<T> = Ctor(T);
+ method M()
+ {
+ var d: MD<MD<int>>;
+ }
+
+ datatype A = Ctor(B); // superficially looks like a cycle, but can still be constructed
+ datatype B = Ctor(List<A>);
+ datatype List<T> = Nil | Cons(T, List);
+}
+
+module MoreInductive {
+ datatype Tree<G> = Node(G, List<Tree<G>>);
+ datatype List<T> = Nil | Cons(T, List<T>);
+
+ datatype M = All(List<M>);
+ datatype H<'a> = HH('a, Tree<'a>);
+ datatype K<'a> = KK('a, Tree<K<'a>>); // error
+ datatype L<'a> = LL('a, Tree<List<L<'a>>>);
+}
+
+// --------------------------------------------------
+
+module TestCoinductiveDatatypes
+{
+ codatatype InfList<T> = Done | Continue(T, InfList);
+
+ codatatype Stream<T> = More(T, Stream<T>);
+
+ codatatype BinaryTreeForever<T> = BNode(val: T, left: BinaryTreeForever<T>, right: BinaryTreeForever<T>);
+
+ datatype List<T> = Nil | Cons(T, List);
+
+ codatatype BestBushEver<T> = Node(value: T, branches: List<BestBushEver<T>>);
+
+ codatatype LazyRecord<T> = Lazy(contents: T);
+ class MyClass<T> { }
+ datatype GenericDt<T> = Blue | Green(T);
+ datatype GenericRecord<T> = Rec(T);
+
+ datatype FiniteEnough_Class = Ctor(MyClass<FiniteEnough_Class>);
+ datatype FiniteEnough_Co = Ctor(LazyRecord<FiniteEnough_Co>);
+ datatype FiniteEnough_Dt = Ctor(GenericDt<FiniteEnough_Dt>); // fine
+ datatype NotFiniteEnough_Dt = Ctor(GenericRecord<NotFiniteEnough_Dt>); // error
+
+}
+
+// --------------------------------------------------
diff --git a/Test/dafny0/Compilation.dfy b/Test/dafny0/Compilation.dfy new file mode 100644 index 00000000..bf21432f --- /dev/null +++ b/Test/dafny0/Compilation.dfy @@ -0,0 +1,59 @@ +// The tests in this file are designed to run through the compiler. They contain
+// program snippets that are tricky to compile or whose compilation once was buggy.
+
+module OnceBuggy {
+ datatype MyDt<T> = Nil | Cons(T, MyDt<T>);
+
+ method M<U>(x: MyDt<int>)
+ {
+ match (x) {
+ case Cons(head, tail) =>
+ var y: int := head;
+ case Nil =>
+ }
+ }
+}
+
+// --------------------------------------------------
+
+module CoRecursion {
+ codatatype Stream<T> = More(head: T, rest: Stream);
+
+ function method AscendingChain(n: int): Stream<int>
+ {
+ More(n, AscendingChain(n+1))
+ }
+
+ datatype List<T> = Nil | Cons(car: T, cdr: List);
+
+ function method Prefix(n: nat, s: Stream): List
+ {
+ if n == 0 then Nil else
+ Cons(s.head, Prefix(n-1, s.rest))
+ }
+
+ class Cell { var data: int; }
+
+ // When run, the following method should print
+ // 400
+ // 320
+ // 40
+ // 41
+ // 42
+ method Main() {
+ var m := 17;
+ var cell := new Cell;
+ cell.data := 40;
+ var mr := More(400, More(320, AscendingChain(cell.data)));
+ m := 30;
+ cell.data := 60;
+ var l := Prefix(5, mr);
+ while (l != Nil)
+ decreases l;
+ {
+ match (l) { case Cons(x,y) => }
+ print l.car, "\n";
+ l := l.cdr;
+ }
+ }
+}
diff --git a/Test/dafny0/Corecursion.dfy b/Test/dafny0/Corecursion.dfy new file mode 100644 index 00000000..decb68fc --- /dev/null +++ b/Test/dafny0/Corecursion.dfy @@ -0,0 +1,27 @@ +
+// --------------------------------------------------
+
+module CoRecursion {
+ codatatype Stream<T> = More(head: T, rest: Stream);
+
+ function AscendingChain(n: int): Stream<int>
+ {
+ More(n, AscendingChain(n+1))
+ }
+
+ function AscendingChainAndRead(n: int): Stream<int>
+ reads this; // with a reads clause, this function is not a co-recusvie function
+ {
+ More(n, AscendingChainAndRead(n+1)) // error: cannot prove termination
+ }
+
+ datatype List<T> = Nil | Cons(T, List);
+
+ function Prefix(n: nat, s: Stream): List
+ {
+ if n == 0 then Nil else
+ Cons(s.head, Prefix(n-1, s.rest))
+ }
+}
+
+// --------------------------------------------------
diff --git a/Test/dafny0/LetExpr.dfy b/Test/dafny0/LetExpr.dfy index 48e4810b..11bf4fbe 100644 --- a/Test/dafny0/LetExpr.dfy +++ b/Test/dafny0/LetExpr.dfy @@ -107,3 +107,43 @@ method PMain(a: array<int>) assert index == old(index) ==> a[index] == 21 && old(a[index]) == 19;
}
}
+
+// ---------- lemmas ----------
+
+method Theorem0(n: int)
+ requires 1 <= n;
+ ensures 1 <= Fib(n);
+{
+ if (n < 3) {
+ } else {
+ Theorem0(n-2);
+ Theorem0(n-1);
+ }
+}
+
+ghost method Theorem1(n: int)
+ requires 1 <= n;
+ ensures 1 <= Fib(n);
+{
+ // in a ghost method, the induction tactic takes care of it
+}
+
+function Theorem2(n: int): int
+ requires 1 <= n;
+ ensures 1 <= Fib(n);
+{
+ if n < 3 then 5 else
+ var x := Theorem2(n-2);
+ var y := Theorem2(n-1);
+ x + y
+}
+
+function Theorem3(n: int): int
+ requires 1 <= n;
+ ensures 1 <= Fib(n);
+{
+ if n < 3 then 5 else
+ var x := Theorem3(n-2);
+ var y := Theorem3(n-1);
+ 5
+}
diff --git a/Test/dafny0/NoTypeArgs.dfy b/Test/dafny0/NoTypeArgs.dfy new file mode 100644 index 00000000..c41c7990 --- /dev/null +++ b/Test/dafny0/NoTypeArgs.dfy @@ -0,0 +1,82 @@ +datatype List<T> = Nil | Cons(hd: T, tl: List);
+
+method M0() {
+ var l: List;
+ l := Cons(5, Nil);
+ assert l.hd == 5;
+
+ var k: MyClass<bool>;
+ k := new MyClass;
+ k.data := false;
+
+ var h := new MyClass;
+ h.data := false;
+
+ var y := new MyClass.Init(120);
+ var z: int := y.data;
+}
+
+method M1() { // same thing as above, but with types filled in explicitly
+ var l: List<int>;
+ l := Cons(5, Nil);
+ assert l.hd == 5;
+
+ var k: MyClass<bool>;
+ k := new MyClass<bool>;
+ k.data := false;
+
+ var h := new MyClass<bool>;
+ h.data := false;
+
+ var y := new MyClass<int>.Init(120);
+ var z: int := y.data;
+}
+
+class MyClass<G> {
+ var data: G;
+ method Init(g: G)
+ modifies this;
+ {
+ data := g;
+ }
+}
+
+// ---------------------------------------------------
+
+// The followinng functions and methods are oblivious of the fact that
+// List takes a type parameter.
+
+function concat(xs: List, ys: List): List
+{
+ match xs
+ case Nil => ys
+ case Cons(x, tail) => Cons(x, concat(tail, ys))
+}
+
+function reverse(xs: List): List
+{
+ match xs
+ case Nil => Nil
+ case Cons(t, rest) => concat(reverse(rest), Cons(t, Nil))
+}
+
+ghost method Theorem(xs: List)
+ ensures reverse(reverse(xs)) == xs;
+{
+ match (xs) {
+ case Nil =>
+ case Cons(t, rest) =>
+ Lemma(reverse(rest), Cons(t, Nil));
+ }
+}
+
+ghost method Lemma(xs: List, ys: List)
+ ensures reverse(concat(xs, ys)) == concat(reverse(ys), reverse(xs));
+{
+ match (xs) {
+ case Nil =>
+ assert forall ws :: concat(ws, Nil) == ws;
+ case Cons(t, rest) =>
+ assert forall a, b, c :: concat(a, concat(b, c)) == concat(concat(a, b), c);
+ }
+}
diff --git a/Test/dafny0/NonGhostQuantifiers.dfy b/Test/dafny0/NonGhostQuantifiers.dfy index 58e64827..dc938496 100644 --- a/Test/dafny0/NonGhostQuantifiers.dfy +++ b/Test/dafny0/NonGhostQuantifiers.dfy @@ -138,3 +138,54 @@ class MyClass<T> { }
}
}
+
+// The following functions test what was once a soundness problem
+module DependencyOnAllAllocatedObjects {
+ function AllObjects0(): bool
+ {
+ forall c: SomeClass :: c != null ==> c.f == 0 // error: not allowed to dependend on which objects are allocated
+ }
+ function AllObjects1(): bool
+ {
+ forall c: SomeClass :: true // error: not allowed to dependend on which objects are allocated
+ }
+ function AllObjects10(): bool
+ reads *;
+ {
+ forall c: SomeClass :: c != null ==> c.f == 0 // error: not allowed to dependend on which objects are allocated
+ }
+ function AllObjects11(): bool
+ reads *;
+ {
+ forall c: SomeClass :: true // error: not allowed to dependend on which objects are allocated
+ }
+ function method AllObjects20(): bool
+ {
+ forall c: SomeClass :: c != null ==> c.f == 0 // error: not allowed to dependend on which objects are allocated
+ }
+ function method AllObjects21(): bool
+ {
+ forall c: SomeClass :: true // error: not allowed to dependend on which objects are allocated
+ }
+ function method AllObjects30(): bool
+ reads *;
+ {
+ forall c: SomeClass :: c != null ==> c.f == 0 // error: not allowed to dependend on which objects are allocated
+ }
+ function method AllObjects31(): bool
+ reads *;
+ {
+ forall c: SomeClass :: true // error: not allowed to dependend on which objects are allocated
+ }
+
+ method M()
+ {
+ var b := forall c: SomeClass :: c != null ==> c.f == 0; // error: non-ghost code requires bounds
+ ghost var g := forall c: SomeClass :: c != null ==> c.f == 0; // cool (this is in a ghost context
+ // outside a function)
+ }
+
+ class SomeClass {
+ var f: int;
+ }
+}
diff --git a/Test/dafny0/ParallelResolveErrors.dfy b/Test/dafny0/ParallelResolveErrors.dfy index 98f1ae3a..ab711d02 100644 --- a/Test/dafny0/ParallelResolveErrors.dfy +++ b/Test/dafny0/ParallelResolveErrors.dfy @@ -99,3 +99,10 @@ method M1() { }
}
}
+
+method M2() {
+ var a := new int[100];
+ parallel (x | 0 <= x < 100) {
+ a[x] :| a[x] > 0; // error: not allowed to update heap location in a parallel statement with a(n implicit) assume
+ }
+}
diff --git a/Test/dafny0/Refinement.dfy b/Test/dafny0/Refinement.dfy index 280227f1..da7f0ac2 100644 --- a/Test/dafny0/Refinement.dfy +++ b/Test/dafny0/Refinement.dfy @@ -25,7 +25,7 @@ module B refines A { } method M(x: int) returns (y: int) ensures y % 2 == 0; // add a postcondition - method Q() returns (q: int, r: int, s: int) + method Q ... ensures 12 <= r; ensures 1200 <= s; // error: postcondition is not established by // inherited method body @@ -44,7 +44,7 @@ module A_AnonymousClass { } module B_AnonymousClass refines A_AnonymousClass { - method Increment(d: int) + method Increment... ensures x <= old(x) + d; } @@ -96,10 +96,10 @@ module FullBodied refines BodyFree { } // ------------------------------------------------ -/* SOON + module Abstract { class MyNumber { - var N: int; + ghost var N: int; ghost var Repr: set<object>; predicate Valid reads this, Repr; @@ -125,7 +125,8 @@ module Abstract { requires Valid; ensures n == N; { - n := N; + var k; assume k == N; + n := k; } } } @@ -148,7 +149,8 @@ module Concrete refines Abstract { } method Get() returns (n: int) { - n := a - b; + var k := a - b; + assert ...; } } } @@ -164,4 +166,27 @@ module Client imports Concrete { } } } -*/ + +module IncorrectConcrete refines Abstract { + class MyNumber { + var a: int; + var b: int; + predicate Valid + { + N == 2*a - b + } + constructor Init() + { // error: postcondition violation + a := b; + } + method Inc() + { // error: postcondition violation + if (*) { a := a + 1; } else { b := b - 1; } + } + method Get() returns (n: int) + { + var k := a - b; + assert ...; // error: assertion violation + } + } +} diff --git a/Test/dafny0/RefinementErrors.dfy b/Test/dafny0/RefinementErrors.dfy index 25ba94ad..df6f1a71 100644 --- a/Test/dafny0/RefinementErrors.dfy +++ b/Test/dafny0/RefinementErrors.dfy @@ -44,7 +44,7 @@ module B refines A { { // yes, can give it a body } method FullBodied(x: int) returns (y: bool, k: seq<set<object>>) - { // error: not allowed to change body (not yet implemented) + { } } } diff --git a/Test/dafny0/ResolutionErrors.dfy b/Test/dafny0/ResolutionErrors.dfy index 34cfc762..274cc95a 100644 --- a/Test/dafny0/ResolutionErrors.dfy +++ b/Test/dafny0/ResolutionErrors.dfy @@ -317,3 +317,40 @@ method PrintOnlyNonGhosts(a: int, ghost b: int) print "a: ", a, "\n";
print "b: ", b, "\n"; // error: print statement cannot take ghosts
}
+
+// ------------------- auto-added type arguments ------------------------------
+
+class GenericClass<T> { var data: T; }
+
+method MG0(a: GenericClass, b: GenericClass)
+ requires a != null && b != null;
+ modifies a;
+{
+ a.data := b.data; // allowed, since both a and b get the same auto type argument
+}
+
+method G_Caller()
+{
+ var x := new GenericClass;
+ MG0(x, x); // fine
+ var y := new GenericClass;
+ MG0(x, y); // also fine (and now y's type argument is constrained to be that of x's)
+ var z := new GenericClass<int>;
+ y.data := z.data; // this will have the effect of unifying all type args so far to be 'int'
+ assert x.data == 5; // this is type correct
+
+ var w := new GenericClass<bool>;
+ MG0(x, w); // error: types don't match up
+}
+
+datatype GList<T> = GNil | GCons(hd: T, tl: GList);
+
+method MG1(l: GList, n: nat)
+{
+ if (n != 0) {
+ MG1(l, n-1);
+ MG1(GCons(12, GCons(20, GNil)), n-1);
+ }
+ var t := GCons(100, GNil);
+ t := GCons(120, l); // error: types don't match up (List<T$0> versus List<int>)
+}
diff --git a/Test/dafny0/Skeletons.dfy b/Test/dafny0/Skeletons.dfy new file mode 100644 index 00000000..e9fef946 --- /dev/null +++ b/Test/dafny0/Skeletons.dfy @@ -0,0 +1,63 @@ +module A { + method M(p: int) returns (y: int) + requires p <= 30; + { + assume p < 100; + var x; + assume x == p + 20; + x := x + 1; + while (*) + invariant x <= 120; + decreases 120 - x; + { + if (x == 120) { break; } + x := x + 1; + } + y := x; + } +} + +module B refines A { + method M ... + { + assert p < 50; + assert ...; + var x := p + 20; + assert ...; + var k := x + 1; + ...; + while ... + invariant k == x; + { + k := k + 1; + } + assert k == x || k == x + 1; // there are two exits from the loop + } +} + + +module C0 refines B { + method M ... + ensures y == 120; // error: this holds only if the loop does not end early + { + } +} + +module C1 refines B { + method M ... + ensures y <= 120; + { + } +} + +module C2 refines B { + method M ... + ensures y == 120; + { + ...; + while (true) + ... + assert k == x + 1; // only one loop exit remains + ...; + } +} diff --git a/Test/dafny0/SmallTests.dfy b/Test/dafny0/SmallTests.dfy index 914e228e..4d219cd3 100644 --- a/Test/dafny0/SmallTests.dfy +++ b/Test/dafny0/SmallTests.dfy @@ -535,3 +535,71 @@ static method TestNotNot() assert true == !(!true);
}
+
+// ----------------------- Assign-such-that statements -------
+
+method AssignSuchThat0(a: int, b: int) returns (x: int, y: int)
+ ensures x == a && y == b;
+{
+ if (*) {
+ x, y :| a <= x < a + 1 && b + a <= y + a && y <= b;
+ } else {
+ var xx, yy :| a <= xx < a + 1 && b + a <= yy + a && yy <= b;
+ x, y := xx, yy;
+ }
+}
+
+method AssignSuchThat1(a: int, b: int) returns (x: int, y: int)
+{
+ var k :| 0 <= k < a - b; // this acts like an 'assume 0 < a - b;'
+ assert b < a;
+ k :| k == old(2*k); // note, the 'old' has no effect on local variables like k
+ assert k == 0;
+ var S := {2, 4, 7};
+ var T :| T <= S;
+ assert 3 !in T;
+ assert T == {}; // error: T may be larger
+}
+
+method AssignSuchThat2(i: int, j: int, ghost S: set<Node>)
+ modifies S;
+{
+ var n := new Node;
+ var a := new int[25];
+ var t;
+ if (0 <= i < j < 25) {
+ a[i], t, a[j], n.next, n :| true;
+ }
+ if (n != null && n.next != null) {
+ assume n in S && n.next in S;
+ n.next.next, n.next :| n != null && n.next != null && n.next.next == n.next; // error: n.next may equal n (thus aliasing n.next.next and n.next)
+ } else if (0 <= i < 25 && 0 <= j < 25) {
+ t, a[i], a[j] :| t < a[i] < a[j]; // error: i may equal j (thus aliasing a[i] and a[j])
+ }
+}
+
+method AssignSuchThat3()
+{
+ var n := new Node;
+ n, n.next :| n.next == n; // error: RHS is not well defined (RHS is evaluated after the havocking of the LHS)
+}
+
+method AssignSuchThat4()
+{
+ var n := new Node;
+ n, n.next :| n != null && n.next == n; // that's the ticket
+}
+
+method AssignSuchThat5()
+{
+ var n := new Node;
+ n :| fresh(n); // fine
+ assert false; // error
+}
+
+method AssignSuchThat6()
+{
+ var n: Node;
+ n :| n != null && fresh(n); // there is no non-null fresh object, so this amounts to 'assume false;'
+ assert false; // no problemo
+}
diff --git a/Test/dafny0/runtest.bat b/Test/dafny0/runtest.bat index d09e1cc2..fa81bb8c 100644 --- a/Test/dafny0/runtest.bat +++ b/Test/dafny0/runtest.bat @@ -17,11 +17,12 @@ for %%f in (TypeTests.dfy NatTypes.dfy SmallTests.dfy Definedness.dfy ModulesCycle.dfy Modules0.dfy Modules1.dfy BadFunction.dfy
Comprehensions.dfy Basics.dfy ControlStructures.dfy
Termination.dfy DTypes.dfy ParallelResolveErrors.dfy Parallel.dfy
- TypeParameters.dfy Datatypes.dfy TypeAntecedents.dfy SplitExpr.dfy
+ TypeParameters.dfy Datatypes.dfy Coinductive.dfy Corecursion.dfy
+ TypeAntecedents.dfy NoTypeArgs.dfy SplitExpr.dfy
LoopModifies.dfy Refinement.dfy RefinementErrors.dfy
ReturnErrors.dfy ReturnTests.dfy ChainingDisjointTests.dfy
CallStmtTests.dfy MultiSets.dfy PredExpr.dfy LetExpr.dfy
- Predicates.dfy) do (
+ Predicates.dfy Skeletons.dfy) do (
echo.
echo -------------------- %%f --------------------
%DAFNY_EXE% /compile:0 /print:out.bpl.tmp /dprint:out.dfy.tmp %* %%f
@@ -33,3 +34,5 @@ for %%f in (SmallTests.dfy LetExpr.dfy) do ( %DAFNY_EXE% /compile:0 /dprint:out.tmp.dfy %* %%f
%DAFNY_EXE% /compile:0 %* out.tmp.dfy
)
+
+%DAFNY_EXE% %* Compilation.dfy
diff --git a/Test/dafny1/Answer b/Test/dafny1/Answer index ab10d944..023d80df 100644 --- a/Test/dafny1/Answer +++ b/Test/dafny1/Answer @@ -15,6 +15,10 @@ Dafny program verifier finished with 24 verified, 0 errors Dafny program verifier finished with 11 verified, 0 errors
+-------------------- ExtensibleArrayAuto.dfy --------------------
+
+Dafny program verifier finished with 11 verified, 0 errors
+
-------------------- BinaryTree.dfy --------------------
Dafny program verifier finished with 24 verified, 0 errors
diff --git a/Test/dafny1/ExtensibleArrayAuto.dfy b/Test/dafny1/ExtensibleArrayAuto.dfy new file mode 100644 index 00000000..f7f97deb --- /dev/null +++ b/Test/dafny1/ExtensibleArrayAuto.dfy @@ -0,0 +1,113 @@ +class {:autocontracts} ExtensibleArray<T> {
+ ghost var Contents: seq<T>;
+
+ var elements: array<T>;
+ var more: ExtensibleArray<array<T>>;
+ var length: int;
+ var M: int; // shorthand for: if more == null then 0 else 256 * |more.Contents|
+
+ function Valid(): bool
+ {
+ // shape of data structure
+ elements != null && elements.Length == 256 &&
+ (more != null ==>
+ elements !in more.Repr &&
+ more.Valid() &&
+ |more.Contents| != 0 &&
+ forall j :: 0 <= j && j < |more.Contents| ==>
+ more.Contents[j] != null && more.Contents[j].Length == 256 &&
+ more.Contents[j] in Repr && more.Contents[j] !in more.Repr &&
+ more.Contents[j] != elements &&
+ forall k :: 0 <= k && k < |more.Contents| && k != j ==> more.Contents[j] != more.Contents[k]) &&
+
+ // length
+ M == (if more == null then 0 else 256 * |more.Contents|) &&
+ 0 <= length && length <= M + 256 &&
+ (more != null ==> M < length) &&
+
+ // Contents
+ length == |Contents| &&
+ (forall i :: 0 <= i && i < M ==> Contents[i] == more.Contents[i / 256][i % 256]) &&
+ (forall i :: M <= i && i < length ==> Contents[i] == elements[i - M])
+ }
+
+ constructor Init()
+ ensures Contents == [];
+ {
+ elements := new T[256];
+ more := null;
+ length := 0;
+ M := 0;
+
+ Contents := [];
+ }
+
+ method Get(i: int) returns (t: T)
+ requires 0 <= i && i < |Contents|;
+ ensures t == Contents[i];
+ decreases Repr;
+ {
+ if (M <= i) {
+ t := elements[i - M];
+ } else {
+ var arr := more.Get(i / 256);
+ t := arr[i % 256];
+ }
+ }
+
+ method Set(i: int, t: T)
+ requires 0 <= i && i < |Contents|;
+ ensures Contents == old(Contents)[i := t];
+ {
+ if (M <= i) {
+ elements[i - M] := t;
+ } else {
+ var arr := more.Get(i / 256);
+ arr[i % 256] := t;
+ }
+ Contents := Contents[i := t];
+ }
+
+ method Append(t: T)
+ ensures Contents == old(Contents) + [t];
+ decreases Repr;
+ {
+ if (length == 0 || length % 256 != 0) {
+ // there is room in "elements"
+ elements[length - M] := t;
+ } else {
+ if (more == null) {
+ more := new ExtensibleArray<array<T>>.Init();
+ Repr := Repr + {more} + more.Repr;
+ }
+ // "elements" is full, so move it into "more" and allocate a new array
+ more.Append(elements);
+ Repr := Repr + more.Repr;
+ M := M + 256;
+ elements := new T[256];
+ Repr := Repr + {elements};
+ elements[0] := t;
+ }
+ length := length + 1;
+ Contents := Contents + [t];
+ }
+}
+
+method Main() {
+ var a := new ExtensibleArray<int>.Init();
+ var n := 0;
+ while (n < 256*256+600)
+ invariant a.Valid() && fresh(a.Repr);
+ invariant |a.Contents| == n;
+ {
+ a.Append(n);
+ n := n + 1;
+ }
+ var k := a.Get(570); print k, "\n";
+ k := a.Get(0); print k, "\n";
+ k := a.Get(1000); print k, "\n";
+ a.Set(1000, 23);
+ k := a.Get(0); print k, "\n";
+ k := a.Get(1000); print k, "\n";
+ k := a.Get(66000); print k, "\n";
+}
diff --git a/Test/dafny1/runtest.bat b/Test/dafny1/runtest.bat index 524765cf..0ad75ffa 100644 --- a/Test/dafny1/runtest.bat +++ b/Test/dafny1/runtest.bat @@ -12,7 +12,8 @@ for %%f in (BQueue.bpl) do ( %BPLEXE% %* %%f
)
-for %%f in (Queue.dfy PriorityQueue.dfy ExtensibleArray.dfy
+for %%f in (Queue.dfy PriorityQueue.dfy
+ ExtensibleArray.dfy ExtensibleArrayAuto.dfy
BinaryTree.dfy
UnboundedStack.dfy
SeparationLogicList.dfy
diff --git a/Test/dafny2/Answer b/Test/dafny2/Answer index ea481dae..381b9cb1 100644 --- a/Test/dafny2/Answer +++ b/Test/dafny2/Answer @@ -30,3 +30,7 @@ Dafny program verifier finished with 23 verified, 0 errors -------------------- Intervals.dfy --------------------
Dafny program verifier finished with 5 verified, 0 errors
+
+-------------------- StoreAndRetrieve.dfy --------------------
+
+Dafny program verifier finished with 22 verified, 0 errors
diff --git a/Test/dafny2/StoreAndRetrieve.dfy b/Test/dafny2/StoreAndRetrieve.dfy new file mode 100644 index 00000000..ea26a234 --- /dev/null +++ b/Test/dafny2/StoreAndRetrieve.dfy @@ -0,0 +1,72 @@ +module A imports Library {
+ class {:autocontracts} StoreAndRetrieve<Thing> {
+ ghost var Contents: set<Thing>;
+ predicate Valid
+ {
+ true
+ }
+ constructor Init()
+ {
+ Contents := {};
+ }
+ method Store(t: Thing)
+ {
+ Contents := Contents + {t};
+ }
+ method Retrieve(matchCriterion: Function) returns (thing: Thing)
+ requires exists t :: t in Contents && Function.Apply(matchCriterion, t);
+ ensures Contents == old(Contents);
+ ensures thing in Contents && Function.Apply(matchCriterion, thing);
+ {
+ var k :| k in Contents && Function.Apply(matchCriterion, k);
+ thing := k;
+ }
+ }
+}
+
+module B refines A {
+ class StoreAndRetrieve<Thing> {
+ var arr: seq<Thing>;
+ predicate Valid
+ {
+ Contents == set x | x in arr
+ }
+ constructor Init()
+ {
+ arr := [];
+ }
+ method Store...
+ {
+ arr := arr + [t];
+ }
+ method Retrieve...
+ {
+ var i := 0;
+ while (i < |arr|)
+ invariant i < |arr|;
+ invariant forall j :: 0 <= j < i ==> !Function.Apply(matchCriterion, arr[j]);
+ {
+ if (Function.Apply(matchCriterion, arr[i])) { break; }
+ i := i + 1;
+ }
+ var k := arr[i];
+ }
+ }
+}
+
+module C refines B {
+ class StoreAndRetrieve<Thing> {
+ method Retrieve...
+ {
+ ...;
+ arr := [thing] + arr[..i] + arr[i+1..]; // LRU behavior
+ }
+ }
+}
+
+module Library {
+ // This class simulates function parameters
+ class Function {
+ static function method Apply<T>(f: Function, t: T): bool
+ }
+}
diff --git a/Test/dafny2/runtest.bat b/Test/dafny2/runtest.bat index 79ee0f89..a4796939 100644 --- a/Test/dafny2/runtest.bat +++ b/Test/dafny2/runtest.bat @@ -15,6 +15,7 @@ for %%f in ( COST-verif-comp-2011-3-TwoDuplicates.dfy
COST-verif-comp-2011-4-FloydCycleDetect.dfy
Intervals.dfy
+ StoreAndRetrieve.dfy
) do (
echo.
echo -------------------- %%f --------------------
diff --git a/Test/vstte2012/Answer b/Test/vstte2012/Answer index 15a95de1..bca270c3 100644 --- a/Test/vstte2012/Answer +++ b/Test/vstte2012/Answer @@ -11,6 +11,10 @@ Dafny program verifier finished with 25 verified, 0 errors Dafny program verifier finished with 13 verified, 0 errors
+-------------------- RingBufferAuto.dfy --------------------
+
+Dafny program verifier finished with 13 verified, 0 errors
+
-------------------- Tree.dfy --------------------
Dafny program verifier finished with 15 verified, 0 errors
diff --git a/Test/vstte2012/RingBufferAuto.dfy b/Test/vstte2012/RingBufferAuto.dfy new file mode 100644 index 00000000..712236a8 --- /dev/null +++ b/Test/vstte2012/RingBufferAuto.dfy @@ -0,0 +1,75 @@ +class {:autocontracts} RingBuffer<T>
+{
+ // public view of the class:
+ ghost var Contents: seq<T>; // the contents of the ring buffer
+ ghost var N: nat; // the capacity of the ring buffer
+
+ // private implementation:
+ var data: array<T>;
+ var first: nat;
+ var len: nat;
+
+ // Valid encodes the consistency of RingBuffer objects (think, invariant)
+ predicate Valid
+ {
+ data != null &&
+ data.Length == N &&
+ (N == 0 ==> len == first == 0 && Contents == []) &&
+ (N != 0 ==> len <= N && first < N) &&
+ Contents == if first + len <= N then data[first..first+len]
+ else data[first..] + data[..first+len-N]
+ }
+
+ constructor Create(n: nat)
+ ensures Contents == [] && N == n;
+ {
+ data := new T[n];
+ first, len := 0, 0;
+ Contents, N := [], n;
+ }
+
+ method Clear()
+ ensures Contents == [] && N == old(N);
+ {
+ len := 0;
+ Contents := [];
+ }
+
+ method Head() returns (x: T)
+ requires Contents != [];
+ ensures x == Contents[0];
+ {
+ x := data[first];
+ }
+
+ method Enqueue(x: T)
+ requires |Contents| != N;
+ ensures Contents == old(Contents) + [x] && N == old(N);
+ {
+ var nextEmpty := if first + len < data.Length
+ then first + len else first + len - data.Length;
+ data[nextEmpty] := x;
+ len := len + 1;
+ Contents := Contents + [x];
+ }
+
+ method Dequeue() returns (x: T)
+ requires Contents != [];
+ ensures x == old(Contents)[0] && Contents == old(Contents)[1..] && N == old(N);
+ {
+ x := data[first];
+ first, len := if first + 1 == data.Length then 0 else first + 1, len - 1;
+ Contents := Contents[1..];
+ }
+}
+
+method TestHarness(x: int, y: int, z: int)
+{
+ var b := new RingBuffer.Create(2);
+ b.Enqueue(x);
+ b.Enqueue(y);
+ var h := b.Dequeue(); assert h == x;
+ b.Enqueue(z);
+ h := b.Dequeue(); assert h == y;
+ h := b.Dequeue(); assert h == z;
+}
diff --git a/Test/vstte2012/runtest.bat b/Test/vstte2012/runtest.bat index 5145cb56..770f41dc 100644 --- a/Test/vstte2012/runtest.bat +++ b/Test/vstte2012/runtest.bat @@ -8,7 +8,7 @@ set CSC=c:/Windows/Microsoft.NET/Framework/v4.0.30319/csc.exe for %%f in (
Two-Way-Sort.dfy
Combinators.dfy
- RingBuffer.dfy
+ RingBuffer.dfy RingBufferAuto.dfy
Tree.dfy
BreadthFirstSearch.dfy
) do (
diff --git a/Util/Emacs/dafny-mode.el b/Util/Emacs/dafny-mode.el index 56b56000..f16b09b5 100644 --- a/Util/Emacs/dafny-mode.el +++ b/Util/Emacs/dafny-mode.el @@ -30,7 +30,7 @@ ]\\)*" . font-lock-comment-face)
`(,(dafny-regexp-opt '(
- "class" "datatype" "type" "function" "predicate" "ghost" "var" "method" "constructor" "unlimited"
+ "class" "datatype" "codatatype" "type" "function" "predicate" "ghost" "var" "method" "constructor" "unlimited"
"module" "imports" "static" "refines"
"returns" "requires" "ensures" "modifies" "reads" "free"
"invariant" "decreases"
diff --git a/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs b/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs index 41923a98..012058f6 100644 --- a/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs +++ b/Util/VS2010/Dafny/DafnyLanguageService/Grammar.cs @@ -17,7 +17,7 @@ namespace Demo StringLiteral stringLiteral = TerminalFactory.CreateCSharpString("String");
this.MarkReservedWords( // NOTE: these keywords must also appear once more below
- "class", "ghost", "static", "var", "method", "constructor", "datatype", "type",
+ "class", "ghost", "static", "var", "method", "constructor", "datatype", "codatatype", "type",
"assert", "assume", "new", "this", "object", "refines",
"unlimited", "module", "imports",
"if", "then", "else", "while", "invariant",
@@ -267,6 +267,7 @@ namespace Demo | "method"
| "constructor"
| "datatype"
+ | "codatatype"
| "type"
| "assert"
| "assume"
diff --git a/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs b/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs index 650c01bd..48faa5ec 100644 --- a/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs +++ b/Util/VS2010/DafnyExtension/DafnyExtension/TokenTagger.cs @@ -242,6 +242,7 @@ namespace DafnyLanguage case "case":
case "choose":
case "class":
+ case "codatatype":
case "constructor":
case "datatype":
case "decreases":
diff --git a/Util/latex/dafny.sty b/Util/latex/dafny.sty index b23e2dc4..4126d2f2 100644 --- a/Util/latex/dafny.sty +++ b/Util/latex/dafny.sty @@ -5,7 +5,7 @@ \usepackage{listings}
\lstdefinelanguage{dafny}{
- morekeywords={class,datatype,type,bool,nat,int,object,set,multiset,seq,array,array2,array3,%
+ morekeywords={class,datatype,codatatype,type,bool,nat,int,object,set,multiset,seq,array,array2,array3,%
function,predicate,unlimited,
ghost,var,static,refines,
method,constructor,returns,module,imports,in,
diff --git a/Util/vim/syntax/dafny.vim b/Util/vim/syntax/dafny.vim index 37038f35..6af28094 100644 --- a/Util/vim/syntax/dafny.vim +++ b/Util/vim/syntax/dafny.vim @@ -6,7 +6,7 @@ syntax clear syntax case match syntax keyword dafnyFunction function predicate method constructor -syntax keyword dafnyTypeDef class datatype type +syntax keyword dafnyTypeDef class datatype codatatype type syntax keyword dafnyConditional if then else match case syntax keyword dafnyRepeat while parallel syntax keyword dafnyStatement havoc assume assert return new print break label |